@gravity-ui/date-components 2.4.0 → 2.5.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 (55) hide show
  1. package/dist/cjs/components/Calendar/Calendar.js +1 -0
  2. package/dist/cjs/components/CalendarView/CalendarView.js +1 -0
  3. package/dist/cjs/components/DateField/DateField.js +5 -3
  4. package/dist/cjs/components/DateField/hooks/useBaseDateFieldState.d.ts +2 -0
  5. package/dist/cjs/components/DateField/hooks/useBaseDateFieldState.js +1 -0
  6. package/dist/cjs/components/DateField/hooks/useDateFieldState.js +1 -1
  7. package/dist/cjs/components/DateField/utils.d.ts +1 -2
  8. package/dist/cjs/components/DateField/utils.js +6 -17
  9. package/dist/cjs/components/DatePicker/DatePicker.js +5 -3
  10. package/dist/cjs/components/DatePicker/MobileCalendar.js +1 -0
  11. package/dist/cjs/components/HiddenInput/HiddenInput.d.ts +14 -0
  12. package/dist/cjs/components/HiddenInput/HiddenInput.js +37 -0
  13. package/dist/cjs/components/RangeCalendar/RangeCalendar.js +1 -0
  14. package/dist/cjs/components/RangeDateField/RangeDateField.js +6 -1
  15. package/dist/cjs/components/RangeDatePicker/RangeDatePicker.js +5 -1
  16. package/dist/cjs/components/RelativeDateField/RelativeDateField.js +5 -4
  17. package/dist/cjs/components/RelativeDateField/hooks/useRelativeDateFieldState.js +2 -8
  18. package/dist/cjs/components/RelativeDatePicker/RelativeDatePicker.js +6 -3
  19. package/dist/cjs/components/RelativeRangeDatePicker/RelativeRangeDatePicker.d.ts +2 -2
  20. package/dist/cjs/components/RelativeRangeDatePicker/RelativeRangeDatePicker.js +14 -1
  21. package/dist/cjs/components/RelativeRangeDatePicker/components/PickerDialog/PickerDialog.js +1 -0
  22. package/dist/cjs/components/RelativeRangeDatePicker/components/Presets/Presets.js +1 -0
  23. package/dist/cjs/components/RelativeRangeDatePicker/components/Presets/PresetsDoc.js +1 -0
  24. package/dist/cjs/components/RelativeRangeDatePicker/components/Zones/Zones.js +1 -0
  25. package/dist/cjs/components/types/inputs.d.ts +5 -0
  26. package/dist/cjs/components/utils/mergeProps.js +3 -3
  27. package/dist/cjs/components/utils/validation/datePicker.js +2 -2
  28. package/dist/esm/components/Calendar/Calendar.js +1 -0
  29. package/dist/esm/components/CalendarView/CalendarView.js +1 -0
  30. package/dist/esm/components/DateField/DateField.js +5 -3
  31. package/dist/esm/components/DateField/hooks/useBaseDateFieldState.d.ts +2 -0
  32. package/dist/esm/components/DateField/hooks/useBaseDateFieldState.js +1 -0
  33. package/dist/esm/components/DateField/hooks/useDateFieldState.js +1 -1
  34. package/dist/esm/components/DateField/utils.d.ts +1 -2
  35. package/dist/esm/components/DateField/utils.js +5 -15
  36. package/dist/esm/components/DatePicker/DatePicker.js +5 -3
  37. package/dist/esm/components/DatePicker/MobileCalendar.js +1 -0
  38. package/dist/esm/components/HiddenInput/HiddenInput.d.ts +14 -0
  39. package/dist/esm/components/HiddenInput/HiddenInput.js +31 -0
  40. package/dist/esm/components/RangeCalendar/RangeCalendar.js +1 -0
  41. package/dist/esm/components/RangeDateField/RangeDateField.js +7 -2
  42. package/dist/esm/components/RangeDatePicker/RangeDatePicker.js +5 -1
  43. package/dist/esm/components/RelativeDateField/RelativeDateField.js +5 -4
  44. package/dist/esm/components/RelativeDateField/hooks/useRelativeDateFieldState.js +3 -11
  45. package/dist/esm/components/RelativeDatePicker/RelativeDatePicker.js +6 -3
  46. package/dist/esm/components/RelativeRangeDatePicker/RelativeRangeDatePicker.d.ts +2 -2
  47. package/dist/esm/components/RelativeRangeDatePicker/RelativeRangeDatePicker.js +14 -1
  48. package/dist/esm/components/RelativeRangeDatePicker/components/PickerDialog/PickerDialog.js +1 -0
  49. package/dist/esm/components/RelativeRangeDatePicker/components/Presets/Presets.js +1 -0
  50. package/dist/esm/components/RelativeRangeDatePicker/components/Presets/PresetsDoc.js +1 -0
  51. package/dist/esm/components/RelativeRangeDatePicker/components/Zones/Zones.js +1 -0
  52. package/dist/esm/components/types/inputs.d.ts +5 -0
  53. package/dist/esm/components/utils/mergeProps.js +3 -3
  54. package/dist/esm/components/utils/validation/datePicker.js +2 -2
  55. package/package.json +25 -19
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ 'use client';
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.Calendar = void 0;
4
5
  const tslib_1 = require("tslib");
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ 'use client';
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.CalendarView = void 0;
4
5
  const tslib_1 = require("tslib");
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ 'use client';
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.DateField = void 0;
4
5
  const tslib_1 = require("tslib");
@@ -6,6 +7,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
6
7
  const react_1 = tslib_1.__importDefault(require("react"));
7
8
  const uikit_1 = require("@gravity-ui/uikit");
8
9
  const cn_1 = require("../../utils/cn");
10
+ const HiddenInput_1 = require("../HiddenInput/HiddenInput");
9
11
  const useDateFieldProps_1 = require("./hooks/useDateFieldProps");
10
12
  const useDateFieldState_1 = require("./hooks/useDateFieldState");
11
13
  require("./DateField.css");
@@ -20,8 +22,8 @@ function DateField(_a) {
20
22
  setActive(isFocusWithin);
21
23
  },
22
24
  });
23
- return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: b(null, className), style: props.style }, focusWithinProps, { children: [(0, jsx_runtime_1.jsx)(uikit_1.TextInput, Object.assign({}, inputProps, { value: state.isEmpty && !isActive && props.placeholder ? '' : inputProps.value })), (0, jsx_runtime_1.jsx)("input", { type: "text", hidden: true, name: props.name, value: state.value ? state.value.toISOString() : '',
24
- // Ignore React warning
25
- onChange: () => { } })] })));
25
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: b(null, className), style: props.style }, focusWithinProps, { children: [(0, jsx_runtime_1.jsx)(uikit_1.TextInput, Object.assign({}, inputProps, { value: state.isEmpty && !isActive && props.placeholder ? '' : inputProps.value })), (0, jsx_runtime_1.jsx)(HiddenInput_1.HiddenInput, { name: props.name, value: state.value, toStringValue: (value) => { var _a; return (_a = value === null || value === void 0 ? void 0 : value.toISOString()) !== null && _a !== void 0 ? _a : ''; }, onReset: (value) => {
26
+ state.setDate(value);
27
+ }, disabled: state.disabled, form: props.form })] })));
26
28
  }
27
29
  exports.DateField = DateField;
@@ -37,6 +37,8 @@ export type DateFieldState<T = DateTime> = {
37
37
  displayValue: T;
38
38
  /** Sets the field's value. */
39
39
  setValue: (value: T) => void;
40
+ /** Sets the date value. */
41
+ setDate: (value: T | null) => void;
40
42
  /** Formatted value */
41
43
  text: string;
42
44
  /** Whether the field is read only. */
@@ -34,6 +34,7 @@ function useBaseDateFieldState(props) {
34
34
  isEmpty,
35
35
  displayValue,
36
36
  setValue,
37
+ setDate,
37
38
  text: (0, utils_1.formatSections)(editableSections),
38
39
  readOnly: props.readOnly,
39
40
  disabled: props.disabled,
@@ -139,7 +139,7 @@ function useDateFieldState(props) {
139
139
  }).timeZone(timeZone);
140
140
  }
