@skbkontur/react-ui 6.1.4-5ebac.0 → 6.1.4-6f608.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.
- package/components/MaskedInput/MaskedInput.d.ts +3 -0
- package/components/MaskedInput/MaskedInput.js.map +1 -1
- package/components/MaskedInput/index.d.ts +1 -0
- package/components/MaskedInput/index.js +1 -0
- package/components/MaskedInput/index.js.map +1 -1
- package/components/MaskedInputV2/MaskedInputV2.d.ts +3 -0
- package/components/MaskedInputV2/MaskedInputV2.js +8 -1
- package/components/MaskedInputV2/MaskedInputV2.js.map +1 -1
- package/components/MaskedInputV2/MaskedInputV2.phone.d.ts +28 -0
- package/components/MaskedInputV2/MaskedInputV2.phone.js +38 -0
- package/components/MaskedInputV2/MaskedInputV2.phone.js.map +1 -0
- package/components/MaskedInputV2/index.d.ts +1 -0
- package/components/MaskedInputV2/index.js +1 -0
- package/components/MaskedInputV2/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -30,6 +30,9 @@ export interface MaskedProps {
|
|
|
30
30
|
*
|
|
31
31
|
* Обработчик должен вернуть текст — он попадёт в поле.
|
|
32
32
|
*
|
|
33
|
+
* При `type="tel"` и отсутствии обработчика применяется
|
|
34
|
+
* `normalizeRussianPhonePaste` (только в MaskedInputV2).
|
|
35
|
+
*
|
|
33
36
|
* @param value значение вставки.
|
|
34
37
|
*/
|
|
35
38
|
onBeforePasteValue?: MaskedInputOnBeforePasteValue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MaskedInput.js","sourceRoot":"","sources":["MaskedInput.tsx"],"names":[],"mappings":";;;;;;;;;;;AACA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAG1C,OAAO,EAAE,0BAA0B,EAAE,MAAM,wCAAwC,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAEnE,OAAO,EAAE,aAAa,EAA2B,MAAM,2BAA2B,CAAC;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"MaskedInput.js","sourceRoot":"","sources":["MaskedInput.tsx"],"names":[],"mappings":";;;;;;;;;;;AACA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAG1C,OAAO,EAAE,0BAA0B,EAAE,MAAM,wCAAwC,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAEnE,OAAO,EAAE,aAAa,EAA2B,MAAM,2BAA2B,CAAC;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AA6D3D,MAAM,CAAC,IAAM,oBAAoB,GAAG,UAAC,IAAgB;IACnD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IACd,CAAC;IAED,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ,CAAC;QACd,KAAK,MAAM,CAAC;QACZ,KAAK,MAAM,CAAC;QACZ,KAAK,UAAU;YACb,OAAO,MAAM,CAAC;QAChB;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC,CAAC;AAYF;;;GAGG;AACH,MAAM,CAAC,IAAM,WAAW,GAAG,iBAAiB,CAC1C,aAAa,EACb,SAAS,WAAW,CAAC,KAAuB,EAAE,GAAsB;IAC1D,IAAA,4BAA4B,GAAK,UAAU,CAAC,0BAA0B,CAAC,6BAA3C,CAA4C;IAEhF,IAAI,4BAA4B,EAAE,CAAC;QACjC,OAAO,oBAAC,iBAAiB,aAAC,GAAG,EAAE,GAAG,IAAM,KAAK,EAAI,CAAC;IACpD,CAAC;IAED,OAAO,oBAAC,aAAa,aAAC,GAAG,EAAE,GAAG,EAAE,uBAAuB,UAAM,KAA4B,EAAI,CAAC;AAChG,CAAC,CACF,CAAC","sourcesContent":["import type { IMaskInputProps } from '@skbkontur/react-imask';\nimport React, { useContext } from 'react';\nimport type { Ref } from 'react';\n\nimport { ReactUIFeatureFlagsContext } from '../../lib/featureFlagsContext/index.js';\nimport { forwardRefAndName } from '../../lib/forwardRefAndName.js';\nimport type { Input, InputProps, InputType } from '../Input/index.js';\nimport { MaskedInputV2, type MaskedInputV2Props } from '../MaskedInputV2/index.js';\nimport { MaskedInputLegacy } from './MaskedInputLegacy.js';\n\nexport type MaskedInputOnBeforePasteValue = (value: string) => string;\n\nexport interface MaskedProps {\n /** Шаблон ввода, определяющий допустимые символы. */\n mask: string;\n\n /** Плейсхолдер, который отображается на месте ещё не введённых пользователем символов.\n * @default _ */\n maskChar?: string;\n\n /** Словарь правил для настройки маски, где:\n * ключ — символ для использования в маске;\n * значение — регулярка-правило.\n * @default { '9': '[0-9]', 'a': '[A-Za-z]', '*': '[A-Za-z0-9]' } */\n formatChars?: Record<string, string>;\n\n /** Всегда показывать символы маски, независимо от фокуса в поле.\n * @default false */\n alwaysShowMask?: boolean;\n\n /** Событие некорректного ввода.\n * Вторым аргументом передаётся метод вспыхивания рамки поля.\n *\n * Если обработчик не задан, то при событии рамка всегда вспыхивает.\n *\n * @param value значение поля\n * @param blink метод вспыхивания рамки поля\n */\n onUnexpectedInput?: (value: string, blink: () => void) => void;\n\n /**\n * Событие перед вставкой текста в поле.\n * Вызывается с аргументом value — текст из буфера.\n *\n * Обработчик должен вернуть текст — он попадёт в поле.\n *\n * При `type=\"tel\"` и отсутствии обработчика применяется\n * `normalizeRussianPhonePaste` (только в MaskedInputV2).\n *\n * @param value значение вставки.\n */\n onBeforePasteValue?: MaskedInputOnBeforePasteValue;\n\n /** Убирает из value символы маски, которые пользователь не вводил.\n * @default false */\n unmask?: boolean;\n\n /** Раскрашивает символы маски.\n * @default true\n * @ignore */\n colored?: boolean;\n\n /** Задает пропсы для компонента `IMaskInput`. Необходимы для юнит-тестов\n * @ignore */\n imaskProps?: IMaskInputProps<HTMLInputElement>;\n}\n\nexport type MaskInputType = Exclude<InputType, 'number' | 'date' | 'time' | 'password'>;\n\nexport const getSafeMaskInputType = (type?: InputType): MaskInputType | undefined => {\n if (!type) {\n return type;\n }\n\n switch (type) {\n case 'number':\n case 'date':\n case 'time':\n case 'password':\n return 'text';\n default:\n return type;\n }\n};\n\nexport interface MaskedInputProps\n extends\n MaskedProps,\n Omit<\n InputProps,\n 'showClearIcon' | 'mask' | 'maxLength' | 'type' | 'alwaysShowMask' | 'onUnexpectedInput' | 'maskChar'\n > {\n type?: MaskInputType;\n}\n\n/** Поле ввода, которое ограничивает формат вводимого значения по заданной маске. Такое поле облегчает пользователю ввод и снижает количество ошибок.\n *\n * По умолчанию используется исправленная реализация MaskedInputV2. Для legacy-поведения включите фичафлаг `maskedInputUseLegacyBehavior` в {@link ReactUIFeatureFlagsContext}.\n */\nexport const MaskedInput = forwardRefAndName(\n 'MaskedInput',\n function MaskedInput(props: MaskedInputProps, ref: Ref<Input | null>) {\n const { maskedInputUseLegacyBehavior } = useContext(ReactUIFeatureFlagsContext);\n\n if (maskedInputUseLegacyBehavior) {\n return <MaskedInputLegacy ref={ref} {...props} />;\n }\n\n return <MaskedInputV2 ref={ref} __fromMaskedInputFacade {...(props as MaskedInputV2Props)} />;\n },\n);\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC","sourcesContent":["export * from './MaskedInput.js';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC","sourcesContent":["export * from './MaskedInput.js';\nexport { MaskedInputMasks, normalizeRussianPhonePaste } from '../MaskedInputV2/MaskedInputV2.phone.js';\n"]}
|
|
@@ -32,6 +32,9 @@ export interface MaskedInputV2MaskedProps {
|
|
|
32
32
|
*
|
|
33
33
|
* Обработчик должен вернуть текст — он попадёт в поле.
|
|
34
34
|
*
|
|
35
|
+
* При `type="tel"` и отсутствии обработчика применяется
|
|
36
|
+
* {@link normalizeRussianPhonePaste}.
|
|
37
|
+
*
|
|
35
38
|
* @param value значение вставки.
|
|
36
39
|
*/
|
|
37
40
|
onBeforePasteValue?: MaskedInputV2OnBeforePasteValue;
|
|
@@ -31,6 +31,7 @@ import { MaskedCore } from './internal/MaskedCore.js';
|
|
|
31
31
|
import { setMaskInputSelectionRange } from './internal/setMaskInputSelectionRange.js';
|
|
32
32
|
import { useMaskEngine } from './internal/useMaskEngine.js';
|
|
33
33
|
import { getDefinitions, getMaskChar } from './MaskedInputV2.helpers.js';
|
|
34
|
+
import { normalizeRussianPhonePaste } from './MaskedInputV2.phone.js';
|
|
34
35
|
import { getStyles, globalClasses } from './MaskedInputV2.styles.js';
|
|
35
36
|
var EMPTY_IMASK_PROPS = {};
|
|
36
37
|
export var getSafeMaskInputType = function (type) {
|
|
@@ -199,7 +200,13 @@ export var MaskedInputV2 = forwardRefAndName('MaskedInputV2', function MaskedInp
|
|
|
199
200
|
: findNearestRawLeft(selectionStart, engine.slotMap);
|
|
200
201
|
var rawBefore = raw.slice(0, rawCursorPos);
|
|
201
202
|
var rawAfter = raw.slice(rawCursorPos);
|
|
202
|
-
var transformed =
|
|
203
|
+
var transformed = pasted;
|
|
204
|
+
if (onBeforePasteValue) {
|
|
205
|
+
transformed = onBeforePasteValue(pasted);
|
|
206
|
+
}
|
|
207
|
+
else if (getSafeMaskInputType(type) === 'tel') {
|
|
208
|
+
transformed = normalizeRussianPhonePaste(pasted);
|
|
209
|
+
}
|
|
203
210
|
var result = engine.applyPaste(raw, rawCursorPos, transformed);
|
|
204
211
|
if (result.overflow) {
|
|
205
212
|
// IF-1157: paste с overflow → onUnexpectedInput
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MaskedInputV2.js","sourceRoot":"","sources":["MaskedInputV2.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, {\n useCallback,\n useContext,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { Ref } from 'react';\nimport warning from 'warning';\n\nimport { forwardRefAndName } from '../../lib/forwardRefAndName.js';\nimport { useEmotion, useStyles } from '../../lib/renderEnvironment/index.js';\nimport { ThemeContext } from '../../lib/theming/ThemeContext.js';\nimport type { InputProps, InputType } from '../Input/index.js';\nimport { Input, selectionAllowedTypes } from '../Input/index.js';\nimport { extractRaw, findNearestRawLeft, computePasteMaskedCursor } from './internal/helpers.js';\nimport { MaskedCore } from './internal/MaskedCore.js';\nimport type { MaskedSelectionIntent } from './internal/MaskedCore.types.js';\nimport { setMaskInputSelectionRange } from './internal/setMaskInputSelectionRange.js';\nimport { useMaskEngine } from './internal/useMaskEngine.js';\nimport { getDefinitions, getMaskChar } from './MaskedInputV2.helpers.js';\nimport { getStyles, globalClasses } from './MaskedInputV2.styles.js';\nimport type { IMaskInputProps } from './react-imask/mixin.js';\n\nexport type MaskedInputV2OnBeforePasteValue = (value: string) => string;\n\nexport interface MaskedInputV2MaskedProps {\n /** Шаблон ввода, определяющий допустимые символы. */\n mask: string;\n\n /** Плейсхолдер, который отображается на месте ещё не введённых пользователем символов.\n * @default _ */\n maskChar?: string;\n\n /** Словарь правил для настройки маски, где:\n * ключ — символ для использования в маске;\n * значение — регулярка-правило.\n * @default { '9': '[0-9]', 'a': '[A-Za-z]', '*': '[A-Za-z0-9]' } */\n formatChars?: Record<string, string>;\n\n /** Всегда показывать символы маски, независимо от фокуса в поле.\n * @default false */\n alwaysShowMask?: boolean;\n\n /** Событие некорректного ввода.\n * Вторым аргументом передаётся метод вспыхивания рамки поля.\n *\n * Если обработчик не задан, то при событии рамка всегда вспыхивает.\n *\n * @param value значение поля\n * @param blink метод вспыхивания рамки поля\n */\n onUnexpectedInput?: (value: string, blink: () => void) => void;\n\n /**\n * Событие перед вставкой текста в поле.\n * Вызывается с аргументом value — текст из буфера.\n *\n * Обработчик должен вернуть текст — он попадёт в поле.\n *\n * @param value значение вставки.\n */\n onBeforePasteValue?: MaskedInputV2OnBeforePasteValue;\n\n /** Убирает из value символы маски, которые пользователь не вводил.\n * @default false */\n unmask?: boolean;\n\n /** Раскрашивает символы маски.\n * @default true\n * @ignore */\n colored?: boolean;\n\n /** Задает пропсы для компонента `IMaskInput`. Необходимы для юнит-тестов\n * @ignore */\n imaskProps?: IMaskInputProps<HTMLInputElement>;\n}\n\nexport type MaskInputType = Exclude<InputType, 'number' | 'date' | 'time' | 'password'>;\n\nconst EMPTY_IMASK_PROPS = {};\n\nexport const getSafeMaskInputType = (type?: InputType | string): MaskInputType | undefined => {\n if (!type) {\n return undefined;\n }\n\n const normalizedType = type.trim() as InputType;\n\n if (normalizedType === 'password' || !selectionAllowedTypes.includes(normalizedType)) {\n return 'text';\n }\n\n return normalizedType as MaskInputType;\n};\n\nfunction getMaskInputMode(\n type: InputType | string | undefined,\n inputMode: React.InputHTMLAttributes<HTMLInputElement>['inputMode'],\n): React.InputHTMLAttributes<HTMLInputElement>['inputMode'] {\n if (inputMode) {\n return inputMode;\n }\n\n if (type?.trim() === 'email') {\n return 'email';\n }\n\n return undefined;\n}\n\nexport interface MaskedInputV2Props\n extends\n MaskedInputV2MaskedProps,\n Omit<\n InputProps,\n 'showClearIcon' | 'mask' | 'maxLength' | 'type' | 'alwaysShowMask' | 'onUnexpectedInput' | 'maskChar'\n > {\n type?: MaskInputType;\n\n /** @ignore */\n __fromMaskedInputFacade?: boolean;\n}\n\n/** @deprecated Используйте {@link MaskedInput}. Для legacy-поведения включите фичафлаг `maskedInputUseLegacyBehavior` в {@link ReactUIFeatureFlagsContext}. */\nexport const MaskedInputV2 = forwardRefAndName(\n 'MaskedInputV2',\n function MaskedInputV2(props: MaskedInputV2Props, ref: Ref<Input | null>) {\n const {\n mask,\n maskChar,\n formatChars,\n alwaysShowMask = false,\n colored = true,\n imaskProps: customIMaskProps = EMPTY_IMASK_PROPS,\n unmask = false,\n onValueChange,\n onUnexpectedInput,\n onBeforePasteValue,\n element: _element,\n className,\n // @ts-expect-error: могут передавать игнорируя ошибку\n maxLength,\n // @ts-expect-error: могут передавать игнорируя ошибку\n showClearIcon: _showClearIcon,\n selectAllOnFocus,\n type,\n __fromMaskedInputFacade,\n ...inputProps\n } = props;\n\n useEffect(() => {\n if (!__fromMaskedInputFacade) {\n warning(false, '[MaskedInputV2]: This component is for internal use only. Please use MaskedInput instead.');\n }\n }, [__fromMaskedInputFacade]);\n\n const theme = useContext(ThemeContext);\n const { cx } = useEmotion();\n const styles = useStyles(getStyles);\n\n const inputRef = useRef<Input>(null);\n const coreInputRef = useRef<HTMLInputElement>(null);\n\n const [focused, setFocused] = useState(false);\n const [selectionIntent, setSelectionIntent] = useState<MaskedSelectionIntent>(null);\n\n const prevMaskRef = useRef(props.mask);\n const pendingCursorRestoreRef = useRef<number | null>(null);\n const lastCaretRef = useRef(0);\n\n const requestSelectionIntent = useCallback((intent: MaskedSelectionIntent) => {\n setSelectionIntent((current) => (current === 'select-all' && intent === 'caret-end' ? current : intent));\n }, []);\n\n const historyRef = useRef<Array<{ raw: string; cursorPos: number }>>([]);\n const historyIndexRef = useRef(-1);\n\n // Сохраняем позицию курсора перед сменой маски (render-phase read of stable ref).\n // При коммите DOM браузер сбросит курсор в конец из-за изменения value,\n // поэтому восстанавливаем его синхронно в useLayoutEffect ниже.\n if (prevMaskRef.current !== props.mask) {\n pendingCursorRestoreRef.current = lastCaretRef.current;\n prevMaskRef.current = props.mask;\n historyRef.current = [];\n historyIndexRef.current = -1;\n }\n\n // Движок: IMask как чистый калькулятор, не привязанный к DOM\n const engine = useMaskEngine({\n mask,\n maskChar,\n formatChars,\n unmask,\n alwaysShowMask,\n imaskProps: customIMaskProps,\n });\n\n // Единственный источник истины — raw (только то, что ввёл пользователь, без маски)\n const [raw, setRaw] = useState<string>(() =>\n extractRaw((props.value ?? props.defaultValue) as string | number | undefined, engine),\n );\n\n // MaskState вычисляется синхронно из raw — оба визуальных слоя читают из него\n const maskState = useMemo(() => engine.compute(raw, focused), [raw, focused, engine]);\n\n const syncedImaskRef = useRef(engine.imask);\n const prevSyncedValueRef = useRef(props.value);\n\n // Синхронизировать raw при изменении props.value или правил маски\n useEffect(() => {\n const engineChanged = syncedImaskRef.current !== engine.imask;\n const valueChanged = prevSyncedValueRef.current !== props.value;\n syncedImaskRef.current = engine.imask;\n prevSyncedValueRef.current = props.value;\n\n if (props.value !== undefined) {\n if (valueChanged || engineChanged) {\n setRaw(extractRaw(props.value, engine));\n }\n return;\n }\n\n if (engineChanged) {\n setRaw((prev) => {\n engine.imask.unmaskedValue = prev;\n return engine.imask.rawInputValue;\n });\n }\n }, [props.value, engine]);\n\n // Вызывать onValueChange только при реальном изменении outputValue,\n // и НЕ при первом рендере (воспроизводит нативное поведение onChange)\n const isFirstRender = useRef(true);\n const prevOutputValue = useRef<string>(maskState.outputValue);\n useEffect(() => {\n if (isFirstRender.current) {\n isFirstRender.current = false;\n prevOutputValue.current = maskState.outputValue;\n return;\n }\n if (maskState.outputValue !== prevOutputValue.current) {\n prevOutputValue.current = maskState.outputValue;\n onValueChange?.(maskState.outputValue);\n }\n }, [maskState.outputValue]);\n\n useImperativeHandle<Input | null, (Input & { selectAll: () => void }) | null>(ref, () => {\n if (!inputRef.current) {\n return null;\n }\n return Object.assign(inputRef.current, {\n selectAll: () => {\n requestSelectionIntent('select-all');\n inputRef.current?.focus();\n const el = coreInputRef.current;\n if (el && el.ownerDocument.activeElement !== el) {\n requestSelectionIntent(null);\n }\n },\n });\n }, [requestSelectionIntent]);\n\n useLayoutEffect(() => {\n if (pendingCursorRestoreRef.current !== null && coreInputRef.current) {\n setMaskInputSelectionRange(coreInputRef.current, pendingCursorRestoreRef.current);\n lastCaretRef.current = pendingCursorRestoreRef.current;\n pendingCursorRestoreRef.current = null;\n }\n });\n\n useEffect(() => {\n if (!focused) {\n return;\n }\n\n const el = coreInputRef.current;\n if (!el) {\n return;\n }\n\n const syncCaret = () => {\n if (document.activeElement === el) {\n lastCaretRef.current = el.selectionStart ?? 0;\n }\n };\n\n document.addEventListener('selectionchange', syncCaret);\n return () => document.removeEventListener('selectionchange', syncCaret);\n }, [focused]);\n\n return (\n <Input\n ref={inputRef}\n {...inputProps}\n type={getSafeMaskInputType(type)}\n inputMode={getMaskInputMode(type, inputProps.inputMode)}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onSelect={handleSelect}\n className={cx(globalClasses.root, className, styles.root(theme))}\n element={\n <MaskedCore\n maskState={maskState}\n slotMap={engine.slotMap}\n engine={engine}\n focused={focused}\n currentRaw={raw}\n onRawChange={handleRawChange}\n onUnexpectedInput={triggerUnexpectedInput}\n onUndo={handleUndo}\n onRedo={handleRedo}\n coreInputRef={coreInputRef}\n colored={colored}\n selectAllOnFocus={selectAllOnFocus}\n selectionIntent={selectionIntent}\n onSelectionIntentChange={requestSelectionIntent}\n />\n }\n />\n );\n\n function handleRawChange(input: string, source: 'input' | 'paste', cursorPos?: number) {\n if (source === 'paste') {\n handlePasteChange(input, cursorPos);\n } else {\n if (input !== raw && cursorPos !== undefined) {\n pushHistory(input, cursorPos);\n }\n setRaw(input);\n }\n }\n\n function handlePasteChange(pasted: string, _cursorPos?: number) {\n const el = coreInputRef.current;\n const selectionStart = el?.selectionStart ?? 0;\n\n // Находим rawPos по maskedPos курсора\n const rawCursorPos =\n engine.slotMap.maskedToRaw[selectionStart] !== null && engine.slotMap.maskedToRaw[selectionStart] !== undefined\n ? (engine.slotMap.maskedToRaw[selectionStart] as number)\n : findNearestRawLeft(selectionStart, engine.slotMap);\n\n const rawBefore = raw.slice(0, rawCursorPos);\n const rawAfter = raw.slice(rawCursorPos);\n const transformed = onBeforePasteValue ? onBeforePasteValue(pasted) : pasted;\n const result = engine.applyPaste(raw, rawCursorPos, transformed);\n\n if (result.overflow) {\n // IF-1157: paste с overflow → onUnexpectedInput\n triggerUnexpectedInput();\n }\n\n const postPasteMaskState = engine.compute(result.raw, true);\n const maskedCursorPos = computePasteMaskedCursor(\n rawBefore,\n rawAfter,\n result.raw,\n rawCursorPos,\n engine.slotMap,\n postPasteMaskState.typedLength,\n );\n\n if (result.raw !== raw) {\n pushHistory(result.raw, maskedCursorPos);\n }\n\n setRaw(result.raw);\n pendingCursorRestoreRef.current = maskedCursorPos;\n\n if (onBeforePasteValue && onValueChange) {\n // Legacy-контракт: при кастомной вставке наружу уходит результат onBeforePasteValue,\n // а не masked/unmasked outputValue (нужно для ComboBox и совместимости с IMaskInput).\n prevOutputValue.current = engine.compute(result.raw, focused).outputValue;\n onValueChange(transformed);\n }\n }\n\n function pushHistory(newRaw: string, cursorPos: number) {\n const MAX_HISTORY_LENGTH = 100;\n\n if (historyRef.current.length === 0) {\n historyRef.current.push({ raw, cursorPos: 0 });\n historyIndexRef.current = 0;\n }\n\n if (historyIndexRef.current < historyRef.current.length - 1) {\n historyRef.current = historyRef.current.slice(0, historyIndexRef.current + 1);\n }\n\n historyRef.current.push({ raw: newRaw, cursorPos });\n if (historyRef.current.length > MAX_HISTORY_LENGTH) {\n historyRef.current.shift();\n }\n historyIndexRef.current = historyRef.current.length - 1;\n }\n\n function handleUndo() {\n if (historyRef.current.length === 0) {\n return;\n }\n const nextIndex = Math.max(0, historyIndexRef.current - 1);\n if (nextIndex !== historyIndexRef.current) {\n historyIndexRef.current = nextIndex;\n const state = historyRef.current[nextIndex];\n setRaw(state.raw);\n pendingCursorRestoreRef.current = state.cursorPos;\n }\n }\n\n function handleRedo() {\n if (historyRef.current.length === 0) {\n return;\n }\n const nextIndex = Math.min(historyRef.current.length - 1, historyIndexRef.current + 1);\n if (nextIndex !== historyIndexRef.current) {\n historyIndexRef.current = nextIndex;\n const state = historyRef.current[nextIndex];\n setRaw(state.raw);\n pendingCursorRestoreRef.current = state.cursorPos;\n }\n }\n\n function triggerUnexpectedInput() {\n const blink = inputRef.current?.blink.bind(inputRef.current) ?? (() => undefined);\n onUnexpectedInput ? onUnexpectedInput(maskState.outputValue, blink) : blink();\n }\n\n function handleFocus(e: React.FocusEvent<HTMLInputElement>) {\n setFocused(true);\n props.onFocus?.(e);\n }\n\n function handleBlur(e: React.FocusEvent<HTMLInputElement>) {\n setFocused(false);\n props.onBlur?.(e);\n }\n\n function handleSelect(e: React.SyntheticEvent<HTMLInputElement>) {\n if (coreInputRef.current) {\n lastCaretRef.current = coreInputRef.current.selectionStart ?? 0;\n }\n inputProps.onSelect?.(e);\n }\n },\n);\n\n// Вспомогательные функции для совместимости (используются в стори и тестах)\nexport { getDefinitions, getMaskChar };\n"]}
|
|
1
|
+
{"version":3,"file":"MaskedInputV2.js","sourceRoot":"","sources":["MaskedInputV2.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, {\n useCallback,\n useContext,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { Ref } from 'react';\nimport warning from 'warning';\n\nimport { forwardRefAndName } from '../../lib/forwardRefAndName.js';\nimport { useEmotion, useStyles } from '../../lib/renderEnvironment/index.js';\nimport { ThemeContext } from '../../lib/theming/ThemeContext.js';\nimport type { InputProps, InputType } from '../Input/index.js';\nimport { Input, selectionAllowedTypes } from '../Input/index.js';\nimport { extractRaw, findNearestRawLeft, computePasteMaskedCursor } from './internal/helpers.js';\nimport { MaskedCore } from './internal/MaskedCore.js';\nimport type { MaskedSelectionIntent } from './internal/MaskedCore.types.js';\nimport { setMaskInputSelectionRange } from './internal/setMaskInputSelectionRange.js';\nimport { useMaskEngine } from './internal/useMaskEngine.js';\nimport { getDefinitions, getMaskChar } from './MaskedInputV2.helpers.js';\nimport { normalizeRussianPhonePaste } from './MaskedInputV2.phone.js';\nimport { getStyles, globalClasses } from './MaskedInputV2.styles.js';\nimport type { IMaskInputProps } from './react-imask/mixin.js';\n\nexport type MaskedInputV2OnBeforePasteValue = (value: string) => string;\n\nexport interface MaskedInputV2MaskedProps {\n /** Шаблон ввода, определяющий допустимые символы. */\n mask: string;\n\n /** Плейсхолдер, который отображается на месте ещё не введённых пользователем символов.\n * @default _ */\n maskChar?: string;\n\n /** Словарь правил для настройки маски, где:\n * ключ — символ для использования в маске;\n * значение — регулярка-правило.\n * @default { '9': '[0-9]', 'a': '[A-Za-z]', '*': '[A-Za-z0-9]' } */\n formatChars?: Record<string, string>;\n\n /** Всегда показывать символы маски, независимо от фокуса в поле.\n * @default false */\n alwaysShowMask?: boolean;\n\n /** Событие некорректного ввода.\n * Вторым аргументом передаётся метод вспыхивания рамки поля.\n *\n * Если обработчик не задан, то при событии рамка всегда вспыхивает.\n *\n * @param value значение поля\n * @param blink метод вспыхивания рамки поля\n */\n onUnexpectedInput?: (value: string, blink: () => void) => void;\n\n /**\n * Событие перед вставкой текста в поле.\n * Вызывается с аргументом value — текст из буфера.\n *\n * Обработчик должен вернуть текст — он попадёт в поле.\n *\n * При `type=\"tel\"` и отсутствии обработчика применяется\n * {@link normalizeRussianPhonePaste}.\n *\n * @param value значение вставки.\n */\n onBeforePasteValue?: MaskedInputV2OnBeforePasteValue;\n\n /** Убирает из value символы маски, которые пользователь не вводил.\n * @default false */\n unmask?: boolean;\n\n /** Раскрашивает символы маски.\n * @default true\n * @ignore */\n colored?: boolean;\n\n /** Задает пропсы для компонента `IMaskInput`. Необходимы для юнит-тестов\n * @ignore */\n imaskProps?: IMaskInputProps<HTMLInputElement>;\n}\n\nexport type MaskInputType = Exclude<InputType, 'number' | 'date' | 'time' | 'password'>;\n\nconst EMPTY_IMASK_PROPS = {};\n\nexport const getSafeMaskInputType = (type?: InputType | string): MaskInputType | undefined => {\n if (!type) {\n return undefined;\n }\n\n const normalizedType = type.trim() as InputType;\n\n if (normalizedType === 'password' || !selectionAllowedTypes.includes(normalizedType)) {\n return 'text';\n }\n\n return normalizedType as MaskInputType;\n};\n\nfunction getMaskInputMode(\n type: InputType | string | undefined,\n inputMode: React.InputHTMLAttributes<HTMLInputElement>['inputMode'],\n): React.InputHTMLAttributes<HTMLInputElement>['inputMode'] {\n if (inputMode) {\n return inputMode;\n }\n\n if (type?.trim() === 'email') {\n return 'email';\n }\n\n return undefined;\n}\n\nexport interface MaskedInputV2Props\n extends\n MaskedInputV2MaskedProps,\n Omit<\n InputProps,\n 'showClearIcon' | 'mask' | 'maxLength' | 'type' | 'alwaysShowMask' | 'onUnexpectedInput' | 'maskChar'\n > {\n type?: MaskInputType;\n\n /** @ignore */\n __fromMaskedInputFacade?: boolean;\n}\n\n/** @deprecated Используйте {@link MaskedInput}. Для legacy-поведения включите фичафлаг `maskedInputUseLegacyBehavior` в {@link ReactUIFeatureFlagsContext}. */\nexport const MaskedInputV2 = forwardRefAndName(\n 'MaskedInputV2',\n function MaskedInputV2(props: MaskedInputV2Props, ref: Ref<Input | null>) {\n const {\n mask,\n maskChar,\n formatChars,\n alwaysShowMask = false,\n colored = true,\n imaskProps: customIMaskProps = EMPTY_IMASK_PROPS,\n unmask = false,\n onValueChange,\n onUnexpectedInput,\n onBeforePasteValue,\n element: _element,\n className,\n // @ts-expect-error: могут передавать игнорируя ошибку\n maxLength,\n // @ts-expect-error: могут передавать игнорируя ошибку\n showClearIcon: _showClearIcon,\n selectAllOnFocus,\n type,\n __fromMaskedInputFacade,\n ...inputProps\n } = props;\n\n useEffect(() => {\n if (!__fromMaskedInputFacade) {\n warning(false, '[MaskedInputV2]: This component is for internal use only. Please use MaskedInput instead.');\n }\n }, [__fromMaskedInputFacade]);\n\n const theme = useContext(ThemeContext);\n const { cx } = useEmotion();\n const styles = useStyles(getStyles);\n\n const inputRef = useRef<Input>(null);\n const coreInputRef = useRef<HTMLInputElement>(null);\n\n const [focused, setFocused] = useState(false);\n const [selectionIntent, setSelectionIntent] = useState<MaskedSelectionIntent>(null);\n\n const prevMaskRef = useRef(props.mask);\n const pendingCursorRestoreRef = useRef<number | null>(null);\n const lastCaretRef = useRef(0);\n\n const requestSelectionIntent = useCallback((intent: MaskedSelectionIntent) => {\n setSelectionIntent((current) => (current === 'select-all' && intent === 'caret-end' ? current : intent));\n }, []);\n\n const historyRef = useRef<Array<{ raw: string; cursorPos: number }>>([]);\n const historyIndexRef = useRef(-1);\n\n // Сохраняем позицию курсора перед сменой маски (render-phase read of stable ref).\n // При коммите DOM браузер сбросит курсор в конец из-за изменения value,\n // поэтому восстанавливаем его синхронно в useLayoutEffect ниже.\n if (prevMaskRef.current !== props.mask) {\n pendingCursorRestoreRef.current = lastCaretRef.current;\n prevMaskRef.current = props.mask;\n historyRef.current = [];\n historyIndexRef.current = -1;\n }\n\n // Движок: IMask как чистый калькулятор, не привязанный к DOM\n const engine = useMaskEngine({\n mask,\n maskChar,\n formatChars,\n unmask,\n alwaysShowMask,\n imaskProps: customIMaskProps,\n });\n\n // Единственный источник истины — raw (только то, что ввёл пользователь, без маски)\n const [raw, setRaw] = useState<string>(() =>\n extractRaw((props.value ?? props.defaultValue) as string | number | undefined, engine),\n );\n\n // MaskState вычисляется синхронно из raw — оба визуальных слоя читают из него\n const maskState = useMemo(() => engine.compute(raw, focused), [raw, focused, engine]);\n\n const syncedImaskRef = useRef(engine.imask);\n const prevSyncedValueRef = useRef(props.value);\n\n // Синхронизировать raw при изменении props.value или правил маски\n useEffect(() => {\n const engineChanged = syncedImaskRef.current !== engine.imask;\n const valueChanged = prevSyncedValueRef.current !== props.value;\n syncedImaskRef.current = engine.imask;\n prevSyncedValueRef.current = props.value;\n\n if (props.value !== undefined) {\n if (valueChanged || engineChanged) {\n setRaw(extractRaw(props.value, engine));\n }\n return;\n }\n\n if (engineChanged) {\n setRaw((prev) => {\n engine.imask.unmaskedValue = prev;\n return engine.imask.rawInputValue;\n });\n }\n }, [props.value, engine]);\n\n // Вызывать onValueChange только при реальном изменении outputValue,\n // и НЕ при первом рендере (воспроизводит нативное поведение onChange)\n const isFirstRender = useRef(true);\n const prevOutputValue = useRef<string>(maskState.outputValue);\n useEffect(() => {\n if (isFirstRender.current) {\n isFirstRender.current = false;\n prevOutputValue.current = maskState.outputValue;\n return;\n }\n if (maskState.outputValue !== prevOutputValue.current) {\n prevOutputValue.current = maskState.outputValue;\n onValueChange?.(maskState.outputValue);\n }\n }, [maskState.outputValue]);\n\n useImperativeHandle<Input | null, (Input & { selectAll: () => void }) | null>(ref, () => {\n if (!inputRef.current) {\n return null;\n }\n return Object.assign(inputRef.current, {\n selectAll: () => {\n requestSelectionIntent('select-all');\n inputRef.current?.focus();\n const el = coreInputRef.current;\n if (el && el.ownerDocument.activeElement !== el) {\n requestSelectionIntent(null);\n }\n },\n });\n }, [requestSelectionIntent]);\n\n useLayoutEffect(() => {\n if (pendingCursorRestoreRef.current !== null && coreInputRef.current) {\n setMaskInputSelectionRange(coreInputRef.current, pendingCursorRestoreRef.current);\n lastCaretRef.current = pendingCursorRestoreRef.current;\n pendingCursorRestoreRef.current = null;\n }\n });\n\n useEffect(() => {\n if (!focused) {\n return;\n }\n\n const el = coreInputRef.current;\n if (!el) {\n return;\n }\n\n const syncCaret = () => {\n if (document.activeElement === el) {\n lastCaretRef.current = el.selectionStart ?? 0;\n }\n };\n\n document.addEventListener('selectionchange', syncCaret);\n return () => document.removeEventListener('selectionchange', syncCaret);\n }, [focused]);\n\n return (\n <Input\n ref={inputRef}\n {...inputProps}\n type={getSafeMaskInputType(type)}\n inputMode={getMaskInputMode(type, inputProps.inputMode)}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onSelect={handleSelect}\n className={cx(globalClasses.root, className, styles.root(theme))}\n element={\n <MaskedCore\n maskState={maskState}\n slotMap={engine.slotMap}\n engine={engine}\n focused={focused}\n currentRaw={raw}\n onRawChange={handleRawChange}\n onUnexpectedInput={triggerUnexpectedInput}\n onUndo={handleUndo}\n onRedo={handleRedo}\n coreInputRef={coreInputRef}\n colored={colored}\n selectAllOnFocus={selectAllOnFocus}\n selectionIntent={selectionIntent}\n onSelectionIntentChange={requestSelectionIntent}\n />\n }\n />\n );\n\n function handleRawChange(input: string, source: 'input' | 'paste', cursorPos?: number) {\n if (source === 'paste') {\n handlePasteChange(input, cursorPos);\n } else {\n if (input !== raw && cursorPos !== undefined) {\n pushHistory(input, cursorPos);\n }\n setRaw(input);\n }\n }\n\n function handlePasteChange(pasted: string, _cursorPos?: number) {\n const el = coreInputRef.current;\n const selectionStart = el?.selectionStart ?? 0;\n\n // Находим rawPos по maskedPos курсора\n const rawCursorPos =\n engine.slotMap.maskedToRaw[selectionStart] !== null && engine.slotMap.maskedToRaw[selectionStart] !== undefined\n ? (engine.slotMap.maskedToRaw[selectionStart] as number)\n : findNearestRawLeft(selectionStart, engine.slotMap);\n\n const rawBefore = raw.slice(0, rawCursorPos);\n const rawAfter = raw.slice(rawCursorPos);\n\n let transformed = pasted;\n if (onBeforePasteValue) {\n transformed = onBeforePasteValue(pasted);\n } else if (getSafeMaskInputType(type) === 'tel') {\n transformed = normalizeRussianPhonePaste(pasted);\n }\n\n const result = engine.applyPaste(raw, rawCursorPos, transformed);\n\n if (result.overflow) {\n // IF-1157: paste с overflow → onUnexpectedInput\n triggerUnexpectedInput();\n }\n\n const postPasteMaskState = engine.compute(result.raw, true);\n const maskedCursorPos = computePasteMaskedCursor(\n rawBefore,\n rawAfter,\n result.raw,\n rawCursorPos,\n engine.slotMap,\n postPasteMaskState.typedLength,\n );\n\n if (result.raw !== raw) {\n pushHistory(result.raw, maskedCursorPos);\n }\n\n setRaw(result.raw);\n pendingCursorRestoreRef.current = maskedCursorPos;\n\n if (onBeforePasteValue && onValueChange) {\n // Legacy-контракт: при кастомной вставке наружу уходит результат onBeforePasteValue,\n // а не masked/unmasked outputValue (нужно для ComboBox и совместимости с IMaskInput).\n prevOutputValue.current = engine.compute(result.raw, focused).outputValue;\n onValueChange(transformed);\n }\n }\n\n function pushHistory(newRaw: string, cursorPos: number) {\n const MAX_HISTORY_LENGTH = 100;\n\n if (historyRef.current.length === 0) {\n historyRef.current.push({ raw, cursorPos: 0 });\n historyIndexRef.current = 0;\n }\n\n if (historyIndexRef.current < historyRef.current.length - 1) {\n historyRef.current = historyRef.current.slice(0, historyIndexRef.current + 1);\n }\n\n historyRef.current.push({ raw: newRaw, cursorPos });\n if (historyRef.current.length > MAX_HISTORY_LENGTH) {\n historyRef.current.shift();\n }\n historyIndexRef.current = historyRef.current.length - 1;\n }\n\n function handleUndo() {\n if (historyRef.current.length === 0) {\n return;\n }\n const nextIndex = Math.max(0, historyIndexRef.current - 1);\n if (nextIndex !== historyIndexRef.current) {\n historyIndexRef.current = nextIndex;\n const state = historyRef.current[nextIndex];\n setRaw(state.raw);\n pendingCursorRestoreRef.current = state.cursorPos;\n }\n }\n\n function handleRedo() {\n if (historyRef.current.length === 0) {\n return;\n }\n const nextIndex = Math.min(historyRef.current.length - 1, historyIndexRef.current + 1);\n if (nextIndex !== historyIndexRef.current) {\n historyIndexRef.current = nextIndex;\n const state = historyRef.current[nextIndex];\n setRaw(state.raw);\n pendingCursorRestoreRef.current = state.cursorPos;\n }\n }\n\n function triggerUnexpectedInput() {\n const blink = inputRef.current?.blink.bind(inputRef.current) ?? (() => undefined);\n onUnexpectedInput ? onUnexpectedInput(maskState.outputValue, blink) : blink();\n }\n\n function handleFocus(e: React.FocusEvent<HTMLInputElement>) {\n setFocused(true);\n props.onFocus?.(e);\n }\n\n function handleBlur(e: React.FocusEvent<HTMLInputElement>) {\n setFocused(false);\n props.onBlur?.(e);\n }\n\n function handleSelect(e: React.SyntheticEvent<HTMLInputElement>) {\n if (coreInputRef.current) {\n lastCaretRef.current = coreInputRef.current.selectionStart ?? 0;\n }\n inputProps.onSelect?.(e);\n }\n },\n);\n\n// Вспомогательные функции для совместимости (используются в стори и тестах)\nexport { getDefinitions, getMaskChar };\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Пресеты часто используемых масок для {@link MaskedInputV2} / {@link MaskedInput}.
|
|
3
|
+
*
|
|
4
|
+
* Российский телефон по [гайду](https://guides.kontur.ru/components/input-fields/phone/):
|
|
5
|
+
* префикс `+7` всегда виден и не стирается, остальные символы маски — только в фокусе.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* <MaskedInput
|
|
10
|
+
* type="tel"
|
|
11
|
+
* mask={MaskedInputMasks.PhoneRU}
|
|
12
|
+
* prefix={MaskedInputMasks.PhoneRUPrefix}
|
|
13
|
+
* />
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare const MaskedInputMasks: {
|
|
17
|
+
/** Национальная часть: `999 999-99-99`. Используйте вместе с `PhoneRUPrefix`. */
|
|
18
|
+
readonly PhoneRU: "999 999-99-99";
|
|
19
|
+
/** Несбрасываемый префикс «+7» (с неразрывным пробелом). */
|
|
20
|
+
readonly PhoneRUPrefix: "+7 ";
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Нормализует вставку российского номера телефона:
|
|
24
|
+
* убирает нецифровые символы и отрезает код страны `7`/`8` у 11+ значных номеров.
|
|
25
|
+
*
|
|
26
|
+
* Используется по умолчанию при `type="tel"`, если не задан `onBeforePasteValue`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function normalizeRussianPhonePaste(value: string): string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Пресеты часто используемых масок для {@link MaskedInputV2} / {@link MaskedInput}.
|
|
3
|
+
*
|
|
4
|
+
* Российский телефон по [гайду](https://guides.kontur.ru/components/input-fields/phone/):
|
|
5
|
+
* префикс `+7` всегда виден и не стирается, остальные символы маски — только в фокусе.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* <MaskedInput
|
|
10
|
+
* type="tel"
|
|
11
|
+
* mask={MaskedInputMasks.PhoneRU}
|
|
12
|
+
* prefix={MaskedInputMasks.PhoneRUPrefix}
|
|
13
|
+
* />
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export var MaskedInputMasks = {
|
|
17
|
+
/** Национальная часть: `999 999-99-99`. Используйте вместе с `PhoneRUPrefix`. */
|
|
18
|
+
PhoneRU: '999 999-99-99',
|
|
19
|
+
/** Несбрасываемый префикс «+7» (с неразрывным пробелом). */
|
|
20
|
+
PhoneRUPrefix: '+7\u00a0',
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Нормализует вставку российского номера телефона:
|
|
24
|
+
* убирает нецифровые символы и отрезает код страны `7`/`8` у 11+ значных номеров.
|
|
25
|
+
*
|
|
26
|
+
* Используется по умолчанию при `type="tel"`, если не задан `onBeforePasteValue`.
|
|
27
|
+
*/
|
|
28
|
+
export function normalizeRussianPhonePaste(value) {
|
|
29
|
+
var digits = value.replace(/\D/g, '');
|
|
30
|
+
if (!digits) {
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
if (digits.length >= 11 && (digits[0] === '7' || digits[0] === '8')) {
|
|
34
|
+
return digits.slice(1);
|
|
35
|
+
}
|
|
36
|
+
return digits;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=MaskedInputV2.phone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MaskedInputV2.phone.js","sourceRoot":"","sources":["MaskedInputV2.phone.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,IAAM,gBAAgB,GAAG;IAC9B,iFAAiF;IACjF,OAAO,EAAE,eAAe;IACxB,4DAA4D;IAC5D,aAAa,EAAE,UAAU;CACjB,CAAC;AAEX;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CAAC,KAAa;IACtD,IAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAExC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;QACpE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["/**\n * Пресеты часто используемых масок для {@link MaskedInputV2} / {@link MaskedInput}.\n *\n * Российский телефон по [гайду](https://guides.kontur.ru/components/input-fields/phone/):\n * префикс `+7` всегда виден и не стирается, остальные символы маски — только в фокусе.\n *\n * @example\n * ```tsx\n * <MaskedInput\n * type=\"tel\"\n * mask={MaskedInputMasks.PhoneRU}\n * prefix={MaskedInputMasks.PhoneRUPrefix}\n * />\n * ```\n */\nexport const MaskedInputMasks = {\n /** Национальная часть: `999 999-99-99`. Используйте вместе с `PhoneRUPrefix`. */\n PhoneRU: '999 999-99-99',\n /** Несбрасываемый префикс «+7» (с неразрывным пробелом). */\n PhoneRUPrefix: '+7\\u00a0',\n} as const;\n\n/**\n * Нормализует вставку российского номера телефона:\n * убирает нецифровые символы и отрезает код страны `7`/`8` у 11+ значных номеров.\n *\n * Используется по умолчанию при `type=\"tel\"`, если не задан `onBeforePasteValue`.\n */\nexport function normalizeRussianPhonePaste(value: string): string {\n const digits = value.replace(/\\D/g, '');\n\n if (!digits) {\n return value;\n }\n\n if (digits.length >= 11 && (digits[0] === '7' || digits[0] === '8')) {\n return digits.slice(1);\n }\n\n return digits;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,oBAAoB,GAIrB,MAAM,oBAAoB,CAAC","sourcesContent":["export {\n MaskedInputV2,\n getSafeMaskInputType,\n type MaskedInputV2Props,\n type MaskedInputV2OnBeforePasteValue,\n type MaskInputType,\n} from './MaskedInputV2.js';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,oBAAoB,GAIrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC","sourcesContent":["export {\n MaskedInputV2,\n getSafeMaskInputType,\n type MaskedInputV2Props,\n type MaskedInputV2OnBeforePasteValue,\n type MaskInputType,\n} from './MaskedInputV2.js';\nexport { MaskedInputMasks, normalizeRussianPhonePaste } from './MaskedInputV2.phone.js';\n"]}
|