@hh.ru/magritte-ui-pincode-input 1.0.1 → 1.0.3

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.
package/PincodeInput.js CHANGED
@@ -1,82 +1,67 @@
1
1
  import './index.css';
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
- import { forwardRef, useState, useRef } from 'react';
3
+ import { forwardRef, useState, useRef, useLayoutEffect } from 'react';
4
4
  import classnames from 'classnames';
5
- import { keyboardMatch, keyboardKeys } from '@hh.ru/magritte-common-keyboard';
6
- import { Selection } from '@hh.ru/magritte-common-text-selection';
5
+ import { keyboardMatch, keyboardKeys, keyboardMatches } from '@hh.ru/magritte-common-keyboard';
7
6
  import { FormHelper } from '@hh.ru/magritte-ui-form-helper';
8
7
 
9
- var styles = {"pincode-input":"magritte-pincode-input___RpWyq_1-0-1","pincodeInput":"magritte-pincode-input___RpWyq_1-0-1","medium":"magritte-medium___wfRSc_1-0-1","placeholder":"magritte-placeholder___10kQ0_1-0-1","focus":"magritte-focus___IuhXb_1-0-1","invalid":"magritte-invalid___hB8h2_1-0-1","focus-visible":"magritte-focus-visible___BN1eD_1-0-1","focusVisible":"magritte-focus-visible___BN1eD_1-0-1","digit-box-container":"magritte-digit-box-container___BqMWw_1-0-1","digitBoxContainer":"magritte-digit-box-container___BqMWw_1-0-1","digit-box":"magritte-digit-box___6J0Q2_1-0-1","digitBox":"magritte-digit-box___6J0Q2_1-0-1","digits-input":"magritte-digits-input___4QeLj_1-0-1","digitsInput":"magritte-digits-input___4QeLj_1-0-1","caret-left":"magritte-caret-left___iZMuA_1-0-1","caretLeft":"magritte-caret-left___iZMuA_1-0-1","caret-right":"magritte-caret-right___u8wNk_1-0-1","caretRight":"magritte-caret-right___u8wNk_1-0-1","caret-blink":"magritte-caret-blink___-bhg7_1-0-1","caretBlink":"magritte-caret-blink___-bhg7_1-0-1","value-container":"magritte-value-container___9JR3e_1-0-1","valueContainer":"magritte-value-container___9JR3e_1-0-1"};
8
+ var styles = {"pincode-input":"magritte-pincode-input___RpWyq_1-0-3","pincodeInput":"magritte-pincode-input___RpWyq_1-0-3","medium":"magritte-medium___wfRSc_1-0-3","placeholder":"magritte-placeholder___10kQ0_1-0-3","focus":"magritte-focus___IuhXb_1-0-3","invalid":"magritte-invalid___hB8h2_1-0-3","focus-visible":"magritte-focus-visible___BN1eD_1-0-3","focusVisible":"magritte-focus-visible___BN1eD_1-0-3","digit-box-container":"magritte-digit-box-container___BqMWw_1-0-3","digitBoxContainer":"magritte-digit-box-container___BqMWw_1-0-3","digit-box":"magritte-digit-box___6J0Q2_1-0-3","digitBox":"magritte-digit-box___6J0Q2_1-0-3","digits-input":"magritte-digits-input___4QeLj_1-0-3","digitsInput":"magritte-digits-input___4QeLj_1-0-3","caret-left":"magritte-caret-left___iZMuA_1-0-3","caretLeft":"magritte-caret-left___iZMuA_1-0-3","caret-right":"magritte-caret-right___u8wNk_1-0-3","caretRight":"magritte-caret-right___u8wNk_1-0-3","caret-blink":"magritte-caret-blink___-bhg7_1-0-3","caretBlink":"magritte-caret-blink___-bhg7_1-0-3","value-container":"magritte-value-container___9JR3e_1-0-3","valueContainer":"magritte-value-container___9JR3e_1-0-3","ghost-value":"magritte-ghost-value___jPQwY_1-0-3","ghostValue":"magritte-ghost-value___jPQwY_1-0-3"};
10
9
 
