@snack-uikit/fields 0.30.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 (150) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +184 -152
  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/FieldSelect/styles.module.css +6 -18
  11. package/dist/cjs/components/FieldSlider/FieldSlider.d.ts +1 -1
  12. package/dist/cjs/components/FieldText/FieldText.d.ts +1 -1
  13. package/dist/cjs/components/FieldTextArea/FieldTextArea.d.ts +1 -1
  14. package/dist/cjs/components/FieldTime/FieldTime.d.ts +30 -0
  15. package/dist/cjs/components/FieldTime/FieldTime.js +298 -0
  16. package/dist/cjs/components/FieldTime/index.d.ts +1 -0
  17. package/dist/cjs/components/{FieldDate/hooks → FieldTime}/index.js +1 -1
  18. package/dist/cjs/components/FieldTime/styles.module.css +27 -0
  19. package/dist/cjs/components/index.d.ts +6 -5
  20. package/dist/cjs/components/index.js +6 -5
  21. package/dist/cjs/constants/dateFields.d.ts +24 -0
  22. package/dist/cjs/constants/dateFields.js +152 -0
  23. package/dist/cjs/constants/index.d.ts +2 -0
  24. package/dist/cjs/constants/index.js +26 -0
  25. package/dist/cjs/hooks/dateHandlers/index.d.ts +3 -0
  26. package/dist/cjs/hooks/dateHandlers/index.js +27 -0
  27. package/dist/cjs/{components/FieldDate/hooks → hooks/dateHandlers}/useDateField.d.ts +13 -5
  28. package/dist/cjs/{components/FieldDate/hooks → hooks/dateHandlers}/useDateField.js +49 -34
  29. package/dist/cjs/hooks/dateHandlers/useDateFieldHelpersForMode.d.ts +18 -0
  30. package/dist/cjs/hooks/dateHandlers/useDateFieldHelpersForMode.js +113 -0
  31. package/dist/cjs/hooks/index.d.ts +1 -0
  32. package/dist/cjs/hooks/index.js +1 -0
  33. package/dist/cjs/hooks/useCopyButton.js +1 -1
  34. package/dist/cjs/{types.d.ts → types/allFields.d.ts} +1 -1
  35. package/dist/cjs/types/dateFields.d.ts +11 -0
  36. package/dist/cjs/types/index.d.ts +2 -0
  37. package/dist/cjs/types/index.js +26 -0
  38. package/dist/cjs/utils/dateFields.d.ts +10 -0
  39. package/dist/cjs/utils/dateFields.js +71 -0
  40. package/dist/esm/components/FieldDate/FieldDate.d.ts +15 -24
  41. package/dist/esm/components/FieldDate/FieldDate.js +39 -31
  42. package/dist/esm/components/FieldDate/index.d.ts +0 -1
  43. package/dist/esm/components/FieldDate/index.js +0 -1
  44. package/dist/esm/components/FieldSecure/FieldSecure.d.ts +1 -1
  45. package/dist/esm/components/FieldSelect/hooks.d.ts +2 -2
  46. package/dist/esm/components/FieldSelect/hooks.js +9 -3
  47. package/dist/esm/components/FieldSelect/styles.module.css +6 -18
  48. package/dist/esm/components/FieldSlider/FieldSlider.d.ts +1 -1
  49. package/dist/esm/components/FieldText/FieldText.d.ts +1 -1
  50. package/dist/esm/components/FieldTextArea/FieldTextArea.d.ts +1 -1
  51. package/dist/esm/components/FieldTime/FieldTime.d.ts +30 -0
  52. package/dist/esm/components/FieldTime/FieldTime.js +161 -0
  53. package/dist/esm/components/FieldTime/index.d.ts +1 -0
  54. package/dist/esm/components/FieldTime/index.js +1 -0
  55. package/dist/esm/components/FieldTime/styles.module.css +27 -0
  56. package/dist/esm/components/index.d.ts +6 -5
  57. package/dist/esm/components/index.js +6 -5
  58. package/dist/esm/constants/dateFields.d.ts +24 -0
  59. package/dist/esm/constants/dateFields.js +103 -0
  60. package/dist/esm/constants/index.d.ts +2 -0
  61. package/dist/esm/constants/index.js +2 -0
  62. package/dist/esm/hooks/dateHandlers/index.d.ts +3 -0
  63. package/dist/esm/hooks/dateHandlers/index.js +3 -0
  64. package/dist/esm/{components/FieldDate/hooks → hooks/dateHandlers}/useDateField.d.ts +13 -5
  65. package/dist/esm/{components/FieldDate/hooks → hooks/dateHandlers}/useDateField.js +48 -35
  66. package/dist/esm/hooks/dateHandlers/useDateFieldHelpersForMode.d.ts +18 -0
  67. package/dist/esm/hooks/dateHandlers/useDateFieldHelpersForMode.js +95 -0
  68. package/dist/esm/hooks/index.d.ts +1 -0
  69. package/dist/esm/hooks/index.js +1 -0
  70. package/dist/esm/hooks/useCopyButton.js +1 -1
  71. package/dist/esm/{types.d.ts → types/allFields.d.ts} +1 -1
  72. package/dist/esm/types/dateFields.d.ts +11 -0
  73. package/dist/esm/types/index.d.ts +2 -0
  74. package/dist/esm/types/index.js +2 -0
  75. package/dist/esm/utils/dateFields.d.ts +10 -0
  76. package/dist/esm/utils/dateFields.js +59 -0
  77. package/package.json +16 -16
  78. package/src/components/FieldColor/styles.module.scss +9 -10
  79. package/src/components/FieldDate/FieldDate.tsx +72 -52
  80. package/src/components/FieldDate/index.ts +0 -1
  81. package/src/components/FieldDate/styles.module.scss +10 -11
  82. package/src/components/FieldDecorator/styles.module.scss +44 -45
  83. package/src/components/FieldSelect/hooks.ts +15 -3
  84. package/src/components/FieldSelect/styles.module.scss +20 -20
  85. package/src/components/FieldSlider/styles.module.scss +4 -4
  86. package/src/components/FieldTextArea/styles.module.scss +18 -18
  87. package/src/components/FieldTime/FieldTime.tsx +350 -0
  88. package/src/components/FieldTime/index.ts +1 -0
  89. package/src/components/FieldTime/styles.module.scss +41 -0
  90. package/src/components/index.ts +6 -5
  91. package/src/constants/dateFields.ts +127 -0
  92. package/src/constants/index.ts +2 -0
  93. package/src/helperComponents/ButtonCopyValue/styles.module.scss +2 -2
  94. package/src/helperComponents/ButtonField/styles.module.scss +9 -9
  95. package/src/helperComponents/ButtonFieldList/styles.module.scss +2 -2
  96. package/src/helperComponents/ButtonHideValue/styles.module.scss +2 -2
  97. package/src/helperComponents/FieldContainerPrivate/styles.module.scss +24 -26
  98. package/src/helperComponents/TextArea/styles.module.scss +5 -5
  99. package/src/hooks/dateHandlers/index.ts +3 -0
  100. package/src/{components/FieldDate/hooks → hooks/dateHandlers}/useDateField.ts +93 -47
  101. package/src/hooks/dateHandlers/useDateFieldHelpersForMode.ts +145 -0
  102. package/src/hooks/index.ts +1 -0
  103. package/src/hooks/styles.module.scss +5 -5
  104. package/src/hooks/useCopyButton.tsx +1 -1
  105. package/src/styles.module.scss +15 -15
  106. package/src/{types.ts → types/allFields.ts} +1 -1
  107. package/src/types/dateFields.ts +14 -0
  108. package/src/types/index.ts +2 -0
  109. package/src/utils/dateFields.ts +75 -0
  110. package/dist/cjs/components/FieldDate/constants.d.ts +0 -10
  111. package/dist/cjs/components/FieldDate/constants.js +0 -49
  112. package/dist/cjs/components/FieldDate/hooks/index.d.ts +0 -1
  113. package/dist/cjs/components/FieldDate/hooks/useDateFieldHelpers.d.ts +0 -10
  114. package/dist/cjs/components/FieldDate/hooks/useDateFieldHelpers.js +0 -82
  115. package/dist/cjs/components/FieldDate/types.d.ts +0 -6
  116. package/dist/cjs/components/FieldDate/utils.d.ts +0 -9
  117. package/dist/cjs/components/FieldDate/utils.js +0 -56
  118. package/dist/esm/components/FieldDate/constants.d.ts +0 -10
  119. package/dist/esm/components/FieldDate/constants.js +0 -28
  120. package/dist/esm/components/FieldDate/hooks/index.d.ts +0 -1
  121. package/dist/esm/components/FieldDate/hooks/index.js +0 -1
  122. package/dist/esm/components/FieldDate/hooks/useDateFieldHelpers.d.ts +0 -10
  123. package/dist/esm/components/FieldDate/hooks/useDateFieldHelpers.js +0 -66
  124. package/dist/esm/components/FieldDate/types.d.ts +0 -6
  125. package/dist/esm/components/FieldDate/utils.d.ts +0 -9
  126. package/dist/esm/components/FieldDate/utils.js +0 -43
  127. package/src/components/FieldDate/constants.ts +0 -33
  128. package/src/components/FieldDate/hooks/index.ts +0 -1
  129. package/src/components/FieldDate/hooks/useDateFieldHelpers.ts +0 -96
  130. package/src/components/FieldDate/types.ts +0 -6
  131. package/src/components/FieldDate/utils.ts +0 -49
  132. /package/dist/cjs/{constants.d.ts → constants/allFields.d.ts} +0 -0
  133. /package/dist/cjs/{constants.js → constants/allFields.js} +0 -0
  134. /package/dist/cjs/{components/FieldDate/hooks → hooks/dateHandlers}/useFocusHandlers.d.ts +0 -0
  135. /package/dist/cjs/{components/FieldDate/hooks → hooks/dateHandlers}/useFocusHandlers.js +0 -0
  136. /package/dist/cjs/{components/FieldDate/hooks → hooks/dateHandlers}/useHandlers.d.ts +0 -0
  137. /package/dist/cjs/{components/FieldDate/hooks → hooks/dateHandlers}/useHandlers.js +0 -0
  138. /package/dist/cjs/{components/FieldDate/types.js → types/allFields.js} +0 -0
  139. /package/dist/cjs/{types.js → types/dateFields.js} +0 -0
  140. /package/dist/esm/{constants.d.ts → constants/allFields.d.ts} +0 -0
  141. /package/dist/esm/{constants.js → constants/allFields.js} +0 -0
  142. /package/dist/esm/{components/FieldDate/hooks → hooks/dateHandlers}/useFocusHandlers.d.ts +0 -0
  143. /package/dist/esm/{components/FieldDate/hooks → hooks/dateHandlers}/useFocusHandlers.js +0 -0
  144. /package/dist/esm/{components/FieldDate/hooks → hooks/dateHandlers}/useHandlers.d.ts +0 -0
  145. /package/dist/esm/{components/FieldDate/hooks → hooks/dateHandlers}/useHandlers.js +0 -0
  146. /package/dist/esm/{components/FieldDate/types.js → types/allFields.js} +0 -0
  147. /package/dist/esm/{types.js → types/dateFields.js} +0 -0
  148. /package/src/{constants.ts → constants/allFields.ts} +0 -0
  149. /package/src/{components/FieldDate/hooks → hooks/dateHandlers}/useFocusHandlers.ts +0 -0
  150. /package/src/{components/FieldDate/hooks → hooks/dateHandlers}/useHandlers.ts +0 -0