141
141
  function setValueFromString(str) {
142
- const date = (0, utils_1.parseDateFromString)(str, props.format || 'L', timeZone);
142
+ const date = (0, utils_1.parseDateFromString)(str, format, timeZone);
143
143
  if ((0, date_utils_1.isValid)(date)) {
144
144
  handleUpdateDate(date);
145
145
  return true;
@@ -1,7 +1,6 @@
1
1
  import type { DateTime } from '@gravity-ui/date-utils';
2
2
  import type { DateFieldSection, DateFieldSectionType, DateFieldSectionWithoutPosition } from './types';
3
3
  export declare const EDITABLE_SEGMENTS: Partial<Record<DateFieldSectionType, boolean>>;
4
- export declare function expandFormat(format: string): string;
5
4
  export declare function getSectionLimits(section: DateFieldSectionWithoutPosition, date: DateTime): {
6
5
  minValue: number;
7
6
  maxValue: number;
@@ -9,7 +8,7 @@ export declare function getSectionLimits(section: DateFieldSectionWithoutPositio
9
8
  minValue?: undefined;
10
9
  maxValue?: undefined;
11
10
  };
12
- export declare function getSectionValue(sections: DateFieldSectionWithoutPosition, date: DateTime): number | undefined;
11
+ export declare function getSectionValue(section: DateFieldSectionWithoutPosition, date: DateTime): number | undefined;
13
12
  export declare function getDurationUnitFromSectionType(type: DateFieldSectionType): "year" | "month" | "day" | "hour" | "minute" | "second" | "date";
14
13
  export declare function addSegment(section: DateFieldSection, date: DateTime, amount: number): DateTime;
15
14
  export declare function setSegment(section: DateFieldSection, date: DateTime, amount: number): DateTime;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useFormatSections = exports.isAllSegmentsValid = exports.parseDateFromString = exports.formatSections = exports.getCurrentEditableSectionIndex = exports.toEditableSection = exports.isEditableSection = exports.getEditableSections = exports.cleanString = exports.splitFormatIntoSections = exports.setSegment = exports.addSegment = exports.getDurationUnitFromSectionType = exports.getSectionValue = exports.getSectionLimits = exports.expandFormat = exports.EDITABLE_SEGMENTS = void 0;
3
+ exports.useFormatSections = exports.isAllSegmentsValid = exports.parseDateFromString = exports.formatSections = exports.getCurrentEditableSectionIndex = exports.toEditableSection = exports.isEditableSection = exports.getEditableSections = exports.cleanString = exports.splitFormatIntoSections = exports.setSegment = exports.addSegment = exports.getDurationUnitFromSectionType = exports.getSectionValue = exports.getSectionLimits = exports.EDITABLE_SEGMENTS = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const date_utils_1 = require("@gravity-ui/date-utils");
@@ -16,17 +16,6 @@ exports.EDITABLE_SEGMENTS = {
16
16
  dayPeriod: true,
17
17
  weekday: true,
18
18
  };
19
- function expandFormat(format) {
20
- const localeFormats = date_utils_1.settings.getLocaleData().formats;
21
- const getShortLocalizedFormatFromLongLocalizedFormat = (formatBis) => formatBis.replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g, (_, escapeSequence, localizedFormat) => escapeSequence || localizedFormat.slice(1));
22
- return format.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g, (_, escapeSequence, localizedFormat) => {
23
- const LongLocalizedFormat = localizedFormat && localizedFormat.toUpperCase();
24
- return (escapeSequence ||
25
- localeFormats[localizedFormat] ||
26
- getShortLocalizedFormatFromLongLocalizedFormat(localeFormats[LongLocalizedFormat]));
27
- });
28
- }
29
- exports.expandFormat = expandFormat;
30
19
  const escapedCharacters = { start: '[', end: ']' };
31
20
  const formatTokenMap = {
32
21
  // Year
@@ -148,13 +137,13 @@ function getSectionLimits(section, date) {
148
137
  return {};
149
138
  }
150
139
  exports.getSectionLimits = getSectionLimits;
151
- function getSectionValue(sections, date) {
152
- const type = sections.type;
140
+ function getSectionValue(section, date) {
141
+ const type = section.type;
153
142
  switch (type) {
154
143
  case 'year': {
155
- return isFourDigitYearFormat(sections.format)
144
+ return isFourDigitYearFormat(section.format)
156
145
  ? date.year()
157
- : Number(date.format(sections.format));
146
+ : Number(date.format(section.format));
158
147
  }
159
148
  case 'month':
160
149
  case 'hour':
@@ -329,7 +318,7 @@ function getSectionPlaceholder(sectionConfig, currentTokenValue) {
329
318
  }
330
319
  function splitFormatIntoSections(format) {
331
320
  const sections = [];
332
- const expandedFormat = expandFormat(format);
321
+ const expandedFormat = (0, date_utils_1.expandFormat)(format);
333
322
  let currentTokenValue = '';
334
323
  let isSeparator = false;
335
324
  let isInEscapeBoundary = false;
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ 'use client';
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.DatePicker = void 0;
4
5
  const tslib_1 = require("tslib");
@@ -8,6 +9,7 @@ const icons_1 = require("@gravity-ui/icons");
8
9
  const uikit_1 = require("@gravity-ui/uikit");
9
10
  const Calendar_1 = require("../Calendar");
10
11
  const DateField_1 = require("../DateField");
12
+ const HiddenInput_1 = require("../HiddenInput/HiddenInput");
11
13
  const MobileCalendar_1 = require("./MobileCalendar");
12
14
  const StubButton_1 = require("./StubButton");
13
15
  const useDatePickerProps_1 = require("./hooks/useDatePickerProps");
@@ -21,8 +23,8 @@ function DatePicker(_a) {
21
23
  const { groupProps, fieldProps, calendarButtonProps, popupProps, calendarProps, timeInputProps } = (0, useDatePickerProps_1.useDatePickerProps)(state, props);
22
24
  const isMobile = (0, uikit_1.useMobile)();
23
25
  const isOnlyTime = state.hasTime && !state.hasDate;
24
- return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: (0, utils_1.b)(null, className) }, groupProps, { children: [isMobile ? ((0, jsx_runtime_1.jsx)(MobileCalendar_1.MobileCalendar, { props: props, state: state })) : (!isOnlyTime && ((0, jsx_runtime_1.jsx)("div", { ref: anchorRef, className: (0, utils_1.b)('popup-anchor'), children: (0, jsx_runtime_1.jsx)(uikit_1.Popup, Object.assign({ anchorRef: anchorRef }, popupProps, { children: (0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.b)('popup-content'), children: [typeof props.children === 'function' ? (props.children(calendarProps)) : ((0, jsx_runtime_1.jsx)(Calendar_1.Calendar, Object.assign({}, calendarProps))), state.hasTime && ((0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.b)('time-field-wrapper'), children: (0, jsx_runtime_1.jsx)(DateField_1.DateField, Object.assign({}, timeInputProps)) }))] }) })) }))), (0, jsx_runtime_1.jsx)(uikit_1.TextInput, Object.assign({}, fieldProps, { className: (0, utils_1.b)('field', { mobile: isMobile }), hasClear: !isMobile && fieldProps.hasClear, endContent: (0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [!isMobile && !isOnlyTime && ((0, jsx_runtime_1.jsx)(uikit_1.Button, Object.assign({}, calendarButtonProps, { children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Calendar }) }))), !isMobile && isOnlyTime && ((0, jsx_runtime_1.jsx)(StubButton_1.StubButton, { size: calendarButtonProps.size, icon: icons_1.Clock })), isMobile && ((0, jsx_runtime_1.jsx)(StubButton_1.StubButton, { size: calendarButtonProps.size, icon: isOnlyTime ? icons_1.Clock : icons_1.Calendar }))] }) })), (0, jsx_runtime_1.jsx)("input", { type: "text", hidden: true, name: props.name, value: state.value ? state.value.toISOString() : '',
25
- // Ignore React warning
26
- onChange: () => { } })] })));
26
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: (0, utils_1.b)(null, className) }, groupProps, { children: [isMobile ? ((0, jsx_runtime_1.jsx)(MobileCalendar_1.MobileCalendar, { props: props, state: state })) : (!isOnlyTime && ((0, jsx_runtime_1.jsx)("div", { ref: anchorRef, className: (0, utils_1.b)('popup-anchor'), children: (0, jsx_runtime_1.jsx)(uikit_1.Popup, Object.assign({ anchorRef: anchorRef }, popupProps, { children: (0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.b)('popup-content'), children: [typeof props.children === 'function' ? (props.children(calendarProps)) : ((0, jsx_runtime_1.jsx)(Calendar_1.Calendar, Object.assign({}, calendarProps))), state.hasTime && ((0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.b)('time-field-wrapper'), children: (0, jsx_runtime_1.jsx)(DateField_1.DateField, Object.assign({}, timeInputProps)) }))] }) })) }))), (0, jsx_runtime_1.jsx)(uikit_1.TextInput, Object.assign({}, fieldProps, { className: (0, utils_1.b)('field', { mobile: isMobile }), hasClear: !isMobile && fieldProps.hasClear, endContent: (0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [!isMobile && !isOnlyTime && ((0, jsx_runtime_1.jsx)(uikit_1.Button, Object.assign({}, calendarButtonProps, { children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Calendar }) }))), !isMobile && isOnlyTime && ((0, jsx_runtime_1.jsx)(StubButton_1.StubButton, { size: calendarButtonProps.size, icon: icons_1.Clock })), isMobile && ((0, jsx_runtime_1.jsx)(StubButton_1.StubButton, { size: calendarButtonProps.size, icon: isOnlyTime ? icons_1.Clock : icons_1.Calendar }))] }) })), (0, jsx_runtime_1.jsx)(HiddenInput_1.HiddenInput, { name: props.name, value: state.value, toStringValue: (value) => { var _a; return (_a = value === null || value === void 0 ? void 0 : value.toISOString()) !== null && _a !== void 0 ? _a : ''; }, onReset: (value) => {
27
+ state.setValue(value);
28
+ }, disabled: state.disabled, form: props.form })] })));
27
29
  }
28
30
  exports.DatePicker = DatePicker;
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ 'use client';
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.MobileCalendar = void 0;
4
5
  const jsx_runtime_1 = require("react/jsx-runtime");
@@ -0,0 +1,14 @@
1
+ interface HiddenInputProps<T> {
2
+ value: T;
3
+ onReset?: (value: T) => void;
4
+ toStringValue?: (value: T) => string;
5
+ name?: string;
6
+ disabled?: boolean;
7
+ form?: string;
8
+ }
9
+ export declare function HiddenInput<T>({ name, value, onReset, form, disabled, toStringValue, }: HiddenInputProps<T>): import("react/jsx-runtime").JSX.Element | null;
10
+ export declare function useFormResetHandler<T>({ initialValue, onReset, }: {
11
+ initialValue: T;
12
+ onReset?: (value: T) => void;
13
+ }): (node: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | null) => void;
14
+ export {};
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useFormResetHandler = exports.HiddenInput = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_1 = tslib_1.__importDefault(require("react"));
7
+ function HiddenInput({ name, value, onReset, form, disabled, toStringValue, }) {
8
+ const ref = useFormResetHandler({ initialValue: value, onReset });
9
+ if (!name) {
10
+ return null;
11
+ }
12
+ const v = toStringValue ? toStringValue(value) : `${value !== null && value !== void 0 ? value : ''}`;
13
+ return (0, jsx_runtime_1.jsx)("input", { ref: ref, type: "hidden", name: name, value: v, disabled: disabled, form: form });
14
+ }
15
+ exports.HiddenInput = HiddenInput;
16
+ function useFormResetHandler({ initialValue, onReset, }) {
17
+ const [formElement, setFormElement] = react_1.default.useState(null);
18
+ const resetValue = react_1.default.useRef(initialValue);
19
+ react_1.default.useEffect(() => {
20
+ if (!formElement || !onReset) {
21
+ return undefined;
22
+ }
23
+ const handleReset = () => {
24
+ onReset(resetValue.current);
25
+ };
26
+ formElement.addEventListener('reset', handleReset);
27
+ return () => {
28
+ formElement.removeEventListener('reset', handleReset);
29
+ };
30
+ }, [formElement, onReset]);
31
+ const ref = react_1.default.useCallback((node) => {
32
+ var _a;
33
+ setFormElement((_a = node === null || node === void 0 ? void 0 : node.form) !== null && _a !== void 0 ? _a : null);
34
+ }, []);
35
+ return ref;
36
+ }
37
+ exports.useFormResetHandler = useFormResetHandler;
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ 'use client';
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.RangeCalendar = void 0;
4
5
  const tslib_1 = require("tslib");
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ 'use client';
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.RangeDateField = void 0;
4
5
  const tslib_1 = require("tslib");
@@ -7,10 +8,12 @@ const react_1 = tslib_1.__importDefault(require("react"));
7
8
  const uikit_1 = require("@gravity-ui/uikit");
