@snack-uikit/fields 0.31.0 → 0.32.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 (134) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +179 -147
  3. package/dist/cjs/components/FieldDate/FieldDate.d.ts +15 -24
  4. package/dist/cjs/components/FieldDate/FieldDate.js +53 -41
  5. package/dist/cjs/components/FieldDate/index.d.ts +0 -1
  6. package/dist/cjs/components/FieldDate/index.js +1 -9
  7. package/dist/cjs/components/FieldSecure/FieldSecure.d.ts +1 -1
  8. package/dist/cjs/components/FieldSelect/hooks.d.ts +2 -2
  9. package/dist/cjs/components/FieldSelect/hooks.js +7 -3
  10. package/dist/cjs/components/FieldSlider/FieldSlider.d.ts +1 -1
  11. package/dist/cjs/components/FieldText/FieldText.d.ts +1 -1
  12. package/dist/cjs/components/FieldTextArea/FieldTextArea.d.ts +1 -1
  13. package/dist/cjs/components/FieldTime/FieldTime.d.ts +30 -0
  14. package/dist/cjs/components/FieldTime/FieldTime.js +298 -0
  15. package/dist/cjs/components/FieldTime/index.d.ts +1 -0
  16. package/dist/cjs/components/{FieldDate/hooks → FieldTime}/index.js +1 -1
  17. package/dist/cjs/components/FieldTime/styles.module.css +27 -0
  18. package/dist/cjs/components/index.d.ts +6 -5
  19. package/dist/cjs/components/index.js +6 -5
  20. package/dist/cjs/constants/dateFields.d.ts +24 -0
  21. package/dist/cjs/constants/dateFields.js +152 -0
  22. package/dist/cjs/constants/index.d.ts +2 -0
  23. package/dist/cjs/constants/index.js +26 -0
  24. package/dist/cjs/hooks/dateHandlers/index.d.ts +3 -0
  25. package/dist/cjs/hooks/dateHandlers/index.js +27 -0
  26. package/dist/cjs/{components/FieldDate/hooks → hooks/dateHandlers}/useDateField.d.ts +13 -5
  27. package/dist/cjs/{components/FieldDate/hooks → hooks/dateHandlers}/useDateField.js +49 -34
  28. package/dist/cjs/hooks/dateHandlers/useDateFieldHelpersForMode.d.ts +18 -0
  29. package/dist/cjs/hooks/dateHandlers/useDateFieldHelpersForMode.js +113 -0
  30. package/dist/cjs/hooks/index.d.ts +1 -0
  31. package/dist/cjs/hooks/index.js +1 -0
  32. package/dist/cjs/hooks/useCopyButton.js +1 -1
  33. package/dist/cjs/{types.d.ts → types/allFields.d.ts} +1 -1
  34. package/dist/cjs/types/dateFields.d.ts +11 -0
  35. package/dist/cjs/types/index.d.ts +2 -0
  36. package/dist/cjs/types/index.js +26 -0
  37. package/dist/cjs/utils/dateFields.d.ts +10 -0
  38. package/dist/cjs/utils/dateFields.js +71 -0
  39. package/dist/esm/components/FieldDate/FieldDate.d.ts +15 -24
  40. package/dist/esm/components/FieldDate/FieldDate.js +39 -31
  41. package/dist/esm/components/FieldDate/index.d.ts +0 -1
  42. package/dist/esm/components/FieldDate/index.js +0 -1
  43. package/dist/esm/components/FieldSecure/FieldSecure.d.ts +1 -1
  44. package/dist/esm/components/FieldSelect/hooks.d.ts +2 -2
  45. package/dist/esm/components/FieldSelect/hooks.js +9 -3
  46. package/dist/esm/components/FieldSlider/FieldSlider.d.ts +1 -1
  47. package/dist/esm/components/FieldText/FieldText.d.ts +1 -1
  48. package/dist/esm/components/FieldTextArea/FieldTextArea.d.ts +1 -1
  49. package/dist/esm/components/FieldTime/FieldTime.d.ts +30 -0
  50. package/dist/esm/components/FieldTime/FieldTime.js +161 -0
  51. package/dist/esm/components/FieldTime/index.d.ts +1 -0
  52. package/dist/esm/components/FieldTime/index.js +1 -0
  53. package/dist/esm/components/FieldTime/styles.module.css +27 -0
  54. package/dist/esm/components/index.d.ts +6 -5
  55. package/dist/esm/components/index.js +6 -5
  56. package/dist/esm/constants/dateFields.d.ts +24 -0
  57. package/dist/esm/constants/dateFields.js +103 -0
  58. package/dist/esm/constants/index.d.ts +2 -0
  59. package/dist/esm/constants/index.js +2 -0
  60. package/dist/esm/hooks/dateHandlers/index.d.ts +3 -0
  61. package/dist/esm/hooks/dateHandlers/index.js +3 -0
  62. package/dist/esm/{components/FieldDate/hooks → hooks/dateHandlers}/useDateField.d.ts +13 -5
  63. package/dist/esm/{components/FieldDate/hooks → hooks/dateHandlers}/useDateField.js +48 -35
  64. package/dist/esm/hooks/dateHandlers/useDateFieldHelpersForMode.d.ts +18 -0
  65. package/dist/esm/hooks/dateHandlers/useDateFieldHelpersForMode.js +95 -0
  66. package/dist/esm/hooks/index.d.ts +1 -0
  67. package/dist/esm/hooks/index.js +1 -0
  68. package/dist/esm/hooks/useCopyButton.js +1 -1
  69. package/dist/esm/{types.d.ts → types/allFields.d.ts} +1 -1
  70. package/dist/esm/types/dateFields.d.ts +11 -0
  71. package/dist/esm/types/index.d.ts +2 -0
  72. package/dist/esm/types/index.js +2 -0
  73. package/dist/esm/utils/dateFields.d.ts +10 -0
  74. package/dist/esm/utils/dateFields.js +59 -0
  75. package/package.json +10 -10
  76. package/src/components/FieldDate/FieldDate.tsx +72 -52
  77. package/src/components/FieldDate/index.ts +0 -1
  78. package/src/components/FieldSelect/hooks.ts +15 -3
  79. package/src/components/FieldTime/FieldTime.tsx +350 -0
  80. package/src/components/FieldTime/index.ts +1 -0
  81. package/src/components/FieldTime/styles.module.scss +41 -0
  82. package/src/components/index.ts +6 -5
  83. package/src/constants/dateFields.ts +127 -0
  84. package/src/constants/index.ts +2 -0
  85. package/src/hooks/dateHandlers/index.ts +3 -0
  86. package/src/{components/FieldDate/hooks → hooks/dateHandlers}/useDateField.ts +93 -47
  87. package/src/hooks/dateHandlers/useDateFieldHelpersForMode.ts +145 -0
  88. package/src/hooks/index.ts +1 -0
  89. package/src/hooks/useCopyButton.tsx +1 -1
  90. package/src/{types.ts → types/allFields.ts} +1 -1
  91. package/src/types/dateFields.ts +14 -0
  92. package/src/types/index.ts +2 -0
  93. package/src/utils/dateFields.ts +75 -0
  94. package/dist/cjs/components/FieldDate/constants.d.ts +0 -10
  95. package/dist/cjs/components/FieldDate/constants.js +0 -49
  96. package/dist/cjs/components/FieldDate/hooks/index.d.ts +0 -1
  97. package/dist/cjs/components/FieldDate/hooks/useDateFieldHelpers.d.ts +0 -10
  98. package/dist/cjs/components/FieldDate/hooks/useDateFieldHelpers.js +0 -82
  99. package/dist/cjs/components/FieldDate/types.d.ts +0 -6
  100. package/dist/cjs/components/FieldDate/utils.d.ts +0 -9
  101. package/dist/cjs/components/FieldDate/utils.js +0 -56
  102. package/dist/esm/components/FieldDate/constants.d.ts +0 -10
  103. package/dist/esm/components/FieldDate/constants.js +0 -28
  104. package/dist/esm/components/FieldDate/hooks/index.d.ts +0 -1
  105. package/dist/esm/components/FieldDate/hooks/index.js +0 -1
  106. package/dist/esm/components/FieldDate/hooks/useDateFieldHelpers.d.ts +0 -10
  107. package/dist/esm/components/FieldDate/hooks/useDateFieldHelpers.js +0 -66
  108. package/dist/esm/components/FieldDate/types.d.ts +0 -6
  109. package/dist/esm/components/FieldDate/utils.d.ts +0 -9
  110. package/dist/esm/components/FieldDate/utils.js +0 -43
  111. package/src/components/FieldDate/constants.ts +0 -33
  112. package/src/components/FieldDate/hooks/index.ts +0 -1
  113. package/src/components/FieldDate/hooks/useDateFieldHelpers.ts +0 -96
  114. package/src/components/FieldDate/types.ts +0 -6
  115. package/src/components/FieldDate/utils.ts +0 -49
  116. /package/dist/cjs/{constants.d.ts → constants/allFields.d.ts} +0 -0
  117. /package/dist/cjs/{constants.js → constants/allFields.js} +0 -0
  118. /package/dist/cjs/{components/FieldDate/hooks → hooks/dateHandlers}/useFocusHandlers.d.ts +0 -0
  119. /package/dist/cjs/{components/FieldDate/hooks → hooks/dateHandlers}/useFocusHandlers.js +0 -0
  120. /package/dist/cjs/{components/FieldDate/hooks → hooks/dateHandlers}/useHandlers.d.ts +0 -0
  121. /package/dist/cjs/{components/FieldDate/hooks → hooks/dateHandlers}/useHandlers.js +0 -0
  122. /package/dist/cjs/{components/FieldDate/types.js → types/allFields.js} +0 -0
  123. /package/dist/cjs/{types.js → types/dateFields.js} +0 -0
  124. /package/dist/esm/{constants.d.ts → constants/allFields.d.ts} +0 -0
  125. /package/dist/esm/{constants.js → constants/allFields.js} +0 -0
  126. /package/dist/esm/{components/FieldDate/hooks → hooks/dateHandlers}/useFocusHandlers.d.ts +0 -0
  127. /package/dist/esm/{components/FieldDate/hooks → hooks/dateHandlers}/useFocusHandlers.js +0 -0
  128. /package/dist/esm/{components/FieldDate/hooks → hooks/dateHandlers}/useHandlers.d.ts +0 -0
  129. /package/dist/esm/{components/FieldDate/hooks → hooks/dateHandlers}/useHandlers.js +0 -0
  130. /package/dist/esm/{components/FieldDate/types.js → types/allFields.js} +0 -0
  131. /package/dist/esm/{types.js → types/dateFields.js} +0 -0
  132. /package/src/{constants.ts → constants/allFields.ts} +0 -0
  133. /package/src/{components/FieldDate/hooks → hooks/dateHandlers}/useFocusHandlers.ts +0 -0
  134. /package/src/{components/FieldDate/hooks → hooks/dateHandlers}/useHandlers.ts +0 -0
