From 5bf7eab55a19328dace61dc57156ddf624f56507 Mon Sep 17 00:00:00 2001 From: Slizhevsky Vladislav Date: Thu, 30 Jul 2026 11:03:31 +0200 Subject: [PATCH] [UIK-5647][input-mask] rewrite component to NS --- playground/entries/InputMask.tsx | 4 +- semcore/date-picker/src/index.d.ts | 8 +- semcore/input-mask/src/InputMask.tsx | 110 +++------------- semcore/input-mask/src/InputMask.type.ts | 119 ++++++++++++++++++ semcore/input-mask/src/index.tsx | 1 + .../components/input-mask/input-mask-api.md | 2 +- 6 files changed, 142 insertions(+), 102 deletions(-) create mode 100644 semcore/input-mask/src/InputMask.type.ts diff --git a/playground/entries/InputMask.tsx b/playground/entries/InputMask.tsx index ae4ea6afee..2ced1dd192 100644 --- a/playground/entries/InputMask.tsx +++ b/playground/entries/InputMask.tsx @@ -1,5 +1,5 @@ import type { NSInput } from '@semcore/ui/input'; -import type { InputMaskValueProps } from '@semcore/ui/input-mask'; +import type { NSInputMask } from '@semcore/ui/input-mask'; import InputMask from '@semcore/ui/input-mask'; import React from 'react'; @@ -7,7 +7,7 @@ import type { JSXProps } from '../types/JSXProps'; import type { PlaygroundEntry } from '../types/Playground'; import createGithubLink from '../utils/createGHLink'; -export type InputMaskJSXProps = JSXProps; +export type InputMaskJSXProps = JSXProps; function getJSX(props: InputMaskJSXProps) { return ( diff --git a/semcore/date-picker/src/index.d.ts b/semcore/date-picker/src/index.d.ts index c8698b9046..3eacef0fe4 100644 --- a/semcore/date-picker/src/index.d.ts +++ b/semcore/date-picker/src/index.d.ts @@ -11,7 +11,7 @@ import type Divider from '@semcore/divider'; import type { DropdownProps, DropdownTriggerProps } from '@semcore/dropdown'; import type { NSInput } from '@semcore/input'; import type Input from '@semcore/input'; -import type { InputMaskValueProps } from '@semcore/input-mask'; +import type { NSInputMask } from '@semcore/input-mask'; import type { TooltipProps } from '@semcore/tooltip'; import type dayjs from 'dayjs'; import type { ChangeEvent } from 'react'; @@ -315,7 +315,7 @@ declare const InputTrigger: Intergalactic.Component< Value: typeof Input.Value; SingleDateInput: Intergalactic.Component<'div', NSInput.Props & SingleDateInputProps> & { Indicator: typeof Input.Addon; - MaskedInput: Intergalactic.Component<'input', InputMaskValueProps & DatePickerMaskedInputProps>; + MaskedInput: Intergalactic.Component<'input', NSInputMask.Value.Props & DatePickerMaskedInputProps>; }; }; @@ -330,11 +330,11 @@ declare const RangeInputTrigger: Intergalactic.Component< RangeSep: typeof Input.Addon; FromMaskedInput: Intergalactic.Component< 'input', - InputMaskValueProps & DatePickerMaskedInputProps + NSInputMask.Value.Props & DatePickerMaskedInputProps >; ToMaskedInput: Intergalactic.Component< 'input', - InputMaskValueProps & DatePickerMaskedInputProps + NSInputMask.Value.Props & DatePickerMaskedInputProps >; }; }; diff --git a/semcore/input-mask/src/InputMask.tsx b/semcore/input-mask/src/InputMask.tsx index ff5184c679..7fe701b4aa 100644 --- a/semcore/input-mask/src/InputMask.tsx +++ b/semcore/input-mask/src/InputMask.tsx @@ -1,12 +1,6 @@ import { NeighborLocation, Box, Flex, ScreenReaderOnly } from '@semcore/base-components'; -import { - createComponent, - Component, - sstyled, - Root, - type PropGetterFn, - type Intergalactic, -} from '@semcore/core'; +import type { Intergalactic } from '@semcore/core'; +import { createComponent, Component, sstyled, Root } from '@semcore/core'; import fire from '@semcore/core/lib/utils/fire'; import getInputProps, { inputProps } from '@semcore/core/lib/utils/inputProps'; import logger from '@semcore/core/lib/utils/logger'; @@ -16,80 +10,9 @@ import Input, { type NSInput } from '@semcore/input'; import React from 'react'; import * as mask from 'text-mask-core'; +import type { NSInputMask } from './InputMask.type'; import style from './style/input-mask.shadow.css'; -export type IInputMaskAsFn = (rawValue?: string) => string | RegExp[]; - -export type InputMaskAliases = { - [s: string]: RegExp; -}; - -export type InputMaskValueProps = NSInput.Value.Props & { - /** - * Mask for entering text - */ - mask?: string | boolean | IInputMaskAsFn; - /** - * The property for visibility of the mask - * @default false - */ - hideMask?: boolean; - /** - * This function allows you to change the input value before it is displayed on the screen. - */ - pipe?: ( - conformedValue: string, - config: { - rawValue: string; - }, - ) => string | false | { value: string; indexesOfPipedChars: number[] }; - /** Internal */ - keepCharPositions?: boolean; - /** - * The aliases object for the mask values. The key is the symbol used in the mask, - * and the value is the regular expression that this symbol must match - * @default {'9': /\d/, 'a': /[a-zA-Zа-яА-Я]/, '*': /[\da-zA-Zа-яА-Я]/} - */ - aliases?: InputMaskAliases; - /** - * Event that is called when the input value fully matches the mask - */ - onSuccess?: (value: string) => void; - /** - * A field that explains the mask for blind users - * */ - title?: string; - - /** Specifies which props to pass to input element */ - includeInputProps?: string[]; - - /** - * Field for describe which symbols will use as mask - * @default `{_: true}` - */ - maskOnlySymbols?: Record; - - /** - * Overrids width of the input field - */ - inputW?: string | number; - - /** - * Aria role for input - */ - inputRole?: string; -}; - -type InputMaskCtx = { - getInputProps: PropGetterFn; - getValueProps: PropGetterFn; -}; - -type InputMaskComponent = Intergalactic.Component<'div', NSInput.Props, InputMaskCtx> & { - Value: Intergalactic.Component<'input', InputMaskValueProps>; - Addon: typeof Input.Addon; -}; - const { createTextMaskInputElement } = mask; export function getAfterPositionValue(value: string, mask: any = ''): number { @@ -106,7 +29,9 @@ export function getAfterPositionValue(value: string, mask: any = ''): number { return afterPotionValue; } -class InputMask extends Component { +class InputMask extends Component< + Intergalactic.InternalTypings.InferComponentProps +> { static displayName = 'InputMask'; static style = style; @@ -115,8 +40,12 @@ class InputMask extends Component { } } -class Value extends Component string> }> { - static defaultProps = { +class Value extends Component< + Intergalactic.InternalTypings.InferComponentProps, + typeof Value.enhance, + NSInputMask.Value.Handlers +> { + static defaultProps: NSInputMask.Value.DefaultProps = { includeInputProps: inputProps, defaultValue: '', hideMask: false, @@ -138,16 +67,7 @@ class Value extends Component this.asProps[prop] !== prevProps[prop], @@ -403,7 +323,7 @@ class Value extends Component(InputMask, { +export default createComponent(InputMask, { Value, Addon: Input.Addon, }); diff --git a/semcore/input-mask/src/InputMask.type.ts b/semcore/input-mask/src/InputMask.type.ts new file mode 100644 index 0000000000..c7007d1aca --- /dev/null +++ b/semcore/input-mask/src/InputMask.type.ts @@ -0,0 +1,119 @@ +import type { PropGetterFn, Intergalactic } from '@semcore/core'; +import type { NSInput } from '@semcore/input'; + +declare namespace NSInputMask { + type Props = NSInput.Props; + type Ctx = { + getInputProps: PropGetterFn; + getValueProps: PropGetterFn; + }; + + namespace Value { + type Props = NSInput.Value.Props & { + /** + * Mask for entering text + */ + mask?: string | boolean | ((rawValue?: string) => string | RegExp[]); + /** + * The property for visibility of the mask + * @default false + */ + hideMask?: boolean; + /** + * This function allows you to change the input value before it is displayed on the screen. + */ + pipe?: ( + conformedValue: string, + config: { + rawValue: string; + }, + ) => string | false | { value: string; indexesOfPipedChars: number[] }; + /** Internal */ + keepCharPositions?: boolean; + /** + * The aliases object for the mask values. The key is the symbol used in the mask, + * and the value is the regular expression that this symbol must match + * @default {'9': /\d/, 'a': /[a-zA-Zа-яА-Я]/, '*': /[\da-zA-Zа-яА-Я]/} + */ + aliases?: { + [s: string]: RegExp; + }; + /** + * Event that is called when the input value fully matches the mask + */ + onSuccess?: (value: string) => void; + /** + * A field that explains the mask for blind users + * */ + title?: string; + + /** Specifies which props to pass to input element */ + includeInputProps?: string[]; + + /** + * Field for describe which symbols will use as mask + * @default `{_: true}` + */ + maskOnlySymbols?: Record; + + /** + * Overrids width of the input field + */ + inputW?: string | number; + + /** + * Aria role for input + */ + inputRole?: string; + }; + type DefaultProps = { + includeInputProps: Array; + defaultValue: ''; + hideMask: false; + keepCharPositions: false; + aliases: { + '9': RegExp; + 'a': RegExp; + '*': RegExp; + }; + maskOnlySymbols: { + _: boolean; + }; + }; + type Handlers = { + value: Array<(value?: string) => string>; + }; + type State = { + lastConformed: + | { + all: string; + userInput: string; + maskOnly: string; + } + | undefined; + maskWidth: number | undefined; + }; + + type Component = Intergalactic.Component<'input', Props>; + } + + namespace Addon { + type Component = NSInput.Addon.Component; + } + + type Component = Intergalactic.Component<'div', Props, Ctx> & { + Value: Value.Component; + Addon: Addon.Component; + }; +} + +/** @deprecated It will be removed in v19. */ +export type InputMaskValueProps = NSInputMask.Value.Props; +/** @deprecated It will be removed in v19. */ +export type InputMaskAliases = { + [s: string]: RegExp; +}; +/** @deprecated It will be removed in v19. */ +export type IInputMaskAsFn = (rawValue?: string) => string | RegExp[]; + +export type { NSInputMask }; diff --git a/semcore/input-mask/src/index.tsx b/semcore/input-mask/src/index.tsx index 5555a464be..539d46677e 100644 --- a/semcore/input-mask/src/index.tsx +++ b/semcore/input-mask/src/index.tsx @@ -1,2 +1,3 @@ export { default } from './InputMask'; export * from './InputMask'; +export * from './InputMask.type'; diff --git a/website/docs/components/input-mask/input-mask-api.md b/website/docs/components/input-mask/input-mask-api.md index bca5a0b84f..743acf88bd 100644 --- a/website/docs/components/input-mask/input-mask-api.md +++ b/website/docs/components/input-mask/input-mask-api.md @@ -23,7 +23,7 @@ import InputMask from '@semcore/ui/input-mask'; ; ``` - + ## InputMask.Addon