11
- const moveCaretTo = (ref, position, callback) =>
12
- // Каретка сдвигается при изменении содержимого инпута автоматически
13
- // Поэтому двигаем её асинхронно, чтобы сдвиг происходил после нативного, иначе она окажется не в нужной позиции
14
- requestAnimationFrame(() => {
15
- if (ref.current) {
16
- Selection.setCaretPosition(ref.current, position);
17
- callback?.();
18
- }
19
- });
20
- const getCaretPosition = (ref) => ref.current ? (Selection.getCaretPosition(ref.current) ?? 0) : 0;
10
+ const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
11
+ const noop = () => { };
21
12
  const PincodeInput = forwardRef(({ digitsCount: _digitsCount = null, size = 'large', invalid = false, onFocus, onBlur, onChange, description, errorMessage, 'data-qa': dataQa = 'magritte-pincode-input', }, ref) => {
22
13
  const digitsCount = _digitsCount ?? (size === 'medium' ? 6 : 4);
23
14
  const [value, setValue] = useState('');
24
15
  const [caretPosition, setCaretPosition] = useState(0);
25
16
  const [focused, setFocused] = useState(false);
26
17
  const [focusVisible, setFocusVisible] = useState(false);
18
+ const ghostLastDigitRef = useRef(null);
19
+ const containerRef = useRef(null);
27
20
  const inputRef = useRef(null);
28
- const selectionRef = useRef(null);
21
+ useLayoutEffect(() => {
22
+ if (!containerRef.current || !ghostLastDigitRef.current) {
23
+ return;
24
+ }
25
+ const lastWidth = ghostLastDigitRef.current.getBoundingClientRect().width;
26
+ containerRef.current.style.setProperty('--magritte-pincode-last-digit-width', `${lastWidth}px`);
27
+ }, [caretPosition, value]);
29
28
  const updateValue = (newValue) => {
30
29
  setValue(newValue);
31
30
  onChange?.(newValue);
32
31
  };
33
- const refineCaretPosition = () => {
34
- // если попытаться получить позицию каретки синхронно, то получим позицию до изменения
35
- requestAnimationFrame(() => {
36
- if (!inputRef.current) {
37
- return;
38
- }
39
- // Когда перемещаемся между цифрами если в позиции введена цифра, то ввод должен заменят именно её
40
- // а не сдвигать весь текст после нее врпаво, как в обычном инпуте.
41
- // Поэтому здесь проверяем если в позиции что-то введено, то не просто устанавливаем каретку, а выделяем
42
- // символ, чтобы при вводе он заменился
43
- const caretPosition = getCaretPosition(inputRef);
44
- const value = inputRef.current?.value ?? '';
45
- const digitNumberToSelect = Math.min(caretPosition, Math.min(value.length, digitsCount - 1));
46
- const selection = Selection.get(inputRef.current);
47
- if (selectionRef.current && selection.start !== selection.end) {
48
- return;
49
- }
50
- selectionRef.current = null;
51
- if (value.length > digitNumberToSelect) {
52
- Selection.set(inputRef.current, digitNumberToSelect, digitNumberToSelect + 1, 'forward');
53
- selectionRef.current = digitNumberToSelect;
54
- }
55
- setCaretPosition(caretPosition);
56
- });
57
- };
58
- return (jsxs("div", { ref: ref, "data-qa": dataQa, children: [jsxs("div", { "data-qa": "magritte-pincode-input-wrapper", className: classnames(styles.pincodeInput, {
32
+ const caretPos = clamp(caretPosition, 0, value.length);
33
+ return (jsxs("div", { ref: ref, "data-qa": dataQa, children: [jsxs("div", { "data-qa": "magritte-pincode-input-wrapper", ref: containerRef, className: classnames(styles.pincodeInput, {
59
34
  [styles.focus]: focused,
60
35
  [styles.focusVisible]: focusVisible,
61
36
  [styles.medium]: size === 'medium',
62
37
  [styles.invalid]: invalid,
63
- }), onClick: (event) => {
38
+ }), onMouseDown: (event) => {
39
+ if (event.target === inputRef.current) {
40
+ return;
41
+ }
42
+ event.preventDefault();
64
43
  const caretPosition = Math.min(Number(event.target?.dataset?.digitIndex ?? value.length), value.length);
65
- inputRef.current?.focus();
66
- moveCaretTo(inputRef, caretPosition);
67
- refineCaretPosition();
68
- },
69
- // Этот обработчик нужен для того, чтобы не сбрасывался фокус при клике на дочерние элементы
70
- // Визуально это проявляется как моргание цвета рамки если клик происходит когда инпут в фокусе
71
- onMouseDown: (event) => event.preventDefault(), style: { '--magritte-pincode-digits-count': digitsCount }, children: [jsx("input", { ref: inputRef, autoComplete: "one-time-code", pattern: `\\d{${digitsCount}}`, "data-qa": "magritte-pincode-input-field", className: styles.digitsInput, type: "text", inputMode: "numeric", maxLength: digitsCount, value: value, onFocus: (event) => {
44
+ if (!focused) {
45
+ inputRef.current?.focus();
46
+ }
47
+ setCaretPosition(caretPosition);
48
+ }, style: {
49
+ '--magritte-pincode-digits-count': digitsCount,
50
+ '--magritte-pincode-caret-position': caretPos,
51
+ }, children: [jsx("input", { ref: inputRef, autoComplete: "one-time-code", pattern: `\\d{${digitsCount}}`, "data-qa": "magritte-pincode-input-field", className: styles.digitsInput, type: "text", inputMode: "numeric", maxLength: digitsCount,
52
+ // оставляем инпут всегда пустым, т.к. он нам нужен только для показа контекстного меню вставки,
53
+ // обработки события вставки и обработки фокуса
54
+ value: "",
55
+ // без change хендлера react пишет warning в консоль
56
+ onChange: noop, onFocus: (event) => {
72
57
  onFocus?.(event);
73
- refineCaretPosition();
74
58
  if (!event.defaultPrevented) {
75
59
  setFocused(true);
76
60
  setFocusVisible(!!inputRef.current?.classList.contains('focus-visible'));
77
61
  if (invalid) {
78
62
  // По спеке если инпут помечен как invalid при фокусе содержимое должно очищаться
79
63
  updateValue('');
64
+ setCaretPosition(0);
80
65
  }
81
66
  }
82
67
  }, onBlur: (event) => {
@@ -90,73 +75,64 @@ const PincodeInput = forwardRef(({ digitsCount: _digitsCount = null, size = 'lar
90
75
  return;
91
76
  }
92
77
  const isLeft = keyboardMatch(event, keyboardKeys.ArrowLeft);
93
- // Если одна из цифр выделена, и мы пытаемся передвинут каретку влево с помощью клавиатуры,
94
- // нужно делать это вручную, так как цифры мы выделяем справо на лево, и при нативном
95
- // перемещении курсо просто встанет перед выделенной цифрой, а refineCaretPosition yсова её
96
- // выделит и поставит каретку в исходное положение. Т.е. без этого кода не получится
97
- // передвинуть каретку влево, если выделена цифра
98
- if (isLeft && selectionRef.current !== null) {
78
+ const isRight = keyboardMatch(event, keyboardKeys.ArrowRight);
79
+ if (isLeft || isRight) {
80
+ event.preventDefault();
81
+ setCaretPosition((caretPosition) => clamp(caretPosition + (isRight ? 1 : -1), 0, value.length));
82
+ return;
83
+ }
84
+ if (keyboardMatches(event, keyboardKeys.DigitKeys)) {
85
+ updateValue(`${value.slice(0, caretPos)}${event.key}${value.slice(caretPos + 1)}`);
86
+ setCaretPosition((caretPosition) => clamp(caretPosition + 1, 0, digitsCount - 1));
99
87
  event.preventDefault();
100
- moveCaretTo(inputRef, Math.max(0, Math.min(selectionRef.current - 1, digitsCount - 1)), refineCaretPosition);
101
88
  return;
102
89
  }
103
- if (keyboardMatch(event, keyboardKeys.Backspace) && selectionRef.current !== null) {
90
+ const isBackspace = keyboardMatch(event, keyboardKeys.Backspace);
91
+ const isDelete = keyboardMatch(event, keyboardKeys.Delete);
92
+ if (isBackspace || isDelete) {
104
93
  // При нажатии backspace действует следующая логика:
105
94
  // Если каретка находится в позиции последней введенной цифры, то удаляем её
106
95
  // и оставляем каретку на той же позиции
107
96
  // Если каретка находится в другой позиции, то удаляем цифру слева от каретки и
108
97
  // сдвигаем каретку влево
98
+ const isLastDigit = caretPos === value.length - 1;
99
+ const deleteIndex = clamp(caretPos - (isDelete || isLastDigit ? 0 : 1), 0, digitsCount - 1);
100
+ updateValue(`${value.slice(0, deleteIndex)}${value.slice(deleteIndex + 1)}`);
101
+ setCaretPosition((caretPosition) => {
102
+ const newPosition = isLastDigit || isDelete ? caretPosition : Math.max(caretPosition - 1, 0);
103
+ return newPosition;
104
+ });
109
105
  event.preventDefault();
110
- const deleteIndex = selectionRef.current === value.length - 1
111
- ? selectionRef.current
112
- : Math.max(selectionRef.current - 1, 0);
113
- const newValue = `${value.slice(0, deleteIndex)}${value.slice(deleteIndex + 1)}`;
114
- updateValue(newValue);
115
- if (selectionRef.current !== value.length - 1) {
116
- moveCaretTo(inputRef, Math.max(selectionRef.current - 1, 0), refineCaretPosition);
117
- return;
118
- }
119
- }
120
- refineCaretPosition();
121
- }, onChange: (event) => {
122
- updateValue(event.target.value);
123
- if (selectionRef.current !== null) {
124
- // При изменении, если была выделена цифра, то каретку надо сдвинуть на следующую
125
- // позицию вручную
126
- moveCaretTo(inputRef, selectionRef.current + 1, refineCaretPosition);
127
- return;
128
106
  }
129
- refineCaretPosition();
130
107
  }, onPaste: (event) => {
131
108
  event.preventDefault();
132
109
  const pasteValue = event.clipboardData.getData('text').replace(/\D/g, '');
133
110
  if (pasteValue.length === digitsCount) {
134
111
  updateValue(pasteValue);
135
- moveCaretTo(inputRef, digitsCount, refineCaretPosition);
112
+ setCaretPosition(digitsCount - 1);
136
113
  return;
137
114
  }
138
- const caretPosition = Math.min(getCaretPosition(inputRef), selectionRef.current ?? value.length);
139
- const newValue = `${value.slice(0, caretPosition)}${pasteValue}${value.slice(caretPosition + pasteValue.length)}`.slice(0, digitsCount);
115
+ const newValue = `${value.slice(0, caretPos)}${pasteValue}${value.slice(caretPos + pasteValue.length)}`.slice(0, digitsCount);
140
116
  updateValue(newValue);
141
- moveCaretTo(inputRef, caretPosition + pasteValue.length, refineCaretPosition);
117
+ setCaretPosition(Math.min(digitsCount - 1, caretPos + pasteValue.length));
142
118
  } }), jsx("div", { className: styles.digitBoxContainer, children: Array.from({ length: digitsCount }).map((_, index) => (jsx("div", { className: classnames(styles.digitBox), "data-digit-index": index, children: jsx("span", { className: classnames(styles.valueContainer, {
143
119
  // в позицию ничего не введено, и каретка не находится в этой позиции
144
120
  [styles.placeholder]: index >= value.length &&
145
121
  (!focused ||
146
- (index !== caretPosition &&
147
- !(caretPosition === digitsCount && index === digitsCount - 1))),
122
+ (index !== caretPos &&
123
+ !(caretPos === digitsCount && index === digitsCount - 1))),
148
124
  // в позицию введена цифра, каретка находится в этой позиции, фокус
149
125
  // установлен в инпут, это не крайняя справа цифра из введенных
150
- [styles.caretLeft]: index === caretPosition && index !== value.length - 1 && focused,
126
+ [styles.caretLeft]: index === caretPos && index !== value.length - 1 && focused,
151
127
  // в позицию введена цифра, каретка находится в этой позиции, либо в следующей
152
128
  // если введены все цифры (потому что при вводе последней цифры каретка
153
129
  // должна уходить за нее), фокус установлен в инпут, это крайняя справа цифра
154
130
  // из введенных
155
- [styles.caretRight]: (index === caretPosition ||
156
- (index === digitsCount - 1 && index === caretPosition - 1)) &&
131
+ [styles.caretRight]: (index === caretPos ||
132
+ (index === digitsCount - 1 && index === caretPos - 1)) &&
157
133
  index === value.length - 1 &&
158
134
  focused,
159
- }), "data-qa": `magritte-pincode-input-digit-${index}`, children: value[index] || (caretPosition === index && focused ? '' : '•') }) }, index))) })] }), jsx(FormHelper, { invalid: invalid, description: description, errorMessage: errorMessage, "data-qa": "magritte-pincode-input-message" })] }));
135
+ }), "data-qa": `magritte-pincode-input-digit-${index}`, children: value[index] || (caretPos === index && focused ? '' : '•') }) }, index))) }), jsx("div", { className: styles.ghostValue, ref: ghostLastDigitRef, children: value.slice(caretPos, caretPos + 1) })] }), jsx(FormHelper, { invalid: invalid, description: description, errorMessage: errorMessage, "data-qa": "magritte-pincode-input-message" })] }));
160
136
  });