8
9
  const cn_1 = require("../../utils/cn");
9
10
  const useDateFieldProps_1 = require("../DateField/hooks/useDateFieldProps");
11
+ const HiddenInput_1 = require("../HiddenInput/HiddenInput");
10
12
  const useRangeDateFieldState_1 = require("./hooks/useRangeDateFieldState");
11
13
  require("./RangeDateField.css");
12
14
  const b = (0, cn_1.block)('range-date-field');
13
15
  function RangeDateField(_a) {
16
+ var _b, _c;
14
17
  var { className } = _a, props = tslib_1.__rest(_a, ["className"]);
15
18
  const state = (0, useRangeDateFieldState_1.useRangeDateFieldState)(props);
16
19
  const { inputProps } = (0, useDateFieldProps_1.useDateFieldProps)(state, props);
@@ -20,6 +23,8 @@ function RangeDateField(_a) {
20
23
  setActive(isFocusWithin);
21
24
  },
22
25
  });
23
- return ((0, jsx_runtime_1.jsx)("div", Object.assign({ className: b(null, className), style: props.style }, focusWithinProps, { children: (0, jsx_runtime_1.jsx)(uikit_1.TextInput, Object.assign({}, inputProps, { value: state.isEmpty && !isActive && props.placeholder ? '' : inputProps.value })) })));
26
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: b(null, className), style: props.style }, focusWithinProps, { children: [(0, jsx_runtime_1.jsx)(uikit_1.TextInput, Object.assign({}, inputProps, { value: state.isEmpty && !isActive && props.placeholder ? '' : inputProps.value })), (0, jsx_runtime_1.jsx)(HiddenInput_1.HiddenInput, { name: props.name, form: props.form, onReset: (v) => {
27
+ state.setDate(v);
28
+ }, value: (_b = state.value) !== null && _b !== void 0 ? _b : null, toStringValue: (v) => (v ? v.start.toISOString() : ''), disabled: state.disabled }), (0, jsx_runtime_1.jsx)(HiddenInput_1.HiddenInput, { name: props.name, form: props.form, value: (_c = state.value) !== null && _c !== void 0 ? _c : null, toStringValue: (v) => (v ? v.end.toISOString() : ''), disabled: state.disabled })] })));
24
29
  }
25
30
  exports.RangeDateField = RangeDateField;
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ 'use client';
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.RangeDatePicker = void 0;
4
5
  const tslib_1 = require("tslib");
@@ -10,6 +11,7 @@ const cn_1 = require("../../utils/cn");
10
11
  const Calendar_1 = require("../Calendar");
11
12
  const DatePicker_1 = require("../DatePicker");
12
13
  const StubButton_1 = require("../DatePicker/StubButton");
14
+ const HiddenInput_1 = require("../HiddenInput/HiddenInput");
13
15
  const RangeDateField_1 = require("../RangeDateField");
14
16
  const useRangeDatePickerState_1 = require("./hooks/useRangeDatePickerState");
15
17
  require("./RangeDatePicker.css");
@@ -20,6 +22,8 @@ function RangeDatePicker(_a) {
20
22
  const state = (0, useRangeDatePickerState_1.useRangeDatePickerState)(props);
21
23
  const { groupProps, fieldProps, calendarButtonProps, popupProps, calendarProps, timeInputProps } = (0, DatePicker_1.useDatePickerProps)(state, props);
22
24
  const isOnlyTime = state.hasTime && !state.hasDate;
23
- return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: b(null, className) }, groupProps, { children: [!isOnlyTime && ((0, jsx_runtime_1.jsx)("div", { ref: anchorRef, className: b('popup-anchor'), children: (0, jsx_runtime_1.jsx)(uikit_1.Popup, Object.assign({ anchorRef: anchorRef }, popupProps, { children: (0, jsx_runtime_1.jsxs)("div", { className: b('popup-content'), children: [typeof props.children === 'function' ? (props.children(Object.assign(Object.assign({}, calendarProps), { value: state.value }))) : ((0, jsx_runtime_1.jsx)(Calendar_1.RangeCalendar, Object.assign({}, calendarProps, { value: state.value }))), state.hasTime && ((0, jsx_runtime_1.jsx)("div", { className: b('time-field-wrapper'), children: (0, jsx_runtime_1.jsx)(RangeDateField_1.RangeDateField, Object.assign({}, timeInputProps)) }))] }) })) })), (0, jsx_runtime_1.jsx)(uikit_1.TextInput, Object.assign({}, fieldProps, { className: b('field'), hasClear: fieldProps.hasClear, endContent: (0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [!isOnlyTime && ((0, jsx_runtime_1.jsx)(uikit_1.Button, Object.assign({}, calendarButtonProps, { children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Calendar }) }))), isOnlyTime && ((0, jsx_runtime_1.jsx)(StubButton_1.StubButton, { size: calendarButtonProps.size, icon: icons_1.Clock }))] }) }))] })));
25
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: b(null, className) }, groupProps, { children: [!isOnlyTime && ((0, jsx_runtime_1.jsx)("div", { ref: anchorRef, className: b('popup-anchor'), children: (0, jsx_runtime_1.jsx)(uikit_1.Popup, Object.assign({ anchorRef: anchorRef }, popupProps, { children: (0, jsx_runtime_1.jsxs)("div", { className: b('popup-content'), children: [typeof props.children === 'function' ? (props.children(Object.assign(Object.assign({}, calendarProps), { value: state.value }))) : ((0, jsx_runtime_1.jsx)(Calendar_1.RangeCalendar, Object.assign({}, calendarProps, { value: state.value }))), state.hasTime && ((0, jsx_runtime_1.jsx)("div", { className: b('time-field-wrapper'), children: (0, jsx_runtime_1.jsx)(RangeDateField_1.RangeDateField, Object.assign({}, timeInputProps)) }))] }) })) })), (0, jsx_runtime_1.jsx)(uikit_1.TextInput, Object.assign({}, fieldProps, { className: b('field'), hasClear: fieldProps.hasClear, endContent: (0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [!isOnlyTime && ((0, jsx_runtime_1.jsx)(uikit_1.Button, Object.assign({}, calendarButtonProps, { children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Calendar }) }))), isOnlyTime && ((0, jsx_runtime_1.jsx)(StubButton_1.StubButton, { size: calendarButtonProps.size, icon: icons_1.Clock }))] }) })), (0, jsx_runtime_1.jsx)(HiddenInput_1.HiddenInput, { name: props.name, form: props.form, onReset: (v) => {
26
+ state.dateFieldState.setDate(v);
27
+ }, value: state.value, toStringValue: (v) => (v ? v.start.toISOString() : ''), disabled: state.disabled }), (0, jsx_runtime_1.jsx)(HiddenInput_1.HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => (v ? v.end.toISOString() : ''), disabled: state.disabled })] })));
24
28
  }
25
29
  exports.RangeDatePicker = RangeDatePicker;
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ 'use client';
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.RelativeDateField = void 0;
4
5
  const tslib_1 = require("tslib");
@@ -8,12 +9,12 @@ const uikit_1 = require("@gravity-ui/uikit");
8
9
  const cn_1 = require("../../utils/cn");
9
10
  const Calendar_1 = require("../Calendar");
10
11
  const DateField_1 = require("../DateField");
12
+ const HiddenInput_1 = require("../HiddenInput/HiddenInput");
11
13
  const useRelativeDateFieldProps_1 = require("./hooks/useRelativeDateFieldProps");
12
14
  const useRelativeDateFieldState_1 = require("./hooks/useRelativeDateFieldState");
13
15
  require("./RelativeDateField.css");
14
16
  const b = (0, cn_1.block)('relative-date-field');
15
17
  function RelativeDateField(props) {
16
- var _a;
17
18
  const state = (0, useRelativeDateFieldState_1.useRelativeDateFieldState)(props);
18
19
  const { inputProps, calendarProps, timeInputProps } = (0, useRelativeDateFieldProps_1.useRelativeDateFieldProps)(state, props);
19
20
  const isMobile = (0, uikit_1.useMobile)();
@@ -31,8 +32,8 @@ function RelativeDateField(props) {
31
32
  setOpen(true);
32
33
  }
33
34
  (_a = props.onFocus) === null || _a === void 0 ? void 0 : _a.call(props, e);
34
- }, onBlur: props.onBlur })), (0, jsx_runtime_1.jsx)("input", { type: "text", hidden: true, name: props.name, value: (_a = state.value) !== null && _a !== void 0 ? _a : '',
35
- // Ignore React warning
36
- onChange: () => { } }), !isMobile && ((0, jsx_runtime_1.jsx)(uikit_1.Popup, { anchorRef: anchorRef, open: isOpen, children: (0, jsx_runtime_1.jsxs)("div", { className: b('popup-content'), children: [(0, jsx_runtime_1.jsx)(Calendar_1.Calendar, Object.assign({}, calendarProps)), props.hasTime ? ((0, jsx_runtime_1.jsx)("div", { className: b('time-field-wrapper'), children: (0, jsx_runtime_1.jsx)(DateField_1.DateField, Object.assign({ className: b('time-field') }, timeInputProps)) })) : null] }) }))] })));
35
+ }, onBlur: props.onBlur })), (0, jsx_runtime_1.jsx)(HiddenInput_1.HiddenInput, { name: props.name, value: state.value, onReset: (value) => {
36
+ state.setValue(value);
37
+ }, disabled: state.disabled, form: props.form }), !isMobile && ((0, jsx_runtime_1.jsx)(uikit_1.Popup, { anchorRef: anchorRef, open: isOpen, children: (0, jsx_runtime_1.jsxs)("div", { className: b('popup-content'), children: [(0, jsx_runtime_1.jsx)(Calendar_1.Calendar, Object.assign({}, calendarProps)), props.hasTime ? ((0, jsx_runtime_1.jsx)("div", { className: b('time-field-wrapper'), children: (0, jsx_runtime_1.jsx)(DateField_1.DateField, Object.assign({ className: b('time-field') }, timeInputProps)) })) : null] }) }))] })));
37
38
  }
38
39
  exports.RelativeDateField = RelativeDateField;
@@ -17,7 +17,7 @@ function useRelativeDateFieldState(props) {
17
17
  return;
18
18
  }
19
19
  setText(t);
