@alfalab/core-components-calendar-input 5.2.7 → 6.1.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.
@@ -45,6 +45,10 @@ type CalendarInputProps = Omit<DateInputProps, 'onChange' | 'mobileMode'> & {
45
45
  * Максимальная дата, доступная для выбора (timestamp)
46
46
  */
47
47
  maxDate?: number;
48
+ /**
49
+ * Список событий
50
+ */
51
+ events?: Array<Date | number>;
48
52
  /**
49
53
  * Список выходных
50
54
  */
@@ -97,7 +101,7 @@ type CalendarInputProps = Omit<DateInputProps, 'onChange' | 'mobileMode'> & {
97
101
  */
98
102
  useAnchorWidth?: boolean;
99
103
  };
100
- declare const CalendarInput: React.ForwardRefExoticComponent<Pick<DateInputProps, "children" | "value" | "form" | "label" | "slot" | "style" | "title" | "pattern" | "dir" | "className" | "dataTestId" | "height" | "name" | "width" | "hidden" | "color" | "size" | "block" | "clear" | "multiple" | "disabled" | "leftAddons" | "rightAddons" | "colors" | "type" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "contentEditable" | "contextMenu" | "draggable" | "id" | "lang" | "placeholder" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "list" | "step" | "autoFocus" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "fieldClassName" | "labelClassName" | "addonsClassName" | "error" | "hint" | "bottomAddons" | "accept" | "alt" | "autoComplete" | "capture" | "checked" | "crossOrigin" | "max" | "maxLength" | "min" | "minLength" | "readOnly" | "required" | "src" | "success" | "inputClassName" | "focusedClassName" | "filledClassName" | "onClear" | "wrapperRef" | "keepCharPositions" | "minYear" | "maxYear"> & {
104
+ declare const CalendarInput: React.ForwardRefExoticComponent<Pick<DateInputProps, "children" | "value" | "form" | "label" | "slot" | "style" | "title" | "pattern" | "dir" | "className" | "dataTestId" | "height" | "name" | "width" | "hidden" | "color" | "size" | "block" | "clear" | "multiple" | "disabled" | "leftAddons" | "rightAddons" | "colors" | "type" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "contentEditable" | "contextMenu" | "draggable" | "id" | "lang" | "placeholder" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "list" | "step" | "autoFocus" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "fieldClassName" | "labelClassName" | "addonsClassName" | "error" | "hint" | "bottomAddons" | "accept" | "alt" | "autoComplete" | "capture" | "checked" | "crossOrigin" | "max" | "maxLength" | "min" | "minLength" | "readOnly" | "required" | "src" | "success" | "inputClassName" | "focusedClassName" | "filledClassName" | "onClear" | "wrapperRef" | "onComplete"> & {
101
105
  /**
102
106
  * Дополнительный класс
103
107
  */
@@ -138,6 +142,10 @@ declare const CalendarInput: React.ForwardRefExoticComponent<Pick<DateInputProps
138
142
  * Максимальная дата, доступная для выбора (timestamp)
139
143
  */
140
144
  maxDate?: number | undefined;
145
+ /**
146
+ * Список событий
147
+ */
148
+ events?: (number | Date)[] | undefined;
141
149
  /**
142
150
  * Список выходных
143
151
  */
@@ -1,10 +1,14 @@
1
- import React, { forwardRef, useState, useRef, useCallback, useEffect } from 'react';
1
+ import React, { forwardRef, useState, useCallback, useRef, useEffect } from 'react';
2
2
  import cn from 'classnames';
3
3
  import mergeRefs from 'react-merge-refs';
4
4
  import { Popover } from '@alfalab/core-components-popover/dist/esm';
5
- import { parseDateString, isCompleteDateInput, formatDate, DateInput, SUPPORTS_INPUT_TYPE_DATE } from '@alfalab/core-components-date-input/dist/esm';
6
- import { dateInLimits, Calendar } from '@alfalab/core-components-calendar/dist/esm';
7
5
  import { CalendarMIcon } from '@alfalab/icons-glyph/CalendarMIcon';
6
+ import { parseDateString, isCompleteDateInput, formatDate, DateInput } from '@alfalab/core-components-date-input/dist/esm';
7
+ import { dateInLimits, Calendar } from '@alfalab/core-components-calendar/dist/esm';
8
+ import 'date-fns/parse';
9
+ import 'date-fns/format';
10
+ import 'date-fns/isSameDay';
11
+ import { SUPPORTS_INPUT_TYPE_DATE } from './utils.js';
8
12
 
9
13
  /*! *****************************************************************************
10
14
  Copyright (c) Microsoft Corporation.
@@ -45,24 +49,28 @@ function __rest(s, e) {
45
49
  return t;
46
50
  }
47
51
 
48
- var styles = {"component":"calendar-input__component_qd42g","block":"calendar-input__block_qd42g","calendarContainer":"calendar-input__calendarContainer_qd42g","calendarIcon":"calendar-input__calendarIcon_qd42g","nativeInput":"calendar-input__nativeInput_qd42g"};
52
+ var styles = {"component":"calendar-input__component_1u5qx","block":"calendar-input__block_1u5qx","calendarContainer":"calendar-input__calendarContainer_1u5qx","calendarIcon":"calendar-input__calendarIcon_1u5qx","nativeInput":"calendar-input__nativeInput_1u5qx"};
49
53
  require('./index.css')
50
54
 
51
55
  var CalendarInput = forwardRef(function (_a, ref) {
52
56
  var _b;
53
- var _c = _a.block, block = _c === void 0 ? false : _c, className = _a.className, inputClassName = _a.inputClassName, popoverClassName = _a.popoverClassName, _d = _a.defaultOpen, defaultOpen = _d === void 0 ? false : _d, defaultMonth = _a.defaultMonth, _e = _a.defaultValue, defaultValue = _e === void 0 ? '' : _e, _f = _a.calendarPosition, calendarPosition = _f === void 0 ? 'popover' : _f, value = _a.value, dataTestId = _a.dataTestId, _g = _a.calendarProps, calendarProps = _g === void 0 ? {} : _g, _h = _a.minDate, minDate = _h === void 0 ? calendarProps.minDate : _h, _j = _a.maxDate, maxDate = _j === void 0 ? calendarProps.maxDate : _j, _k = _a.offDays, offDays = _k === void 0 ? calendarProps.offDays || [] : _k, preventFlip = _a.preventFlip, _l = _a.mobileMode, mobileMode = _l === void 0 ? 'popover' : _l, _m = _a.wrapperRef, wrapperRef = _m === void 0 ? null : _m, disabled = _a.disabled, onChange = _a.onChange, onInputChange = _a.onInputChange, onCalendarChange = _a.onCalendarChange, onKeyDown = _a.onKeyDown, readOnly = _a.readOnly, _o = _a.Calendar, Calendar$1 = _o === void 0 ? Calendar : _o, _p = _a.popoverPosition, popoverPosition = _p === void 0 ? 'bottom-start' : _p, zIndexPopover = _a.zIndexPopover, useAnchorWidth = _a.useAnchorWidth, rightAddons = _a.rightAddons, restProps = __rest(_a, ["block", "className", "inputClassName", "popoverClassName", "defaultOpen", "defaultMonth", "defaultValue", "calendarPosition", "value", "dataTestId", "calendarProps", "minDate", "maxDate", "offDays", "preventFlip", "mobileMode", "wrapperRef", "disabled", "onChange", "onInputChange", "onCalendarChange", "onKeyDown", "readOnly", "Calendar", "popoverPosition", "zIndexPopover", "useAnchorWidth", "rightAddons"]);
54
- var uncontrolled = value === undefined;
57
+ var _c = _a.block, block = _c === void 0 ? false : _c, className = _a.className, inputClassName = _a.inputClassName, popoverClassName = _a.popoverClassName, _d = _a.defaultOpen, defaultOpen = _d === void 0 ? false : _d, defaultMonth = _a.defaultMonth, _e = _a.defaultValue, defaultValue = _e === void 0 ? '' : _e, _f = _a.calendarPosition, calendarPosition = _f === void 0 ? 'popover' : _f, value = _a.value, dataTestId = _a.dataTestId, _g = _a.calendarProps, calendarProps = _g === void 0 ? {} : _g, _h = _a.minDate, minDate = _h === void 0 ? calendarProps.minDate : _h, _j = _a.maxDate, maxDate = _j === void 0 ? calendarProps.maxDate : _j, _k = _a.offDays, offDays = _k === void 0 ? calendarProps.offDays || [] : _k, _l = _a.events, events = _l === void 0 ? calendarProps.events || [] : _l, preventFlip = _a.preventFlip, _m = _a.mobileMode, mobileMode = _m === void 0 ? 'popover' : _m, _o = _a.wrapperRef, wrapperRef = _o === void 0 ? null : _o, disabled = _a.disabled, _p = _a.onChange, onChange = _p === void 0 ? function () { return null; } : _p, onInputChange = _a.onInputChange, onCalendarChange = _a.onCalendarChange, onKeyDown = _a.onKeyDown, readOnly = _a.readOnly, _q = _a.Calendar, Calendar$1 = _q === void 0 ? Calendar : _q, _r = _a.popoverPosition, popoverPosition = _r === void 0 ? 'bottom-start' : _r, zIndexPopover = _a.zIndexPopover, useAnchorWidth = _a.useAnchorWidth, rightAddons = _a.rightAddons, error = _a.error, restProps = __rest(_a, ["block", "className", "inputClassName", "popoverClassName", "defaultOpen", "defaultMonth", "defaultValue", "calendarPosition", "value", "dataTestId", "calendarProps", "minDate", "maxDate", "offDays", "events", "preventFlip", "mobileMode", "wrapperRef", "disabled", "onChange", "onInputChange", "onCalendarChange", "onKeyDown", "readOnly", "Calendar", "popoverPosition", "zIndexPopover", "useAnchorWidth", "rightAddons", "error"]);
55
58
  var shouldRenderNative = SUPPORTS_INPUT_TYPE_DATE && mobileMode === 'native';
56
59
  var shouldRenderOnlyInput = mobileMode === 'input';
57
60
  var shouldRenderStatic = calendarPosition === 'static' && !shouldRenderOnlyInput;
58
61
  var shouldRenderPopover = calendarPosition === 'popover' && !shouldRenderNative && !shouldRenderOnlyInput;
59
- var _q = useState(false), open = _q[0], setOpen = _q[1];
60
- var _r = useState(defaultValue), stateValue = _r[0], setStateValue = _r[1];
61
- var inputValue = uncontrolled ? stateValue : value;
62
+ var _s = useState(false), open = _s[0], setOpen = _s[1];
63
+ var _t = useState(value || defaultValue), inputValue = _t[0], setInputValue = _t[1];
62
64
  var calendarValue = inputValue ? parseDateString(inputValue).getTime() : undefined;
63
- var isCalendarValueValid = calendarValue &&
64
- dateInLimits(calendarValue, minDate, maxDate) &&
65
- !offDays.includes(calendarValue);
65
+ var checkInputValueIsValid = useCallback(function (newInputValue) {
66
+ if (!newInputValue || error)
67
+ return false;
68
+ var dateValue = parseDateString(newInputValue).getTime();
69
+ return (dateValue &&
70
+ isCompleteDateInput(newInputValue) &&
71
+ dateInLimits(dateValue, minDate, maxDate) &&
72
+ !offDays.includes(dateValue));
73
+ }, [error, maxDate, minDate, offDays]);
66
74
  var inputDisabled = disabled || readOnly;
67
75
  var inputWrapperRef = useRef(null);
68
76
  var calendarRef = useRef(null);
@@ -107,18 +115,14 @@ var CalendarInput = forwardRef(function (_a, ref) {
107
115
  if (initiator === 'calendar' && onCalendarChange) {
108
116
  onCalendarChange(newDate.getTime());
109
117
  }
118
+ setInputValue(newValue);
110
119
  if (shouldChange) {
111
- if (uncontrolled) {
112
- setStateValue(newValue);
113
- }
114
- if (onChange) {
115
- onChange(event, { date: newDate, value: newValue });
116
- }
120
+ onChange(event, { date: newDate, value: newValue });
117
121
  }
118
- }, [onCalendarChange, onChange, onInputChange, uncontrolled]);
122
+ }, [onCalendarChange, onChange, onInputChange]);
119
123
  var handleInputChange = useCallback(function (event, payload) {
120
- changeHandler(event, payload.value, payload.date, 'input', !payload.value || isCompleteDateInput(payload.value));
121
- }, [changeHandler]);
124
+ changeHandler(event, payload.value, payload.date, 'input', !payload.value || checkInputValueIsValid(payload.value));
125
+ }, [changeHandler, checkInputValueIsValid]);
122
126
  var handleCalendarChange = useCallback(function (date) {
123
127
  changeHandler(null, formatDate(date), new Date(date), 'calendar');
124
128
  setOpen(false);
@@ -130,16 +134,23 @@ var CalendarInput = forwardRef(function (_a, ref) {
130
134
  useEffect(function () {
131
135
  setOpen(defaultOpen);
132
136
  }, [defaultOpen]);
137
+ useEffect(function () {
138
+ if (typeof value !== 'undefined') {
139
+ setInputValue(value);
140
+ }
141
+ }, [value]);
133
142
  var renderCalendar = useCallback(function () { return (
134
143
  // eslint-disable-next-line jsx-a11y/no-static-element-interactions
135
144
  React.createElement("div", { onMouseDown: handleCalendarWrapperMouseDown },
136
- React.createElement(Calendar$1, __assign({}, calendarProps, { ref: calendarRef, defaultMonth: defaultMonth, value: isCalendarValueValid ? calendarValue : undefined, onChange: handleCalendarChange, minDate: minDate, maxDate: maxDate, offDays: offDays })))); }, [
145
+ React.createElement(Calendar$1, __assign({}, calendarProps, { ref: calendarRef, defaultMonth: defaultMonth, value: checkInputValueIsValid(inputValue) ? calendarValue : undefined, onChange: handleCalendarChange, minDate: minDate, maxDate: maxDate, offDays: offDays, events: events })))); }, [
137
146
  calendarProps,
138
147
  calendarValue,
148
+ checkInputValueIsValid,
139
149
  defaultMonth,
150
+ events,
140
151
  handleCalendarChange,
141
152
  handleCalendarWrapperMouseDown,
142
- isCalendarValueValid,
153
+ inputValue,
143
154
  maxDate,
144
155
  minDate,
145
156
  offDays,
@@ -149,9 +160,9 @@ var CalendarInput = forwardRef(function (_a, ref) {
149
160
  React.createElement("div", { className: cn(styles.component, className, (_b = {},
150
161
  _b[styles.block] = block,
151
162
  _b)), tabIndex: -1, onKeyDown: inputDisabled ? undefined : handleKeyDown, onClick: inputDisabled ? undefined : handleClick, onFocus: inputDisabled ? undefined : handleFocus, onBlur: handleBlur, "data-test-id": dataTestId },
152
- React.createElement(DateInput, __assign({}, restProps, { ref: ref, wrapperRef: mergeRefs([wrapperRef, inputWrapperRef]), value: inputValue, defaultValue: defaultValue, disabled: disabled, readOnly: readOnly, mobileMode: mobileMode === 'native' ? 'native' : 'input', rightAddons: React.createElement(React.Fragment, null,
163
+ React.createElement(DateInput, __assign({}, restProps, { ref: ref, wrapperRef: mergeRefs([wrapperRef, inputWrapperRef]), value: inputValue, defaultValue: defaultValue, disabled: disabled, readOnly: readOnly, mobileMode: mobileMode === 'native' ? 'native' : 'input', error: error, rightAddons: React.createElement(React.Fragment, null,
153
164
  rightAddons,
154
- React.createElement(CalendarMIcon, { className: styles.calendarIcon })), onKeyDown: handleInputKeyDown, onChange: handleInputChange, block: true })),
165
+ shouldRenderPopover && (React.createElement(CalendarMIcon, { className: styles.calendarIcon }))), onKeyDown: handleInputKeyDown, onChange: handleInputChange, block: true })),
155
166
  shouldRenderStatic && renderCalendar(),
156
167
  shouldRenderPopover && (React.createElement(Popover, { open: open, useAnchorWidth: useAnchorWidth, anchorElement: inputWrapperRef.current, popperClassName: styles.calendarContainer, className: popoverClassName, position: popoverPosition, offset: [0, 8], withTransition: false, preventFlip: preventFlip, zIndex: zIndexPopover }, renderCalendar()))));
157
168
  });
@@ -1,10 +1,8 @@
1
- /* hash: qjg4u */
1
+ /* hash: 12mh8 */
2
2
  :root {
3
- --color-light-border-primary: #dbdee1;
4
3
  --color-light-graphic-primary: #0b1f35;
5
4
  }
6
5
  :root {
7
- --shadow-s: 0 0 8px rgba(11, 31, 53, 0.04), 0 4px 8px rgba(11, 31, 53, 0.08);
8
6
 
9
7
  /* Hard */
10
8
 
@@ -16,7 +14,7 @@
16
14
  --gap-2xs: 4px;
17
15
  }
18
16
  :root {
19
- --border-radius-m: 8px;
17
+ --border-radius-s: 4px;
20
18
  }
21
19
  :root {
22
20
 
@@ -40,40 +38,37 @@
40
38
  }
41
39
  :root {
42
40
  --calendar-input-icon-color: var(--color-light-graphic-primary);
43
- --calendar-input-popover-border-color: var(--color-light-border-primary);
44
- --calendar-input-popover-border-radius: var(--border-radius-m);
41
+ --calendar-input-popover-border-radius: 0 0 var(--border-radius-s) var(--border-radius-s);
45
42
  }
46
- .calendar-input__component_qd42g {
43
+ .calendar-input__component_1u5qx {
47
44
  display: inline-block;
48
45
  outline: none;
49
46
  position: relative;
50
47
  }
51
- .calendar-input__block_qd42g {
48
+ .calendar-input__block_1u5qx {
52
49
  width: 100%;
53
50
  }
54
- .calendar-input__calendarContainer_qd42g {
51
+ .calendar-input__calendarContainer_1u5qx {
55
52
  display: inline-block;
56
53
  box-sizing: border-box;
57
- box-shadow: var(--shadow-s);
58
- border: 1px solid var(--calendar-input-popover-border-color);
59
54
  border-radius: var(--calendar-input-popover-border-radius)
60
55
  }
61
56
  @media (max-width: 374px) {
62
- .calendar-input__calendarContainer_qd42g {
57
+ .calendar-input__calendarContainer_1u5qx {
63
58
  width: 100%;
64
59
  min-width: 288px
65
60
  }
66
61
  }
67
- .calendar-input__calendarIcon_qd42g {
62
+ .calendar-input__calendarIcon_1u5qx {
68
63
  width: 24px;
69
64
  height: 24px;
70
65
  display: block;
71
66
  color: var(--calendar-input-icon-color)
72
67
  }
73
- .calendar-input__calendarIcon_qd42g:not(:only-child) {
68
+ .calendar-input__calendarIcon_1u5qx:not(:only-child) {
74
69
  margin-right: var(--gap-2xs);
75
70
  }
76
- .calendar-input__nativeInput_qd42g {
71
+ .calendar-input__nativeInput_1u5qx {
77
72
  opacity: 0;
78
73
  position: absolute;
79
74
  top: 0;
@@ -84,9 +79,9 @@
84
79
  appearance: none;
85
80
  z-index: 1
86
81
  }
87
- .calendar-input__nativeInput_qd42g::-webkit-calendar-picker-indicator {
82
+ .calendar-input__nativeInput_1u5qx::-webkit-calendar-picker-indicator {
88
83
  display: none;
89
84
  }
90
- .calendar-input__nativeInput_qd42g::-webkit-inner-spin-button {
85
+ .calendar-input__nativeInput_1u5qx::-webkit-inner-spin-button {
91
86
  display: none;
92
87
  }
package/dist/esm/index.js CHANGED
@@ -3,8 +3,10 @@ import 'react';
3
3
  import 'classnames';
4
4
  import 'react-merge-refs';
5
5
  import '@alfalab/core-components-popover/dist/esm';
6
+ import '@alfalab/icons-glyph/CalendarMIcon';
6
7
  import '@alfalab/core-components-date-input/dist/esm';
7
8
  import '@alfalab/core-components-calendar/dist/esm';
8
- import '@alfalab/icons-glyph/CalendarMIcon';
9
- import 'date-fns';
10
- export { DATE_FORMAT, DATE_MASK, IS_BROWSER, NATIVE_DATE_FORMAT, SUPPORTS_INPUT_TYPE_DATE, formatDate, isCompleteDateInput, isInputDateSupported, parseDateString } from './utils.js';
9
+ import 'date-fns/parse';
10
+ import 'date-fns/format';
11
+ import 'date-fns/isSameDay';
12
+ export { DATE_FORMAT, DATE_MASK, IS_BROWSER, NATIVE_DATE_FORMAT, SUPPORTS_INPUT_TYPE_DATE, formatDate, isInputDateSupported, isValidInputValue, parseDateString } from './utils.js';
@@ -3,11 +3,11 @@ declare const NATIVE_DATE_FORMAT = "yyyy-MM-dd";
3
3
  declare const DATE_MASK: (string | RegExp)[];
4
4
  declare const IS_BROWSER: boolean;
5
5
  declare const SUPPORTS_INPUT_TYPE_DATE: boolean;
6
- declare const isCompleteDateInput: (input: string) => boolean;
7
6
  declare const formatDate: (date: number | Date, dateFormat?: string) => string;
8
7
  declare const parseDateString: (value: string, dateFormat?: string) => Date;
9
8
  /**
10
9
  * Возвращает `true`, если поддерживается `input[type="date"]`
11
10
  */
12
11
  declare function isInputDateSupported(): boolean;
13
- export { DATE_FORMAT, NATIVE_DATE_FORMAT, DATE_MASK, IS_BROWSER, SUPPORTS_INPUT_TYPE_DATE, isCompleteDateInput, formatDate, parseDateString, isInputDateSupported };
12
+ declare const isValidInputValue: (newInputValue: string | undefined, minDate: number | undefined, maxDate: number | undefined, offDays?: (number | Date)[]) => boolean;
13
+ export { DATE_FORMAT, NATIVE_DATE_FORMAT, DATE_MASK, IS_BROWSER, SUPPORTS_INPUT_TYPE_DATE, formatDate, parseDateString, isInputDateSupported, isValidInputValue };
package/dist/esm/utils.js CHANGED
@@ -1,11 +1,14 @@
1
- import { format, parse } from 'date-fns';
1
+ import { isCompleteDateInput } from '@alfalab/core-components-date-input/dist/esm';
2
+ import { dateInLimits } from '@alfalab/core-components-calendar/dist/esm';
3
+ import parse from 'date-fns/parse';
4
+ import format from 'date-fns/format';
5
+ import isSameDay from 'date-fns/isSameDay';
2
6
 
3
7
  var DATE_FORMAT = 'dd.MM.yyyy';
4
8
  var NATIVE_DATE_FORMAT = 'yyyy-MM-dd';
5
9
  var DATE_MASK = [/\d/, /\d/, '.', /\d/, /\d/, '.', /\d/, /\d/, /\d/, /\d/];
6
10
  var IS_BROWSER = typeof window !== 'undefined';
7
11
  var SUPPORTS_INPUT_TYPE_DATE = IS_BROWSER && isInputDateSupported();
8
- var isCompleteDateInput = function (input) { return input.length === DATE_MASK.length; };
9
12
  var formatDate = function (date, dateFormat) {
10
13
  if (dateFormat === void 0) { dateFormat = DATE_FORMAT; }
11
14
  return format(date, dateFormat);
@@ -24,5 +27,15 @@ function isInputDateSupported() {
24
27
  input.setAttribute('value', value);
25
28
  return input.value !== value;
26
29
  }
30
+ var isValidInputValue = function (newInputValue, minDate, maxDate, offDays) {
31
+ if (offDays === void 0) { offDays = []; }
32
+ if (!newInputValue)
33
+ return false;
34
+ var dateValue = parseDateString(newInputValue).getTime();
35
+ return Boolean(dateValue &&
36
+ isCompleteDateInput(newInputValue) &&
37
+ dateInLimits(dateValue, minDate, maxDate) &&
38
+ !offDays.some(function (offDay) { return isSameDay(offDay, dateValue); }));
39
+ };
27
40
 
28
- export { DATE_FORMAT, DATE_MASK, IS_BROWSER, NATIVE_DATE_FORMAT, SUPPORTS_INPUT_TYPE_DATE, formatDate, isCompleteDateInput, isInputDateSupported, parseDateString };
41
+ export { DATE_FORMAT, DATE_MASK, IS_BROWSER, NATIVE_DATE_FORMAT, SUPPORTS_INPUT_TYPE_DATE, formatDate, isInputDateSupported, isValidInputValue, parseDateString };
package/dist/index.css CHANGED
@@ -1,10 +1,8 @@
1
- /* hash: qjg4u */
1
+ /* hash: 12mh8 */
2
2
  :root {
3
- --color-light-border-primary: #dbdee1;
4
3
  --color-light-graphic-primary: #0b1f35;
5
4
  }
6
5
  :root {
7
- --shadow-s: 0 0 8px rgba(11, 31, 53, 0.04), 0 4px 8px rgba(11, 31, 53, 0.08);
8
6
 
9
7
  /* Hard */
10
8
 
@@ -16,7 +14,7 @@
16
14
  --gap-2xs: 4px;
17
15
  }
18
16
  :root {
19
- --border-radius-m: 8px;
17
+ --border-radius-s: 4px;
20
18
  }
21
19
  :root {
22
20
 
@@ -40,40 +38,37 @@
40
38
  }
41
39
  :root {
42
40
  --calendar-input-icon-color: var(--color-light-graphic-primary);
43
- --calendar-input-popover-border-color: var(--color-light-border-primary);
44
- --calendar-input-popover-border-radius: var(--border-radius-m);
41
+ --calendar-input-popover-border-radius: 0 0 var(--border-radius-s) var(--border-radius-s);
45
42
  }
46
- .calendar-input__component_qd42g {
43
+ .calendar-input__component_1u5qx {
47
44
  display: inline-block;
48
45
  outline: none;
49
46
  position: relative;
50
47
  }
51
- .calendar-input__block_qd42g {
48
+ .calendar-input__block_1u5qx {
52
49
  width: 100%;
53
50
  }
54
- .calendar-input__calendarContainer_qd42g {
51
+ .calendar-input__calendarContainer_1u5qx {
55
52
  display: inline-block;
56
53
  box-sizing: border-box;
57
- box-shadow: var(--shadow-s);
58
- border: 1px solid var(--calendar-input-popover-border-color);
59
54
  border-radius: var(--calendar-input-popover-border-radius)
60
55
  }
61
56
  @media (max-width: 374px) {
62
- .calendar-input__calendarContainer_qd42g {
57
+ .calendar-input__calendarContainer_1u5qx {
63
58
  width: 100%;
64
59
  min-width: 288px
65
60
  }
66
61
  }
67
- .calendar-input__calendarIcon_qd42g {
62
+ .calendar-input__calendarIcon_1u5qx {
68
63
  width: 24px;
69
64
  height: 24px;
70
65
  display: block;
71
66
  color: var(--calendar-input-icon-color)
72
67
  }
73
- .calendar-input__calendarIcon_qd42g:not(:only-child) {
68
+ .calendar-input__calendarIcon_1u5qx:not(:only-child) {
74
69
  margin-right: var(--gap-2xs);
75
70
  }
76
- .calendar-input__nativeInput_qd42g {
71
+ .calendar-input__nativeInput_1u5qx {
77
72
  opacity: 0;
78
73
  position: absolute;
79
74
  top: 0;
@@ -84,9 +79,9 @@
84
79
  appearance: none;
85
80
  z-index: 1
86
81
  }
87
- .calendar-input__nativeInput_qd42g::-webkit-calendar-picker-indicator {
82
+ .calendar-input__nativeInput_1u5qx::-webkit-calendar-picker-indicator {
88
83
  display: none;
89
84
  }
90
- .calendar-input__nativeInput_qd42g::-webkit-inner-spin-button {
85
+ .calendar-input__nativeInput_1u5qx::-webkit-inner-spin-button {
91
86
  display: none;
92
87
  }
package/dist/index.js CHANGED
@@ -7,10 +7,12 @@ require('react');
7
7
  require('classnames');
8
8
  require('react-merge-refs');
9
9
  require('@alfalab/core-components-popover');
10
+ require('@alfalab/icons-glyph/CalendarMIcon');
10
11
  require('@alfalab/core-components-date-input');
11
12
  require('@alfalab/core-components-calendar');
12
- require('@alfalab/icons-glyph/CalendarMIcon');
13
- require('date-fns');
13
+ require('date-fns/parse');
14
+ require('date-fns/format');
15
+ require('date-fns/isSameDay');
14
16
  var utils = require('./utils.js');
15
17
 
16
18
 
@@ -22,6 +24,6 @@ exports.IS_BROWSER = utils.IS_BROWSER;
22
24
  exports.NATIVE_DATE_FORMAT = utils.NATIVE_DATE_FORMAT;
23
25
  exports.SUPPORTS_INPUT_TYPE_DATE = utils.SUPPORTS_INPUT_TYPE_DATE;
24
26
  exports.formatDate = utils.formatDate;
25
- exports.isCompleteDateInput = utils.isCompleteDateInput;
26
27
  exports.isInputDateSupported = utils.isInputDateSupported;
28
+ exports.isValidInputValue = utils.isValidInputValue;
27
29
  exports.parseDateString = utils.parseDateString;
@@ -45,6 +45,10 @@ type CalendarInputProps = Omit<DateInputProps, 'onChange' | 'mobileMode'> & {
45
45
  * Максимальная дата, доступная для выбора (timestamp)
46
46
  */
47
47
  maxDate?: number;
48
+ /**
49
+ * Список событий
50
+ */
51
+ events?: Array<Date | number>;
48
52
  /**
49
53
  * Список выходных
50
54
  */
@@ -97,7 +101,7 @@ type CalendarInputProps = Omit<DateInputProps, 'onChange' | 'mobileMode'> & {
97
101
  */
98
102
  useAnchorWidth?: boolean;
99
103
  };
100
- declare const CalendarInput: React.ForwardRefExoticComponent<Pick<DateInputProps, "children" | "value" | "form" | "label" | "slot" | "style" | "title" | "pattern" | "dir" | "className" | "dataTestId" | "height" | "name" | "width" | "hidden" | "color" | "size" | "block" | "clear" | "multiple" | "disabled" | "leftAddons" | "rightAddons" | "colors" | "type" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "contentEditable" | "contextMenu" | "draggable" | "id" | "lang" | "placeholder" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "list" | "step" | "autoFocus" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "fieldClassName" | "labelClassName" | "addonsClassName" | "error" | "hint" | "bottomAddons" | "accept" | "alt" | "autoComplete" | "capture" | "checked" | "crossOrigin" | "max" | "maxLength" | "min" | "minLength" | "readOnly" | "required" | "src" | "success" | "inputClassName" | "focusedClassName" | "filledClassName" | "onClear" | "wrapperRef" | "keepCharPositions" | "minYear" | "maxYear"> & {
104
+ declare const CalendarInput: React.ForwardRefExoticComponent<Pick<DateInputProps, "children" | "value" | "form" | "label" | "slot" | "style" | "title" | "pattern" | "dir" | "className" | "dataTestId" | "height" | "name" | "width" | "hidden" | "color" | "size" | "block" | "clear" | "multiple" | "disabled" | "leftAddons" | "rightAddons" | "colors" | "type" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "contentEditable" | "contextMenu" | "draggable" | "id" | "lang" | "placeholder" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "list" | "step" | "autoFocus" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "fieldClassName" | "labelClassName" | "addonsClassName" | "error" | "hint" | "bottomAddons" | "accept" | "alt" | "autoComplete" | "capture" | "checked" | "crossOrigin" | "max" | "maxLength" | "min" | "minLength" | "readOnly" | "required" | "src" | "success" | "inputClassName" | "focusedClassName" | "filledClassName" | "onClear" | "wrapperRef" | "onComplete"> & {
101
105
  /**
102
106
  * Дополнительный класс
103
107
  */
@@ -138,6 +142,10 @@ declare const CalendarInput: React.ForwardRefExoticComponent<Pick<DateInputProps
138
142
  * Максимальная дата, доступная для выбора (timestamp)
139
143
  */
140
144
  maxDate?: number | undefined;
145
+ /**
146
+ * Список событий
147
+ */
148
+ events?: (number | Date)[] | undefined;
141
149
  /**
142
150
  * Список выходных
143
151
  */
@@ -1,27 +1,35 @@
1
- import React, { forwardRef, useState, useRef, useCallback, useEffect } from 'react';
1
+ import React, { forwardRef, useState, useCallback, useRef, useEffect } from 'react';
2
2
  import cn from 'classnames';
3
3
  import mergeRefs from 'react-merge-refs';
4
4
  import { Popover } from '@alfalab/core-components-popover/dist/modern';
5
- import { parseDateString, isCompleteDateInput, formatDate, DateInput, SUPPORTS_INPUT_TYPE_DATE } from '@alfalab/core-components-date-input/dist/modern';
6
- import { Calendar, dateInLimits } from '@alfalab/core-components-calendar/dist/modern';
7
5
  import { CalendarMIcon } from '@alfalab/icons-glyph/CalendarMIcon';
6
+ import { parseDateString, isCompleteDateInput, formatDate, DateInput } from '@alfalab/core-components-date-input/dist/modern';
7
+ import { Calendar, dateInLimits } from '@alfalab/core-components-calendar/dist/modern';
8
+ import 'date-fns/parse';
9
+ import 'date-fns/format';
10
+ import 'date-fns/isSameDay';
11
+ import { SUPPORTS_INPUT_TYPE_DATE } from './utils.js';
8
12
 
9
- var styles = {"component":"calendar-input__component_qd42g","block":"calendar-input__block_qd42g","calendarContainer":"calendar-input__calendarContainer_qd42g","calendarIcon":"calendar-input__calendarIcon_qd42g","nativeInput":"calendar-input__nativeInput_qd42g"};
13
+ var styles = {"component":"calendar-input__component_1u5qx","block":"calendar-input__block_1u5qx","calendarContainer":"calendar-input__calendarContainer_1u5qx","calendarIcon":"calendar-input__calendarIcon_1u5qx","nativeInput":"calendar-input__nativeInput_1u5qx"};
10
14
  require('./index.css')
11
15
 
12
- const CalendarInput = forwardRef(({ block = false, className, inputClassName, popoverClassName, defaultOpen = false, defaultMonth, defaultValue = '', calendarPosition = 'popover', value, dataTestId, calendarProps = {}, minDate = calendarProps.minDate, maxDate = calendarProps.maxDate, offDays = calendarProps.offDays || [], preventFlip, mobileMode = 'popover', wrapperRef = null, disabled, onChange, onInputChange, onCalendarChange, onKeyDown, readOnly, Calendar: Calendar$1 = Calendar, popoverPosition = 'bottom-start', zIndexPopover, useAnchorWidth, rightAddons, ...restProps }, ref) => {
13
- const uncontrolled = value === undefined;
16
+ const CalendarInput = forwardRef(({ block = false, className, inputClassName, popoverClassName, defaultOpen = false, defaultMonth, defaultValue = '', calendarPosition = 'popover', value, dataTestId, calendarProps = {}, minDate = calendarProps.minDate, maxDate = calendarProps.maxDate, offDays = calendarProps.offDays || [], events = calendarProps.events || [], preventFlip, mobileMode = 'popover', wrapperRef = null, disabled, onChange = () => null, onInputChange, onCalendarChange, onKeyDown, readOnly, Calendar: Calendar$1 = Calendar, popoverPosition = 'bottom-start', zIndexPopover, useAnchorWidth, rightAddons, error, ...restProps }, ref) => {
14
17
  const shouldRenderNative = SUPPORTS_INPUT_TYPE_DATE && mobileMode === 'native';
15
18
  const shouldRenderOnlyInput = mobileMode === 'input';
16
19
  const shouldRenderStatic = calendarPosition === 'static' && !shouldRenderOnlyInput;
17
20
  const shouldRenderPopover = calendarPosition === 'popover' && !shouldRenderNative && !shouldRenderOnlyInput;
18
21
  const [open, setOpen] = useState(false);
19
- const [stateValue, setStateValue] = useState(defaultValue);
20
- const inputValue = uncontrolled ? stateValue : value;
22
+ const [inputValue, setInputValue] = useState(value || defaultValue);
21
23
  const calendarValue = inputValue ? parseDateString(inputValue).getTime() : undefined;
22
- const isCalendarValueValid = calendarValue &&
23
- dateInLimits(calendarValue, minDate, maxDate) &&
24
- !offDays.includes(calendarValue);
24
+ const checkInputValueIsValid = useCallback((newInputValue) => {
25
+ if (!newInputValue || error)
26
+ return false;
27
+ const dateValue = parseDateString(newInputValue).getTime();
28
+ return (dateValue &&
29
+ isCompleteDateInput(newInputValue) &&
30
+ dateInLimits(dateValue, minDate, maxDate) &&
31
+ !offDays.includes(dateValue));
32
+ }, [error, maxDate, minDate, offDays]);
25
33
  const inputDisabled = disabled || readOnly;
26
34
  const inputWrapperRef = useRef(null);
27
35
  const calendarRef = useRef(null);
@@ -64,18 +72,14 @@ const CalendarInput = forwardRef(({ block = false, className, inputClassName, po
64
72
  if (initiator === 'calendar' && onCalendarChange) {
65
73
  onCalendarChange(newDate.getTime());
66
74
  }
75
+ setInputValue(newValue);
67
76
  if (shouldChange) {
68
- if (uncontrolled) {
69
- setStateValue(newValue);
70
- }
71
- if (onChange) {
72
- onChange(event, { date: newDate, value: newValue });
73
- }
77
+ onChange(event, { date: newDate, value: newValue });
74
78
  }
75
- }, [onCalendarChange, onChange, onInputChange, uncontrolled]);
79
+ }, [onCalendarChange, onChange, onInputChange]);
76
80
  const handleInputChange = useCallback((event, payload) => {
77
- changeHandler(event, payload.value, payload.date, 'input', !payload.value || isCompleteDateInput(payload.value));
78
- }, [changeHandler]);
81
+ changeHandler(event, payload.value, payload.date, 'input', !payload.value || checkInputValueIsValid(payload.value));
82
+ }, [changeHandler, checkInputValueIsValid]);
79
83
  const handleCalendarChange = useCallback(date => {
80
84
  changeHandler(null, formatDate(date), new Date(date), 'calendar');
81
85
  setOpen(false);
@@ -87,16 +91,23 @@ const CalendarInput = forwardRef(({ block = false, className, inputClassName, po
87
91
  useEffect(() => {
88
92
  setOpen(defaultOpen);
89
93
  }, [defaultOpen]);
94
+ useEffect(() => {
95
+ if (typeof value !== 'undefined') {
96
+ setInputValue(value);
97
+ }
98
+ }, [value]);
90
99
  const renderCalendar = useCallback(() => (
91
100
  // eslint-disable-next-line jsx-a11y/no-static-element-interactions
92
101
  React.createElement("div", { onMouseDown: handleCalendarWrapperMouseDown },
93
- React.createElement(Calendar$1, Object.assign({}, calendarProps, { ref: calendarRef, defaultMonth: defaultMonth, value: isCalendarValueValid ? calendarValue : undefined, onChange: handleCalendarChange, minDate: minDate, maxDate: maxDate, offDays: offDays })))), [
102
+ React.createElement(Calendar$1, Object.assign({}, calendarProps, { ref: calendarRef, defaultMonth: defaultMonth, value: checkInputValueIsValid(inputValue) ? calendarValue : undefined, onChange: handleCalendarChange, minDate: minDate, maxDate: maxDate, offDays: offDays, events: events })))), [
94
103
  calendarProps,
95
104
  calendarValue,
105
+ checkInputValueIsValid,
96
106
  defaultMonth,
107
+ events,
97
108
  handleCalendarChange,
98
109
  handleCalendarWrapperMouseDown,
99
- isCalendarValueValid,
110
+ inputValue,
100
111
  maxDate,
101
112
  minDate,
102
113
  offDays,
@@ -106,9 +117,9 @@ const CalendarInput = forwardRef(({ block = false, className, inputClassName, po
106
117
  React.createElement("div", { className: cn(styles.component, className, {
107
118
  [styles.block]: block,
108
119
  }), tabIndex: -1, onKeyDown: inputDisabled ? undefined : handleKeyDown, onClick: inputDisabled ? undefined : handleClick, onFocus: inputDisabled ? undefined : handleFocus, onBlur: handleBlur, "data-test-id": dataTestId },
109
- React.createElement(DateInput, Object.assign({}, restProps, { ref: ref, wrapperRef: mergeRefs([wrapperRef, inputWrapperRef]), value: inputValue, defaultValue: defaultValue, disabled: disabled, readOnly: readOnly, mobileMode: mobileMode === 'native' ? 'native' : 'input', rightAddons: React.createElement(React.Fragment, null,
120
+ React.createElement(DateInput, Object.assign({}, restProps, { ref: ref, wrapperRef: mergeRefs([wrapperRef, inputWrapperRef]), value: inputValue, defaultValue: defaultValue, disabled: disabled, readOnly: readOnly, mobileMode: mobileMode === 'native' ? 'native' : 'input', error: error, rightAddons: React.createElement(React.Fragment, null,
110
121
  rightAddons,
111
- React.createElement(CalendarMIcon, { className: styles.calendarIcon })), onKeyDown: handleInputKeyDown, onChange: handleInputChange, block: true })),
122
+ shouldRenderPopover && (React.createElement(CalendarMIcon, { className: styles.calendarIcon }))), onKeyDown: handleInputKeyDown, onChange: handleInputChange, block: true })),
112
123
  shouldRenderStatic && renderCalendar(),
113
124
  shouldRenderPopover && (React.createElement(Popover, { open: open, useAnchorWidth: useAnchorWidth, anchorElement: inputWrapperRef.current, popperClassName: styles.calendarContainer, className: popoverClassName, position: popoverPosition, offset: [0, 8], withTransition: false, preventFlip: preventFlip, zIndex: zIndexPopover }, renderCalendar()))));
114
125
  });