@@ -1,15 +1,14 @@
1
- @import '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-element';
2
- @import '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-fields';
1
+ @use '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-element';
3
2
 
4
3
  $sizes: 's', 'm', 'l';
5
4
  $icons-sizes: (
6
- 's': $icon-xs,
7
- 'm': $icon-s,
8
- 'l': $icon-s,
5
+ 's': styles-tokens-element.$icon-xs,
6
+ 'm': styles-tokens-element.$icon-s,
7
+ 'l': styles-tokens-element.$icon-s,
9
8
  );
10
9
 
11
10
  .triggerClassName {
12
- --offset: #{$space-drop-list-drop-offset};
11
+ --offset: #{styles-tokens-element.$space-drop-list-drop-offset};
13
12
 
14
13
  display: block;
15
14
  width: 100%;
@@ -18,12 +17,12 @@ $icons-sizes: (
18
17
  .colorPreview {
19
18
  position: relative;
20
19
 
21
- width: $dimension-2m;
22
- height: $dimension-2m;
20
+ width: styles-tokens-element.$dimension-2m;
21
+ height: styles-tokens-element.$dimension-2m;
23
22
 
24
23
  /* stylelint-disable-next-line color-no-hex */
25
24
  background-color: #fff;
26
- border-radius: $dimension-050m;
25
+ border-radius: styles-tokens-element.$dimension-050m;
27
26
 
28
27
  &::after {
29
28
  content: '';
@@ -36,6 +35,6 @@ $icons-sizes: (
36
35
  height: 100%;
37
36
 
38
37
  background-color: var(--color);
39
- border-radius: $dimension-050m;
38
+ border-radius: styles-tokens-element.$dimension-050m;
40
39
  }
41
40
  }
@@ -1,15 +1,5 @@
1
1
  import mergeRefs from 'merge-refs';
2
- import {
3
- FocusEvent,
4
- forwardRef,
5
- KeyboardEvent,
6
- MouseEvent,
7
- useCallback,
8
- useEffect,
9
- useMemo,
10
- useRef,
11
- useState,
12
- } from 'react';
2
+ import { FocusEvent, forwardRef, KeyboardEvent, MouseEvent, useCallback, useEffect, useMemo, useRef } from 'react';
13
3
  import { useUncontrolledProp } from 'uncontrollable';
14
4
 
15
5
  import { Calendar, CalendarProps } from '@snack-uikit/calendar';
@@ -22,25 +12,20 @@ import {
22
12
  InputPrivateProps,
23
13
  runAfterRerender,
24
14
  SIZE,
25
- Size,
26
15
  useButtonNavigation,
27
16
  useClearButton,
28
17
  } from '@snack-uikit/input-private';
29
18
  import { extractSupportProps, WithSupportProps } from '@snack-uikit/utils';
30
19
 
31
- import { CONTAINER_VARIANT, VALIDATION_STATE } from '../../constants';
20
+ import { CONTAINER_VARIANT, DEFAULT_LOCALE, MODES, SlotKey, VALIDATION_STATE } from '../../constants';
32
21
  import { FieldContainerPrivate } from '../../helperComponents';
33
- import { useCopyButton } from '../../hooks';
22
+ import { useCopyButton, useDateField, useFocusHandlers, useHandlers } from '../../hooks';
23
+ import { Mode } from '../../types';
34
24
  import { getValidationState } from '../../utils/getValidationState';
35
25
  import { FieldDecorator, FieldDecoratorProps } from '../FieldDecorator';
36
- import { DEFAULT_LOCALE, SlotKey } from './constants';
37
- import { useDateField } from './hooks';
38
- import { useFocusHandlers } from './hooks/useFocusHandlers';
39
- import { useHandlers } from './hooks/useHandlers';
40
26
  import styles from './styles.module.scss';
41
- import { parseDate } from './utils';
42
27
 
43
- type InputProps = Pick<InputPrivateProps, 'id' | 'name' | 'value' | 'disabled' | 'readonly' | 'onFocus' | 'onBlur'>;
28
+ type InputProps = Pick<InputPrivateProps, 'id' | 'name' | 'disabled' | 'readonly' | 'onFocus' | 'onBlur'>;
44
29
 
45
30
  type WrapperProps = Pick<
46
31
  FieldDecoratorProps,
@@ -57,13 +42,20 @@ type WrapperProps = Pick<
57
42
  | 'error'
58
43
  >;
59
44
 
45
+ type FieldDateWithSeconds = {
46
+ mode: typeof MODES.DateTime;
47
+ showSeconds?: boolean;
48
+ };
49
+
60
50
  type FieldDateOwnProps = {
61
51
  /** Открыт date-picker */
62
52
  open?: boolean;
63
53
  /** Колбек открытия пикера */
64
54
  onOpenChange?(value: boolean): void;
55
+ /** Значение поля */
56
+ value?: Date;
65
57
  /** Колбек смены значения */
66
- onChange?(value: string): void;
58
+ onChange?(value: Date | undefined): void;
67
59
  /** Отображение кнопки копирования */
68
60
  showCopyButton?: boolean;
69
61
  /**
@@ -71,18 +63,17 @@ type FieldDateOwnProps = {
71
63
  * @default true
72
64
  */
73
65
  showClearButton?: boolean;
74
- /** Текущая локаль календаря */
75
- locale?: Intl.Locale;
76
- } & Pick<CalendarProps, 'buildCellProps'>;
66
+ mode: Mode;
67
+ } & Pick<CalendarProps, 'buildCellProps'> &
68
+ (
69
+ | {
70
+ mode: typeof MODES.Date;
71
+ }
72
+ | FieldDateWithSeconds
73
+ );
77
74
 
78
75
  export type FieldDateProps = WithSupportProps<FieldDateOwnProps & InputProps & WrapperProps>;
79
76
 
80
- const CALENDAR_SIZE_MAP: Record<Size, CalendarProps['size']> = {
81
- [SIZE.S]: 's',
82
- [SIZE.M]: 'm',
83
- [SIZE.L]: 'm',
84
- };
85
-
86
77
  export const FieldDate = forwardRef<HTMLInputElement, FieldDateProps>(
87
78
  (
88
79
  {
@@ -108,15 +99,14 @@ export const FieldDate = forwardRef<HTMLInputElement, FieldDateProps>(
108
99
  showHintIcon,
109
100
  size = SIZE.S,
110
101
  validationState = VALIDATION_STATE.Default,
111
- locale = DEFAULT_LOCALE,
112
102
  buildCellProps,
113
103
  error,
104
+ mode,
114
105
  ...rest
115
106
  },
116
107
  ref,
117
108
  ) => {
118
109
  const [isOpen, setIsOpen] = useUncontrolledProp(open, false, onOpenChange);
119
- const [pickerAutofocus, setPickerAutofocus] = useState(false);
120
110
 
121
111
  const localRef = useRef<HTMLInputElement>(null);
122
112
  const clearButtonRef = useRef<HTMLButtonElement>(null);
@@ -126,20 +116,23 @@ export const FieldDate = forwardRef<HTMLInputElement, FieldDateProps>(
126
116
  const showAdditionalButton = Boolean(valueProp && !disabled);
127
117
  const showClearButton = showClearButtonProp && showAdditionalButton && !readonly;
128
118
  const showCopyButton = showCopyButtonProp && showAdditionalButton && readonly;
119
+ const showSeconds = mode === 'date-time' ? ((rest as FieldDateWithSeconds).showSeconds ?? true) : undefined;
129
120
  const fieldValidationState = getValidationState({ validationState, error });
130
121
 
122
+ const navigationStartRef: CalendarProps['navigationStartRef'] = useRef(null);
123
+
131
124
  const checkForLeavingFocus = useCallback(
132
125
  <T extends HTMLInputElement | HTMLButtonElement>(event: KeyboardEvent<T>) => {
133
126
  if (event.key === 'ArrowDown') {
134
- setPickerAutofocus(true);
135
127
  setIsOpen(true);
128
+ setTimeout(() => navigationStartRef.current?.focus(), 0);
136
129
  }
137
130
  },
138
131
  [setIsOpen],
139
132
  );
140
133
 
141
134
  const handleClear = useCallback(() => {
142
- onChange && onChange('');
135
+ onChange && onChange(undefined);
143
136
  if (localRef.current?.value) {
144
137
  localRef.current.value = '';
145
138
  }
@@ -153,8 +146,29 @@ export const FieldDate = forwardRef<HTMLInputElement, FieldDateProps>(
153
146
  }
154
147
  }, [onChange, required, setIsOpen]);
155
148
 
149
+ const getStringDateValue = useCallback(
150
+ (date: Date | undefined) => {
151
+ if (!date) return '';
152
+
153
+ if (mode === 'date') {
154
+ return date.toLocaleDateString(DEFAULT_LOCALE);
155
+ }
156
+
157
+ return date.toLocaleString(DEFAULT_LOCALE, {
158
+ year: 'numeric',
159
+ month: 'numeric',
160
+ day: 'numeric',
161
+ hour: '2-digit',
162
+ minute: '2-digit',
163
+ second: showSeconds ? '2-digit' : undefined,
164
+ });
165
+ },
166
+ [mode, showSeconds],
167
+ );
168
+
169
+ const valueToCopy = getStringDateValue(valueProp);
156
170
  const clearButtonSettings = useClearButton({ clearButtonRef, showClearButton, size, onClear: handleClear });
157
- const copyButtonSettings = useCopyButton({ copyButtonRef, showCopyButton, size, valueToCopy: valueProp || '' });
171
+ const copyButtonSettings = useCopyButton({ copyButtonRef, showCopyButton, size, valueToCopy });
158
172
  const calendarIcon: ButtonProps = useMemo(
159
173
  () => ({
160
174
  active: false,
@@ -184,11 +198,16 @@ export const FieldDate = forwardRef<HTMLInputElement, FieldDateProps>(
184
198
  inputRef: localRef,
185
199
  onChange,
186
200
  readonly,
187
- locale,
201
+ locale: DEFAULT_LOCALE,
188
202
  setIsOpen,
203
+ mode,
204
+ showSeconds,
189
205
  });
190
206
 
191
- const setInputFocusFromButtons = useCallback(() => setInputFocus(SlotKey.Year), [setInputFocus]);
207
+ const setInputFocusFromButtons = useCallback(
208
+ () => setInputFocus(mode === 'date' ? SlotKey.Year : SlotKey.Seconds),
209
+ [mode, setInputFocus],
210
+ );
192
211
 
193
212
  const {
194
213
  postfixButtons,
@@ -204,11 +223,14 @@ export const FieldDate = forwardRef<HTMLInputElement, FieldDateProps>(
204
223
  submitKeys: ['Enter', 'Space', 'Tab'],
205
224
  });
206
225
 
207
- // TODO: do not hardcode locale here
208
226
  const handleSelectDate = (date: Date) => {
209
- onChange && onChange(date.toLocaleDateString(DEFAULT_LOCALE));
227
+ onChange && onChange(date);
210
228
  localRef.current?.focus();
211
229
  setIsOpen(false);
230
+
231
+ if (localRef.current) {
232
+ localRef.current.value = getStringDateValue(date);
233
+ }
212
234
  };
213
235
 
214
236
  const handleCalendarFocusLeave: CalendarProps['onFocusLeave'] = () => {
@@ -233,11 +255,12 @@ export const FieldDate = forwardRef<HTMLInputElement, FieldDateProps>(
233
255
  }
234
256
  }, [open]);
235
257
 
258
+ // TODO input ref - determine whether to update ref based on input/non-input state
236
259
  useEffect(() => {
237
- if (localRef.current) {
238
- localRef.current.value = valueProp;
260
+ if (localRef.current && document.activeElement !== localRef.current) {
261
+ localRef.current.value = getStringDateValue(valueProp);
239
262
  }
240
- }, [valueProp]);
263
+ }, [getStringDateValue, valueProp]);
241
264
 
242
265
  const onFocusByKeyboard = useCallback(
243
266
  (e: FocusEvent<HTMLInputElement>) => {
@@ -296,20 +319,17 @@ export const FieldDate = forwardRef<HTMLInputElement, FieldDateProps>(
296
319
  content={
297
320
  <div className={styles.calendarWrapper} data-size={size}>
298
321
  <Calendar
299
- mode='date'
300
- size={CALENDAR_SIZE_MAP[size]}
301
- value={valueProp ? parseDate(valueProp) : undefined}
322
+ mode={mode}
323
+ size={size}
324
+ value={valueProp}
325
+ showSeconds={showSeconds}
302
326
  onChangeValue={handleSelectDate}
303
327
  buildCellProps={buildCellProps}
304
- navigationStartRef={element => {
305
- if (pickerAutofocus) {
306
- element?.focus();
307
- setPickerAutofocus(false);
308
- }
309
- }}
328
+ navigationStartRef={navigationStartRef}
310
329
  onFocusLeave={handleCalendarFocusLeave}
311
- locale={locale}
330
+ locale={DEFAULT_LOCALE}
312
331
  data-test-id='field-date__calendar'
332
+ fitToContainer={false}
313
333
  />
314
334
  </div>
315
335
  }
@@ -1,2 +1 @@
1
1
  export * from './FieldDate';
2
- export { parseDate } from './utils';
@@ -1,15 +1,14 @@
1
- @import '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-element';
2
- @import '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-fields';
1
+ @use '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-element';
3
2
 
4
3
  $sizes: 's', 'm', 'l';
5
4
  $icons-sizes: (
6
- 's': $icon-xs,
7
- 'm': $icon-s,
8
- 'l': $icon-s
5
+ 's': styles-tokens-element.$icon-xs,
6
+ 'm': styles-tokens-element.$icon-s,
7
+ 'l': styles-tokens-element.$icon-s
9
8
  );
10
9
 
11
10
  .triggerClassName {
12
- --offset: #{$space-drop-list-drop-offset};
11
+ --offset: #{styles-tokens-element.$space-drop-list-drop-offset};
13
12
 
14
13
  display: block;
15
14
  width: 100%;
@@ -35,25 +34,25 @@ $icons-sizes: (
35
34
 
36
35
  .container {
37
36
  .calendarIcon {
38
- color: $sys-neutral-text-light;
37
+ color: styles-tokens-element.$sys-neutral-text-light;
39
38
 
40
39
  @each $size in $sizes {
41
40
  &[data-size='#{$size}'] {
42
- width: simple-var($icons-sizes, $size) !important; /* stylelint-disable-line declaration-no-important */
43
- height: simple-var($icons-sizes, $size) !important; /* stylelint-disable-line declaration-no-important */
41
+ width: styles-tokens-element.simple-var($icons-sizes, $size) !important; /* stylelint-disable-line declaration-no-important */
42
+ height: styles-tokens-element.simple-var($icons-sizes, $size) !important; /* stylelint-disable-line declaration-no-important */
44
43
  }
45
44
  }
46
45
  }
47
46
 
48
47
  &:hover, &:focus-within, &[data-focused] {
49
48
  .calendarIcon {
50
- color: $sys-neutral-text-support;
49
+ color: styles-tokens-element.$sys-neutral-text-support;
51
50
  }
52
51
  }
53
52
 
54
53
  &[data-disabled], &[data-readonly] {
55
54
  .calendarIcon {
56
- color: $sys-neutral-text-disabled;
55
+ color: styles-tokens-element.$sys-neutral-text-disabled;
57
56
  }
58
57
  }
59
58
  }
@@ -1,26 +1,25 @@
1
- @import '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-fields';
2
- @import '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-element';
1
+ @use '@snack-uikit/figma-tokens/build/scss/components/styles-tokens-fields';
3
2
 
4
3
  $sizes: 's', 'm', 'l';
5
4
  $header-typography: (
6
- 's': $sans-label-m,
7
- 'm': $sans-label-l,
8
- 'l': $sans-label-l,
5
+ 's': styles-tokens-fields.$sans-label-m,
6
+ 'm': styles-tokens-fields.$sans-label-l,
7
+ 'l': styles-tokens-fields.$sans-label-l,
9
8
  );
10
9
  $footer-typography: (
11
- 's': $sans-body-s,
12
- 'm': $sans-body-m,
13
- 'l': $sans-body-m,
10
+ 's': styles-tokens-fields.$sans-body-s,
11
+ 'm': styles-tokens-fields.$sans-body-m,
12
+ 'l': styles-tokens-fields.$sans-body-m,
14
13
  );
15
14
  $hint-icon-container: (
16
- 's': $fields-hint-icon-container-s,
17
- 'm': $fields-hint-icon-container-m,
18
- 'l': $fields-hint-icon-container-m,
15
+ 's': styles-tokens-fields.$fields-hint-icon-container-s,
16
+ 'm': styles-tokens-fields.$fields-hint-icon-container-m,
17
+ 'l': styles-tokens-fields.$fields-hint-icon-container-m,
19
18
  );
20
19
  $caption-typography: (
21
- 's': $sans-body-s,
22
- 'm': $sans-body-m,
23
- 'l': $sans-body-m,
20
+ 's': styles-tokens-fields.$sans-body-s,
21
+ 'm': styles-tokens-fields.$sans-body-m,
22
+ 'l': styles-tokens-fields.$sans-body-m,
24
23
  );
25
24
 
26
25
  .decorator {
@@ -33,50 +32,50 @@ $caption-typography: (
33
32
 
34
33
  @each $size in $sizes {
35
34
  &[data-size='#{$size}'] {
36
- @include composite-var($fields, 'decorator', $size);
35
+ @include styles-tokens-fields.composite-var(styles-tokens-fields.$fields, 'decorator', $size);
37
36
  }
38
37
  }
39
38
  }
40
39
 
41
40
  .header {
42
41
  display: flex;
43
- gap: $dimension-050m;
42
+ gap: styles-tokens-fields.$dimension-050m;
44
43
  box-sizing: border-box;
45
- color: $sys-neutral-text-support;
44
+ color: styles-tokens-fields.$sys-neutral-text-support;
46
45
 
47
46
  @each $size in $sizes {
48
47
  &[data-size='#{$size}'] {
49
- @include composite-var($header-typography, $size);
48
+ @include styles-tokens-fields.composite-var($header-typography, $size);
50
49
 
51
50
  .caption {
52
- @include composite-var($caption-typography, $size);
51
+ @include styles-tokens-fields.composite-var($caption-typography, $size);
53
52
 
54
53
  margin-left: auto;
55
- color: $sys-neutral-text-light;
54
+ color: styles-tokens-fields.$sys-neutral-text-light;
56
55
  }
57
56
  }
58
57
  }
59
58
  }
60
59
 
61
60
  .labelLayout {
62
- @include composite-var($fields-label-label-layout);
61
+ @include styles-tokens-fields.composite-var(styles-tokens-fields.$fields-label-label-layout);
63
62
 
64
63
  display: inline-flex;
65
64
  align-items: center;
66
- color: $sys-neutral-text-light;
65
+ color: styles-tokens-fields.$sys-neutral-text-light;
67
66
  }
68
67
 
69
68
  .label {
70
69
  display: grid;
71
- color: $sys-neutral-text-support;
70
+ color: styles-tokens-fields.$sys-neutral-text-support;
72
71
  }
73
72
 
74
73
  .required {
75
- color: $sys-neutral-text-support;
74
+ color: styles-tokens-fields.$sys-neutral-text-support;
76
75
  }
77
76
 
78
77
  .footer {
79
- @include composite-var($fields-hint-container);
78
+ @include styles-tokens-fields.composite-var(styles-tokens-fields.$fields-hint-container);
80
79
 
81
80
  display: flex;
82
81
  justify-content: space-between;
@@ -84,7 +83,7 @@ $caption-typography: (
84
83
 
85
84
  @each $size in $sizes {
86
85
  &[data-size='#{$size}'] {
87
- @include composite-var($footer-typography, $size);
86
+ @include styles-tokens-fields.composite-var($footer-typography, $size);
88
87
  }
89
88
  }
90
89
 
@@ -94,7 +93,7 @@ $caption-typography: (
94
93
  }
95
94
 
96
95
  .hintLayout {
97
- @include composite-var($fields-hint-hint-layout);
96
+ @include styles-tokens-fields.composite-var(styles-tokens-fields.$fields-hint-hint-layout);
98
97
 
99
98
  display: inline-flex;
100
99
  align-items: flex-start;
@@ -108,7 +107,7 @@ $caption-typography: (
108
107
 
109
108
  @each $size in $sizes {
110
109
  &[data-size='#{$size}'] {
111
- @include composite-var($hint-icon-container, $size);
110
+ @include styles-tokens-fields.composite-var($hint-icon-container, $size);
112
111
  }
113
112
  }
114
113
  }
@@ -119,26 +118,26 @@ $caption-typography: (
119
118
  word-break: break-word;
120
119
 
121
120
  &[data-validation='default'] {
122
- color: $sys-neutral-text-light;
121
+ color: styles-tokens-fields.$sys-neutral-text-light;
123
122
  }
124
123
 
125
124
  &[data-validation='error'] {
126
- color: $sys-red-text-main;
125
+ color: styles-tokens-fields.$sys-red-text-main;
127
126
  }
128
127
 
129
128
  &[data-validation='warning'] {
130
- color: $sys-yellow-text-main;
129
+ color: styles-tokens-fields.$sys-yellow-text-main;
131
130
  }
132
131
 
133
132
  &[data-validation='success'] {
134
- color: $sys-green-text-main;
133
+ color: styles-tokens-fields.$sys-green-text-main;
135
134
  }
136
135
  }
137
136
 
138
137
  .icon {
139
138
  flex-shrink: 0;
140
139
  box-sizing: content-box;
141
- color: $sys-neutral-text-light;
140
+ color: styles-tokens-fields.$sys-neutral-text-light;
142
141
  }
143
142
 
144
143
  .hintIcon {
@@ -146,39 +145,39 @@ $caption-typography: (
146
145
  box-sizing: content-box;
147
146
 
148
147
  &[data-validation='default'] {
149
- color: $sys-neutral-accent-default;
148
+ color: styles-tokens-fields.$sys-neutral-accent-default;
150
149
  }
151
150
 
152
151
  &[data-validation='error'] {
153
- color: $sys-red-accent-default;
152
+ color: styles-tokens-fields.$sys-red-accent-default;
154
153
  }
155
154
 
156
155
  &[data-validation='warning'] {
157
- color: $sys-yellow-accent-default;
156
+ color: styles-tokens-fields.$sys-yellow-accent-default;
158
157
  }
159
158
 
160
159
  &[data-validation='success'] {
161
- color: $sys-green-accent-default;
160
+ color: styles-tokens-fields.$sys-green-accent-default;
162
161
  }
163
162
  }
164
163
 
165
164
  .counterLimit {
166
165
  > span {
167
166
  &[data-validation='default'] {
168
- color: $sys-neutral-text-light;
167
+ color: styles-tokens-fields.$sys-neutral-text-light;
169
168
  }
170
169
 
171
170
  &[data-limit-exceeded],
172
171
  &[data-validation='error'] {
173
- color: $sys-red-text-light;
172
+ color: styles-tokens-fields.$sys-red-text-light;
174
173
  }
175
174
 
176
175
  &[data-validation='warning'] {
177
- color: $sys-yellow-text-light;
176
+ color: styles-tokens-fields.$sys-yellow-text-light;
178
177
  }
179
178
 
180
179
  &[data-validation='success'] {
181
- color: $sys-green-text-light;
180
+ color: styles-tokens-fields.$sys-green-text-light;
182
181
  }
183
182
  }
184
183
  }
@@ -186,18 +185,18 @@ $caption-typography: (
186
185
  .counterCurrentValue {
187
186
  &[data-limit-exceeded] {
188
187
  &[data-validation='default'] {
189
- color: $sys-neutral-text-main;
188
+ color: styles-tokens-fields.$sys-neutral-text-main;
190
189
  }
191
190
  &[data-validation='error'] {
192
- color: $sys-red-text-main;
191
+ color: styles-tokens-fields.$sys-red-text-main;
193
192
  }
194
193
 
195
194
  &[data-validation='warning'] {
196
- color: $sys-yellow-text-main;
195
+ color: styles-tokens-fields.$sys-yellow-text-main;
197
196
  }
198
197
 
199
198
  &[data-validation='success'] {
200
- color: $sys-green-text-light;
199
+ color: styles-tokens-fields.$sys-green-text-light;
201
200
  }
202
201
  }
203
202
  }
@@ -108,7 +108,7 @@ export function useSearchInput({
108
108
  selectedOptionFormatter,
109
109
  resetSearchOnOptionSelection = true,
110
110
  }: SearchState & { selectedOptionFormatter: SelectedOptionFormatter; resetSearchOnOptionSelection?: boolean }) {
111
- const [inputValue = '', setInputValue] = useValueControl<string>({ value, onChange, defaultValue });
111
+ const [inputValue = '', setInputValueState] = useValueControl<string>({ value, onChange, defaultValue });
112
112
 
113
113
  const prevInputValue = useRef<string>(inputValue);
114
114
 
@@ -117,12 +117,24 @@ export function useSearchInput({
117
117
  const newInputValue = selectedOptionFormatter(selectedItem);
118
118
 
119
119
  if (resetSearchOnOptionSelection && (inputValue !== newInputValue || prevInputValue.current !== newInputValue)) {
120
- setInputValue(newInputValue);
120
+ setInputValueState(newInputValue);
121
121
 
122
122
  prevInputValue.current = newInputValue;
123
123
  }
124
124
  },
125
- [inputValue, resetSearchOnOptionSelection, selectedOptionFormatter, setInputValue],
125
+ [inputValue, resetSearchOnOptionSelection, selectedOptionFormatter, setInputValueState],
126
+ );
127
+
128
+ const setInputValue = useCallback(
129
+ (value: string) => {
130
+ const updatedValue =
131
+ prevInputValue.current && value.includes(prevInputValue.current)
132
+ ? value.replace(prevInputValue.current, '')
133
+ : value;
134
+
135
+ setInputValueState(updatedValue);
136
+ },
137
+ [setInputValueState],
126
138
  );
127
139
 
128
140
  return { inputValue, setInputValue, prevInputValue, onInputValueChange: setInputValue, updateInputValue };