20
- if (isLikeRelativeDate(t)) {
20
+ if ((0, date_utils_1.isLikeRelative)(t)) {
21
21
  const date = (0, date_utils_1.dateTimeParse)(t);
22
22
  if (date && (0, date_utils_1.isValid)(date)) {
23
23
  setValue(t);
@@ -36,7 +36,7 @@ function useRelativeDateFieldState(props) {
36
36
  return null;
37
37
  }
38
38
  return (_a = (0, date_utils_1.dateTimeParse)(value, { timeZone: props.timeZone, roundUp: props.roundUp })) !== null && _a !== void 0 ? _a : null;
39
- }, [value, props.timeZone]);
39
+ }, [value, props.timeZone, props.roundUp]);
40
40
  const [lastCorrectDate, setLastCorrectDate] = react_1.default.useState(parsedDate);
41
41
  if (parsedDate && parsedDate !== lastCorrectDate) {
42
42
  setLastCorrectDate(parsedDate);
@@ -60,9 +60,3 @@ function useRelativeDateFieldState(props) {
60
60
  };
61
61
  }
62
62
  exports.useRelativeDateFieldState = useRelativeDateFieldState;
63
- function isLikeRelativeDate(text) {
64
- if (typeof date_utils_1.isLikeRelative === 'function') {
65
- return (0, date_utils_1.isLikeRelative)(text);
66
- }
67
- return /^now/i.test(text);
68
- }
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ 'use client';
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.RelativeDatePicker = void 0;
4
5
  const tslib_1 = require("tslib");
@@ -11,11 +12,13 @@ const Calendar_1 = require("../Calendar");
11
12
  const DateField_1 = require("../DateField");
12
13
  const MobileCalendar_1 = require("../DatePicker/MobileCalendar");
13
14
  const StubButton_1 = require("../DatePicker/StubButton");
15
+ const HiddenInput_1 = require("../HiddenInput/HiddenInput");
14
16
  const useRelativeDatePickerProps_1 = require("./hooks/useRelativeDatePickerProps");
15
17
  const useRelativeDatePickerState_1 = require("./hooks/useRelativeDatePickerState");
16
18
  require("./RelativeDatePicker.css");
17
19
  const b = (0, cn_1.block)('relative-date-picker');
18
20
  function RelativeDatePicker(props) {
21
+ var _a;
19
22
  const state = (0, useRelativeDatePickerState_1.useRelativeDatePickerState)(props);
20
23
  const { groupProps, fieldProps, modeSwitcherProps, calendarButtonProps, popupProps, calendarProps, timeInputProps, } = (0, useRelativeDatePickerProps_1.useRelativeDatePickerProps)(state, props);
21
24
  const anchorRef = react_1.default.useRef(null);
@@ -27,9 +30,9 @@ function RelativeDatePicker(props) {
27
30
  readOnly: props.readOnly,
28
31
  placeholderValue: props.placeholderValue,
29
32
  timeZone: props.timeZone,
30
- } })), (0, jsx_runtime_1.jsx)(uikit_1.TextInput, Object.assign({}, fieldProps, { controlProps: Object.assign(Object.assign({}, fieldProps.controlProps), { disabled: isMobile && state.mode === 'absolute', className: b('input', { mobile: isMobile && state.mode === 'absolute' }) }), hasClear: props.hasClear && !(isMobile && state.mode === 'absolute'), startContent: (0, jsx_runtime_1.jsx)(uikit_1.Button, Object.assign({}, modeSwitcherProps, { children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Function }) })), endContent: (0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [!isMobile && !isOnlyTime && ((0, jsx_runtime_1.jsx)(uikit_1.Button, Object.assign({}, calendarButtonProps, { children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Calendar }) }))), !isMobile && isOnlyTime && ((0, jsx_runtime_1.jsx)(StubButton_1.StubButton, { size: calendarButtonProps.size, icon: icons_1.Clock })), isMobile && state.mode === 'absolute' && ((0, jsx_runtime_1.jsx)(StubButton_1.StubButton, { size: calendarButtonProps.size, icon: isOnlyTime ? icons_1.Clock : icons_1.Calendar }))] }) })), (0, jsx_runtime_1.jsx)("input", { type: "text", hidden: true, name: props.name, value: getNativeValue(state.value),
31
- // Ignore React warning
32
- onChange: () => { } }), !isMobile && !isOnlyTime && ((0, jsx_runtime_1.jsx)(uikit_1.Popup, Object.assign({}, popupProps, { anchorRef: anchorRef, children: (0, jsx_runtime_1.jsxs)("div", { className: b('popup-content'), children: [typeof props.children === 'function' ? (props.children(calendarProps)) : ((0, jsx_runtime_1.jsx)(Calendar_1.Calendar, Object.assign({}, calendarProps))), state.datePickerState.hasTime && ((0, jsx_runtime_1.jsx)("div", { className: b('time-field-wrapper'), children: (0, jsx_runtime_1.jsx)(DateField_1.DateField, Object.assign({}, timeInputProps)) }))] }) })))] })));
33
+ } })), (0, jsx_runtime_1.jsx)(uikit_1.TextInput, Object.assign({}, fieldProps, { controlProps: Object.assign(Object.assign({}, fieldProps.controlProps), { disabled: isMobile && state.mode === 'absolute', className: b('input', { mobile: isMobile && state.mode === 'absolute' }) }), hasClear: props.hasClear && !(isMobile && state.mode === 'absolute'), startContent: (0, jsx_runtime_1.jsx)(uikit_1.Button, Object.assign({}, modeSwitcherProps, { children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Function }) })), endContent: (0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [!isMobile && !isOnlyTime && ((0, jsx_runtime_1.jsx)(uikit_1.Button, Object.assign({}, calendarButtonProps, { children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Calendar }) }))), !isMobile && isOnlyTime && ((0, jsx_runtime_1.jsx)(StubButton_1.StubButton, { size: calendarButtonProps.size, icon: icons_1.Clock })), isMobile && state.mode === 'absolute' && ((0, jsx_runtime_1.jsx)(StubButton_1.StubButton, { size: calendarButtonProps.size, icon: isOnlyTime ? icons_1.Clock : icons_1.Calendar }))] }) })), (0, jsx_runtime_1.jsx)(HiddenInput_1.HiddenInput, { name: props.name, value: (_a = state.value) === null || _a === void 0 ? void 0 : _a.type, disabled: state.disabled, form: props.form }), (0, jsx_runtime_1.jsx)(HiddenInput_1.HiddenInput, { name: props.name, value: state.value, toStringValue: (value) => getNativeValue(value), onReset: (value) => {
34
+ state.setValue(value);
35
+ }, disabled: state.disabled, form: props.form }), !isMobile && !isOnlyTime && ((0, jsx_runtime_1.jsx)(uikit_1.Popup, Object.assign({}, popupProps, { anchorRef: anchorRef, children: (0, jsx_runtime_1.jsxs)("div", { className: b('popup-content'), children: [typeof props.children === 'function' ? (props.children(calendarProps)) : ((0, jsx_runtime_1.jsx)(Calendar_1.Calendar, Object.assign({}, calendarProps))), state.datePickerState.hasTime && ((0, jsx_runtime_1.jsx)("div", { className: b('time-field-wrapper'), children: (0, jsx_runtime_1.jsx)(DateField_1.DateField, Object.assign({}, timeInputProps)) }))] }) })))] })));
33
36
  }
34
37
  exports.RelativeDatePicker = RelativeDatePicker;
35
38
  function getNativeValue(value) {
@@ -1,11 +1,11 @@
1
1
  import type { DateTime } from '@gravity-ui/date-utils';
2
2
  import type { Value } from '../RelativeDatePicker';
3
- import type { DomProps, FocusableProps, InputBase, RangeValue, StyleProps, TextInputProps, Validation } from '../types';
3
+ import type { DomProps, FocusableProps, InputBase, InputDOMProps, RangeValue, StyleProps, TextInputProps, Validation } from '../types';
4
4
  import type { Preset } from './components/Presets/defaultPresets';
5
5
  import type { PresetTab } from './components/Presets/utils';
6
6
  import type { RelativeRangeDatePickerStateOptions } from './hooks/useRelativeRangeDatePickerState';
7
7
  import './RelativeRangeDatePicker.css';
8
- export interface RelativeRangeDatePickerProps extends RelativeRangeDatePickerStateOptions, DomProps, InputBase, TextInputProps, Validation, FocusableProps, StyleProps {
8
+ export interface RelativeRangeDatePickerProps extends RelativeRangeDatePickerStateOptions, DomProps, InputBase, InputDOMProps, TextInputProps, Validation, FocusableProps, StyleProps {
9
9
  /** Format of the date when rendered in the input. [Available formats](https://day.js.org/docs/en/display/format) */
10
10
  format?: string;
11
11
  /** A placeholder date that controls the default values of each segment when the user first interacts with them. Defaults to today's date at midnight. */
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ 'use client';
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.RelativeRangeDatePicker = void 0;
4
5
  const tslib_1 = require("tslib");
@@ -7,6 +8,7 @@ const react_1 = tslib_1.__importDefault(require("react"));
7
8
  const icons_1 = require("@gravity-ui/icons");
8
9
  const uikit_1 = require("@gravity-ui/uikit");
9
10
  const cn_1 = require("../../utils/cn");
11
+ const HiddenInput_1 = require("../HiddenInput/HiddenInput");
10
12
  const getButtonSizeForInput_1 = require("../utils/getButtonSizeForInput");
11
13
  const PickerDialog_1 = require("./components/PickerDialog/PickerDialog");
12
14
  const useRelativeRangeDatePickerState_1 = require("./hooks/useRelativeRangeDatePickerState");
@@ -88,8 +90,19 @@ function RelativeRangeDatePicker(props) {
88
90
  }), onClick: () => {
89
91
  setIsActive(true);
90
92
  setOpen(true);
91
- } })) : null, (0, jsx_runtime_1.jsx)(PickerDialog_1.PickerDialog, { state: state, props: props, open: open, onClose: () => {
93
+ } })) : null, (0, jsx_runtime_1.jsx)(HiddenInput_1.HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => { var _a, _b; return (_b = (_a = v === null || v === void 0 ? void 0 : v.start) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : ''; }, disabled: props.disabled }), (0, jsx_runtime_1.jsx)(HiddenInput_1.HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => { var _a; return getNativeValue((_a = v === null || v === void 0 ? void 0 : v.start) !== null && _a !== void 0 ? _a : null); }, disabled: props.disabled }), (0, jsx_runtime_1.jsx)(HiddenInput_1.HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => { var _a, _b; return (_b = (_a = v === null || v === void 0 ? void 0 : v.end) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : ''; }, disabled: props.disabled }), (0, jsx_runtime_1.jsx)(HiddenInput_1.HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => { var _a; return getNativeValue((_a = v === null || v === void 0 ? void 0 : v.end) !== null && _a !== void 0 ? _a : null); }, disabled: props.disabled }), (0, jsx_runtime_1.jsx)(HiddenInput_1.HiddenInput, { name: props.name, form: props.form, onReset: (v) => {
94
+ state.setValue(v.value, v.timeZone);
95
+ }, value: { value: state.value, timeZone: state.timeZone }, toStringValue: (v) => v.timeZone, disabled: props.disabled }), (0, jsx_runtime_1.jsx)(PickerDialog_1.PickerDialog, { state: state, props: props, open: open, onClose: () => {
92
96
  setOpen(false);
93
97
  }, anchorRef: anchorRef, isMobile: isMobile, className: props.className })] })));