161
137
  PincodeInput.displayName = 'PincodeInput';
162
138
 
@@ -1 +1 @@
1
- {"version":3,"file":"PincodeInput.js","sources":["../src/PincodeInput.tsx"],"sourcesContent":["import { type CSSProperties, type FocusEventHandler, useRef, useState, RefObject, forwardRef } from 'react';\nimport classnames from 'classnames';\n\nimport { keyboardKeys, keyboardMatch } from '@hh.ru/magritte-common-keyboard';\nimport { Selection } from '@hh.ru/magritte-common-text-selection';\nimport { FormHelper } from '@hh.ru/magritte-ui-form-helper';\n\nimport styles from './pincodeInput.less';\n\nconst moveCaretTo = (ref: RefObject<HTMLInputElement>, position: number, callback?: VoidFunction) =>\n // Каретка сдвигается при изменении содержимого инпута автоматически\n // Поэтому двигаем её асинхронно, чтобы сдвиг происходил после нативного, иначе она окажется не в нужной позиции\n requestAnimationFrame(() => {\n if (ref.current) {\n Selection.setCaretPosition(ref.current, position);\n callback?.();\n }\n });\n\nconst getCaretPosition = (ref: RefObject<HTMLInputElement>) =>\n ref.current ? (Selection.getCaretPosition(ref.current) ?? 0) : 0;\n\nexport type PincodeInputSize = 'medium' | 'large';\n\nexport interface PincodeInputProps {\n /**\n * Количество цифр в пин-коде, если не указано будет выбрано автоматически\n * в зависимости от размера инпута ( medium - 6, large - 4)\n */\n digitsCount?: number | null;\n /** Размер инпута */\n size?: PincodeInputSize;\n /** Обработчик изменений */\n onChange?: (value: string) => void;\n /** Обработчик фокуса */\n onFocus?: FocusEventHandler<HTMLInputElement>;\n /** Обработчик потери фокуса */\n onBlur?: FocusEventHandler<HTMLInputElement>;\n /** Флаг наличия ошибки */\n invalid?: boolean;\n /** Текст описания */\n description?: string;\n /** Текст сообщения об ошибке */\n errorMessage?: string;\n 'data-qa'?: string;\n}\n\nexport const PincodeInput = forwardRef<HTMLDivElement, PincodeInputProps>(\n (\n {\n digitsCount: _digitsCount = null,\n size = 'large',\n invalid = false,\n onFocus,\n onBlur,\n onChange,\n description,\n errorMessage,\n 'data-qa': dataQa = 'magritte-pincode-input',\n },\n ref\n ) => {\n const digitsCount = _digitsCount ?? (size === 'medium' ? 6 : 4);\n const [value, setValue] = useState<string>('');\n const [caretPosition, setCaretPosition] = useState<number>(0);\n const [focused, setFocused] = useState(false);\n const [focusVisible, setFocusVisible] = useState(false);\n\n const inputRef = useRef<HTMLInputElement>(null);\n const selectionRef = useRef<number | null>(null);\n\n const updateValue = (newValue: string) => {\n setValue(newValue);\n onChange?.(newValue);\n };\n\n const refineCaretPosition = () => {\n // если попытаться получить позицию каретки синхронно, то получим позицию до изменения\n requestAnimationFrame(() => {\n if (!inputRef.current) {\n return;\n }\n // Когда перемещаемся между цифрами если в позиции введена цифра, то ввод должен заменят именно её\n // а не сдвигать весь текст после нее врпаво, как в обычном инпуте.\n // Поэтому здесь проверяем если в позиции что-то введено, то не просто устанавливаем каретку, а выделяем\n // символ, чтобы при вводе он заменился\n const caretPosition = getCaretPosition(inputRef);\n const value = inputRef.current?.value ?? '';\n const digitNumberToSelect = Math.min(caretPosition, Math.min(value.length, digitsCount - 1));\n const selection = Selection.get(inputRef.current);\n if (selectionRef.current && selection.start !== selection.end) {\n return;\n }\n selectionRef.current = null;\n if (value.length > digitNumberToSelect) {\n Selection.set(inputRef.current, digitNumberToSelect, digitNumberToSelect + 1, 'forward');\n selectionRef.current = digitNumberToSelect;\n }\n setCaretPosition(caretPosition);\n });\n };\n\n return (\n <div ref={ref} data-qa={dataQa}>\n <div\n data-qa=\"magritte-pincode-input-wrapper\"\n className={classnames(styles.pincodeInput, {\n [styles.focus]: focused,\n [styles.focusVisible]: focusVisible,\n [styles.medium]: size === 'medium',\n [styles.invalid]: invalid,\n })}\n onClick={(event) => {\n const caretPosition = Math.min(\n Number((event.target as HTMLElement)?.dataset?.digitIndex ?? value.length),\n value.length\n );\n inputRef.current?.focus();\n moveCaretTo(inputRef, caretPosition);\n refineCaretPosition();\n }}\n // Этот обработчик нужен для того, чтобы не сбрасывался фокус при клике на дочерние элементы\n // Визуально это проявляется как моргание цвета рамки если клик происходит когда инпут в фокусе\n onMouseDown={(event) => event.preventDefault()}\n style={{ '--magritte-pincode-digits-count': digitsCount } as CSSProperties}\n >\n <input\n ref={inputRef}\n autoComplete=\"one-time-code\"\n pattern={`\\\\d{${digitsCount}}`}\n data-qa=\"magritte-pincode-input-field\"\n className={styles.digitsInput}\n type=\"text\"\n inputMode=\"numeric\"\n maxLength={digitsCount}\n value={value}\n onFocus={(event) => {\n onFocus?.(event);\n refineCaretPosition();\n if (!event.defaultPrevented) {\n setFocused(true);\n setFocusVisible(!!inputRef.current?.classList.contains('focus-visible'));\n if (invalid) {\n // По спеке если инпут помечен как invalid при фокусе содержимое должно очищаться\n updateValue('');\n }\n }\n }}\n onBlur={(event) => {\n onBlur?.(event);\n if (!event.defaultPrevented) {\n setFocused(false);\n setFocusVisible(false);\n }\n }}\n onKeyDown={(event) => {\n if (!inputRef.current) {\n return;\n }\n\n const isLeft = keyboardMatch(event, keyboardKeys.ArrowLeft);\n\n // Если одна из цифр выделена, и мы пытаемся передвинут каретку влево с помощью клавиатуры,\n // нужно делать это вручную, так как цифры мы выделяем справо на лево, и при нативном\n // перемещении курсо просто встанет перед выделенной цифрой, а refineCaretPosition yсова её\n // выделит и поставит каретку в исходное положение. Т.е. без этого кода не получится\n // передвинуть каретку влево, если выделена цифра\n if (isLeft && selectionRef.current !== null) {\n event.preventDefault();\n moveCaretTo(\n inputRef,\n Math.max(0, Math.min(selectionRef.current - 1, digitsCount - 1)),\n refineCaretPosition\n );\n return;\n }\n\n if (keyboardMatch(event, keyboardKeys.Backspace) && selectionRef.current !== null) {\n // При нажатии backspace действует следующая логика:\n // Если каретка находится в позиции последней введенной цифры, то удаляем её\n // и оставляем каретку на той же позиции\n // Если каретка находится в другой позиции, то удаляем цифру слева от каретки и\n // сдвигаем каретку влево\n event.preventDefault();\n const deleteIndex =\n selectionRef.current === value.length - 1\n ? selectionRef.current\n : Math.max(selectionRef.current - 1, 0);\n const newValue = `${value.slice(0, deleteIndex)}${value.slice(deleteIndex + 1)}`;\n updateValue(newValue);\n if (selectionRef.current !== value.length - 1) {\n moveCaretTo(inputRef, Math.max(selectionRef.current - 1, 0), refineCaretPosition);\n return;\n }\n }\n\n refineCaretPosition();\n }}\n onChange={(event) => {\n updateValue(event.target.value);\n if (selectionRef.current !== null) {\n // При изменении, если была выделена цифра, то каретку надо сдвинуть на следующую\n // позицию вручную\n moveCaretTo(inputRef, selectionRef.current + 1, refineCaretPosition);\n return;\n }\n refineCaretPosition();\n }}\n onPaste={(event) => {\n event.preventDefault();\n const pasteValue = event.clipboardData.getData('text').replace(/\\D/g, '');\n if (pasteValue.length === digitsCount) {\n updateValue(pasteValue);\n moveCaretTo(inputRef, digitsCount, refineCaretPosition);\n return;\n }\n\n const caretPosition = Math.min(\n getCaretPosition(inputRef),\n selectionRef.current ?? value.length\n );\n const newValue =\n `${value.slice(0, caretPosition)}${pasteValue}${value.slice(caretPosition + pasteValue.length)}`.slice(\n 0,\n digitsCount\n );\n updateValue(newValue);\n moveCaretTo(inputRef, caretPosition + pasteValue.length, refineCaretPosition);\n }}\n />\n <div className={styles.digitBoxContainer}>\n {/* eslint-disable-next-line no-restricted-properties */}\n {Array.from({ length: digitsCount }).map((_, index) => (\n <div key={index} className={classnames(styles.digitBox)} data-digit-index={index}>\n <span\n className={classnames(styles.valueContainer, {\n // в позицию ничего не введено, и каретка не находится в этой позиции\n [styles.placeholder]:\n index >= value.length &&\n (!focused ||\n (index !== caretPosition &&\n !(caretPosition === digitsCount && index === digitsCount - 1))),\n // в позицию введена цифра, каретка находится в этой позиции, фокус\n // установлен в инпут, это не крайняя справа цифра из введенных\n [styles.caretLeft]:\n index === caretPosition && index !== value.length - 1 && focused,\n // в позицию введена цифра, каретка находится в этой позиции, либо в следующей\n // если введены все цифры (потому что при вводе последней цифры каретка\n // должна уходить за нее), фокус установлен в инпут, это крайняя справа цифра\n // из введенных\n [styles.caretRight]:\n (index === caretPosition ||\n (index === digitsCount - 1 && index === caretPosition - 1)) &&\n index === value.length - 1 &&\n focused,\n })}\n data-qa={`magritte-pincode-input-digit-${index}`}\n >\n {value[index] || (caretPosition === index && focused ? '' : '•')}\n </span>\n </div>\n ))}\n </div>\n </div>\n <FormHelper\n invalid={invalid}\n description={description}\n errorMessage={errorMessage}\n data-qa=\"magritte-pincode-input-message\"\n />\n </div>\n );\n }\n);\n\nPincodeInput.displayName = 'PincodeInput';\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
1
+ {"version":3,"file":"PincodeInput.js","sources":["../src/PincodeInput.tsx"],"sourcesContent":["import { type CSSProperties, type FocusEventHandler, useRef, useState, forwardRef, useLayoutEffect } from 'react';\nimport classnames from 'classnames';\n\nimport { keyboardKeys, keyboardMatch, keyboardMatches } from '@hh.ru/magritte-common-keyboard';\nimport { FormHelper } from '@hh.ru/magritte-ui-form-helper';\n\nimport styles from './pincodeInput.less';\n\nexport type PincodeInputSize = 'medium' | 'large';\n\nexport interface PincodeInputProps {\n /**\n * Количество цифр в пин-коде, если не указано будет выбрано автоматически\n * в зависимости от размера инпута ( medium - 6, large - 4)\n */\n digitsCount?: number | null;\n /** Размер инпута */\n size?: PincodeInputSize;\n /** Обработчик изменений */\n onChange?: (value: string) => void;\n /** Обработчик фокуса */\n onFocus?: FocusEventHandler<HTMLInputElement>;\n /** Обработчик потери фокуса */\n onBlur?: FocusEventHandler<HTMLInputElement>;\n /** Флаг наличия ошибки */\n invalid?: boolean;\n /** Текст описания */\n description?: string;\n /** Текст сообщения об ошибке */\n errorMessage?: string;\n 'data-qa'?: string;\n}\n\nconst clamp = (value: number, min: number, max: number) => Math.min(Math.max(value, min), max);\nconst noop = () => {};\n\nexport const PincodeInput = forwardRef<HTMLDivElement, PincodeInputProps>(\n (\n {\n digitsCount: _digitsCount = null,\n size = 'large',\n invalid = false,\n onFocus,\n onBlur,\n onChange,\n description,\n errorMessage,\n 'data-qa': dataQa = 'magritte-pincode-input',\n },\n ref\n ) => {\n const digitsCount = _digitsCount ?? (size === 'medium' ? 6 : 4);\n const [value, setValue] = useState<string>('');\n const [caretPosition, setCaretPosition] = useState<number>(0);\n const [focused, setFocused] = useState(false);\n const [focusVisible, setFocusVisible] = useState(false);\n\n const ghostLastDigitRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n useLayoutEffect(() => {\n if (!containerRef.current || !ghostLastDigitRef.current) {\n return;\n }\n\n const lastWidth = ghostLastDigitRef.current.getBoundingClientRect().width;\n containerRef.current.style.setProperty('--magritte-pincode-last-digit-width', `${lastWidth}px`);\n }, [caretPosition, value]);\n\n const updateValue = (newValue: string) => {\n setValue(newValue);\n onChange?.(newValue);\n };\n\n const caretPos = clamp(caretPosition, 0, value.length);\n\n return (\n <div ref={ref} data-qa={dataQa}>\n <div\n data-qa=\"magritte-pincode-input-wrapper\"\n ref={containerRef}\n className={classnames(styles.pincodeInput, {\n [styles.focus]: focused,\n [styles.focusVisible]: focusVisible,\n [styles.medium]: size === 'medium',\n [styles.invalid]: invalid,\n })}\n onMouseDown={(event) => {\n if (event.target === inputRef.current) {\n return;\n }\n event.preventDefault();\n\n const caretPosition = Math.min(\n Number((event.target as HTMLElement)?.dataset?.digitIndex ?? value.length),\n value.length\n );\n\n if (!focused) {\n inputRef.current?.focus();\n }\n\n setCaretPosition(caretPosition);\n }}\n style={\n {\n '--magritte-pincode-digits-count': digitsCount,\n '--magritte-pincode-caret-position': caretPos,\n } as CSSProperties\n }\n >\n <input\n ref={inputRef}\n autoComplete=\"one-time-code\"\n pattern={`\\\\d{${digitsCount}}`}\n data-qa=\"magritte-pincode-input-field\"\n className={styles.digitsInput}\n type=\"text\"\n inputMode=\"numeric\"\n maxLength={digitsCount}\n // оставляем инпут всегда пустым, т.к. он нам нужен только для показа контекстного меню вставки,\n // обработки события вставки и обработки фокуса\n value=\"\"\n // без change хендлера react пишет warning в консоль\n onChange={noop}\n onFocus={(event) => {\n onFocus?.(event);\n if (!event.defaultPrevented) {\n setFocused(true);\n setFocusVisible(!!inputRef.current?.classList.contains('focus-visible'));\n if (invalid) {\n // По спеке если инпут помечен как invalid при фокусе содержимое должно очищаться\n updateValue('');\n setCaretPosition(0);\n }\n }\n }}\n onBlur={(event) => {\n onBlur?.(event);\n if (!event.defaultPrevented) {\n setFocused(false);\n setFocusVisible(false);\n }\n }}\n onKeyDown={(event) => {\n if (!inputRef.current) {\n return;\n }\n\n const isLeft = keyboardMatch(event, keyboardKeys.ArrowLeft);\n const isRight = keyboardMatch(event, keyboardKeys.ArrowRight);\n if (isLeft || isRight) {\n event.preventDefault();\n setCaretPosition((caretPosition) =>\n clamp(caretPosition + (isRight ? 1 : -1), 0, value.length)\n );\n return;\n }\n\n if (keyboardMatches(event, keyboardKeys.DigitKeys)) {\n updateValue(`${value.slice(0, caretPos)}${event.key}${value.slice(caretPos + 1)}`);\n setCaretPosition((caretPosition) => clamp(caretPosition + 1, 0, digitsCount - 1));\n event.preventDefault();\n return;\n }\n\n const isBackspace = keyboardMatch(event, keyboardKeys.Backspace);\n const isDelete = keyboardMatch(event, keyboardKeys.Delete);\n\n if (isBackspace || isDelete) {\n // При нажатии backspace действует следующая логика:\n // Если каретка находится в позиции последней введенной цифры, то удаляем её\n // и оставляем каретку на той же позиции\n // Если каретка находится в другой позиции, то удаляем цифру слева от каретки и\n // сдвигаем каретку влево\n\n const isLastDigit = caretPos === value.length - 1;\n const deleteIndex = clamp(\n caretPos - (isDelete || isLastDigit ? 0 : 1),\n 0,\n digitsCount - 1\n );\n updateValue(`${value.slice(0, deleteIndex)}${value.slice(deleteIndex + 1)}`);\n setCaretPosition((caretPosition) => {\n const newPosition =\n isLastDigit || isDelete ? caretPosition : Math.max(caretPosition - 1, 0);\n\n return newPosition;\n });\n\n event.preventDefault();\n }\n }}\n onPaste={(event) => {\n event.preventDefault();\n const pasteValue = event.clipboardData.getData('text').replace(/\\D/g, '');\n if (pasteValue.length === digitsCount) {\n updateValue(pasteValue);\n setCaretPosition(digitsCount - 1);\n return;\n }\n\n const newValue =\n `${value.slice(0, caretPos)}${pasteValue}${value.slice(caretPos + pasteValue.length)}`.slice(\n 0,\n digitsCount\n );\n updateValue(newValue);\n setCaretPosition(Math.min(digitsCount - 1, caretPos + pasteValue.length));\n }}\n />\n <div className={styles.digitBoxContainer}>\n {/* eslint-disable-next-line no-restricted-properties */}\n {Array.from({ length: digitsCount }).map((_, index) => (\n <div key={index} className={classnames(styles.digitBox)} data-digit-index={index}>\n <span\n className={classnames(styles.valueContainer, {\n // в позицию ничего не введено, и каретка не находится в этой позиции\n [styles.placeholder]:\n index >= value.length &&\n (!focused ||\n (index !== caretPos &&\n !(caretPos === digitsCount && index === digitsCount - 1))),\n // в позицию введена цифра, каретка находится в этой позиции, фокус\n // установлен в инпут, это не крайняя справа цифра из введенных\n [styles.caretLeft]: index === caretPos && index !== value.length - 1 && focused,\n // в позицию введена цифра, каретка находится в этой позиции, либо в следующей\n // если введены все цифры (потому что при вводе последней цифры каретка\n // должна уходить за нее), фокус установлен в инпут, это крайняя справа цифра\n // из введенных\n [styles.caretRight]:\n (index === caretPos ||\n (index === digitsCount - 1 && index === caretPos - 1)) &&\n index === value.length - 1 &&\n focused,\n })}\n data-qa={`magritte-pincode-input-digit-${index}`}\n >\n {value[index] || (caretPos === index && focused ? '' : '•')}\n </span>\n </div>\n ))}\n </div>\n <div className={styles.ghostValue} ref={ghostLastDigitRef}>\n {value.slice(caretPos, caretPos + 1)}\n </div>\n </div>\n <FormHelper\n invalid={invalid}\n description={description}\n errorMessage={errorMessage}\n data-qa=\"magritte-pincode-input-message\"\n />\n </div>\n );\n }\n);\n\nPincodeInput.displayName = 'PincodeInput';\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
package/index.css CHANGED
@@ -1,143 +1,170 @@
1
1
  :root{
2
- --magritte-color-text-primary-v21-0-0:#000000;
3
- --magritte-color-component-input-stroke-state-field-hovered-v21-0-0:#CCD5DF;
4
- --magritte-color-component-input-stroke-state-field-focused-v21-0-0:#0070ff;
5
- --magritte-color-component-input-stroke-state-accent-focused-accessible-v21-0-0:#0070ff7a;
6
- --magritte-color-component-input-stroke-state-field-invalid-v21-0-0:#ff4d3a;
7
- --magritte-color-component-input-background-field-v21-0-0:#ffffff;
8
- --magritte-color-component-input-background-state-field-hovered-v21-0-0:#ffffff;
9
- --magritte-color-component-input-background-state-field-focused-v21-0-0:#ffffff;
10
- --magritte-color-component-input-background-state-field-invalid-v21-0-0:#ffffff;
11
- --magritte-color-component-input-stroke-field-v21-0-0:#DCE3EB;
12
- --magritte-color-component-input-text-state-content-focused-v21-0-0:#000000;
13
- --magritte-color-component-input-text-state-placeholder-hovered-v21-0-0:#768694;
14
- --magritte-color-component-input-text-state-placeholder-focused-v21-0-0:#AABBCA;
15
- --magritte-color-component-input-text-state-placeholder-invalid-v21-0-0:#AABBCA;
16
- --magritte-color-component-input-text-placeholder-v21-0-0:#AABBCA;
2
+ --magritte-color-text-primary-v21-1-0:#000000;
3
+ --magritte-color-component-input-stroke-state-field-hovered-v21-1-0:#CCD5DF;
4
+ --magritte-color-component-input-stroke-state-field-focused-v21-1-0:#0070ff;
5
+ --magritte-color-component-input-stroke-state-accent-focused-accessible-v21-1-0:#0070ff7a;
6
+ --magritte-color-component-input-stroke-state-field-invalid-v21-1-0:#ff4d3a;
7
+ --magritte-color-component-input-stroke-state-negative-focused-accessible-v21-1-0:#ff4d3a7a;
8
+ --magritte-color-component-input-background-field-v21-1-0:#ffffff;
9
+ --magritte-color-component-input-background-state-field-hovered-v21-1-0:#ffffff;
10
+ --magritte-color-component-input-background-state-field-focused-v21-1-0:#ffffff;
11
+ --magritte-color-component-input-background-state-field-invalid-v21-1-0:#ffffff;
12
+ --magritte-color-component-input-stroke-field-v21-1-0:#DCE3EB;
13
+ --magritte-color-component-input-text-state-content-focused-v21-1-0:#000000;
14
+ --magritte-color-component-input-text-state-placeholder-hovered-v21-1-0:#768694;
15
+ --magritte-color-component-input-text-state-placeholder-focused-v21-1-0:#AABBCA;
16
+ --magritte-color-component-input-text-state-placeholder-invalid-v21-1-0:#AABBCA;
17
+ --magritte-color-component-input-text-placeholder-v21-1-0:#AABBCA;
17
18
  }
18
19
  :root{
19
- --magritte-font-families-body-v21-0-0:hh sans;
20
- --magritte-semantic-border-width-default-v21-0-0:1px;
21
- --magritte-semantic-border-width-focused-v21-0-0:2px;
22
- --magritte-static-border-radius-300-v21-0-0:12px;
23
- --magritte-static-border-radius-450-v21-0-0:18px;
20
+ --magritte-font-families-body-v21-1-0:hh sans;
21
+ --magritte-semantic-border-width-default-v21-1-0:1px;
22
+ --magritte-semantic-border-width-focused-v21-1-0:2px;
23
+ --magritte-static-border-radius-300-v21-1-0:12px;
24
+ --magritte-static-border-radius-450-v21-1-0:18px;
24
25
  }
25
26
  .magritte-night-theme{
26
- --magritte-color-text-primary-v21-0-0:#ffffff;
27
- --magritte-color-component-input-stroke-state-field-hovered-v21-0-0:#3B3B3B;
28
- --magritte-color-component-input-stroke-state-field-focused-v21-0-0:#0070ff;
29
- --magritte-color-component-input-stroke-state-accent-focused-accessible-v21-0-0:#0070ff7a;
30
- --magritte-color-component-input-stroke-state-field-invalid-v21-0-0:#ff4d3a;
31
- --magritte-color-component-input-background-field-v21-0-0:#1B1B1B;
32
- --magritte-color-component-input-background-state-field-hovered-v21-0-0:#1B1B1B;
33
- --magritte-color-component-input-background-state-field-focused-v21-0-0:#1B1B1B;
34
- --magritte-color-component-input-background-state-field-invalid-v21-0-0:#1B1B1B;
35
- --magritte-color-component-input-stroke-field-v21-0-0:#303030;
36
- --magritte-color-component-input-text-placeholder-v21-0-0:#535353;
37
- --magritte-color-component-input-text-state-content-focused-v21-0-0:#ffffff;
38
- --magritte-color-component-input-text-state-placeholder-hovered-v21-0-0:#5E5E5E;
39
- --magritte-color-component-input-text-state-placeholder-focused-v21-0-0:#535353;
40
- --magritte-color-component-input-text-state-placeholder-invalid-v21-0-0:#535353;
41
- }
42
- .magritte-pincode-input___RpWyq_1-0-1{
27
+ --magritte-color-text-primary-v21-1-0:#ffffff;
28
+ --magritte-color-component-input-stroke-state-field-hovered-v21-1-0:#3B3B3B;
29
+ --magritte-color-component-input-stroke-state-field-focused-v21-1-0:#0070ff;
30
+ --magritte-color-component-input-stroke-state-accent-focused-accessible-v21-1-0:#0070ff7a;
31
+ --magritte-color-component-input-stroke-state-field-invalid-v21-1-0:#ff4d3a;
32
+ --magritte-color-component-input-stroke-state-negative-focused-accessible-v21-1-0:#ff4d3a7a;
33
+ --magritte-color-component-input-background-field-v21-1-0:#1B1B1B;
34
+ --magritte-color-component-input-background-state-field-hovered-v21-1-0:#1B1B1B;
35
+ --magritte-color-component-input-background-state-field-focused-v21-1-0:#1B1B1B;
36
+ --magritte-color-component-input-background-state-field-invalid-v21-1-0:#1B1B1B;
37
+ --magritte-color-component-input-stroke-field-v21-1-0:#303030;
38
+ --magritte-color-component-input-text-placeholder-v21-1-0:#535353;
39
+ --magritte-color-component-input-text-state-content-focused-v21-1-0:#ffffff;
40
+ --magritte-color-component-input-text-state-placeholder-hovered-v21-1-0:#5E5E5E;
41
+ --magritte-color-component-input-text-state-placeholder-focused-v21-1-0:#535353;
42
+ --magritte-color-component-input-text-state-placeholder-invalid-v21-1-0:#535353;
43
+ }
44
+ .magritte-pincode-input___RpWyq_1-0-3{
43
45
  --magritte-pincode-input-padding-horizontal:20px;
44
46
  --magritte-pincode-input-padding-vertical:8px;
45
47
  --magritte-pincode-input-gap:6px;
48
+ --magritte-digit-box-width:calc((100% - (var(--magritte-pincode-input-gap) * (var(--magritte-pincode-digits-count) - 1)) - (var(--magritte-pincode-input-padding-horizontal) * 2)) / var(--magritte-pincode-digits-count));
46
49
  box-sizing:border-box;
47
50
  height:88px;
48
- border:var(--magritte-semantic-border-width-default-v21-0-0) solid var(--magritte-color-component-input-stroke-field-v21-0-0);
49
- border-radius:var(--magritte-static-border-radius-450-v21-0-0);
50
- background-color:var(--magritte-color-component-input-background-field-v21-0-0);
51
- padding:var(--magritte-pincode-input-padding-vertical) var(--magritte-pincode-input-padding-horizontal);
51
+ box-shadow:inset 0 0 0 var(--magritte-semantic-border-width-default-v21-1-0) var(--magritte-color-component-input-stroke-field-v21-1-0);
52
+ border-radius:var(--magritte-static-border-radius-450-v21-1-0);
53
+ background-color:var(--magritte-color-component-input-background-field-v21-1-0);
52
54
  position:relative;
55
+ overflow:clip;
53
56
  cursor:text;
54
- font-family:var(--magritte-font-families-body-v21-0-0);
57
+ font-family:var(--magritte-font-families-body-v21-1-0);
55
58
  font-size:32px;
56
59
  font-style:normal;
57
60
  font-weight:normal;
58
61
  line-height:40px;
59
- color:var(--magritte-color-component-input-text-state-content-focused-v21-0-0);
62
+ color:var(--magritte-color-component-input-text-state-content-focused-v21-1-0);
60
63
  }
61
- .magritte-pincode-input___RpWyq_1-0-1.magritte-medium___wfRSc_1-0-1{
64
+ .magritte-pincode-input___RpWyq_1-0-3.magritte-medium___wfRSc_1-0-3{
62
65
  font-size:28px;
63
66
  --magritte-pincode-input-padding-horizontal:16px;
64
67
  --magritte-pincode-input-padding-vertical:6px;
65
68
  --magritte-pincode-input-gap:4px;
66
- border-radius:var(--magritte-static-border-radius-300-v21-0-0);
69
+ border-radius:var(--magritte-static-border-radius-300-v21-1-0);
67
70
  height:76px;
68
71
  }
69
- .magritte-pincode-input___RpWyq_1-0-1:hover{
70
- border-color:var(--magritte-color-component-input-stroke-state-field-hovered-v21-0-0);
71
- background-color:var(--magritte-color-component-input-background-state-field-hovered-v21-0-0);
72
+ .magritte-pincode-input___RpWyq_1-0-3:hover{
73
+ box-shadow:inset 0 0 0 var(--magritte-semantic-border-width-default-v21-1-0) var(--magritte-color-component-input-stroke-state-field-hovered-v21-1-0);
74
+ background-color:var(--magritte-color-component-input-background-state-field-hovered-v21-1-0);
72
75
  }
73
- .magritte-pincode-input___RpWyq_1-0-1:hover .magritte-placeholder___10kQ0_1-0-1{
74
- color:var(--magritte-color-component-input-text-state-placeholder-hovered-v21-0-0);
76
+ .magritte-pincode-input___RpWyq_1-0-3:hover .magritte-placeholder___10kQ0_1-0-3{
77
+ color:var(--magritte-color-component-input-text-state-placeholder-hovered-v21-1-0);
75
78
  }
76
- .magritte-pincode-input___RpWyq_1-0-1.magritte-focus___IuhXb_1-0-1{
77
- border:var(--magritte-semantic-border-width-focused-v21-0-0) solid var(--magritte-color-component-input-stroke-state-field-focused-v21-0-0);
78
- background-color:var(--magritte-color-component-input-background-state-field-focused-v21-0-0);
79
- padding:var(--magritte-pincode-input-padding-vertical) calc(var(--magritte-pincode-input-padding-horizontal) - 1px);
79
+ .magritte-pincode-input___RpWyq_1-0-3.magritte-focus___IuhXb_1-0-3{
80
+ box-shadow:inset 0 0 0 var(--magritte-semantic-border-width-focused-v21-1-0) var(--magritte-color-component-input-stroke-state-field-focused-v21-1-0);
81
+ background-color:var(--magritte-color-component-input-background-state-field-focused-v21-1-0);
80
82
  }
81
- .magritte-pincode-input___RpWyq_1-0-1.magritte-focus___IuhXb_1-0-1 .magritte-placeholder___10kQ0_1-0-1{
82
- color:var(--magritte-color-component-input-text-state-placeholder-focused-v21-0-0);
83
+ .magritte-pincode-input___RpWyq_1-0-3.magritte-focus___IuhXb_1-0-3 .magritte-placeholder___10kQ0_1-0-3{
84
+ color:var(--magritte-color-component-input-text-state-placeholder-focused-v21-1-0);
83
85
  }
84
- .magritte-pincode-input___RpWyq_1-0-1.magritte-invalid___hB8h2_1-0-1{
85
- border:var(--magritte-semantic-border-width-default-v21-0-0) solid var(--magritte-color-component-input-stroke-state-field-invalid-v21-0-0);
86
- background-color:var(--magritte-color-component-input-background-state-field-invalid-v21-0-0);
86
+ .magritte-pincode-input___RpWyq_1-0-3.magritte-invalid___hB8h2_1-0-3{
87
+ box-shadow:inset 0 0 0 var(--magritte-semantic-border-width-default-v21-1-0) var(--magritte-color-component-input-stroke-state-field-invalid-v21-1-0);
88
+ background-color:var(--magritte-color-component-input-background-state-field-invalid-v21-1-0);
87
89
  }
88
- .magritte-pincode-input___RpWyq_1-0-1.magritte-invalid___hB8h2_1-0-1 .magritte-placeholder___10kQ0_1-0-1{
89
- color:var(--magritte-color-component-input-text-state-placeholder-invalid-v21-0-0);
90
+ .magritte-pincode-input___RpWyq_1-0-3.magritte-invalid___hB8h2_1-0-3 .magritte-placeholder___10kQ0_1-0-3{
91
+ color:var(--magritte-color-component-input-text-state-placeholder-invalid-v21-1-0);
90
92
  }
91
- .magritte-pincode-input___RpWyq_1-0-1.magritte-focus-visible___BN1eD_1-0-1{
92
- outline:var(--magritte-color-component-input-stroke-state-accent-focused-accessible-v21-0-0) solid 4px;
93
+ .magritte-pincode-input___RpWyq_1-0-3.magritte-focus-visible___BN1eD_1-0-3{
94
+ outline:var(--magritte-color-component-input-stroke-state-accent-focused-accessible-v21-1-0) solid 4px;
93
95
  }
94
- .magritte-digit-box-container___BqMWw_1-0-1{
96
+ .magritte-pincode-input___RpWyq_1-0-3.magritte-focus-visible___BN1eD_1-0-3.magritte-invalid___hB8h2_1-0-3{
97
+ outline-color:var(--magritte-color-component-input-stroke-state-negative-focused-accessible-v21-1-0);
98
+ }
99
+ .magritte-digit-box-container___BqMWw_1-0-3{
95
100
  display:flex;
96
101
  gap:var(--magritte-pincode-input-gap);
97
- position:relative;
98
- justify-content:stretch;
102
+ position:absolute;
103
+ inset:0;
104
+ justify-content:center;
99
105
  align-items:stretch;
100
106
  height:100%;
107
+ pointer-events:none;
108
+ z-index:0;
101
109
  }
102
- .magritte-digit-box___6J0Q2_1-0-1{
103
- flex:0 0 calc((100% - (var(--magritte-pincode-input-gap) * (var(--magritte-pincode-digits-count) - 1))) / var(--magritte-pincode-digits-count));
110
+ .magritte-digit-box___6J0Q2_1-0-3{
111
+ flex:0 0 var(--magritte-digit-box-width);
112
+ pointer-events:auto;
104
113
  display:flex;
105
114
  align-items:center;
106
115
  justify-content:center;
116
+ user-select:none;
117
+ }
118
+ .magritte-digit-box___6J0Q2_1-0-3::selection{
119
+ background-color:transparent;
107
120
  }
108
- .magritte-digits-input___4QeLj_1-0-1{
121
+ .magritte-digit-box___6J0Q2_1-0-3::-moz-selection{
122
+ background-color:transparent;
123
+ }
124
+ .magritte-digits-input___4QeLj_1-0-3{
109
125
  display:block;
110
126
  position:absolute;
111
- inset:0;
127
+ top:0;
128
+ bottom:0;
129
+ --last-digit-width:max(var(--magritte-pincode-last-digit-width), 10px);
130
+ padding:0 calc(var(--last-digit-width) / 2);
131
+ left:calc(var(--magritte-pincode-input-padding-horizontal) + (var(--magritte-pincode-caret-position) * var(--magritte-digit-box-width)) + (var(--magritte-pincode-caret-position) * var(--magritte-pincode-input-gap)) + (var(--magritte-digit-box-width) / 2) - var(--last-digit-width) / 2);
132
+ height:100%;
133
+ width:var(--last-digit-width);
134
+ z-index:1;
112
135
  border-width:0;
113
136
  background:none;
114
- opacity:0;
137
+ color:transparent;
115
138
  outline:none;
116
139
  appearance:none;
117
140
  caret-color:transparent;
118
- z-index:0;
119
- pointer-events:none;
120
141
  }
121
- .magritte-digits-input___4QeLj_1-0-1::selection{
142
+ .magritte-digits-input___4QeLj_1-0-3::selection{
122
143
  background-color:transparent;
144
+ appearance:none;
123
145
  }
124
- .magritte-digits-input___4QeLj_1-0-1::-moz-selection{
146
+ .magritte-digits-input___4QeLj_1-0-3::-moz-selection{
125
147
  background-color:transparent;
148
+ appearance:none;
126
149
  }
127
- .magritte-caret-left___iZMuA_1-0-1::before,
128
- .magritte-caret-right___u8wNk_1-0-1::after{
150
+ .magritte-caret-left___iZMuA_1-0-3::before,
151
+ .magritte-caret-right___u8wNk_1-0-3::after{
129
152
  content:'';
130
153
  block-size:1em;
131
- border-left:1px solid var(--magritte-color-text-primary-v21-0-0);
132
- animation:magritte-caret-blink___-bhg7_1-0-1 1s steps(1) infinite;
154
+ border-left:1px solid var(--magritte-color-text-primary-v21-1-0);
155
+ animation:magritte-caret-blink___-bhg7_1-0-3 1s steps(1) infinite;
133
156
  }
134
- .magritte-placeholder___10kQ0_1-0-1{
135
- color:var(--magritte-color-component-input-text-placeholder-v21-0-0);
157
+ .magritte-placeholder___10kQ0_1-0-3{
158
+ color:var(--magritte-color-component-input-text-placeholder-v21-1-0);
136
159
  }
137
- .magritte-value-container___9JR3e_1-0-1{
160
+ .magritte-value-container___9JR3e_1-0-3{
138
161
  pointer-events:none;
139
162
  }
140
- @keyframes magritte-caret-blink___-bhg7_1-0-1{
163
+ .magritte-ghost-value___jPQwY_1-0-3{
164
+ display:inline-block;
165
+ visibility:hidden;
166
+ }
167
+ @keyframes magritte-caret-blink___-bhg7_1-0-3{
141
168
  50%{
142
169
  opacity:0;
143
170
  }
package/index.js CHANGED
@@ -4,6 +4,5 @@ import 'react/jsx-runtime';
4
4
  import 'react';
5
5
  import 'classnames';
6
6
  import '@hh.ru/magritte-common-keyboard';
7
- import '@hh.ru/magritte-common-text-selection';
8
7
  import '@hh.ru/magritte-ui-form-helper';
9
8
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hh.ru/magritte-ui-pincode-input",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "main": "index.js",
5
5
  "types": "index.d.ts",
6
6
  "sideEffects": [
@@ -23,13 +23,12 @@
23
23
  "access": "public"
24
24
  },
25
25
  "dependencies": {
26
- "@hh.ru/magritte-common-keyboard": "4.0.4",
27
- "@hh.ru/magritte-common-text-selection": "0.1.5",
28
- "@hh.ru/magritte-ui-form-helper": "1.0.21"
26
+ "@hh.ru/magritte-common-keyboard": "4.1.0",
27
+ "@hh.ru/magritte-ui-form-helper": "1.0.22"
29
28
  },
30
29
  "peerDependencies": {
31
30
  "classnames": ">=2.3.2",
32
31
  "react": ">=18.2.0"
33
32
  },
34
- "gitHead": "75a6b12c08b7ca443e43da143a22adfc91282816"
33
+ "gitHead": "d271475c7ce8c1d6fc8b33ed345f1d9a6dcd8835"
35
34
  }