@@ -31,18 +31,9 @@ const helperComponents_1 = require("../../helperComponents");
31
31
  const hooks_1 = require("../../hooks");
32
32
  const getValidationState_1 = require("../../utils/getValidationState");
33
33
  const FieldDecorator_1 = require("../FieldDecorator");
34
- const constants_2 = require("./constants");
35
- const hooks_2 = require("./hooks");
36
- const useFocusHandlers_1 = require("./hooks/useFocusHandlers");
37
- const useHandlers_1 = require("./hooks/useHandlers");
38
34
  const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
39
- const utils_2 = require("./utils");
40
- const CALENDAR_SIZE_MAP = {
41
- [input_private_1.SIZE.S]: 's',
42
- [input_private_1.SIZE.M]: 'm',
43
- [input_private_1.SIZE.L]: 'm'
44
- };
45
35
  exports.FieldDate = (0, react_1.forwardRef)((_a, ref) => {
36
+ var _b;
46
37
  var {
47
38
  id,
48
39
  name,
@@ -66,13 +57,12 @@ exports.FieldDate = (0, react_1.forwardRef)((_a, ref) => {
66
57
  showHintIcon,
67
58
  size = input_private_1.SIZE.S,
68
59
  validationState = constants_1.VALIDATION_STATE.Default,
69
- locale = constants_2.DEFAULT_LOCALE,
70
60
  buildCellProps,
71
- error
61
+ error,
62
+ mode
72
63
  } = _a,
73
- rest = __rest(_a, ["id", "name", "value", "disabled", "readonly", "showCopyButton", "showClearButton", "open", "onOpenChange", "onChange", "onFocus", "onBlur", "className", "label", "labelTooltip", "labelTooltipPlacement", "required", "caption", "hint", "showHintIcon", "size", "validationState", "locale", "buildCellProps", "error"]);
64
+ rest = __rest(_a, ["id", "name", "value", "disabled", "readonly", "showCopyButton", "showClearButton", "open", "onOpenChange", "onChange", "onFocus", "onBlur", "className", "label", "labelTooltip", "labelTooltipPlacement", "required", "caption", "hint", "showHintIcon", "size", "validationState", "buildCellProps", "error", "mode"]);
74
65
  const [isOpen, setIsOpen] = (0, uncontrollable_1.useUncontrolledProp)(open, false, onOpenChange);
75
- const [pickerAutofocus, setPickerAutofocus] = (0, react_1.useState)(false);
76
66
  const localRef = (0, react_1.useRef)(null);
77
67
  const clearButtonRef = (0, react_1.useRef)(null);
78
68
  const copyButtonRef = (0, react_1.useRef)(null);
@@ -81,19 +71,24 @@ exports.FieldDate = (0, react_1.forwardRef)((_a, ref) => {
81
71
  const showAdditionalButton = Boolean(valueProp && !disabled);
82
72
  const showClearButton = showClearButtonProp && showAdditionalButton && !readonly;
83
73
  const showCopyButton = showCopyButtonProp && showAdditionalButton && readonly;
74
+ const showSeconds = mode === 'date-time' ? (_b = rest.showSeconds) !== null && _b !== void 0 ? _b : true : undefined;
84
75
  const fieldValidationState = (0, getValidationState_1.getValidationState)({
85
76
  validationState,
86
77
  error
87
78
  });
79
+ const navigationStartRef = (0, react_1.useRef)(null);
88
80
  const checkForLeavingFocus = (0, react_1.useCallback)(event => {
89
81
  if (event.key === 'ArrowDown') {
90
- setPickerAutofocus(true);
91
82
  setIsOpen(true);
83
+ setTimeout(() => {
84
+ var _a;
85
+ return (_a = navigationStartRef.current) === null || _a === void 0 ? void 0 : _a.focus();
86
+ }, 0);
92
87
  }
93
88
  }, [setIsOpen]);
94
89
  const handleClear = (0, react_1.useCallback)(() => {
95
90
  var _a, _b, _c;
96
- onChange && onChange('');
91
+ onChange && onChange(undefined);
97
92
  if ((_a = localRef.current) === null || _a === void 0 ? void 0 : _a.value) {
98
93
  localRef.current.value = '';
99
94
  }
@@ -105,6 +100,21 @@ exports.FieldDate = (0, react_1.forwardRef)((_a, ref) => {
105
100
  setIsOpen(false);
106
101
  }
107
102
  }, [onChange, required, setIsOpen]);
103
+ const getStringDateValue = (0, react_1.useCallback)(date => {
104
+ if (!date) return '';
105
+ if (mode === 'date') {
106
+ return date.toLocaleDateString(constants_1.DEFAULT_LOCALE);
107
+ }
108
+ return date.toLocaleString(constants_1.DEFAULT_LOCALE, {
109
+ year: 'numeric',
110
+ month: 'numeric',
111
+ day: 'numeric',
112
+ hour: '2-digit',
113
+ minute: '2-digit',
114
+ second: showSeconds ? '2-digit' : undefined
115
+ });
116
+ }, [mode, showSeconds]);
117
+ const valueToCopy = getStringDateValue(valueProp);
108
118
  const clearButtonSettings = (0, input_private_1.useClearButton)({
109
119
  clearButtonRef,
110
120
  showClearButton,
@@ -115,7 +125,7 @@ exports.FieldDate = (0, react_1.forwardRef)((_a, ref) => {
115
125
  copyButtonRef,
116
126
  showCopyButton,
117
127
  size,
118
- valueToCopy: valueProp || ''
128
+ valueToCopy
119
129
  });
120
130
  const calendarIcon = (0, react_1.useMemo)(() => ({
121
131
  active: false,
@@ -136,14 +146,16 @@ exports.FieldDate = (0, react_1.forwardRef)((_a, ref) => {
136
146
  handleBlur: dateInputBlurHandler,
137
147
  mask,
138
148
  setInputFocus
139
- } = (0, hooks_2.useDateField)({
149
+ } = (0, hooks_1.useDateField)({
140
150
  inputRef: localRef,
141
151
  onChange,
142
152
  readonly,
143
- locale,
144
- setIsOpen
153
+ locale: constants_1.DEFAULT_LOCALE,
154
+ setIsOpen,
155
+ mode,
156
+ showSeconds
145
157
  });
146
- const setInputFocusFromButtons = (0, react_1.useCallback)(() => setInputFocus(constants_2.SlotKey.Year), [setInputFocus]);
158
+ const setInputFocusFromButtons = (0, react_1.useCallback)(() => setInputFocus(mode === 'date' ? constants_1.SlotKey.Year : constants_1.SlotKey.Seconds), [mode, setInputFocus]);
147
159
  const {
148
160
  postfixButtons,
149
161
  inputTabIndex,
@@ -157,43 +169,46 @@ exports.FieldDate = (0, react_1.forwardRef)((_a, ref) => {
157
169
  readonly,
158
170
  submitKeys: ['Enter', 'Space', 'Tab']
159
171
  });
160
- // TODO: do not hardcode locale here
161
172
  const handleSelectDate = date => {
162
173
  var _a;
163
- onChange && onChange(date.toLocaleDateString(constants_2.DEFAULT_LOCALE));
174
+ onChange && onChange(date);
164
175
  (_a = localRef.current) === null || _a === void 0 ? void 0 : _a.focus();
165
176
  setIsOpen(false);
177
+ if (localRef.current) {
178
+ localRef.current.value = getStringDateValue(date);
179
+ }
166
180
  };
167
181
  const handleCalendarFocusLeave = () => {
168
182
  setInitialTabIndices();
169
183
  // TODO: find out why it works not as expected (focus is moved to the next element instead of the focused one)
170
184
  // maybe floating-ui causes the problem
171
185
  (0, input_private_1.runAfterRerender)(() => {
172
- setInputFocus(constants_2.SlotKey.Day);
186
+ setInputFocus(constants_1.SlotKey.Day);
173
187
  setIsOpen(false);
174
188
  });
175
189
  };
176
- const handleInputKeyDown = (0, useHandlers_1.useHandlers)([checkForLeavingFocus, dateInputKeyDownHandler, navigationInputKeyDownHandler]);
190
+ const handleInputKeyDown = (0, hooks_1.useHandlers)([checkForLeavingFocus, dateInputKeyDownHandler, navigationInputKeyDownHandler]);
177
191
  (0, react_1.useEffect)(() => {
178
192
  var _a;
179
193
  if (open) {
180
194
  (_a = localRef.current) === null || _a === void 0 ? void 0 : _a.focus();
181
195
  }
182
196
  }, [open]);
197
+ // TODO input ref - determine whether to update ref based on input/non-input state
183
198
  (0, react_1.useEffect)(() => {
184
- if (localRef.current) {
185
- localRef.current.value = valueProp;
199
+ if (localRef.current && document.activeElement !== localRef.current) {
200
+ localRef.current.value = getStringDateValue(valueProp);
186
201
  }
187
- }, [valueProp]);
202
+ }, [getStringDateValue, valueProp]);
188
203
  const onFocusByKeyboard = (0, react_1.useCallback)(e => {
189
204
  setInputFocus();
190
205
  onFocus === null || onFocus === void 0 ? void 0 : onFocus(e);
191
206
  }, [onFocus, setInputFocus]);
192
- const inputHandlers = (0, useFocusHandlers_1.useFocusHandlers)({
207
+ const inputHandlers = (0, hooks_1.useFocusHandlers)({
193
208
  onFocusByClick: onFocus,
194
209
  onFocusByKeyboard
195
210
  });
196
- const onBlur = (0, useHandlers_1.useHandlers)([dateInputBlurHandler, inputHandlers.onBlur, onBlurProp]);
211
+ const onBlur = (0, hooks_1.useHandlers)([dateInputBlurHandler, inputHandlers.onBlur, onBlurProp]);
197
212
  const onClick = (0, react_1.useCallback)(e => {
198
213
  dateInputClickHandler();
199
214
  if (isOpen) {
@@ -231,20 +246,17 @@ exports.FieldDate = (0, react_1.forwardRef)((_a, ref) => {
231
246
  className: styles_module_scss_1.default.calendarWrapper,
232
247
  "data-size": size,
233
248
  children: (0, jsx_runtime_1.jsx)(calendar_1.Calendar, {
234
- mode: 'date',
235
- size: CALENDAR_SIZE_MAP[size],
236
- value: valueProp ? (0, utils_2.parseDate)(valueProp) : undefined,
249
+ mode: mode,
250
+ size: size,
251
+ value: valueProp,
252
+ showSeconds: showSeconds,
237
253
  onChangeValue: handleSelectDate,
238
254
  buildCellProps: buildCellProps,
239
- navigationStartRef: element => {
240
- if (pickerAutofocus) {
241
- element === null || element === void 0 ? void 0 : element.focus();
242
- setPickerAutofocus(false);
243
- }
244
- },
255
+ navigationStartRef: navigationStartRef,
245
256
  onFocusLeave: handleCalendarFocusLeave,
246
- locale: locale,
247
- "data-test-id": 'field-date__calendar'
257
+ locale: constants_1.DEFAULT_LOCALE,
258
+ "data-test-id": 'field-date__calendar',
259
+ fitToContainer: false
248
260
  })
249
261
  }),
250
262
  children: (0, jsx_runtime_1.jsx)(helperComponents_1.FieldContainerPrivate, {
@@ -1,2 +1 @@
1
1
  export * from './FieldDate';
2
- export { parseDate } from './utils';
@@ -22,12 +22,4 @@ var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) {
22
22
  Object.defineProperty(exports, "__esModule", {
23
23
  value: true
24
24
  });
25
- exports.parseDate = void 0;
26
- __exportStar(require("./FieldDate"), exports);
27
- var utils_1 = require("./utils");
28
- Object.defineProperty(exports, "parseDate", {
29
- enumerable: true,
30
- get: function () {
31
- return utils_1.parseDate;
32
- }
33
- });
25
+ __exportStar(require("./FieldDate"), exports);
@@ -21,5 +21,5 @@ type FieldSecureOwnProps = {
21
21
  export type FieldSecureProps = WithSupportProps<FieldSecureOwnProps & InputProps & WrapperProps>;
22
22
  export declare const FieldSecure: import("react").ForwardRefExoticComponent<{
23
23
  'data-test-id'?: string;
24
- } & import("react").AriaAttributes & FieldSecureOwnProps & Pick<Partial<InputPrivateProps>, "value" | "onChange"> & Pick<InputPrivateProps, "onFocus" | "onBlur" | "id" | "disabled" | "readonly" | "name" | "placeholder" | "autoComplete" | "maxLength"> & WrapperProps & import("react").RefAttributes<HTMLInputElement>>;
24
+ } & import("react").AriaAttributes & FieldSecureOwnProps & Pick<Partial<InputPrivateProps>, "value" | "onChange"> & Pick<InputPrivateProps, "onFocus" | "onBlur" | "id" | "disabled" | "name" | "readonly" | "placeholder" | "autoComplete" | "maxLength"> & WrapperProps & import("react").RefAttributes<HTMLInputElement>>;
25
25
  export {};
@@ -27,9 +27,9 @@ export declare function useSearchInput({ value, onChange, defaultValue, selected
27
27
  resetSearchOnOptionSelection?: boolean;
28
28
  }): {
29
29
  inputValue: string;
30
- setInputValue: (value: any, ...args: any[]) => ReturnType<Handler> | void;
30
+ setInputValue: (value: string) => void;
31
31
  prevInputValue: import("react").MutableRefObject<string>;
32
- onInputValueChange: (value: any, ...args: any[]) => ReturnType<Handler> | void;
32
+ onInputValueChange: (value: string) => void;
33
33
  updateInputValue: (selectedItem?: ItemWithId) => void;
34
34
  };
35
35
  export declare function useHandleDeleteItem(setValue: Handler): (item?: ItemWithId) => (e?: MouseEvent<HTMLButtonElement>) => void;
@@ -94,7 +94,7 @@ function useSearchInput(_ref3) {
94
94
  selectedOptionFormatter,
95
95
  resetSearchOnOptionSelection = true
96
96
  } = _ref3;
97
- const [inputValue = '', setInputValue] = (0, hooks_1.useValueControl)({
97
+ const [inputValue = '', setInputValueState] = (0, hooks_1.useValueControl)({
98
98
  value,
99
99
  onChange,
100
100
  defaultValue
@@ -103,10 +103,14 @@ function useSearchInput(_ref3) {
103
103
  const updateInputValue = (0, react_1.useCallback)(selectedItem => {
104
104
  const newInputValue = selectedOptionFormatter(selectedItem);
105
105
  if (resetSearchOnOptionSelection && (inputValue !== newInputValue || prevInputValue.current !== newInputValue)) {
106
- setInputValue(newInputValue);
106
+ setInputValueState(newInputValue);
107
107
  prevInputValue.current = newInputValue;
108
108
  }
109
- }, [inputValue, resetSearchOnOptionSelection, selectedOptionFormatter, setInputValue]);
109
+ }, [inputValue, resetSearchOnOptionSelection, selectedOptionFormatter, setInputValueState]);
110
+ const setInputValue = (0, react_1.useCallback)(value => {
111
+ const updatedValue = prevInputValue.current && value.includes(prevInputValue.current) ? value.replace(prevInputValue.current, '') : value;
112
+ setInputValueState(updatedValue);
113
+ }, [setInputValueState]);
110
114
  return {
111
115
  inputValue,
112
116
  setInputValue,
@@ -23,5 +23,5 @@ type FieldSliderOwnProps = {
23
23
  export type FieldSliderProps = WithSupportProps<FieldSliderOwnProps & SliderProps & WrapperProps>;
24
24
  export declare const FieldSlider: import("react").ForwardRefExoticComponent<{
25
25
  'data-test-id'?: string;
26
- } & import("react").AriaAttributes & FieldSliderOwnProps & Pick<InputPrivateProps, "onFocus" | "onBlur" | "id" | "disabled" | "readonly" | "name"> & Pick<SliderComponentProps, "value" | "onChange" | "range" | "tipFormatter"> & Required<Pick<SliderComponentProps, "max" | "min" | "step" | "marks">> & WrapperProps & import("react").RefAttributes<HTMLInputElement>>;
26
+ } & import("react").AriaAttributes & FieldSliderOwnProps & Pick<InputPrivateProps, "onFocus" | "onBlur" | "id" | "disabled" | "name" | "readonly"> & Pick<SliderComponentProps, "value" | "onChange" | "range" | "tipFormatter"> & Required<Pick<SliderComponentProps, "max" | "min" | "step" | "marks">> & WrapperProps & import("react").RefAttributes<HTMLInputElement>>;
27
27
  export {};
@@ -27,5 +27,5 @@ type FieldTextOwnProps = {
27
27
  export type FieldTextProps = WithSupportProps<FieldTextOwnProps & InputProps & WrapperProps>;
28
28
  export declare const FieldText: import("react").ForwardRefExoticComponent<{
29
29
  'data-test-id'?: string;
30
- } & import("react").AriaAttributes & FieldTextOwnProps & Pick<Partial<InputPrivateProps>, "value" | "onChange"> & Pick<InputPrivateProps, "onFocus" | "onBlur" | "id" | "disabled" | "readonly" | "name" | "placeholder" | "autoComplete" | "maxLength"> & WrapperProps & import("react").RefAttributes<HTMLInputElement>>;
30
+ } & import("react").AriaAttributes & FieldTextOwnProps & Pick<Partial<InputPrivateProps>, "value" | "onChange"> & Pick<InputPrivateProps, "onFocus" | "onBlur" | "id" | "disabled" | "name" | "readonly" | "placeholder" | "autoComplete" | "maxLength"> & WrapperProps & import("react").RefAttributes<HTMLInputElement>>;
31
31
  export {};
@@ -26,5 +26,5 @@ type FieldTextAreaOwnProps = {
26
26
  export type FieldTextAreaProps = WithSupportProps<FieldTextAreaOwnProps & InputProps & WrapperProps>;
27
27
  export declare const FieldTextArea: import("react").ForwardRefExoticComponent<{
28
28
  'data-test-id'?: string;
29
- } & import("react").AriaAttributes & FieldTextAreaOwnProps & Pick<Partial<TextAreaProps>, "value"> & Pick<TextAreaProps, "onFocus" | "onBlur" | "id" | "disabled" | "readonly" | "name" | "placeholder" | "maxLength"> & WrapperProps & import("react").RefAttributes<HTMLTextAreaElement>>;
29
+ } & import("react").AriaAttributes & FieldTextAreaOwnProps & Pick<Partial<TextAreaProps>, "value"> & Pick<TextAreaProps, "onFocus" | "onBlur" | "id" | "disabled" | "name" | "readonly" | "placeholder" | "maxLength"> & WrapperProps & import("react").RefAttributes<HTMLTextAreaElement>>;
30
30
  export {};
@@ -0,0 +1,30 @@
1
+ import { TimePickerProps } from '@snack-uikit/calendar';
2
+ import { InputPrivateProps } from '@snack-uikit/input-private';
3
+ import { WithSupportProps } from '@snack-uikit/utils';
4
+ import { FieldDecoratorProps } from '../FieldDecorator';
5
+ type InputProps = Pick<InputPrivateProps, 'id' | 'name' | 'disabled' | 'readonly' | 'onFocus' | 'onBlur'>;
6
+ type WrapperProps = Pick<FieldDecoratorProps, 'className' | 'label' | 'labelTooltip' | 'required' | 'caption' | 'hint' | 'showHintIcon' | 'size' | 'validationState' | 'labelTooltipPlacement' | 'error'>;
7
+ type FieldTimeOwnProps = {
8
+ /** Открыт time-picker */
9
+ open?: boolean;
10
+ /** Колбек открытия пикера */
11
+ onOpenChange?(value: boolean): void;
12
+ /** Значение поля */
13
+ value?: TimePickerProps['value'];
14
+ /** Колбек смены значения */
15
+ onChange?: TimePickerProps['onChangeValue'];
16
+ /** Отображение кнопки копирования */
17
+ showCopyButton?: boolean;
18
+ /** Показывать ли секунды */
19
+ showSeconds?: boolean;
20
+ /**
21
+ * Отображение кнопки Очистки поля
22
+ * @default true
23
+ */
24
+ showClearButton?: boolean;
25
+ };
26
+ export type FieldTimeProps = WithSupportProps<FieldTimeOwnProps & InputProps & WrapperProps>;
27
+ export declare const FieldTime: import("react").ForwardRefExoticComponent<{
28
+ 'data-test-id'?: string;
29
+ } & import("react").AriaAttributes & FieldTimeOwnProps & InputProps & WrapperProps & import("react").RefAttributes<HTMLInputElement>>;
30
+ export {};
@@ -0,0 +1,298 @@
1
+ "use strict";
2
+
3
+ var __rest = void 0 && (void 0).__rest || function (s, e) {
4
+ var t = {};
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
8
+ }
9
+ return t;
10
+ };
11
+ var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
12
+ return mod && mod.__esModule ? mod : {
13
+ "default": mod
14
+ };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", {
17
+ value: true
18
+ });
19
+ exports.FieldTime = void 0;
20
+ const jsx_runtime_1 = require("react/jsx-runtime");
21
+ const merge_refs_1 = __importDefault(require("merge-refs"));
22
+ const react_1 = require("react");
23
+ const uncontrollable_1 = require("uncontrollable");
24
+ const calendar_1 = require("@snack-uikit/calendar");
25
+ const dropdown_1 = require("@snack-uikit/dropdown");
26
+ const icons_1 = require("@snack-uikit/icons");
27
+ const input_private_1 = require("@snack-uikit/input-private");
28
+ const utils_1 = require("@snack-uikit/utils");
29
+ const constants_1 = require("../../constants");
30
+ const helperComponents_1 = require("../../helperComponents");
31
+ const hooks_1 = require("../../hooks");
32
+ const getValidationState_1 = require("../../utils/getValidationState");
33
+ const FieldDecorator_1 = require("../FieldDecorator");
34
+ const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
35
+ const getStringTimeValue = (time, _ref) => {
36
+ let {
37
+ showSeconds,
38
+ locale
39
+ } = _ref;
40
+ var _a, _b, _c;
41
+ if (!time) {
42
+ return '';
43
+ }
44
+ const date = new Date();
45
+ date.setHours((_a = time.hours) !== null && _a !== void 0 ? _a : 0);
46
+ date.setMinutes((_b = time.minutes) !== null && _b !== void 0 ? _b : 0);
47
+ date.setSeconds((_c = time.seconds) !== null && _c !== void 0 ? _c : 0);
48
+ return date.toLocaleTimeString(locale, {
49
+ hour: 'numeric',
50
+ minute: 'numeric',
51
+ second: showSeconds ? 'numeric' : undefined
52
+ });
53
+ };
54
+ exports.FieldTime = (0, react_1.forwardRef)((_a, ref) => {
55
+ var {
56
+ id,
57
+ name,
58
+ value: valueProp,
59
+ disabled = false,
60
+ readonly = false,
61
+ showCopyButton: showCopyButtonProp = true,
62
+ showClearButton: showClearButtonProp = true,
63
+ open,
64
+ onOpenChange,
65
+ onChange,
66
+ onFocus,
67
+ onBlur: onBlurProp,
68
+ className,
69
+ label,
70
+ labelTooltip,
71
+ labelTooltipPlacement,
72
+ required = false,
73
+ caption,
74
+ hint,
75
+ showHintIcon,
76
+ showSeconds = true,
77
+ size = input_private_1.SIZE.S,
78
+ validationState = constants_1.VALIDATION_STATE.Default,
79
+ error
80
+ } = _a,
81
+ rest = __rest(_a, ["id", "name", "value", "disabled", "readonly", "showCopyButton", "showClearButton", "open", "onOpenChange", "onChange", "onFocus", "onBlur", "className", "label", "labelTooltip", "labelTooltipPlacement", "required", "caption", "hint", "showHintIcon", "showSeconds", "size", "validationState", "error"]);
82
+ const [isOpen, setIsOpen] = (0, uncontrollable_1.useUncontrolledProp)(open, false, onOpenChange);
83
+ const localRef = (0, react_1.useRef)(null);
84
+ const clearButtonRef = (0, react_1.useRef)(null);
85
+ const copyButtonRef = (0, react_1.useRef)(null);
86
+ const calendarIconSize = size === input_private_1.SIZE.S ? input_private_1.ICON_SIZE.Xs : input_private_1.ICON_SIZE.S;
87
+ const showDropList = isOpen && !readonly && !disabled;
88
+ const showAdditionalButton = Boolean(valueProp && !disabled);
89
+ const showClearButton = showClearButtonProp && showAdditionalButton && !readonly;
90
+ const showCopyButton = showCopyButtonProp && showAdditionalButton && readonly;
91
+ const fieldValidationState = (0, getValidationState_1.getValidationState)({
92
+ validationState,
93
+ error
94
+ });
95
+ const navigationStartRef = (0, react_1.useRef)(null);
96
+ const checkForLeavingFocus = (0, react_1.useCallback)(event => {
97
+ if (event.key === 'ArrowDown') {
98
+ setIsOpen(true);
99
+ setTimeout(() => {
100
+ var _a;
101
+ return (_a = navigationStartRef.current) === null || _a === void 0 ? void 0 : _a.focus();
102
+ }, 0);
103
+ }
104
+ }, [setIsOpen]);
105
+ const handleClear = (0, react_1.useCallback)(() => {
106
+ var _a, _b, _c;
107
+ onChange && onChange(undefined);
108
+ if ((_a = localRef.current) === null || _a === void 0 ? void 0 : _a.value) {
109
+ localRef.current.value = '';
110
+ }
111
+ if (required) {
112
+ (_b = localRef.current) === null || _b === void 0 ? void 0 : _b.focus();
113
+ setIsOpen(true);
114
+ } else {
115
+ (_c = localRef.current) === null || _c === void 0 ? void 0 : _c.blur();
116
+ setIsOpen(false);
117
+ }
118
+ }, [onChange, required, setIsOpen]);
119
+ const valueToCopy = getStringTimeValue(valueProp, {
120
+ showSeconds,
121
+ locale: constants_1.DEFAULT_LOCALE
122
+ });
123
+ const clearButtonSettings = (0, input_private_1.useClearButton)({
124
+ clearButtonRef,
125
+ showClearButton,
126
+ size,
127
+ onClear: handleClear
128
+ });
129
+ const copyButtonSettings = (0, hooks_1.useCopyButton)({
130
+ copyButtonRef,
131
+ showCopyButton,
132
+ size,
133
+ valueToCopy
134
+ });
135
+ const calendarIcon = (0, react_1.useMemo)(() => ({
136
+ active: false,
137
+ show: true,
138
+ id: 'watchIcon',
139
+ render: props => (0, jsx_runtime_1.jsx)(icons_1.WatchSVG, Object.assign({}, props, {
140
+ size: calendarIconSize,
141
+ className: styles_module_scss_1.default.calendarIcon,
142
+ "data-size": size
143
+ }))
144
+ }), [calendarIconSize, size]);
145
+ const memorizedButtons = (0, react_1.useMemo)(() => [clearButtonSettings, copyButtonSettings, calendarIcon], [clearButtonSettings, copyButtonSettings, calendarIcon]);
146
+ const {
147
+ value,
148
+ handleChange,
149
+ handleClick: timeInputClickHandler,
150
+ handleKeyDown: timeInputKeyDownHandler,
151
+ handleBlur: timeInputBlurHandler,
152
+ mask,
153
+ setInputFocus
154
+ } = (0, hooks_1.useDateField)({
155
+ inputRef: localRef,
156
+ onChange,
157
+ readonly,
158
+ locale: constants_1.DEFAULT_LOCALE,
159
+ setIsOpen,
160
+ mode: showSeconds ? constants_1.TIME_MODES.FullTime : constants_1.TIME_MODES.NoSeconds,
161
+ showSeconds
162
+ });
163
+ const setInputFocusFromButtons = (0, react_1.useCallback)(() => setInputFocus(constants_1.SlotKey.Seconds), [setInputFocus]);
164
+ const {
165
+ postfixButtons,
166
+ inputTabIndex,
167
+ onInputKeyDown: navigationInputKeyDownHandler,
168
+ setInitialTabIndices
169
+ } = (0, input_private_1.useButtonNavigation)({
170
+ setInputFocus: setInputFocusFromButtons,
171
+ inputRef: localRef,
172
+ postfixButtons: memorizedButtons,
173
+ onButtonKeyDown: checkForLeavingFocus,
174
+ readonly,
175
+ submitKeys: ['Enter', 'Space', 'Tab']
176
+ });
177
+ const handleSelectTime = time => {
178
+ var _a;
179
+ onChange && onChange(time);
180
+ (_a = localRef.current) === null || _a === void 0 ? void 0 : _a.focus();
181
+ setIsOpen(false);
182
+ if (localRef.current) {
183
+ localRef.current.value = getStringTimeValue(time, {
184
+ showSeconds,
185
+ locale: constants_1.DEFAULT_LOCALE
186
+ });
187
+ }
188
+ };
189
+ const handleCalendarFocusLeave = () => {
190
+ setInitialTabIndices();
191
+ // TODO: find out why it works not as expected (focus is moved to the next element instead of the focused one)
192
+ // maybe floating-ui causes the problem
193
+ (0, input_private_1.runAfterRerender)(() => {
194
+ setInputFocus(constants_1.SlotKey.Hours);
195
+ setIsOpen(false);
196
+ });
197
+ };
198
+ const handleInputKeyDown = (0, hooks_1.useHandlers)([checkForLeavingFocus, timeInputKeyDownHandler, navigationInputKeyDownHandler]);
199
+ (0, react_1.useEffect)(() => {
200
+ var _a;
201
+ if (open) {
202
+ (_a = localRef.current) === null || _a === void 0 ? void 0 : _a.focus();
203
+ }
204
+ }, [open]);
205
+ // TODO input ref - determine whether to update ref based on input/non-input state
206
+ (0, react_1.useEffect)(() => {
207
+ if (localRef.current && document.activeElement !== localRef.current) {
208
+ localRef.current.value = getStringTimeValue(valueProp, {
209
+ showSeconds,
210
+ locale: constants_1.DEFAULT_LOCALE
211
+ });
212
+ }
213
+ }, [showSeconds, valueProp]);
214
+ const onFocusByKeyboard = (0, react_1.useCallback)(e => {
215
+ setInputFocus();
216
+ onFocus === null || onFocus === void 0 ? void 0 : onFocus(e);
217
+ }, [onFocus, setInputFocus]);
218
+ const inputHandlers = (0, hooks_1.useFocusHandlers)({
219
+ onFocusByClick: onFocus,
220
+ onFocusByKeyboard
221
+ });
222
+ const onBlur = (0, hooks_1.useHandlers)([timeInputBlurHandler, inputHandlers.onBlur, onBlurProp]);
223
+ const onClick = (0, react_1.useCallback)(e => {
224
+ timeInputClickHandler();
225
+ if (isOpen) {
226
+ // stop the event because want picker to stay opened
227
+ e.stopPropagation();
228
+ }
229
+ }, [timeInputClickHandler, isOpen]);
230
+ return (0, jsx_runtime_1.jsx)(FieldDecorator_1.FieldDecorator, Object.assign({
231
+ className: className,
232
+ label: label,
233
+ labelTooltip: labelTooltip,
234
+ labelTooltipPlacement: labelTooltipPlacement,
235
+ labelFor: id,
236
+ required: required,
237
+ caption: caption,
238
+ hint: hint,
239
+ disabled: disabled,
240
+ readonly: readonly,
241
+ showHintIcon: showHintIcon,
242
+ size: size,
243
+ error: error,
244
+ validationState: fieldValidationState
245
+ }, (0, utils_1.extractSupportProps)(rest), {
246
+ children: (0, jsx_runtime_1.jsx)(dropdown_1.Dropdown, Object.assign({
247
+ trigger: 'click',
248
+ triggerClassName: styles_module_scss_1.default.triggerClassName,
249
+ widthStrategy: 'auto'
250
+ }, readonly || disabled ? {
251
+ open: false
252
+ } : {
253
+ open: showDropList,
254
+ onOpenChange: setIsOpen
255
+ }, {
256
+ content: (0, jsx_runtime_1.jsx)(calendar_1.TimePicker, {
257
+ size: size,
258
+ value: valueProp,
259
+ onChangeValue: handleSelectTime,
260
+ navigationStartRef: navigationStartRef,
261
+ onFocusLeave: handleCalendarFocusLeave,
262
+ "data-test-id": 'field-time__timepicker',
263
+ fitToContainer: false,
264
+ showSeconds: showSeconds
265
+ }),
266
+ children: (0, jsx_runtime_1.jsx)(helperComponents_1.FieldContainerPrivate, {
267
+ className: styles_module_scss_1.default.container,
268
+ size: size,
269
+ validationState: fieldValidationState,
270
+ disabled: disabled,
271
+ readonly: readonly,
272
+ variant: constants_1.CONTAINER_VARIANT.SingleLine,
273
+ focused: showDropList,
274
+ inputRef: localRef,
275
+ postfix: postfixButtons,
276
+ children: (0, jsx_runtime_1.jsx)(input_private_1.InputPrivate, {
277
+ ref: (0, merge_refs_1.default)(ref, localRef),
278
+ "data-size": size,
279
+ value: value || '',
280
+ placeholder: mask,
281
+ onChange: handleChange,
282
+ onFocus: inputHandlers.onFocus,
283
+ onMouseDown: inputHandlers.onMouseDown,
284
+ onBlur: onBlur,
285
+ onKeyDown: handleInputKeyDown,
286
+ onClick: onClick,
287
+ disabled: disabled,
288
+ readonly: readonly,
289
+ tabIndex: inputTabIndex,
290
+ type: 'text',
291
+ id: id,
292
+ name: name,
293
+ "data-test-id": 'field-time__input'
294
+ })
295
+ })
296
+ }))
297
+ }));
298
+ });
@@ -0,0 +1 @@
1
+ export * from './FieldTime';
@@ -22,4 +22,4 @@ var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) {
22
22
  Object.defineProperty(exports, "__esModule", {
23
23
  value: true
24
24
  });
25
- __exportStar(require("./useDateField"), exports);
25
+ __exportStar(require("./FieldTime"), exports);
@@ -0,0 +1,27 @@
1
+ .triggerClassName{
2
+ --offset:var(--space-drop-list-drop-offset, 4px);
3
+ display:block;
4
+ width:100%;
5
+ }
6
+
7
+ .container .calendarIcon{
8
+ color:var(--sys-neutral-text-light, #8b8e9b);
9
+ }
10
+ .container .calendarIcon[data-size=s]{
11
+ width:var(--size-icon-container-xs, 16px) !important;
12
+ height:var(--size-icon-container-xs, 16px) !important;
13
+ }
14
+ .container .calendarIcon[data-size=m]{
15
+ width:var(--size-icon-container-s, 24px) !important;
16
+ height:var(--size-icon-container-s, 24px) !important;
17
+ }
18
+ .container .calendarIcon[data-size=l]{
19
+ width:var(--size-icon-container-s, 24px) !important;
20
+ height:var(--size-icon-container-s, 24px) !important;
21
+ }
22
+ .container:hover .calendarIcon, .container:focus-within .calendarIcon, .container[data-focused] .calendarIcon{
23
+ color:var(--sys-neutral-text-support, #6d707f);
24
+ }
25
+ .container[data-disabled] .calendarIcon, .container[data-readonly] .calendarIcon{
26
+ color:var(--sys-neutral-text-disabled, #aaaebd);
27
+ }