94
98
  }
95
99
  exports.RelativeRangeDatePicker = RelativeRangeDatePicker;
100
+ function getNativeValue(value) {
101
+ if (!value) {
102
+ return '';
103
+ }
104
+ if (value.type === 'relative') {
105
+ return value.value;
106
+ }
107
+ return value.value.toISOString();
108
+ }
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ 'use client';
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.PickerDialog = void 0;
4
5
  const jsx_runtime_1 = require("react/jsx-runtime");
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ 'use client';
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.SIZE_TO_ITEM_HEIGHT = exports.Presets = void 0;
4
5
  const tslib_1 = require("tslib");
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ 'use client';
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.PresetsDoc = void 0;
4
5
  const tslib_1 = require("tslib");
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ 'use client';
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.Zones = void 0;
4
5
  const jsx_runtime_1 = require("react/jsx-runtime");
@@ -29,6 +29,11 @@ export interface InputDOMProps {
29
29
  * The name of the input element, used when submitting an HTML form.
30
30
  */
31
31
  name?: string;
32
+ /**
33
+ * The id of a <form> in the same document. If this attribute is not set,
34
+ * the <input> is associated with its ancestor <form> element, if any.
35
+ */
36
+ form?: string;
32
37
  }
33
38
  export interface InputBase {
34
39
  /**
@@ -38,9 +38,9 @@ function mergeProps(...args) {
38
38
  exports.mergeProps = mergeProps;
39
39
  function chain(...fns) {
40
40
  return (...args) => {
41
- for (const callback of fns) {
42
- if (typeof callback === 'function') {
43
- callback(...args);
41
+ for (const fn of fns) {
42
+ if (typeof fn === 'function') {
43
+ fn(...args);
44
44
  }
45
45
  }
46
46
  };
@@ -9,13 +9,13 @@ function getValidationResult(value, minValue, maxValue, isDateUnavailable, timeZ
9
9
  const isInvalid = rangeOverflow || rangeUnderflow || isUnavailable;
10
10
  const errors = [];
11
11
  if (isInvalid) {
12
- if (rangeUnderflow) {
12
+ if (rangeUnderflow && minValue) {
13
13
  errors.push((0, i18n_1.i18n)('Value must be {minValue} or later.', {
14
14
  minValue: minValue.timeZone(timeZone).format(),
15
15
  value: valueTitle,
16
16
  }));
17
17
  }
18
- if (rangeOverflow) {
18
+ if (rangeOverflow && maxValue) {
19
19
  errors.push((0, i18n_1.i18n)('Value must be {maxValue} or earlier.', {
20
20
  maxValue: maxValue.timeZone(timeZone).format(),
21
21
  value: valueTitle,
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx } from "react/jsx-runtime";
2
3
  import React from 'react';
3
4
  import { CalendarView } from '../CalendarView/CalendarView';
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import React from 'react';
3
4
  import { ChevronLeft, ChevronRight } from '@gravity-ui/icons';
@@ -1,8 +1,10 @@
1
+ 'use client';
1
2
  import { __rest } from "tslib";
2
3
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
4
  import React from 'react';
4
5
  import { TextInput, useFocusWithin } from '@gravity-ui/uikit';
5
6
  import { block } from '../../utils/cn';
7
+ import { HiddenInput } from '../HiddenInput/HiddenInput';
6
8
  import { useDateFieldProps } from './hooks/useDateFieldProps';
7
9
  import { useDateFieldState } from './hooks/useDateFieldState';
8
10
  import './DateField.css';
@@ -17,7 +19,7 @@ export function DateField(_a) {
17
19
  setActive(isFocusWithin);
18
20
  },
19
21
  });
20
- return (_jsxs("div", Object.assign({ className: b(null, className), style: props.style }, focusWithinProps, { children: [_jsx(TextInput, Object.assign({}, inputProps, { value: state.isEmpty && !isActive && props.placeholder ? '' : inputProps.value })), _jsx("input", { type: "text", hidden: true, name: props.name, value: state.value ? state.value.toISOString() : '',
21
- // Ignore React warning
22
- onChange: () => { } })] })));
22
+ return (_jsxs("div", Object.assign({ className: b(null, className), style: props.style }, focusWithinProps, { children: [_jsx(TextInput, Object.assign({}, inputProps, { value: state.isEmpty && !isActive && props.placeholder ? '' : inputProps.value })), _jsx(HiddenInput, { name: props.name, value: state.value, toStringValue: (value) => { var _a; return (_a = value === null || value === void 0 ? void 0 : value.toISOString()) !== null && _a !== void 0 ? _a : ''; }, onReset: (value) => {
23
+ state.setDate(value);
24
+ }, disabled: state.disabled, form: props.form })] })));
23
25
  }
@@ -37,6 +37,8 @@ export type DateFieldState<T = DateTime> = {
37
37
  displayValue: T;
38
38
  /** Sets the field's value. */
39
39
  setValue: (value: T) => void;
40
+ /** Sets the date value. */
41
+ setDate: (value: T | null) => void;
40
42
  /** Formatted value */
41
43
  text: string;
42
44
  /** Whether the field is read only. */
@@ -30,6 +30,7 @@ export function useBaseDateFieldState(props) {
30
30
  isEmpty,
31
31
  displayValue,
32
32
  setValue,
33
+ setDate,
33
34
  text: formatSections(editableSections),
34
35
  readOnly: props.readOnly,
35
36
  disabled: props.disabled,
@@ -135,7 +135,7 @@ export function useDateFieldState(props) {
135
135
  }).timeZone(timeZone);
136
136
  }
137
137
  function setValueFromString(str) {
138
- const date = parseDateFromString(str, props.format || 'L', timeZone);
138
+ const date = parseDateFromString(str, format, timeZone);
139
139
  if (isValid(date)) {
140
140
  handleUpdateDate(date);
141
141
  return true;
@@ -1,7 +1,6 @@
1
1
  import type { DateTime } from '@gravity-ui/date-utils';
2
2
  import type { DateFieldSection, DateFieldSectionType, DateFieldSectionWithoutPosition } from './types';
3
3
  export declare const EDITABLE_SEGMENTS: Partial<Record<DateFieldSectionType, boolean>>;
4
- export declare function expandFormat(format: string): string;
5
4
  export declare function getSectionLimits(section: DateFieldSectionWithoutPosition, date: DateTime): {
6
5
  minValue: number;
7
6
  maxValue: number;
@@ -9,7 +8,7 @@ export declare function getSectionLimits(section: DateFieldSectionWithoutPositio
9
8
  minValue?: undefined;
10
9
  maxValue?: undefined;
11
10
  };
12
- export declare function getSectionValue(sections: DateFieldSectionWithoutPosition, date: DateTime): number | undefined;
11
+ export declare function getSectionValue(section: DateFieldSectionWithoutPosition, date: DateTime): number | undefined;
13
12
  export declare function getDurationUnitFromSectionType(type: DateFieldSectionType): "year" | "month" | "day" | "hour" | "minute" | "second" | "date";
14
13
  export declare function addSegment(section: DateFieldSection, date: DateTime, amount: number): DateTime;
15
14
  export declare function setSegment(section: DateFieldSection, date: DateTime, amount: number): DateTime;
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { dateTime, isValid, settings } from '@gravity-ui/date-utils';
2
+ import { dateTime, expandFormat, isValid } from '@gravity-ui/date-utils';
3
3
  import { mergeDateTime } from '../utils/dates';
4
4
  import { i18n } from './i18n';
5
5
  export const EDITABLE_SEGMENTS = {
@@ -12,16 +12,6 @@ export const EDITABLE_SEGMENTS = {
12
12
  dayPeriod: true,
13
13
  weekday: true,
14
14
  };
15
- export function expandFormat(format) {
16
- const localeFormats = settings.getLocaleData().formats;
17
- const getShortLocalizedFormatFromLongLocalizedFormat = (formatBis) => formatBis.replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g, (_, escapeSequence, localizedFormat) => escapeSequence || localizedFormat.slice(1));
18
- return format.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g, (_, escapeSequence, localizedFormat) => {
19
- const LongLocalizedFormat = localizedFormat && localizedFormat.toUpperCase();
20
- return (escapeSequence ||
21
- localeFormats[localizedFormat] ||
22
- getShortLocalizedFormatFromLongLocalizedFormat(localeFormats[LongLocalizedFormat]));
23
- });
24
- }
25
15
  const escapedCharacters = { start: '[', end: ']' };
26
16
  const formatTokenMap = {
27
17
  // Year
@@ -142,13 +132,13 @@ export function getSectionLimits(section, date) {
142
132
  }
143
133
  return {};
144
134
  }
145
- export function getSectionValue(sections, date) {
146
- const type = sections.type;
135
+ export function getSectionValue(section, date) {
136
+ const type = section.type;
147
137
  switch (type) {
148
138
  case 'year': {
149
- return isFourDigitYearFormat(sections.format)
139
+ return isFourDigitYearFormat(section.format)
150
140
  ? date.year()
151
- : Number(date.format(sections.format));
141
+ : Number(date.format(section.format));
152
142
  }
153
143
  case 'month':
154
144
  case 'hour':
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { __rest } from "tslib";
2
3
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
4
  import React from 'react';
@@ -5,6 +6,7 @@ import { Calendar as CalendarIcon, Clock as ClockIcon } from '@gravity-ui/icons'
5
6
  import { Button, Icon, Popup, TextInput, useMobile } from '@gravity-ui/uikit';
6
7
  import { Calendar } from '../Calendar';
7
8
  import { DateField } from '../DateField';
9
+ import { HiddenInput } from '../HiddenInput/HiddenInput';
8
10
  import { MobileCalendar } from './MobileCalendar';
9
11
  import { StubButton } from './StubButton';
10
12
  import { useDatePickerProps } from './hooks/useDatePickerProps';
@@ -18,7 +20,7 @@ export function DatePicker(_a) {
18
20
  const { groupProps, fieldProps, calendarButtonProps, popupProps, calendarProps, timeInputProps } = useDatePickerProps(state, props);
19
21
  const isMobile = useMobile();
20
22
  const isOnlyTime = state.hasTime && !state.hasDate;
21
- return (_jsxs("div", Object.assign({ className: b(null, className) }, groupProps, { children: [isMobile ? (_jsx(MobileCalendar, { props: props, state: state })) : (!isOnlyTime && (_jsx("div", { ref: anchorRef, className: b('popup-anchor'), children: _jsx(Popup, Object.assign({ anchorRef: anchorRef }, popupProps, { children: _jsxs("div", { className: b('popup-content'), children: [typeof props.children === 'function' ? (props.children(calendarProps)) : (_jsx(Calendar, Object.assign({}, calendarProps))), state.hasTime && (_jsx("div", { className: b('time-field-wrapper'), children: _jsx(DateField, Object.assign({}, timeInputProps)) }))] }) })) }))), _jsx(TextInput, Object.assign({}, fieldProps, { className: b('field', { mobile: isMobile }), hasClear: !isMobile && fieldProps.hasClear, endContent: _jsxs(React.Fragment, { children: [!isMobile && !isOnlyTime && (_jsx(Button, Object.assign({}, calendarButtonProps, { children: _jsx(Icon, { data: CalendarIcon }) }))), !isMobile && isOnlyTime && (_jsx(StubButton, { size: calendarButtonProps.size, icon: ClockIcon })), isMobile && (_jsx(StubButton, { size: calendarButtonProps.size, icon: isOnlyTime ? ClockIcon : CalendarIcon }))] }) })), _jsx("input", { type: "text", hidden: true, name: props.name, value: state.value ? state.value.toISOString() : '',
22
- // Ignore React warning
23
- onChange: () => { } })] })));
23
+ return (_jsxs("div", Object.assign({ className: b(null, className) }, groupProps, { children: [isMobile ? (_jsx(MobileCalendar, { props: props, state: state })) : (!isOnlyTime && (_jsx("div", { ref: anchorRef, className: b('popup-anchor'), children: _jsx(Popup, Object.assign({ anchorRef: anchorRef }, popupProps, { children: _jsxs("div", { className: b('popup-content'), children: [typeof props.children === 'function' ? (props.children(calendarProps)) : (_jsx(Calendar, Object.assign({}, calendarProps))), state.hasTime && (_jsx("div", { className: b('time-field-wrapper'), children: _jsx(DateField, Object.assign({}, timeInputProps)) }))] }) })) }))), _jsx(TextInput, Object.assign({}, fieldProps, { className: b('field', { mobile: isMobile }), hasClear: !isMobile && fieldProps.hasClear, endContent: _jsxs(React.Fragment, { children: [!isMobile && !isOnlyTime && (_jsx(Button, Object.assign({}, calendarButtonProps, { children: _jsx(Icon, { data: CalendarIcon }) }))), !isMobile && isOnlyTime && (_jsx(StubButton, { size: calendarButtonProps.size, icon: ClockIcon })), isMobile && (_jsx(StubButton, { size: calendarButtonProps.size, icon: isOnlyTime ? ClockIcon : CalendarIcon }))] }) })), _jsx(HiddenInput, { name: props.name, value: state.value, toStringValue: (value) => { var _a; return (_a = value === null || value === void 0 ? void 0 : value.toISOString()) !== null && _a !== void 0 ? _a : ''; }, onReset: (value) => {
24
+ state.setValue(value);
25
+ }, disabled: state.disabled, form: props.form })] })));
24
26
  }
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx } from "react/jsx-runtime";
2
3
  import { dateTime } from '@gravity-ui/date-utils';
3
4
  import { block } from '../../utils/cn';
@@ -0,0 +1,14 @@
1
+ interface HiddenInputProps<T> {
2
+ value: T;
3
+ onReset?: (value: T) => void;
4
+ toStringValue?: (value: T) => string;
5
+ name?: string;
6
+ disabled?: boolean;
7
+ form?: string;
8
+ }
9
+ export declare function HiddenInput<T>({ name, value, onReset, form, disabled, toStringValue, }: HiddenInputProps<T>): import("react/jsx-runtime").JSX.Element | null;
10
+ export declare function useFormResetHandler<T>({ initialValue, onReset, }: {
11
+ initialValue: T;
12
+ onReset?: (value: T) => void;
13
+ }): (node: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | null) => void;
14
+ export {};
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ export function HiddenInput({ name, value, onReset, form, disabled, toStringValue, }) {
4
+ const ref = useFormResetHandler({ initialValue: value, onReset });
5
+ if (!name) {
6
+ return null;
7
+ }
8
+ const v = toStringValue ? toStringValue(value) : `${value !== null && value !== void 0 ? value : ''}`;
9
+ return _jsx("input", { ref: ref, type: "hidden", name: name, value: v, disabled: disabled, form: form });
10
+ }
11
+ export function useFormResetHandler({ initialValue, onReset, }) {
12
+ const [formElement, setFormElement] = React.useState(null);
13
+ const resetValue = React.useRef(initialValue);
14
+ React.useEffect(() => {
15
+ if (!formElement || !onReset) {
16
+ return undefined;
17
+ }
18
+ const handleReset = () => {
19
+ onReset(resetValue.current);
20
+ };
21
+ formElement.addEventListener('reset', handleReset);
22
+ return () => {
23
+ formElement.removeEventListener('reset', handleReset);
24
+ };
25
+ }, [formElement, onReset]);
26
+ const ref = React.useCallback((node) => {
27
+ var _a;
28
+ setFormElement((_a = node === null || node === void 0 ? void 0 : node.form) !== null && _a !== void 0 ? _a : null);
29
+ }, []);
30
+ return ref;
31
+ }
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx } from "react/jsx-runtime";
2
3
  import React from 'react';
3
4
  import { CalendarView } from '../CalendarView/CalendarView';
@@ -1,13 +1,16 @@
1
+ 'use client';
1
2
  import { __rest } from "tslib";
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
4
  import React from 'react';
4
5
  import { TextInput, useFocusWithin } from '@gravity-ui/uikit';
5
6
  import { block } from '../../utils/cn';
6
7
  import { useDateFieldProps } from '../DateField/hooks/useDateFieldProps';
8
+ import { HiddenInput } from '../HiddenInput/HiddenInput';
7
9
  import { useRangeDateFieldState } from './hooks/useRangeDateFieldState';
8
10
  import './RangeDateField.css';
9
11
  const b = block('range-date-field');
10
12
  export function RangeDateField(_a) {
13
+ var _b, _c;
11
14
  var { className } = _a, props = __rest(_a, ["className"]);
12
15
  const state = useRangeDateFieldState(props);
13
16
  const { inputProps } = useDateFieldProps(state, props);
@@ -17,5 +20,7 @@ export function RangeDateField(_a) {
17
20
  setActive(isFocusWithin);
18
21
  },
19
22
  });
20
- return (_jsx("div", Object.assign({ className: b(null, className), style: props.style }, focusWithinProps, { children: _jsx(TextInput, Object.assign({}, inputProps, { value: state.isEmpty && !isActive && props.placeholder ? '' : inputProps.value })) })));
23
+ return (_jsxs("div", Object.assign({ className: b(null, className), style: props.style }, focusWithinProps, { children: [_jsx(TextInput, Object.assign({}, inputProps, { value: state.isEmpty && !isActive && props.placeholder ? '' : inputProps.value })), _jsx(HiddenInput, { name: props.name, form: props.form, onReset: (v) => {
24
+ state.setDate(v);
25
+ }, value: (_b = state.value) !== null && _b !== void 0 ? _b : null, toStringValue: (v) => (v ? v.start.toISOString() : ''), disabled: state.disabled }), _jsx(HiddenInput, { name: props.name, form: props.form, value: (_c = state.value) !== null && _c !== void 0 ? _c : null, toStringValue: (v) => (v ? v.end.toISOString() : ''), disabled: state.disabled })] })));
21
26
  }
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { __rest } from "tslib";
2
3
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
4
  import React from 'react';
@@ -7,6 +8,7 @@ import { block } from '../../utils/cn';
7
8
  import { RangeCalendar } from '../Calendar';
8
9
  import { useDatePickerProps } from '../DatePicker';
9
10
  import { StubButton } from '../DatePicker/StubButton';
11
+ import { HiddenInput } from '../HiddenInput/HiddenInput';
10
12
  import { RangeDateField } from '../RangeDateField';
11
13
  import { useRangeDatePickerState } from './hooks/useRangeDatePickerState';
12
14
  import './RangeDatePicker.css';
@@ -17,5 +19,7 @@ export function RangeDatePicker(_a) {
17
19
  const state = useRangeDatePickerState(props);
18
20
  const { groupProps, fieldProps, calendarButtonProps, popupProps, calendarProps, timeInputProps } = useDatePickerProps(state, props);
19
21
  const isOnlyTime = state.hasTime && !state.hasDate;
20
- return (_jsxs("div", Object.assign({ className: b(null, className) }, groupProps, { children: [!isOnlyTime && (_jsx("div", { ref: anchorRef, className: b('popup-anchor'), children: _jsx(Popup, Object.assign({ anchorRef: anchorRef }, popupProps, { children: _jsxs("div", { className: b('popup-content'), children: [typeof props.children === 'function' ? (props.children(Object.assign(Object.assign({}, calendarProps), { value: state.value }))) : (_jsx(RangeCalendar, Object.assign({}, calendarProps, { value: state.value }))), state.hasTime && (_jsx("div", { className: b('time-field-wrapper'), children: _jsx(RangeDateField, Object.assign({}, timeInputProps)) }))] }) })) })), _jsx(TextInput, Object.assign({}, fieldProps, { className: b('field'), hasClear: fieldProps.hasClear, endContent: _jsxs(React.Fragment, { children: [!isOnlyTime && (_jsx(Button, Object.assign({}, calendarButtonProps, { children: _jsx(Icon, { data: CalendarIcon }) }))), isOnlyTime && (_jsx(StubButton, { size: calendarButtonProps.size, icon: ClockIcon }))] }) }))] })));
22
+ return (_jsxs("div", Object.assign({ className: b(null, className) }, groupProps, { children: [!isOnlyTime && (_jsx("div", { ref: anchorRef, className: b('popup-anchor'), children: _jsx(Popup, Object.assign({ anchorRef: anchorRef }, popupProps, { children: _jsxs("div", { className: b('popup-content'), children: [typeof props.children === 'function' ? (props.children(Object.assign(Object.assign({}, calendarProps), { value: state.value }))) : (_jsx(RangeCalendar, Object.assign({}, calendarProps, { value: state.value }))), state.hasTime && (_jsx("div", { className: b('time-field-wrapper'), children: _jsx(RangeDateField, Object.assign({}, timeInputProps)) }))] }) })) })), _jsx(TextInput, Object.assign({}, fieldProps, { className: b('field'), hasClear: fieldProps.hasClear, endContent: _jsxs(React.Fragment, { children: [!isOnlyTime && (_jsx(Button, Object.assign({}, calendarButtonProps, { children: _jsx(Icon, { data: CalendarIcon }) }))), isOnlyTime && (_jsx(StubButton, { size: calendarButtonProps.size, icon: ClockIcon }))] }) })), _jsx(HiddenInput, { name: props.name, form: props.form, onReset: (v) => {
23
+ state.dateFieldState.setDate(v);
24
+ }, value: state.value, toStringValue: (v) => (v ? v.start.toISOString() : ''), disabled: state.disabled }), _jsx(HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => (v ? v.end.toISOString() : ''), disabled: state.disabled })] })));
21
25
  }
@@ -1,15 +1,16 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import React from 'react';
3
4
  import { Popup, TextInput, useFocusWithin, useMobile } from '@gravity-ui/uikit';
4
5
  import { block } from '../../utils/cn';
5
6
  import { Calendar } from '../Calendar';
6
7
  import { DateField } from '../DateField';
8
+ import { HiddenInput } from '../HiddenInput/HiddenInput';
7
9
  import { useRelativeDateFieldProps } from './hooks/useRelativeDateFieldProps';
8
10
  import { useRelativeDateFieldState } from './hooks/useRelativeDateFieldState';
9
11
  import './RelativeDateField.css';
10
12
  const b = block('relative-date-field');
11
13
  export function RelativeDateField(props) {
12
- var _a;
13
14
  const state = useRelativeDateFieldState(props);
14
15
  const { inputProps, calendarProps, timeInputProps } = useRelativeDateFieldProps(state, props);
15
16
  const isMobile = useMobile();
@@ -27,7 +28,7 @@ export function RelativeDateField(props) {
27
28
  setOpen(true);
28
29
  }
29
30
  (_a = props.onFocus) === null || _a === void 0 ? void 0 : _a.call(props, e);
30
- }, onBlur: props.onBlur })), _jsx("input", { type: "text", hidden: true, name: props.name, value: (_a = state.value) !== null && _a !== void 0 ? _a : '',
31
- // Ignore React warning
32
- onChange: () => { } }), !isMobile && (_jsx(Popup, { anchorRef: anchorRef, open: isOpen, children: _jsxs("div", { className: b('popup-content'), children: [_jsx(Calendar, Object.assign({}, calendarProps)), props.hasTime ? (_jsx("div", { className: b('time-field-wrapper'), children: _jsx(DateField, Object.assign({ className: b('time-field') }, timeInputProps)) })) : null] }) }))] })));
31
+ }, onBlur: props.onBlur })), _jsx(HiddenInput, { name: props.name, value: state.value, onReset: (value) => {
32
+ state.setValue(value);
33
+ }, disabled: state.disabled, form: props.form }), !isMobile && (_jsx(Popup, { anchorRef: anchorRef, open: isOpen, children: _jsxs("div", { className: b('popup-content'), children: [_jsx(Calendar, Object.assign({}, calendarProps)), props.hasTime ? (_jsx("div", { className: b('time-field-wrapper'), children: _jsx(DateField, Object.assign({ className: b('time-field') }, timeInputProps)) })) : null] }) }))] })));
33
34
  }
@@ -1,7 +1,5 @@
1
1
  import React from 'react';
2
- import { dateTimeParse,
3
- // @ts-expect-error added in new version of date-utils
4
- isLikeRelative, isValid, } from '@gravity-ui/date-utils';
2
+ import { dateTimeParse, isLikeRelative, isValid } from '@gravity-ui/date-utils';
5
3
  import { useControlledState } from '@gravity-ui/uikit';
6
4
  export function useRelativeDateFieldState(props) {
7
5
  var _a;
@@ -15,7 +13,7 @@ export function useRelativeDateFieldState(props) {
15
13
  return;
16
14
  }
17
15
  setText(t);
18
- if (isLikeRelativeDate(t)) {
16
+ if (isLikeRelative(t)) {
19
17
  const date = dateTimeParse(t);
20
18
  if (date && isValid(date)) {
21
19
  setValue(t);
@@ -34,7 +32,7 @@ export function useRelativeDateFieldState(props) {
34
32
  return null;
35
33
  }
36
34
  return (_a = dateTimeParse(value, { timeZone: props.timeZone, roundUp: props.roundUp })) !== null && _a !== void 0 ? _a : null;
37
- }, [value, props.timeZone]);
35
+ }, [value, props.timeZone, props.roundUp]);
38
36
  const [lastCorrectDate, setLastCorrectDate] = React.useState(parsedDate);
39
37
  if (parsedDate && parsedDate !== lastCorrectDate) {
40
38
  setLastCorrectDate(parsedDate);
@@ -57,9 +55,3 @@ export function useRelativeDateFieldState(props) {
57
55
  readOnly: props.readOnly,
58
56
  };
59
57
  }
60
- function isLikeRelativeDate(text) {
61
- if (typeof isLikeRelative === 'function') {
62
- return isLikeRelative(text);
63
- }
64
- return /^now/i.test(text);
65
- }
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import React from 'react';
3
4
  import { Calendar as CalendarIcon, Clock as ClockIcon, Function as FunctionIcon, } from '@gravity-ui/icons';
@@ -7,11 +8,13 @@ import { Calendar } from '../Calendar';
7
8
  import { DateField } from '../DateField';
8
9
  import { MobileCalendar } from '../DatePicker/MobileCalendar';
9
10
  import { StubButton } from '../DatePicker/StubButton';
11
+ import { HiddenInput } from '../HiddenInput/HiddenInput';
10
12
  import { useRelativeDatePickerProps } from './hooks/useRelativeDatePickerProps';
11
13
  import { useRelativeDatePickerState } from './hooks/useRelativeDatePickerState';
12
14
  import './RelativeDatePicker.css';
13
15
  const b = block('relative-date-picker');
14
16
  export function RelativeDatePicker(props) {
17
+ var _a;
15
18
  const state = useRelativeDatePickerState(props);
16
19
  const { groupProps, fieldProps, modeSwitcherProps, calendarButtonProps, popupProps, calendarProps, timeInputProps, } = useRelativeDatePickerProps(state, props);
17
20
  const anchorRef = React.useRef(null);
@@ -23,9 +26,9 @@ export function RelativeDatePicker(props) {
23
26
  readOnly: props.readOnly,
24
27
  placeholderValue: props.placeholderValue,
25
28
  timeZone: props.timeZone,
26
- } })), _jsx(TextInput, Object.assign({}, fieldProps, { controlProps: Object.assign(Object.assign({}, fieldProps.controlProps), { disabled: isMobile && state.mode === 'absolute', className: b('input', { mobile: isMobile && state.mode === 'absolute' }) }), hasClear: props.hasClear && !(isMobile && state.mode === 'absolute'), startContent: _jsx(Button, Object.assign({}, modeSwitcherProps, { children: _jsx(Icon, { data: FunctionIcon }) })), endContent: _jsxs(React.Fragment, { children: [!isMobile && !isOnlyTime && (_jsx(Button, Object.assign({}, calendarButtonProps, { children: _jsx(Icon, { data: CalendarIcon }) }))), !isMobile && isOnlyTime && (_jsx(StubButton, { size: calendarButtonProps.size, icon: ClockIcon })), isMobile && state.mode === 'absolute' && (_jsx(StubButton, { size: calendarButtonProps.size, icon: isOnlyTime ? ClockIcon : CalendarIcon }))] }) })), _jsx("input", { type: "text", hidden: true, name: props.name, value: getNativeValue(state.value),
27
- // Ignore React warning
28
- onChange: () => { } }), !isMobile && !isOnlyTime && (_jsx(Popup, Object.assign({}, popupProps, { anchorRef: anchorRef, children: _jsxs("div", { className: b('popup-content'), children: [typeof props.children === 'function' ? (props.children(calendarProps)) : (_jsx(Calendar, Object.assign({}, calendarProps))), state.datePickerState.hasTime && (_jsx("div", { className: b('time-field-wrapper'), children: _jsx(DateField, Object.assign({}, timeInputProps)) }))] }) })))] })));
29
+ } })), _jsx(TextInput, Object.assign({}, fieldProps, { controlProps: Object.assign(Object.assign({}, fieldProps.controlProps), { disabled: isMobile && state.mode === 'absolute', className: b('input', { mobile: isMobile && state.mode === 'absolute' }) }), hasClear: props.hasClear && !(isMobile && state.mode === 'absolute'), startContent: _jsx(Button, Object.assign({}, modeSwitcherProps, { children: _jsx(Icon, { data: FunctionIcon }) })), endContent: _jsxs(React.Fragment, { children: [!isMobile && !isOnlyTime && (_jsx(Button, Object.assign({}, calendarButtonProps, { children: _jsx(Icon, { data: CalendarIcon }) }))), !isMobile && isOnlyTime && (_jsx(StubButton, { size: calendarButtonProps.size, icon: ClockIcon })), isMobile && state.mode === 'absolute' && (_jsx(StubButton, { size: calendarButtonProps.size, icon: isOnlyTime ? ClockIcon : CalendarIcon }))] }) })), _jsx(HiddenInput, { name: props.name, value: (_a = state.value) === null || _a === void 0 ? void 0 : _a.type, disabled: state.disabled, form: props.form }), _jsx(HiddenInput, { name: props.name, value: state.value, toStringValue: (value) => getNativeValue(value), onReset: (value) => {
30
+ state.setValue(value);
31
+ }, disabled: state.disabled, form: props.form }), !isMobile && !isOnlyTime && (_jsx(Popup, Object.assign({}, popupProps, { anchorRef: anchorRef, children: _jsxs("div", { className: b('popup-content'), children: [typeof props.children === 'function' ? (props.children(calendarProps)) : (_jsx(Calendar, Object.assign({}, calendarProps))), state.datePickerState.hasTime && (_jsx("div", { className: b('time-field-wrapper'), children: _jsx(DateField, Object.assign({}, timeInputProps)) }))] }) })))] })));
29
32
  }
30
33
  function getNativeValue(value) {
31
34
  if (!value) {
@@ -1,11 +1,11 @@
1
1
  import type { DateTime } from '@gravity-ui/date-utils';
2
2
  import type { Value } from '../RelativeDatePicker';
3
- import type { DomProps, FocusableProps, InputBase, RangeValue, StyleProps, TextInputProps, Validation } from '../types';
3
+ import type { DomProps, FocusableProps, InputBase, InputDOMProps, RangeValue, StyleProps, TextInputProps, Validation } from '../types';
4
4
  import type { Preset } from './components/Presets/defaultPresets';
5
5
  import type { PresetTab } from './components/Presets/utils';
6
6
  import type { RelativeRangeDatePickerStateOptions } from './hooks/useRelativeRangeDatePickerState';
7
7
  import './RelativeRangeDatePicker.css';
8
- export interface RelativeRangeDatePickerProps extends RelativeRangeDatePickerStateOptions, DomProps, InputBase, TextInputProps, Validation, FocusableProps, StyleProps {
8
+ export interface RelativeRangeDatePickerProps extends RelativeRangeDatePickerStateOptions, DomProps, InputBase, InputDOMProps, TextInputProps, Validation, FocusableProps, StyleProps {
9
9
  /** Format of the date when rendered in the input. [Available formats](https://day.js.org/docs/en/display/format) */
10
10
  format?: string;
11
11
  /** A placeholder date that controls the default values of each segment when the user first interacts with them. Defaults to today's date at midnight. */
@@ -1,8 +1,10 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import React from 'react';
3
4
  import { Calendar as CalendarIcon } from '@gravity-ui/icons';
4
5
  import { Button, Icon, TextInput, useFocusWithin, useMobile } from '@gravity-ui/uikit';
5
6
  import { block } from '../../utils/cn';
7
+ import { HiddenInput } from '../HiddenInput/HiddenInput';
6
8
  import { getButtonSizeForInput } from '../utils/getButtonSizeForInput';
7
9
  import { PickerDialog } from './components/PickerDialog/PickerDialog';
8
10
  import { useRelativeRangeDatePickerState } from './hooks/useRelativeRangeDatePickerState';
@@ -84,7 +86,18 @@ export function RelativeRangeDatePicker(props) {
84
86
  }), onClick: () => {
85
87
  setIsActive(true);
86
88
  setOpen(true);
87
- } })) : null, _jsx(PickerDialog, { state: state, props: props, open: open, onClose: () => {
89
+ } })) : null, _jsx(HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => { var _a, _b; return (_b = (_a = v === null || v === void 0 ? void 0 : v.start) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : ''; }, disabled: props.disabled }), _jsx(HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => { var _a; return getNativeValue((_a = v === null || v === void 0 ? void 0 : v.start) !== null && _a !== void 0 ? _a : null); }, disabled: props.disabled }), _jsx(HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => { var _a, _b; return (_b = (_a = v === null || v === void 0 ? void 0 : v.end) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : ''; }, disabled: props.disabled }), _jsx(HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => { var _a; return getNativeValue((_a = v === null || v === void 0 ? void 0 : v.end) !== null && _a !== void 0 ? _a : null); }, disabled: props.disabled }), _jsx(HiddenInput, { name: props.name, form: props.form, onReset: (v) => {
90
+ state.setValue(v.value, v.timeZone);
91
+ }, value: { value: state.value, timeZone: state.timeZone }, toStringValue: (v) => v.timeZone, disabled: props.disabled }), _jsx(PickerDialog, { state: state, props: props, open: open, onClose: () => {
88
92
  setOpen(false);
89
93
  }, anchorRef: anchorRef, isMobile: isMobile, className: props.className })] })));
90
94
  }
95
+ function getNativeValue(value) {
96
+ if (!value) {
97
+ return '';
98
+ }
99
+ if (value.type === 'relative') {
100
+ return value.value;
101
+ }
102
+ return value.value.toISOString();
103
+ }
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { dateTime } from '@gravity-ui/date-utils';
3
4
  import { Button, Popup, Sheet } from '@gravity-ui/uikit';
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import React from 'react';
3
4
  import { List, Tabs } from '@gravity-ui/uikit';
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import React from 'react';
3
4
  import { CircleQuestion } from '@gravity-ui/icons';
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { getTimeZonesList } from '@gravity-ui/date-utils';
3
4
  import { ChevronRight } from '@gravity-ui/icons';
@@ -29,6 +29,11 @@ export interface InputDOMProps {
29
29
  * The name of the input element, used when submitting an HTML form.
30
30
  */
31
31
  name?: string;
32
+ /**
33
+ * The id of a <form> in the same document. If this attribute is not set,
34
+ * the <input> is associated with its ancestor <form> element, if any.
35
+ */
36
+ form?: string;
32
37
  }
33
38
  export interface InputBase {
34
39
  /**
@@ -34,9 +34,9 @@ export function mergeProps(...args) {
34
34
  }
35
35
  function chain(...fns) {
36
36
  return (...args) => {
37
- for (const callback of fns) {
38
- if (typeof callback === 'function') {
39
- callback(...args);
37
+ for (const fn of fns) {
38
+ if (typeof fn === 'function') {
39
+ fn(...args);
40
40
  }
41
41
  }
42
42
  };
@@ -6,13 +6,13 @@ export function getValidationResult(value, minValue, maxValue, isDateUnavailable
6
6
  const isInvalid = rangeOverflow || rangeUnderflow || isUnavailable;
7
7
  const errors = [];
8
8
  if (isInvalid) {
9
- if (rangeUnderflow) {
9
+ if (rangeUnderflow && minValue) {
10
10
  errors.push(i18n('Value must be {minValue} or later.', {
11
11
  minValue: minValue.timeZone(timeZone).format(),
12
12
  value: valueTitle,
13
13
  }));
14
14
  }
15
- if (rangeOverflow) {
15
+ if (rangeOverflow && maxValue) {
16
16
  errors.push(i18n('Value must be {maxValue} or earlier.', {
17
17
  maxValue: maxValue.timeZone(timeZone).format(),
18
18
  value: valueTitle,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/date-components",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "main": "dist/cjs/index.js",
@@ -46,7 +46,7 @@
46
46
  },
47
47
  "dependencies": {
48
48
  "@bem-react/classname": "^1.6.0",
49
- "@gravity-ui/date-utils": "^2.0.1",
49
+ "@gravity-ui/date-utils": "^2.5.3",
50
50
  "@gravity-ui/icons": "^2.2.0",
51
51
  "tslib": "^2.6.2"
52
52
  },
@@ -60,24 +60,27 @@
60
60
  "@gravity-ui/prettier-config": "^1.1.0",
61
61
  "@gravity-ui/stylelint-config": "^4.0.1",
62
62
  "@gravity-ui/tsconfig": "^1.0.0",
63
- "@gravity-ui/uikit": "^6.1.1",
64
- "@storybook/addon-a11y": "^8.0.10",
65
- "@storybook/addon-essentials": "^8.0.10",
66
- "@storybook/addon-viewport": "^8.0.10",
63
+ "@gravity-ui/uikit": "^6.15.0",
64
+ "@storybook/addon-a11y": "^8.1.3",
65
+ "@storybook/addon-essentials": "^8.1.3",
66
+ "@storybook/addon-viewport": "^8.1.3",
67
67
  "@storybook/addon-webpack5-compiler-babel": "^3.0.3",
68
- "@storybook/blocks": "^8.0.10",
69
- "@storybook/manager-api": "^8.0.10",
68
+ "@storybook/blocks": "^8.1.3",
69
+ "@storybook/manager-api": "^8.1.3",
70
70
  "@storybook/preset-scss": "^1.0.3",
71
- "@storybook/react": "^8.0.10",
72
- "@storybook/react-webpack5": "^8.0.10",
73
- "@storybook/theming": "^8.0.10",
74
- "@testing-library/jest-dom": "^6.4.5",
75
- "@testing-library/react": "^15.0.7",
71
+ "@storybook/react": "^8.1.3",
72
+ "@storybook/react-webpack5": "^8.1.3",
73
+ "@storybook/theming": "^8.1.3",
74
+ "@storybook/types": "^8.1.3",
75
+ "@testing-library/dom": "^10.1.0",
76
+ "@testing-library/jest-dom": "^6.4.6",
77
+ "@testing-library/react": "^16.0.0",
76
78
  "@testing-library/user-event": "^14.5.2",
77
79
  "@types/jest": "^29.5.12",
78
80
  "@types/react": "^18.3.2",
79
81
  "@types/react-dom": "^18.3.0",
80
82
  "eslint": "^8.57.0",
83
+ "eslint-plugin-react-compiler": "^0.0.0-experimental-c8b3f72-20240517",
81
84
  "eslint-plugin-testing-library": "^6.2.2",
82
85
  "gulp": "^5.0.0",
83
86
  "gulp-cli": "^3.0.0",
@@ -85,8 +88,8 @@
85
88
  "gulp-replace": "^1.1.4",
86
89
  "gulp-typescript": "^5.0.1",
87
90
  "husky": "^9.0.11",
88
- "jest": "^29.5.0",
89
- "jest-environment-jsdom": "^29.5.0",
91
+ "jest": "^29.7.0",
92
+ "jest-environment-jsdom": "^29.7.0",
90
93
  "jest-transform-css": "^6.0.1",
91
94
  "nano-staged": "^0.8.0",
92
95
  "npm-run-all": "^4.1.5",
@@ -95,17 +98,20 @@
95
98
  "react-dom": "^18.3.1",
96
99
  "rimraf": "^5.0.7",
97
100
  "sass": "^1.77.1",
98
- "storybook": "^8.0.10",
101
+ "storybook": "^8.1.3",
99
102
  "stylelint": "^15.11.0",
100
103
  "stylelint-use-logical": "^2.1.2",
101
- "ts-jest": "^29.1.2",
104
+ "ts-jest": "^29.1.5",
102
105
  "ts-node": "^10.9.2",
103
106
  "typescript": "^5.4.5"
104
107
  },
105
108
  "peerDependencies": {
106
109
  "@gravity-ui/uikit": "^6.0.0",
107
- "react": "^17.0.0 || ^18.0.0",
108
- "react-dom": "^17.0.0 || ^18.0.0"
110
+ "react": ">=17.0.0",
111
+ "react-dom": ">=17.0.0"
112
+ },
113
+ "overrides": {
114
+ "nwsapi": "2.2.2"
109
115
  },
110
116
  "nano-staged": {
111
117
  "*.{scss}": [