react-input-mask-format 2.3.0 → 2.4.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/README.md CHANGED
@@ -5,12 +5,21 @@
5
5
  [![CI](https://github.com/Temirtator/react-input-mask-format/actions/workflows/ci.yml/badge.svg)](https://github.com/Temirtator/react-input-mask-format/actions/workflows/ci.yml)
6
6
 
7
7
  General-purpose input masking for React — dates, phone numbers, cards, custom
8
- tokens, and a growing set of ready-made country packs (Kazakhstan ships first).
8
+ tokens, and a growing set of ready-made country packs (Kazakhstan, Russia).
9
9
  Made with attention to UX.
10
10
 
11
11
  A maintained fork of [react-input-mask](https://github.com/sanniassin/react-input-mask).
12
12
 
13
- ## What's new in 2.3
13
+ **Live demo:** https://temirtator.github.io/react-input-mask-format/
14
+
15
+ ## What's new in 2.4
16
+
17
+ - Russia country pack in `react-input-mask-format/presets` — phone, INN, SNILS, OGRN/OGRNIP, KPP, BIK, bank account, IBAN, car plate, postal code, passport, see [Presets](#presets)
18
+ - Russian validators in `react-input-mask-format/validators` — INN, SNILS, OGRN/OGRNIP, bank account key (with BIK), IBAN, plate, KPP/BIK format, see [Validators](#validators)
19
+
20
+ All additive — no migration needed.
21
+
22
+ ### 2.3
14
23
 
15
24
  - `react-input-mask-format/time` — HH:MM (24h) masked input with clamping, see [Time](#time--react-input-mask-formattime)
16
25
 
@@ -144,12 +153,19 @@ import { kzPhone, kzIban } from "react-input-mask-format/presets";
144
153
  <InputMask {...kzIban} value={iban} onChange={onChange} />
145
154
  ```
146
155
 
147
- Presets are a country-agnostic system; Kazakhstan is the first (flagship) country pack —
156
+ Presets are a country-agnostic system with country packs for Kazakhstan and Russia —
148
157
  PRs adding other countries are welcome.
149
158
 
159
+ ### Generic
160
+
150
161
  | export | mask | example |
151
162
  | --- | --- | --- |
152
163
  | `card` | `9999 9999 9999 9999` | `4242 4242 4242 4242` |
164
+
165
+ ### Kazakhstan
166
+
167
+ | export | mask | example |
168
+ | --- | --- | --- |
153
169
  | `kzPhone` | `+7 (799) 999-99-99` | `+7 (701) 234-56-78` |
154
170
  | `kzIin` | `999999999999` | `901010123458` |
155
171
  | `kzBin` | `999999999999` | `150340004984` |
@@ -157,17 +173,56 @@ PRs adding other countries are welcome.
157
173
  | `kzPlate` | `123 ABC 02` (letters `ABCEHKMNOPTXY`, uppercase) | `123 ABC 02` |
158
174
  | `kzPostal` | `999999` | `050000` |
159
175
 
176
+ ### Russia
177
+
178
+ | export | mask | example |
179
+ | --- | --- | --- |
180
+ | `ruPhone` | `+7 (999) 999-99-99` (first digit 3/4/8/9) | `+7 (912) 345-67-89` |
181
+ | `ruInnPerson` | `999999999999` | `500100732259` |
182
+ | `ruInnCompany` | `9999999999` | `7707083893` |
183
+ | `ruSnils` | `999-999-999 99` | `112-233-445 95` |
184
+ | `ruOgrn` | `9999999999999` | `1027700132195` |
185
+ | `ruOgrnip` | `999999999999999` | `304500116000157` |
186
+ | `ruKpp` | `9999**999` (uppercase) | `7707AB001` |
187
+ | `ruBik` | `999999999` | `044525225` |
188
+ | `ruAccount` | `99999 999 9 9999 9999999` | `40817 810 5 3809 1310419` |
189
+ | `ruIban` | `RU99 9999 9999 9999 99** **** **** **** *` (uppercase) | `RU03 0445 2522 5408 1781 0538 0913 1041 9` |
190
+ | `ruPlate` | `А 999 АА 999` (letters `АВЕКМНОРСТУХ`) | `А 123 ВС 77` |
191
+ | `ruPostal` | `999999` | `101000` |
192
+ | `ruPassport` | `9999 999999` | `4506 123456` |
193
+
194
+ Notes:
195
+ - `ruPlate` accepts Latin look-alikes (`A B E K M H O P C T Y X`) and stores **Cyrillic**.
196
+ Regions are 2 or 3 digits: with a 2-digit region the value ends with the placeholder
197
+ (`А 123 ВС 77_`). `isValidRuPlate` accepts both forms (a gap inside the plate is invalid); strip `_` before storing if you need the bare plate.
198
+ - `ruPlate` covers type-1 (passenger car) plates only — not taxi, trailer, motorcycle, or diplomatic plates.
199
+ - `ruPhone` expects the 10-digit national number. A number typed with the domestic
200
+ trunk prefix `8` (`8 912 …`) is read as area code `891`; `+7…` and `7…` input is handled.
201
+
160
202
  ## Validators
161
203
 
162
204
  Optional checksum validators, separate entry point, zero-deps. Accept raw or formatted
163
205
  input; return `false` on empty/invalid.
164
206
 
165
207
  ```jsx
166
- import { isValidIin, isValidBin, isValidKzIban, luhn } from "react-input-mask-format/validators";
167
-
168
- isValidIin("901010123458"); // KZ IIN/BIN mod-11 checksum
169
- isValidKzIban("KZ86 125K ZT50 0410 0100"); // ISO 7064 MOD-97
170
- luhn("4242 4242 4242 4242"); // card Luhn
208
+ import {
209
+ isValidIin, isValidBin, isValidKzIban, luhn,
210
+ isValidRuInn, isValidRuSnils, isValidRuOgrn, isValidRuOgrnip,
211
+ isValidRuKpp, isValidRuBik, isValidRuAccount, isValidRuIban, isValidRuPlate
212
+ } from "react-input-mask-format/validators";
213
+
214
+ isValidIin("901010123458"); // KZ IIN/BIN mod-11 checksum
215
+ isValidKzIban("KZ86 125K ZT50 0410 0100"); // ISO 7064 MOD-97
216
+ luhn("4242 4242 4242 4242"); // card Luhn
217
+
218
+ isValidRuInn("7707083893"); // 10 (company) or 12 (person) digits
219
+ isValidRuSnils("112-233-445 95"); // mod-101; ≤ 001-001-998 not checked
220
+ isValidRuOgrn("1027700132195"); // OGRN (13) · isValidRuOgrnip — 15
221
+ isValidRuAccount("40817810538091310419", "044525225"); // account control key with BIK
222
+ isValidRuAccount("03100643000000018500", "017003983"); // treasury 03… accounts: structure only (no control key)
223
+ isValidRuIban("RU03 0445 2522 5408 1781 0538 0913 1041 9");
224
+ isValidRuPlate("А 123 ВС 77"); // region 2–3 digits, Latin look-alikes OK
225
+ isValidRuKpp("7707AB001"); isValidRuBik("044525225"); // format only (no checksum exists)
171
226
  ```
172
227
 
173
228
  ## `useMask` hook
@@ -0,0 +1,27 @@
1
+ // src/utils/ru-plate.ts
2
+ var RU_PLATE_LETTERS = "\u0410\u0412\u0415\u041A\u041C\u041D\u041E\u0420\u0421\u0422\u0423\u0425";
3
+ var LATIN_TO_CYRILLIC = {
4
+ A: "\u0410",
5
+ B: "\u0412",
6
+ E: "\u0415",
7
+ K: "\u041A",
8
+ M: "\u041C",
9
+ H: "\u041D",
10
+ O: "\u041E",
11
+ P: "\u0420",
12
+ C: "\u0421",
13
+ T: "\u0422",
14
+ Y: "\u0423",
15
+ X: "\u0425"
16
+ };
17
+ function toRuPlateChar(char) {
18
+ var _a;
19
+ const upper = char.toUpperCase();
20
+ return (_a = LATIN_TO_CYRILLIC[upper]) != null ? _a : upper;
21
+ }
22
+
23
+ export {
24
+ RU_PLATE_LETTERS,
25
+ toRuPlateChar
26
+ };
27
+ //# sourceMappingURL=chunk-OMKRB5AE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/ru-plate.ts"],"sourcesContent":["// The 12 Cyrillic letters allowed on Russian plates (ГОСТ Р 50577-2018)\nexport const RU_PLATE_LETTERS = \"АВЕКМНОРСТУХ\";\n\n// Latin look-alikes a user may type on an English layout\nconst LATIN_TO_CYRILLIC: Record<string, string> = {\n A: \"А\", B: \"В\", E: \"Е\", K: \"К\", M: \"М\", H: \"Н\",\n O: \"О\", P: \"Р\", C: \"С\", T: \"Т\", Y: \"У\", X: \"Х\"\n};\n\nexport function toRuPlateChar(char: string): string {\n const upper = char.toUpperCase();\n return LATIN_TO_CYRILLIC[upper] ?? upper;\n}\n"],"mappings":";AACO,IAAM,mBAAmB;AAGhC,IAAM,oBAA4C;AAAA,EAChD,GAAG;AAAA,EAAK,GAAG;AAAA,EAAK,GAAG;AAAA,EAAK,GAAG;AAAA,EAAK,GAAG;AAAA,EAAK,GAAG;AAAA,EAC3C,GAAG;AAAA,EAAK,GAAG;AAAA,EAAK,GAAG;AAAA,EAAK,GAAG;AAAA,EAAK,GAAG;AAAA,EAAK,GAAG;AAC7C;AAEO,SAAS,cAAc,MAAsB;AATpD;AAUE,QAAM,QAAQ,KAAK,YAAY;AAC/B,UAAO,uBAAkB,KAAK,MAAvB,YAA4B;AACrC;","names":[]}
package/dist/presets.cjs CHANGED
@@ -26,13 +26,30 @@ __export(presets_exports, {
26
26
  kzIin: () => kzIin,
27
27
  kzPhone: () => kzPhone,
28
28
  kzPlate: () => kzPlate,
29
- kzPostal: () => kzPostal
29
+ kzPostal: () => kzPostal,
30
+ ruAccount: () => ruAccount,
31
+ ruBik: () => ruBik,
32
+ ruIban: () => ruIban,
33
+ ruInnCompany: () => ruInnCompany,
34
+ ruInnPerson: () => ruInnPerson,
35
+ ruKpp: () => ruKpp,
36
+ ruOgrn: () => ruOgrn,
37
+ ruOgrnip: () => ruOgrnip,
38
+ ruPassport: () => ruPassport,
39
+ ruPhone: () => ruPhone,
40
+ ruPlate: () => ruPlate,
41
+ ruPostal: () => ruPostal,
42
+ ruSnils: () => ruSnils
30
43
  });
31
44
  module.exports = __toCommonJS(presets_exports);
45
+
46
+ // src/presets/generic.ts
32
47
  var card = {
33
48
  mask: "9999 9999 9999 9999",
34
49
  maskPlaceholder: "_"
35
50
  };
51
+
52
+ // src/presets/kz.ts
36
53
  var kzPhone = {
37
54
  mask: "+7 (799) 999-99-99",
38
55
  maskPlaceholder: "_"
@@ -73,6 +90,126 @@ var kzPostal = {
73
90
  mask: "999999",
74
91
  maskPlaceholder: "_"
75
92
  };
93
+
94
+ // src/utils/ru-plate.ts
95
+ var RU_PLATE_LETTERS = "\u0410\u0412\u0415\u041A\u041C\u041D\u041E\u0420\u0421\u0422\u0423\u0425";
96
+ var LATIN_TO_CYRILLIC = {
97
+ A: "\u0410",
98
+ B: "\u0412",
99
+ E: "\u0415",
100
+ K: "\u041A",
101
+ M: "\u041C",
102
+ H: "\u041D",
103
+ O: "\u041E",
104
+ P: "\u0420",
105
+ C: "\u0421",
106
+ T: "\u0422",
107
+ Y: "\u0423",
108
+ X: "\u0425"
109
+ };
110
+ function toRuPlateChar(char) {
111
+ var _a;
112
+ const upper = char.toUpperCase();
113
+ return (_a = LATIN_TO_CYRILLIC[upper]) != null ? _a : upper;
114
+ }
115
+
116
+ // src/presets/ru.ts
117
+ var DIGIT = /[0-9]/;
118
+ var ruPhone = {
119
+ // national number starts with 3/4/8/9; 6/7 belong to Kazakhstan
120
+ mask: [
121
+ "+",
122
+ "7",
123
+ " ",
124
+ "(",
125
+ /[3489]/,
126
+ DIGIT,
127
+ DIGIT,
128
+ ")",
129
+ " ",
130
+ DIGIT,
131
+ DIGIT,
132
+ DIGIT,
133
+ "-",
134
+ DIGIT,
135
+ DIGIT,
136
+ "-",
137
+ DIGIT,
138
+ DIGIT
139
+ ],
140
+ maskPlaceholder: "_"
141
+ };
142
+ var ruInnPerson = {
143
+ mask: "999999999999",
144
+ maskPlaceholder: "_"
145
+ };
146
+ var ruInnCompany = {
147
+ mask: "9999999999",
148
+ maskPlaceholder: "_"
149
+ };
150
+ var ruSnils = {
151
+ mask: "999-999-999 99",
152
+ maskPlaceholder: "_"
153
+ };
154
+ var ruOgrn = {
155
+ mask: "9999999999999",
156
+ maskPlaceholder: "_"
157
+ };
158
+ var ruOgrnip = {
159
+ mask: "999999999999999",
160
+ maskPlaceholder: "_"
161
+ };
162
+ var ruKpp = {
163
+ // positions 5-6 may be Latin A-Z
164
+ mask: "9999**999",
165
+ maskPlaceholder: "_",
166
+ transform: "uppercase"
167
+ };
168
+ var ruBik = {
169
+ mask: "999999999",
170
+ maskPlaceholder: "_"
171
+ };
172
+ var ruAccount = {
173
+ // balance account · currency · check key · branch · account
174
+ mask: "99999 999 9 9999 9999999",
175
+ maskPlaceholder: "_"
176
+ };
177
+ var ruIban = {
178
+ // RU + 2 check + BIK (9) + 5 digits + 15 alnum, grouped by 4
179
+ mask: "RU99 9999 9999 9999 99** **** **** **** *",
180
+ maskPlaceholder: "_",
181
+ transform: "uppercase"
182
+ };
183
+ var RU_PLATE_LETTER = new RegExp(`[${RU_PLATE_LETTERS}]`);
184
+ var ruPlate = {
185
+ // letter · 3 digits · 2 letters · region (2 or 3 digits). A 2-digit region
186
+ // leaves the trailing placeholder (А 123 ВС 77_), which isValidRuPlate accepts.
187
+ mask: [
188
+ RU_PLATE_LETTER,
189
+ " ",
190
+ DIGIT,
191
+ DIGIT,
192
+ DIGIT,
193
+ " ",
194
+ RU_PLATE_LETTER,
195
+ RU_PLATE_LETTER,
196
+ " ",
197
+ DIGIT,
198
+ DIGIT,
199
+ DIGIT
200
+ ],
201
+ maskPlaceholder: "_",
202
+ transform: toRuPlateChar
203
+ };
204
+ var ruPostal = {
205
+ mask: "999999",
206
+ maskPlaceholder: "_"
207
+ };
208
+ var ruPassport = {
209
+ // series (4) + number (6), as entered on Gosuslugi
210
+ mask: "9999 999999",
211
+ maskPlaceholder: "_"
212
+ };
76
213
  // Annotate the CommonJS export names for ESM import in node:
77
214
  0 && (module.exports = {
78
215
  card,
@@ -81,6 +218,19 @@ var kzPostal = {
81
218
  kzIin,
82
219
  kzPhone,
83
220
  kzPlate,
84
- kzPostal
221
+ kzPostal,
222
+ ruAccount,
223
+ ruBik,
224
+ ruIban,
225
+ ruInnCompany,
226
+ ruInnPerson,
227
+ ruKpp,
228
+ ruOgrn,
229
+ ruOgrnip,
230
+ ruPassport,
231
+ ruPhone,
232
+ ruPlate,
233
+ ruPostal,
234
+ ruSnils
85
235
  });
86
236
  //# sourceMappingURL=presets.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/presets/index.ts"],"sourcesContent":["import type { Mask, Transform, FormatChars } from \"../types\";\n\nexport interface MaskPreset {\n mask: Mask;\n maskPlaceholder?: string | null;\n transform?: Transform;\n formatChars?: FormatChars;\n}\n\n// ── Generic (country-agnostic) ───────────────────────────────\nexport const card: MaskPreset = {\n mask: \"9999 9999 9999 9999\",\n maskPlaceholder: \"_\"\n};\n\n// ── Kazakhstan ───────────────────────────────────────────────\nexport const kzPhone: MaskPreset = {\n mask: \"+7 (799) 999-99-99\",\n maskPlaceholder: \"_\"\n};\n\nexport const kzIin: MaskPreset = {\n mask: \"999999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const kzBin: MaskPreset = {\n mask: \"999999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const kzIban: MaskPreset = {\n // KZ + 2 check + 3 bank digits + 13 alnum account, grouped by 4\n mask: \"KZ99 999* **** **** ****\",\n maskPlaceholder: \"_\",\n transform: \"uppercase\"\n};\n\nconst KZ_PLATE_LETTER = /[ABCEHKMNOPTXY]/i;\nexport const kzPlate: MaskPreset = {\n // 3 digits · 3 letters (Latin look-alikes of Cyrillic) · 2-digit region\n mask: [\n /[0-9]/, /[0-9]/, /[0-9]/, \" \",\n KZ_PLATE_LETTER, KZ_PLATE_LETTER, KZ_PLATE_LETTER, \" \",\n /[0-9]/, /[0-9]/\n ],\n maskPlaceholder: \"_\",\n transform: \"uppercase\"\n};\n\nexport const kzPostal: MaskPreset = {\n mask: \"999999\",\n maskPlaceholder: \"_\"\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUO,IAAM,OAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,iBAAiB;AACnB;AAGO,IAAM,UAAsB;AAAA,EACjC,MAAM;AAAA,EACN,iBAAiB;AACnB;AAEO,IAAM,QAAoB;AAAA,EAC/B,MAAM;AAAA,EACN,iBAAiB;AACnB;AAEO,IAAM,QAAoB;AAAA,EAC/B,MAAM;AAAA,EACN,iBAAiB;AACnB;AAEO,IAAM,SAAqB;AAAA;AAAA,EAEhC,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,WAAW;AACb;AAEA,IAAM,kBAAkB;AACjB,IAAM,UAAsB;AAAA;AAAA,EAEjC,MAAM;AAAA,IACJ;AAAA,IAAS;AAAA,IAAS;AAAA,IAAS;AAAA,IAC3B;AAAA,IAAiB;AAAA,IAAiB;AAAA,IAAiB;AAAA,IACnD;AAAA,IAAS;AAAA,EACX;AAAA,EACA,iBAAiB;AAAA,EACjB,WAAW;AACb;AAEO,IAAM,WAAuB;AAAA,EAClC,MAAM;AAAA,EACN,iBAAiB;AACnB;","names":[]}
1
+ {"version":3,"sources":["../src/presets/index.ts","../src/presets/generic.ts","../src/presets/kz.ts","../src/utils/ru-plate.ts","../src/presets/ru.ts"],"sourcesContent":["export type { MaskPreset } from \"./types\";\nexport * from \"./generic\";\nexport * from \"./kz\";\nexport * from \"./ru\";\n","import type { MaskPreset } from \"./types\";\n\nexport const card: MaskPreset = {\n mask: \"9999 9999 9999 9999\",\n maskPlaceholder: \"_\"\n};\n","import type { MaskPreset } from \"./types\";\n\nexport const kzPhone: MaskPreset = {\n mask: \"+7 (799) 999-99-99\",\n maskPlaceholder: \"_\"\n};\n\nexport const kzIin: MaskPreset = {\n mask: \"999999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const kzBin: MaskPreset = {\n mask: \"999999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const kzIban: MaskPreset = {\n // KZ + 2 check + 3 bank digits + 13 alnum account, grouped by 4\n mask: \"KZ99 999* **** **** ****\",\n maskPlaceholder: \"_\",\n transform: \"uppercase\"\n};\n\nconst KZ_PLATE_LETTER = /[ABCEHKMNOPTXY]/i;\nexport const kzPlate: MaskPreset = {\n // 3 digits · 3 letters (Latin look-alikes of Cyrillic) · 2-digit region\n mask: [\n /[0-9]/, /[0-9]/, /[0-9]/, \" \",\n KZ_PLATE_LETTER, KZ_PLATE_LETTER, KZ_PLATE_LETTER, \" \",\n /[0-9]/, /[0-9]/\n ],\n maskPlaceholder: \"_\",\n transform: \"uppercase\"\n};\n\nexport const kzPostal: MaskPreset = {\n mask: \"999999\",\n maskPlaceholder: \"_\"\n};\n","// The 12 Cyrillic letters allowed on Russian plates (ГОСТ Р 50577-2018)\nexport const RU_PLATE_LETTERS = \"АВЕКМНОРСТУХ\";\n\n// Latin look-alikes a user may type on an English layout\nconst LATIN_TO_CYRILLIC: Record<string, string> = {\n A: \"А\", B: \"В\", E: \"Е\", K: \"К\", M: \"М\", H: \"Н\",\n O: \"О\", P: \"Р\", C: \"С\", T: \"Т\", Y: \"У\", X: \"Х\"\n};\n\nexport function toRuPlateChar(char: string): string {\n const upper = char.toUpperCase();\n return LATIN_TO_CYRILLIC[upper] ?? upper;\n}\n","import type { MaskPreset } from \"./types\";\nimport { RU_PLATE_LETTERS, toRuPlateChar } from \"../utils/ru-plate\";\n\nconst DIGIT = /[0-9]/;\n\nexport const ruPhone: MaskPreset = {\n // national number starts with 3/4/8/9; 6/7 belong to Kazakhstan\n mask: [\n \"+\", \"7\", \" \", \"(\", /[3489]/, DIGIT, DIGIT, \")\", \" \",\n DIGIT, DIGIT, DIGIT, \"-\", DIGIT, DIGIT, \"-\", DIGIT, DIGIT\n ],\n maskPlaceholder: \"_\"\n};\n\nexport const ruInnPerson: MaskPreset = {\n mask: \"999999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const ruInnCompany: MaskPreset = {\n mask: \"9999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const ruSnils: MaskPreset = {\n mask: \"999-999-999 99\",\n maskPlaceholder: \"_\"\n};\n\nexport const ruOgrn: MaskPreset = {\n mask: \"9999999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const ruOgrnip: MaskPreset = {\n mask: \"999999999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const ruKpp: MaskPreset = {\n // positions 5-6 may be Latin A-Z\n mask: \"9999**999\",\n maskPlaceholder: \"_\",\n transform: \"uppercase\"\n};\n\nexport const ruBik: MaskPreset = {\n mask: \"999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const ruAccount: MaskPreset = {\n // balance account · currency · check key · branch · account\n mask: \"99999 999 9 9999 9999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const ruIban: MaskPreset = {\n // RU + 2 check + BIK (9) + 5 digits + 15 alnum, grouped by 4\n mask: \"RU99 9999 9999 9999 99** **** **** **** *\",\n maskPlaceholder: \"_\",\n transform: \"uppercase\"\n};\n\nconst RU_PLATE_LETTER = new RegExp(`[${RU_PLATE_LETTERS}]`);\nexport const ruPlate: MaskPreset = {\n // letter · 3 digits · 2 letters · region (2 or 3 digits). A 2-digit region\n // leaves the trailing placeholder (А 123 ВС 77_), which isValidRuPlate accepts.\n mask: [\n RU_PLATE_LETTER, \" \", DIGIT, DIGIT, DIGIT, \" \",\n RU_PLATE_LETTER, RU_PLATE_LETTER, \" \", DIGIT, DIGIT, DIGIT\n ],\n maskPlaceholder: \"_\",\n transform: toRuPlateChar\n};\n\nexport const ruPostal: MaskPreset = {\n mask: \"999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const ruPassport: MaskPreset = {\n // series (4) + number (6), as entered on Gosuslugi\n mask: \"9999 999999\",\n maskPlaceholder: \"_\"\n};\n"],"mappings":"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","names":[]}
@@ -7,7 +7,9 @@ interface MaskPreset {
7
7
  transform?: Transform;
8
8
  formatChars?: FormatChars;
9
9
  }
10
+
10
11
  declare const card: MaskPreset;
12
+
11
13
  declare const kzPhone: MaskPreset;
12
14
  declare const kzIin: MaskPreset;
13
15
  declare const kzBin: MaskPreset;
@@ -15,4 +17,18 @@ declare const kzIban: MaskPreset;
15
17
  declare const kzPlate: MaskPreset;
16
18
  declare const kzPostal: MaskPreset;
17
19
 
18
- export { type MaskPreset, card, kzBin, kzIban, kzIin, kzPhone, kzPlate, kzPostal };
20
+ declare const ruPhone: MaskPreset;
21
+ declare const ruInnPerson: MaskPreset;
22
+ declare const ruInnCompany: MaskPreset;
23
+ declare const ruSnils: MaskPreset;
24
+ declare const ruOgrn: MaskPreset;
25
+ declare const ruOgrnip: MaskPreset;
26
+ declare const ruKpp: MaskPreset;
27
+ declare const ruBik: MaskPreset;
28
+ declare const ruAccount: MaskPreset;
29
+ declare const ruIban: MaskPreset;
30
+ declare const ruPlate: MaskPreset;
31
+ declare const ruPostal: MaskPreset;
32
+ declare const ruPassport: MaskPreset;
33
+
34
+ export { type MaskPreset, card, kzBin, kzIban, kzIin, kzPhone, kzPlate, kzPostal, ruAccount, ruBik, ruIban, ruInnCompany, ruInnPerson, ruKpp, ruOgrn, ruOgrnip, ruPassport, ruPhone, ruPlate, ruPostal, ruSnils };
package/dist/presets.d.ts CHANGED
@@ -7,7 +7,9 @@ interface MaskPreset {
7
7
  transform?: Transform;
8
8
  formatChars?: FormatChars;
9
9
  }
10
+
10
11
  declare const card: MaskPreset;
12
+
11
13
  declare const kzPhone: MaskPreset;
12
14
  declare const kzIin: MaskPreset;
13
15
  declare const kzBin: MaskPreset;
@@ -15,4 +17,18 @@ declare const kzIban: MaskPreset;
15
17
  declare const kzPlate: MaskPreset;
16
18
  declare const kzPostal: MaskPreset;
17
19
 
18
- export { type MaskPreset, card, kzBin, kzIban, kzIin, kzPhone, kzPlate, kzPostal };
20
+ declare const ruPhone: MaskPreset;
21
+ declare const ruInnPerson: MaskPreset;
22
+ declare const ruInnCompany: MaskPreset;
23
+ declare const ruSnils: MaskPreset;
24
+ declare const ruOgrn: MaskPreset;
25
+ declare const ruOgrnip: MaskPreset;
26
+ declare const ruKpp: MaskPreset;
27
+ declare const ruBik: MaskPreset;
28
+ declare const ruAccount: MaskPreset;
29
+ declare const ruIban: MaskPreset;
30
+ declare const ruPlate: MaskPreset;
31
+ declare const ruPostal: MaskPreset;
32
+ declare const ruPassport: MaskPreset;
33
+
34
+ export { type MaskPreset, card, kzBin, kzIban, kzIin, kzPhone, kzPlate, kzPostal, ruAccount, ruBik, ruIban, ruInnCompany, ruInnPerson, ruKpp, ruOgrn, ruOgrnip, ruPassport, ruPhone, ruPlate, ruPostal, ruSnils };
package/dist/presets.js CHANGED
@@ -1,8 +1,15 @@
1
- // src/presets/index.ts
1
+ import {
2
+ RU_PLATE_LETTERS,
3
+ toRuPlateChar
4
+ } from "./chunk-OMKRB5AE.js";
5
+
6
+ // src/presets/generic.ts
2
7
  var card = {
3
8
  mask: "9999 9999 9999 9999",
4
9
  maskPlaceholder: "_"
5
10
  };
11
+
12
+ // src/presets/kz.ts
6
13
  var kzPhone = {
7
14
  mask: "+7 (799) 999-99-99",
8
15
  maskPlaceholder: "_"
@@ -43,6 +50,104 @@ var kzPostal = {
43
50
  mask: "999999",
44
51
  maskPlaceholder: "_"
45
52
  };
53
+
54
+ // src/presets/ru.ts
55
+ var DIGIT = /[0-9]/;
56
+ var ruPhone = {
57
+ // national number starts with 3/4/8/9; 6/7 belong to Kazakhstan
58
+ mask: [
59
+ "+",
60
+ "7",
61
+ " ",
62
+ "(",
63
+ /[3489]/,
64
+ DIGIT,
65
+ DIGIT,
66
+ ")",
67
+ " ",
68
+ DIGIT,
69
+ DIGIT,
70
+ DIGIT,
71
+ "-",
72
+ DIGIT,
73
+ DIGIT,
74
+ "-",
75
+ DIGIT,
76
+ DIGIT
77
+ ],
78
+ maskPlaceholder: "_"
79
+ };
80
+ var ruInnPerson = {
81
+ mask: "999999999999",
82
+ maskPlaceholder: "_"
83
+ };
84
+ var ruInnCompany = {
85
+ mask: "9999999999",
86
+ maskPlaceholder: "_"
87
+ };
88
+ var ruSnils = {
89
+ mask: "999-999-999 99",
90
+ maskPlaceholder: "_"
91
+ };
92
+ var ruOgrn = {
93
+ mask: "9999999999999",
94
+ maskPlaceholder: "_"
95
+ };
96
+ var ruOgrnip = {
97
+ mask: "999999999999999",
98
+ maskPlaceholder: "_"
99
+ };
100
+ var ruKpp = {
101
+ // positions 5-6 may be Latin A-Z
102
+ mask: "9999**999",
103
+ maskPlaceholder: "_",
104
+ transform: "uppercase"
105
+ };
106
+ var ruBik = {
107
+ mask: "999999999",
108
+ maskPlaceholder: "_"
109
+ };
110
+ var ruAccount = {
111
+ // balance account · currency · check key · branch · account
112
+ mask: "99999 999 9 9999 9999999",
113
+ maskPlaceholder: "_"
114
+ };
115
+ var ruIban = {
116
+ // RU + 2 check + BIK (9) + 5 digits + 15 alnum, grouped by 4
117
+ mask: "RU99 9999 9999 9999 99** **** **** **** *",
118
+ maskPlaceholder: "_",
119
+ transform: "uppercase"
120
+ };
121
+ var RU_PLATE_LETTER = new RegExp(`[${RU_PLATE_LETTERS}]`);
122
+ var ruPlate = {
123
+ // letter · 3 digits · 2 letters · region (2 or 3 digits). A 2-digit region
124
+ // leaves the trailing placeholder (А 123 ВС 77_), which isValidRuPlate accepts.
125
+ mask: [
126
+ RU_PLATE_LETTER,
127
+ " ",
128
+ DIGIT,
129
+ DIGIT,
130
+ DIGIT,
131
+ " ",
132
+ RU_PLATE_LETTER,
133
+ RU_PLATE_LETTER,
134
+ " ",
135
+ DIGIT,
136
+ DIGIT,
137
+ DIGIT
138
+ ],
139
+ maskPlaceholder: "_",
140
+ transform: toRuPlateChar
141
+ };
142
+ var ruPostal = {
143
+ mask: "999999",
144
+ maskPlaceholder: "_"
145
+ };
146
+ var ruPassport = {
147
+ // series (4) + number (6), as entered on Gosuslugi
148
+ mask: "9999 999999",
149
+ maskPlaceholder: "_"
150
+ };
46
151
  export {
47
152
  card,
48
153
  kzBin,
@@ -50,6 +155,19 @@ export {
50
155
  kzIin,
51
156
  kzPhone,
52
157
  kzPlate,
53
- kzPostal
158
+ kzPostal,
159
+ ruAccount,
160
+ ruBik,
161
+ ruIban,
162
+ ruInnCompany,
163
+ ruInnPerson,
164
+ ruKpp,
165
+ ruOgrn,
166
+ ruOgrnip,
167
+ ruPassport,
168
+ ruPhone,
169
+ ruPlate,
170
+ ruPostal,
171
+ ruSnils
54
172
  };
55
173
  //# sourceMappingURL=presets.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/presets/index.ts"],"sourcesContent":["import type { Mask, Transform, FormatChars } from \"../types\";\n\nexport interface MaskPreset {\n mask: Mask;\n maskPlaceholder?: string | null;\n transform?: Transform;\n formatChars?: FormatChars;\n}\n\n// ── Generic (country-agnostic) ───────────────────────────────\nexport const card: MaskPreset = {\n mask: \"9999 9999 9999 9999\",\n maskPlaceholder: \"_\"\n};\n\n// ── Kazakhstan ───────────────────────────────────────────────\nexport const kzPhone: MaskPreset = {\n mask: \"+7 (799) 999-99-99\",\n maskPlaceholder: \"_\"\n};\n\nexport const kzIin: MaskPreset = {\n mask: \"999999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const kzBin: MaskPreset = {\n mask: \"999999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const kzIban: MaskPreset = {\n // KZ + 2 check + 3 bank digits + 13 alnum account, grouped by 4\n mask: \"KZ99 999* **** **** ****\",\n maskPlaceholder: \"_\",\n transform: \"uppercase\"\n};\n\nconst KZ_PLATE_LETTER = /[ABCEHKMNOPTXY]/i;\nexport const kzPlate: MaskPreset = {\n // 3 digits · 3 letters (Latin look-alikes of Cyrillic) · 2-digit region\n mask: [\n /[0-9]/, /[0-9]/, /[0-9]/, \" \",\n KZ_PLATE_LETTER, KZ_PLATE_LETTER, KZ_PLATE_LETTER, \" \",\n /[0-9]/, /[0-9]/\n ],\n maskPlaceholder: \"_\",\n transform: \"uppercase\"\n};\n\nexport const kzPostal: MaskPreset = {\n mask: \"999999\",\n maskPlaceholder: \"_\"\n};\n"],"mappings":";AAUO,IAAM,OAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,iBAAiB;AACnB;AAGO,IAAM,UAAsB;AAAA,EACjC,MAAM;AAAA,EACN,iBAAiB;AACnB;AAEO,IAAM,QAAoB;AAAA,EAC/B,MAAM;AAAA,EACN,iBAAiB;AACnB;AAEO,IAAM,QAAoB;AAAA,EAC/B,MAAM;AAAA,EACN,iBAAiB;AACnB;AAEO,IAAM,SAAqB;AAAA;AAAA,EAEhC,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,WAAW;AACb;AAEA,IAAM,kBAAkB;AACjB,IAAM,UAAsB;AAAA;AAAA,EAEjC,MAAM;AAAA,IACJ;AAAA,IAAS;AAAA,IAAS;AAAA,IAAS;AAAA,IAC3B;AAAA,IAAiB;AAAA,IAAiB;AAAA,IAAiB;AAAA,IACnD;AAAA,IAAS;AAAA,EACX;AAAA,EACA,iBAAiB;AAAA,EACjB,WAAW;AACb;AAEO,IAAM,WAAuB;AAAA,EAClC,MAAM;AAAA,EACN,iBAAiB;AACnB;","names":[]}
1
+ {"version":3,"sources":["../src/presets/generic.ts","../src/presets/kz.ts","../src/presets/ru.ts"],"sourcesContent":["import type { MaskPreset } from \"./types\";\n\nexport const card: MaskPreset = {\n mask: \"9999 9999 9999 9999\",\n maskPlaceholder: \"_\"\n};\n","import type { MaskPreset } from \"./types\";\n\nexport const kzPhone: MaskPreset = {\n mask: \"+7 (799) 999-99-99\",\n maskPlaceholder: \"_\"\n};\n\nexport const kzIin: MaskPreset = {\n mask: \"999999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const kzBin: MaskPreset = {\n mask: \"999999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const kzIban: MaskPreset = {\n // KZ + 2 check + 3 bank digits + 13 alnum account, grouped by 4\n mask: \"KZ99 999* **** **** ****\",\n maskPlaceholder: \"_\",\n transform: \"uppercase\"\n};\n\nconst KZ_PLATE_LETTER = /[ABCEHKMNOPTXY]/i;\nexport const kzPlate: MaskPreset = {\n // 3 digits · 3 letters (Latin look-alikes of Cyrillic) · 2-digit region\n mask: [\n /[0-9]/, /[0-9]/, /[0-9]/, \" \",\n KZ_PLATE_LETTER, KZ_PLATE_LETTER, KZ_PLATE_LETTER, \" \",\n /[0-9]/, /[0-9]/\n ],\n maskPlaceholder: \"_\",\n transform: \"uppercase\"\n};\n\nexport const kzPostal: MaskPreset = {\n mask: \"999999\",\n maskPlaceholder: \"_\"\n};\n","import type { MaskPreset } from \"./types\";\nimport { RU_PLATE_LETTERS, toRuPlateChar } from \"../utils/ru-plate\";\n\nconst DIGIT = /[0-9]/;\n\nexport const ruPhone: MaskPreset = {\n // national number starts with 3/4/8/9; 6/7 belong to Kazakhstan\n mask: [\n \"+\", \"7\", \" \", \"(\", /[3489]/, DIGIT, DIGIT, \")\", \" \",\n DIGIT, DIGIT, DIGIT, \"-\", DIGIT, DIGIT, \"-\", DIGIT, DIGIT\n ],\n maskPlaceholder: \"_\"\n};\n\nexport const ruInnPerson: MaskPreset = {\n mask: \"999999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const ruInnCompany: MaskPreset = {\n mask: \"9999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const ruSnils: MaskPreset = {\n mask: \"999-999-999 99\",\n maskPlaceholder: \"_\"\n};\n\nexport const ruOgrn: MaskPreset = {\n mask: \"9999999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const ruOgrnip: MaskPreset = {\n mask: \"999999999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const ruKpp: MaskPreset = {\n // positions 5-6 may be Latin A-Z\n mask: \"9999**999\",\n maskPlaceholder: \"_\",\n transform: \"uppercase\"\n};\n\nexport const ruBik: MaskPreset = {\n mask: \"999999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const ruAccount: MaskPreset = {\n // balance account · currency · check key · branch · account\n mask: \"99999 999 9 9999 9999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const ruIban: MaskPreset = {\n // RU + 2 check + BIK (9) + 5 digits + 15 alnum, grouped by 4\n mask: \"RU99 9999 9999 9999 99** **** **** **** *\",\n maskPlaceholder: \"_\",\n transform: \"uppercase\"\n};\n\nconst RU_PLATE_LETTER = new RegExp(`[${RU_PLATE_LETTERS}]`);\nexport const ruPlate: MaskPreset = {\n // letter · 3 digits · 2 letters · region (2 or 3 digits). A 2-digit region\n // leaves the trailing placeholder (А 123 ВС 77_), which isValidRuPlate accepts.\n mask: [\n RU_PLATE_LETTER, \" \", DIGIT, DIGIT, DIGIT, \" \",\n RU_PLATE_LETTER, RU_PLATE_LETTER, \" \", DIGIT, DIGIT, DIGIT\n ],\n maskPlaceholder: \"_\",\n transform: toRuPlateChar\n};\n\nexport const ruPostal: MaskPreset = {\n mask: \"999999\",\n maskPlaceholder: \"_\"\n};\n\nexport const ruPassport: MaskPreset = {\n // series (4) + number (6), as entered on Gosuslugi\n mask: \"9999 999999\",\n maskPlaceholder: \"_\"\n};\n"],"mappings":";;;;;;AAEO,IAAM,OAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,iBAAiB;AACnB;;;ACHO,IAAM,UAAsB;AAAA,EACjC,MAAM;AAAA,EACN,iBAAiB;AACnB;AAEO,IAAM,QAAoB;AAAA,EAC/B,MAAM;AAAA,EACN,iBAAiB;AACnB;AAEO,IAAM,QAAoB;AAAA,EAC/B,MAAM;AAAA,EACN,iBAAiB;AACnB;AAEO,IAAM,SAAqB;AAAA;AAAA,EAEhC,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,WAAW;AACb;AAEA,IAAM,kBAAkB;AACjB,IAAM,UAAsB;AAAA;AAAA,EAEjC,MAAM;AAAA,IACJ;AAAA,IAAS;AAAA,IAAS;AAAA,IAAS;AAAA,IAC3B;AAAA,IAAiB;AAAA,IAAiB;AAAA,IAAiB;AAAA,IACnD;AAAA,IAAS;AAAA,EACX;AAAA,EACA,iBAAiB;AAAA,EACjB,WAAW;AACb;AAEO,IAAM,WAAuB;AAAA,EAClC,MAAM;AAAA,EACN,iBAAiB;AACnB;;;ACpCA,IAAM,QAAQ;AAEP,IAAM,UAAsB;AAAA;AAAA,EAEjC,MAAM;AAAA,IACJ;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAU;AAAA,IAAO;AAAA,IAAO;AAAA,IAAK;AAAA,IACjD;AAAA,IAAO;AAAA,IAAO;AAAA,IAAO;AAAA,IAAK;AAAA,IAAO;AAAA,IAAO;AAAA,IAAK;AAAA,IAAO;AAAA,EACtD;AAAA,EACA,iBAAiB;AACnB;AAEO,IAAM,cAA0B;AAAA,EACrC,MAAM;AAAA,EACN,iBAAiB;AACnB;AAEO,IAAM,eAA2B;AAAA,EACtC,MAAM;AAAA,EACN,iBAAiB;AACnB;AAEO,IAAM,UAAsB;AAAA,EACjC,MAAM;AAAA,EACN,iBAAiB;AACnB;AAEO,IAAM,SAAqB;AAAA,EAChC,MAAM;AAAA,EACN,iBAAiB;AACnB;AAEO,IAAM,WAAuB;AAAA,EAClC,MAAM;AAAA,EACN,iBAAiB;AACnB;AAEO,IAAM,QAAoB;AAAA;AAAA,EAE/B,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,WAAW;AACb;AAEO,IAAM,QAAoB;AAAA,EAC/B,MAAM;AAAA,EACN,iBAAiB;AACnB;AAEO,IAAM,YAAwB;AAAA;AAAA,EAEnC,MAAM;AAAA,EACN,iBAAiB;AACnB;AAEO,IAAM,SAAqB;AAAA;AAAA,EAEhC,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,WAAW;AACb;AAEA,IAAM,kBAAkB,IAAI,OAAO,IAAI,gBAAgB,GAAG;AACnD,IAAM,UAAsB;AAAA;AAAA;AAAA,EAGjC,MAAM;AAAA,IACJ;AAAA,IAAiB;AAAA,IAAK;AAAA,IAAO;AAAA,IAAO;AAAA,IAAO;AAAA,IAC3C;AAAA,IAAiB;AAAA,IAAiB;AAAA,IAAK;AAAA,IAAO;AAAA,IAAO;AAAA,EACvD;AAAA,EACA,iBAAiB;AAAA,EACjB,WAAW;AACb;AAEO,IAAM,WAAuB;AAAA,EAClC,MAAM;AAAA,EACN,iBAAiB;AACnB;AAEO,IAAM,aAAyB;AAAA;AAAA,EAEpC,MAAM;AAAA,EACN,iBAAiB;AACnB;","names":[]}
@@ -23,12 +23,39 @@ __export(validators_exports, {
23
23
  isValidBin: () => isValidBin,
24
24
  isValidIin: () => isValidIin,
25
25
  isValidKzIban: () => isValidKzIban,
26
+ isValidRuAccount: () => isValidRuAccount,
27
+ isValidRuBik: () => isValidRuBik,
28
+ isValidRuIban: () => isValidRuIban,
29
+ isValidRuInn: () => isValidRuInn,
30
+ isValidRuKpp: () => isValidRuKpp,
31
+ isValidRuOgrn: () => isValidRuOgrn,
32
+ isValidRuOgrnip: () => isValidRuOgrnip,
33
+ isValidRuPlate: () => isValidRuPlate,
34
+ isValidRuSnils: () => isValidRuSnils,
26
35
  luhn: () => luhn
27
36
  });
28
37
  module.exports = __toCommonJS(validators_exports);
38
+
39
+ // src/validators/shared.ts
29
40
  function digitsOnly(value) {
30
41
  return (value != null ? value : "").replace(/\D/g, "");
31
42
  }
43
+ function remainder(numeric, modulus) {
44
+ let r = 0;
45
+ for (let i = 0; i < numeric.length; i++) {
46
+ r = (r * 10 + (numeric.charCodeAt(i) - 48)) % modulus;
47
+ }
48
+ return r;
49
+ }
50
+ function isIbanChecksumValid(iban) {
51
+ const rearranged = iban.slice(4) + iban.slice(0, 4);
52
+ let numeric = "";
53
+ for (let i = 0; i < rearranged.length; i++) {
54
+ const ch = rearranged[i];
55
+ numeric += ch >= "A" && ch <= "Z" ? String(ch.charCodeAt(0) - 55) : ch;
56
+ }
57
+ return remainder(numeric, 97) === 1;
58
+ }
32
59
  function luhn(value) {
33
60
  const digits = digitsOnly(value);
34
61
  if (digits.length === 0) {
@@ -49,6 +76,8 @@ function luhn(value) {
49
76
  }
50
77
  return sum % 10 === 0;
51
78
  }
79
+
80
+ // src/validators/kz.ts
52
81
  var IIN_W1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
53
82
  var IIN_W2 = [3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2];
54
83
  function iinBinChecksum(value) {
@@ -78,22 +107,142 @@ function isValidKzIban(value) {
78
107
  if (s.length !== 20 || !s.startsWith("KZ") || !/^[0-9A-Z]+$/.test(s)) {
79
108
  return false;
80
109
  }
81
- const rearranged = s.slice(4) + s.slice(0, 4);
82
- let remainder = 0;
83
- for (let i = 0; i < rearranged.length; i++) {
84
- const ch = rearranged[i];
85
- const chunk = ch >= "A" && ch <= "Z" ? String(ch.charCodeAt(0) - 55) : ch;
86
- for (let j = 0; j < chunk.length; j++) {
87
- remainder = (remainder * 10 + (chunk.charCodeAt(j) - 48)) % 97;
88
- }
110
+ return isIbanChecksumValid(s);
111
+ }
112
+
113
+ // src/utils/ru-plate.ts
114
+ var RU_PLATE_LETTERS = "\u0410\u0412\u0415\u041A\u041C\u041D\u041E\u0420\u0421\u0422\u0423\u0425";
115
+ var LATIN_TO_CYRILLIC = {
116
+ A: "\u0410",
117
+ B: "\u0412",
118
+ E: "\u0415",
119
+ K: "\u041A",
120
+ M: "\u041C",
121
+ H: "\u041D",
122
+ O: "\u041E",
123
+ P: "\u0420",
124
+ C: "\u0421",
125
+ T: "\u0422",
126
+ Y: "\u0423",
127
+ X: "\u0425"
128
+ };
129
+ function toRuPlateChar(char) {
130
+ var _a;
131
+ const upper = char.toUpperCase();
132
+ return (_a = LATIN_TO_CYRILLIC[upper]) != null ? _a : upper;
133
+ }
134
+
135
+ // src/validators/ru.ts
136
+ var INN10_W = [2, 4, 10, 3, 5, 9, 4, 6, 8];
137
+ var INN12_W1 = [7, 2, 4, 10, 3, 5, 9, 4, 6, 8];
138
+ var INN12_W2 = [3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8];
139
+ var SNILS_W = [9, 8, 7, 6, 5, 4, 3, 2, 1];
140
+ var SNILS_UNCHECKED_MAX = 1001998;
141
+ function toDigits(digits) {
142
+ return digits.split("").map((c) => c.charCodeAt(0) - 48);
143
+ }
144
+ function weightedSum(d, weights) {
145
+ return weights.reduce((sum, w, i) => sum + w * d[i], 0);
146
+ }
147
+ function isValidRuInn(value) {
148
+ const d = toDigits(digitsOnly(value));
149
+ if (d.length === 10) {
150
+ return weightedSum(d, INN10_W) % 11 % 10 === d[9];
151
+ }
152
+ if (d.length === 12) {
153
+ return weightedSum(d, INN12_W1) % 11 % 10 === d[10] && weightedSum(d, INN12_W2) % 11 % 10 === d[11];
154
+ }
155
+ return false;
156
+ }
157
+ function isValidRuSnils(value) {
158
+ const digits = digitsOnly(value);
159
+ if (digits.length !== 11) {
160
+ return false;
161
+ }
162
+ if (Number(digits.slice(0, 9)) <= SNILS_UNCHECKED_MAX) {
163
+ return true;
164
+ }
165
+ const d = toDigits(digits);
166
+ let control = weightedSum(d, SNILS_W) % 101;
167
+ if (control === 100) {
168
+ control = 0;
169
+ }
170
+ return control === d[9] * 10 + d[10];
171
+ }
172
+ function isValidRuOgrn(value) {
173
+ const digits = digitsOnly(value);
174
+ if (digits.length !== 13 || digits[0] !== "1" && digits[0] !== "5") {
175
+ return false;
176
+ }
177
+ return remainder(digits.slice(0, 12), 11) % 10 === Number(digits[12]);
178
+ }
179
+ function isValidRuOgrnip(value) {
180
+ const digits = digitsOnly(value);
181
+ if (digits.length !== 15 || digits[0] !== "3") {
182
+ return false;
183
+ }
184
+ return remainder(digits.slice(0, 14), 13) % 10 === Number(digits[14]);
185
+ }
186
+ function compactUpper(value) {
187
+ return (value != null ? value : "").replace(/\s+/g, "").toUpperCase();
188
+ }
189
+ function isValidRuKpp(value) {
190
+ return /^\d{4}[\dA-Z]{2}\d{3}$/.test(compactUpper(value));
191
+ }
192
+ function isValidRuBik(value) {
193
+ return /^[012]\d{8}$/.test(digitsOnly(value));
194
+ }
195
+ var ACCOUNT_W = [7, 1, 3];
196
+ function isValidRuAccount(account, bik) {
197
+ const a = digitsOnly(account);
198
+ const b = digitsOnly(bik);
199
+ if (a.length !== 20 || !isValidRuBik(b)) {
200
+ return false;
201
+ }
202
+ if (a.startsWith("03")) {
203
+ return true;
204
+ }
205
+ const rkcKeyed = a.startsWith("30101") || a.startsWith("40102");
206
+ const prefix = rkcKeyed ? "0" + b.slice(4, 6) : b.slice(6, 9);
207
+ const s = prefix + a;
208
+ let sum = 0;
209
+ for (let i = 0; i < s.length; i++) {
210
+ sum += (s.charCodeAt(i) - 48) * ACCOUNT_W[i % 3];
211
+ }
212
+ return sum % 10 === 0;
213
+ }
214
+ function isValidRuIban(value) {
215
+ const s = compactUpper(value);
216
+ if (s.length !== 33 || !s.startsWith("RU") || !/^[0-9A-Z]+$/.test(s)) {
217
+ return false;
218
+ }
219
+ return isIbanChecksumValid(s);
220
+ }
221
+ var PLATE_RE = new RegExp(
222
+ `^[${RU_PLATE_LETTERS}](\\d{3})[${RU_PLATE_LETTERS}]{2}(\\d{2}|[1-9]\\d{2})$`
223
+ );
224
+ function isValidRuPlate(value) {
225
+ const s = (value != null ? value : "").replace(/\s+/g, "").replace(/_+$/, "").split("").map(toRuPlateChar).join("");
226
+ const m = PLATE_RE.exec(s);
227
+ if (!m) {
228
+ return false;
89
229
  }
90
- return remainder === 1;
230
+ return m[1] !== "000" && Number(m[2]) !== 0;
91
231
  }
92
232
  // Annotate the CommonJS export names for ESM import in node:
93
233
  0 && (module.exports = {
94
234
  isValidBin,
95
235
  isValidIin,
96
236
  isValidKzIban,
237
+ isValidRuAccount,
238
+ isValidRuBik,
239
+ isValidRuIban,
240
+ isValidRuInn,
241
+ isValidRuKpp,
242
+ isValidRuOgrn,
243
+ isValidRuOgrnip,
244
+ isValidRuPlate,
245
+ isValidRuSnils,
97
246
  luhn
98
247
  });
99
248
  //# sourceMappingURL=validators.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/validators/index.ts"],"sourcesContent":["function digitsOnly(value: string): string {\n return (value ?? \"\").replace(/\\D/g, \"\");\n}\n\nexport function luhn(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length === 0) {\n return false;\n }\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = digits.charCodeAt(i) - 48;\n if (double) {\n d *= 2;\n if (d > 9) {\n d -= 9;\n }\n }\n sum += d;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\nconst IIN_W1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];\nconst IIN_W2 = [3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2];\n\nfunction iinBinChecksum(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length !== 12) {\n return false;\n }\n const d = digits.split(\"\").map(c => c.charCodeAt(0) - 48);\n const weighted = (w: number[]): number =>\n w.reduce((sum, wi, i) => sum + wi * d[i], 0) % 11;\n let control = weighted(IIN_W1);\n if (control === 10) {\n control = weighted(IIN_W2);\n if (control === 10) {\n return false;\n }\n }\n return control === d[11];\n}\n\nexport function isValidIin(value: string): boolean {\n return iinBinChecksum(value);\n}\n\nexport function isValidBin(value: string): boolean {\n return iinBinChecksum(value);\n}\n\nexport function isValidKzIban(value: string): boolean {\n const s = (value ?? \"\").replace(/\\s+/g, \"\").toUpperCase();\n if (s.length !== 20 || !s.startsWith(\"KZ\") || !/^[0-9A-Z]+$/.test(s)) {\n return false;\n }\n const rearranged = s.slice(4) + s.slice(0, 4);\n let remainder = 0;\n for (let i = 0; i < rearranged.length; i++) {\n const ch = rearranged[i];\n // A→10 … Z→35, digits stay as-is\n const chunk = ch >= \"A\" && ch <= \"Z\" ? String(ch.charCodeAt(0) - 55) : ch;\n for (let j = 0; j < chunk.length; j++) {\n remainder = (remainder * 10 + (chunk.charCodeAt(j) - 48)) % 97;\n }\n }\n return remainder === 1;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAS,WAAW,OAAuB;AACzC,UAAQ,wBAAS,IAAI,QAAQ,OAAO,EAAE;AACxC;AAEO,SAAS,KAAK,OAAwB;AAC3C,QAAM,SAAS,WAAW,KAAK;AAC/B,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;AAAA,EACT;AACA,MAAI,MAAM;AACV,MAAI,SAAS;AACb,WAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,QAAI,IAAI,OAAO,WAAW,CAAC,IAAI;AAC/B,QAAI,QAAQ;AACV,WAAK;AACL,UAAI,IAAI,GAAG;AACT,aAAK;AAAA,MACP;AAAA,IACF;AACA,WAAO;AACP,aAAS,CAAC;AAAA,EACZ;AACA,SAAO,MAAM,OAAO;AACtB;AAEA,IAAM,SAAS,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,EAAE;AACjD,IAAM,SAAS,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,GAAG,CAAC;AAEjD,SAAS,eAAe,OAAwB;AAC9C,QAAM,SAAS,WAAW,KAAK;AAC/B,MAAI,OAAO,WAAW,IAAI;AACxB,WAAO;AAAA,EACT;AACA,QAAM,IAAI,OAAO,MAAM,EAAE,EAAE,IAAI,OAAK,EAAE,WAAW,CAAC,IAAI,EAAE;AACxD,QAAM,WAAW,CAAC,MAChB,EAAE,OAAO,CAAC,KAAK,IAAI,MAAM,MAAM,KAAK,EAAE,CAAC,GAAG,CAAC,IAAI;AACjD,MAAI,UAAU,SAAS,MAAM;AAC7B,MAAI,YAAY,IAAI;AAClB,cAAU,SAAS,MAAM;AACzB,QAAI,YAAY,IAAI;AAClB,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,YAAY,EAAE,EAAE;AACzB;AAEO,SAAS,WAAW,OAAwB;AACjD,SAAO,eAAe,KAAK;AAC7B;AAEO,SAAS,WAAW,OAAwB;AACjD,SAAO,eAAe,KAAK;AAC7B;AAEO,SAAS,cAAc,OAAwB;AACpD,QAAM,KAAK,wBAAS,IAAI,QAAQ,QAAQ,EAAE,EAAE,YAAY;AACxD,MAAI,EAAE,WAAW,MAAM,CAAC,EAAE,WAAW,IAAI,KAAK,CAAC,cAAc,KAAK,CAAC,GAAG;AACpE,WAAO;AAAA,EACT;AACA,QAAM,aAAa,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC;AAC5C,MAAI,YAAY;AAChB,WAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC1C,UAAM,KAAK,WAAW,CAAC;AAEvB,UAAM,QAAQ,MAAM,OAAO,MAAM,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,IAAI;AACvE,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,mBAAa,YAAY,MAAM,MAAM,WAAW,CAAC,IAAI,OAAO;AAAA,IAC9D;AAAA,EACF;AACA,SAAO,cAAc;AACvB;","names":[]}
1
+ {"version":3,"sources":["../src/validators/index.ts","../src/validators/shared.ts","../src/validators/kz.ts","../src/utils/ru-plate.ts","../src/validators/ru.ts"],"sourcesContent":["export { luhn } from \"./shared\";\nexport * from \"./kz\";\nexport * from \"./ru\";\n","export function digitsOnly(value: string): string {\n return (value ?? \"\").replace(/\\D/g, \"\");\n}\n\n// Remainder of an arbitrary-length digit string (es2019 target: no BigInt literals)\nexport function remainder(numeric: string, modulus: number): number {\n let r = 0;\n for (let i = 0; i < numeric.length; i++) {\n r = (r * 10 + (numeric.charCodeAt(i) - 48)) % modulus;\n }\n return r;\n}\n\n// ISO 7064 MOD-97-10; expects a compact uppercase [0-9A-Z]+ string\nexport function isIbanChecksumValid(iban: string): boolean {\n const rearranged = iban.slice(4) + iban.slice(0, 4);\n let numeric = \"\";\n for (let i = 0; i < rearranged.length; i++) {\n const ch = rearranged[i];\n // A→10 … Z→35, digits stay as-is\n numeric += ch >= \"A\" && ch <= \"Z\" ? String(ch.charCodeAt(0) - 55) : ch;\n }\n return remainder(numeric, 97) === 1;\n}\n\nexport function luhn(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length === 0) {\n return false;\n }\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = digits.charCodeAt(i) - 48;\n if (double) {\n d *= 2;\n if (d > 9) {\n d -= 9;\n }\n }\n sum += d;\n double = !double;\n }\n return sum % 10 === 0;\n}\n","import { digitsOnly, isIbanChecksumValid } from \"./shared\";\n\nconst IIN_W1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];\nconst IIN_W2 = [3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2];\n\nfunction iinBinChecksum(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length !== 12) {\n return false;\n }\n const d = digits.split(\"\").map(c => c.charCodeAt(0) - 48);\n const weighted = (w: number[]): number =>\n w.reduce((sum, wi, i) => sum + wi * d[i], 0) % 11;\n let control = weighted(IIN_W1);\n if (control === 10) {\n control = weighted(IIN_W2);\n if (control === 10) {\n return false;\n }\n }\n return control === d[11];\n}\n\nexport function isValidIin(value: string): boolean {\n return iinBinChecksum(value);\n}\n\nexport function isValidBin(value: string): boolean {\n return iinBinChecksum(value);\n}\n\nexport function isValidKzIban(value: string): boolean {\n const s = (value ?? \"\").replace(/\\s+/g, \"\").toUpperCase();\n if (s.length !== 20 || !s.startsWith(\"KZ\") || !/^[0-9A-Z]+$/.test(s)) {\n return false;\n }\n return isIbanChecksumValid(s);\n}\n","// The 12 Cyrillic letters allowed on Russian plates (ГОСТ Р 50577-2018)\nexport const RU_PLATE_LETTERS = \"АВЕКМНОРСТУХ\";\n\n// Latin look-alikes a user may type on an English layout\nconst LATIN_TO_CYRILLIC: Record<string, string> = {\n A: \"А\", B: \"В\", E: \"Е\", K: \"К\", M: \"М\", H: \"Н\",\n O: \"О\", P: \"Р\", C: \"С\", T: \"Т\", Y: \"У\", X: \"Х\"\n};\n\nexport function toRuPlateChar(char: string): string {\n const upper = char.toUpperCase();\n return LATIN_TO_CYRILLIC[upper] ?? upper;\n}\n","import { digitsOnly, remainder, isIbanChecksumValid } from \"./shared\";\nimport { RU_PLATE_LETTERS, toRuPlateChar } from \"../utils/ru-plate\";\n\nconst INN10_W = [2, 4, 10, 3, 5, 9, 4, 6, 8];\nconst INN12_W1 = [7, 2, 4, 10, 3, 5, 9, 4, 6, 8];\nconst INN12_W2 = [3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8];\nconst SNILS_W = [9, 8, 7, 6, 5, 4, 3, 2, 1];\n// SNILS numbers up to 001-001-998 were issued before the checksum existed\nconst SNILS_UNCHECKED_MAX = 1001998;\n\nfunction toDigits(digits: string): number[] {\n return digits.split(\"\").map(c => c.charCodeAt(0) - 48);\n}\n\nfunction weightedSum(d: number[], weights: number[]): number {\n return weights.reduce((sum, w, i) => sum + w * d[i], 0);\n}\n\nexport function isValidRuInn(value: string): boolean {\n const d = toDigits(digitsOnly(value));\n if (d.length === 10) {\n return weightedSum(d, INN10_W) % 11 % 10 === d[9];\n }\n if (d.length === 12) {\n return (\n weightedSum(d, INN12_W1) % 11 % 10 === d[10] &&\n weightedSum(d, INN12_W2) % 11 % 10 === d[11]\n );\n }\n return false;\n}\n\nexport function isValidRuSnils(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length !== 11) {\n return false;\n }\n if (Number(digits.slice(0, 9)) <= SNILS_UNCHECKED_MAX) {\n return true;\n }\n const d = toDigits(digits);\n let control = weightedSum(d, SNILS_W) % 101;\n if (control === 100) {\n control = 0;\n }\n return control === d[9] * 10 + d[10];\n}\n\nexport function isValidRuOgrn(value: string): boolean {\n const digits = digitsOnly(value);\n // 1/5 = OGRN; 2, 6-9 are ГРН record numbers\n if (digits.length !== 13 || (digits[0] !== \"1\" && digits[0] !== \"5\")) {\n return false;\n }\n return remainder(digits.slice(0, 12), 11) % 10 === Number(digits[12]);\n}\n\nexport function isValidRuOgrnip(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length !== 15 || digits[0] !== \"3\") {\n return false;\n }\n // the check digit is the last digit of the remainder (10-12 → 0-2)\n return remainder(digits.slice(0, 14), 13) % 10 === Number(digits[14]);\n}\n\nfunction compactUpper(value: string): string {\n return (value ?? \"\").replace(/\\s+/g, \"\").toUpperCase();\n}\n\nexport function isValidRuKpp(value: string): boolean {\n return /^\\d{4}[\\dA-Z]{2}\\d{3}$/.test(compactUpper(value));\n}\n\nexport function isValidRuBik(value: string): boolean {\n // 732-P: first digit 0 (direct), 1 (indirect), 2 (CBR client); legacy BIKs start with 04\n return /^[012]\\d{8}$/.test(digitsOnly(value));\n}\n\nconst ACCOUNT_W = [7, 1, 3];\n\nexport function isValidRuAccount(account: string, bik: string): boolean {\n const a = digitsOnly(account);\n const b = digitsOnly(bik);\n if (a.length !== 20 || !isValidRuBik(b)) {\n return false;\n }\n // Treasury accounts (03…) carry no control key under CBR order 515: structure only.\n if (a.startsWith(\"03\")) {\n return true;\n }\n // Correspondent accounts (30101…) and single treasury accounts (40102…, ЕКС) are keyed\n // with the RKC prefix \"0\" + BIK[4..5]; everything else with the last 3 BIK digits.\n const rkcKeyed = a.startsWith(\"30101\") || a.startsWith(\"40102\");\n const prefix = rkcKeyed ? \"0\" + b.slice(4, 6) : b.slice(6, 9);\n const s = prefix + a;\n let sum = 0;\n for (let i = 0; i < s.length; i++) {\n sum += (s.charCodeAt(i) - 48) * ACCOUNT_W[i % 3];\n }\n return sum % 10 === 0;\n}\n\nexport function isValidRuIban(value: string): boolean {\n const s = compactUpper(value);\n if (s.length !== 33 || !s.startsWith(\"RU\") || !/^[0-9A-Z]+$/.test(s)) {\n return false;\n }\n return isIbanChecksumValid(s);\n}\n\nconst PLATE_RE = new RegExp(\n `^[${RU_PLATE_LETTERS}](\\\\d{3})[${RU_PLATE_LETTERS}]{2}(\\\\d{2}|[1-9]\\\\d{2})$`\n);\n\nexport function isValidRuPlate(value: string): boolean {\n const s = (value ?? \"\").replace(/\\s+/g, \"\").replace(/_+$/, \"\").split(\"\").map(toRuPlateChar).join(\"\");\n const m = PLATE_RE.exec(s);\n if (!m) {\n return false;\n }\n // 000 is never issued; region 00 does not exist\n return m[1] !== \"000\" && Number(m[2]) !== 0;\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,17 @@
1
1
  declare function luhn(value: string): boolean;
2
+
2
3
  declare function isValidIin(value: string): boolean;
3
4
  declare function isValidBin(value: string): boolean;
4
5
  declare function isValidKzIban(value: string): boolean;
5
6
 
6
- export { isValidBin, isValidIin, isValidKzIban, luhn };
7
+ declare function isValidRuInn(value: string): boolean;
8
+ declare function isValidRuSnils(value: string): boolean;
9
+ declare function isValidRuOgrn(value: string): boolean;
10
+ declare function isValidRuOgrnip(value: string): boolean;
11
+ declare function isValidRuKpp(value: string): boolean;
12
+ declare function isValidRuBik(value: string): boolean;
13
+ declare function isValidRuAccount(account: string, bik: string): boolean;
14
+ declare function isValidRuIban(value: string): boolean;
15
+ declare function isValidRuPlate(value: string): boolean;
16
+
17
+ export { isValidBin, isValidIin, isValidKzIban, isValidRuAccount, isValidRuBik, isValidRuIban, isValidRuInn, isValidRuKpp, isValidRuOgrn, isValidRuOgrnip, isValidRuPlate, isValidRuSnils, luhn };
@@ -1,6 +1,17 @@
1
1
  declare function luhn(value: string): boolean;
2
+
2
3
  declare function isValidIin(value: string): boolean;
3
4
  declare function isValidBin(value: string): boolean;
4
5
  declare function isValidKzIban(value: string): boolean;
5
6
 
6
- export { isValidBin, isValidIin, isValidKzIban, luhn };
7
+ declare function isValidRuInn(value: string): boolean;
8
+ declare function isValidRuSnils(value: string): boolean;
9
+ declare function isValidRuOgrn(value: string): boolean;
10
+ declare function isValidRuOgrnip(value: string): boolean;
11
+ declare function isValidRuKpp(value: string): boolean;
12
+ declare function isValidRuBik(value: string): boolean;
13
+ declare function isValidRuAccount(account: string, bik: string): boolean;
14
+ declare function isValidRuIban(value: string): boolean;
15
+ declare function isValidRuPlate(value: string): boolean;
16
+
17
+ export { isValidBin, isValidIin, isValidKzIban, isValidRuAccount, isValidRuBik, isValidRuIban, isValidRuInn, isValidRuKpp, isValidRuOgrn, isValidRuOgrnip, isValidRuPlate, isValidRuSnils, luhn };
@@ -1,7 +1,28 @@
1
- // src/validators/index.ts
1
+ import {
2
+ RU_PLATE_LETTERS,
3
+ toRuPlateChar
4
+ } from "./chunk-OMKRB5AE.js";
5
+
6
+ // src/validators/shared.ts
2
7
  function digitsOnly(value) {
3
8
  return (value != null ? value : "").replace(/\D/g, "");
4
9
  }
10
+ function remainder(numeric, modulus) {
11
+ let r = 0;
12
+ for (let i = 0; i < numeric.length; i++) {
13
+ r = (r * 10 + (numeric.charCodeAt(i) - 48)) % modulus;
14
+ }
15
+ return r;
16
+ }
17
+ function isIbanChecksumValid(iban) {
18
+ const rearranged = iban.slice(4) + iban.slice(0, 4);
19
+ let numeric = "";
20
+ for (let i = 0; i < rearranged.length; i++) {
21
+ const ch = rearranged[i];
22
+ numeric += ch >= "A" && ch <= "Z" ? String(ch.charCodeAt(0) - 55) : ch;
23
+ }
24
+ return remainder(numeric, 97) === 1;
25
+ }
5
26
  function luhn(value) {
6
27
  const digits = digitsOnly(value);
7
28
  if (digits.length === 0) {
@@ -22,6 +43,8 @@ function luhn(value) {
22
43
  }
23
44
  return sum % 10 === 0;
24
45
  }
46
+
47
+ // src/validators/kz.ts
25
48
  var IIN_W1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
26
49
  var IIN_W2 = [3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2];
27
50
  function iinBinChecksum(value) {
@@ -51,21 +74,119 @@ function isValidKzIban(value) {
51
74
  if (s.length !== 20 || !s.startsWith("KZ") || !/^[0-9A-Z]+$/.test(s)) {
52
75
  return false;
53
76
  }
54
- const rearranged = s.slice(4) + s.slice(0, 4);
55
- let remainder = 0;
56
- for (let i = 0; i < rearranged.length; i++) {
57
- const ch = rearranged[i];
58
- const chunk = ch >= "A" && ch <= "Z" ? String(ch.charCodeAt(0) - 55) : ch;
59
- for (let j = 0; j < chunk.length; j++) {
60
- remainder = (remainder * 10 + (chunk.charCodeAt(j) - 48)) % 97;
61
- }
77
+ return isIbanChecksumValid(s);
78
+ }
79
+
80
+ // src/validators/ru.ts
81
+ var INN10_W = [2, 4, 10, 3, 5, 9, 4, 6, 8];
82
+ var INN12_W1 = [7, 2, 4, 10, 3, 5, 9, 4, 6, 8];
83
+ var INN12_W2 = [3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8];
84
+ var SNILS_W = [9, 8, 7, 6, 5, 4, 3, 2, 1];
85
+ var SNILS_UNCHECKED_MAX = 1001998;
86
+ function toDigits(digits) {
87
+ return digits.split("").map((c) => c.charCodeAt(0) - 48);
88
+ }
89
+ function weightedSum(d, weights) {
90
+ return weights.reduce((sum, w, i) => sum + w * d[i], 0);
91
+ }
92
+ function isValidRuInn(value) {
93
+ const d = toDigits(digitsOnly(value));
94
+ if (d.length === 10) {
95
+ return weightedSum(d, INN10_W) % 11 % 10 === d[9];
96
+ }
97
+ if (d.length === 12) {
98
+ return weightedSum(d, INN12_W1) % 11 % 10 === d[10] && weightedSum(d, INN12_W2) % 11 % 10 === d[11];
99
+ }
100
+ return false;
101
+ }
102
+ function isValidRuSnils(value) {
103
+ const digits = digitsOnly(value);
104
+ if (digits.length !== 11) {
105
+ return false;
106
+ }
107
+ if (Number(digits.slice(0, 9)) <= SNILS_UNCHECKED_MAX) {
108
+ return true;
109
+ }
110
+ const d = toDigits(digits);
111
+ let control = weightedSum(d, SNILS_W) % 101;
112
+ if (control === 100) {
113
+ control = 0;
114
+ }
115
+ return control === d[9] * 10 + d[10];
116
+ }
117
+ function isValidRuOgrn(value) {
118
+ const digits = digitsOnly(value);
119
+ if (digits.length !== 13 || digits[0] !== "1" && digits[0] !== "5") {
120
+ return false;
121
+ }
122
+ return remainder(digits.slice(0, 12), 11) % 10 === Number(digits[12]);
123
+ }
124
+ function isValidRuOgrnip(value) {
125
+ const digits = digitsOnly(value);
126
+ if (digits.length !== 15 || digits[0] !== "3") {
127
+ return false;
128
+ }
129
+ return remainder(digits.slice(0, 14), 13) % 10 === Number(digits[14]);
130
+ }
131
+ function compactUpper(value) {
132
+ return (value != null ? value : "").replace(/\s+/g, "").toUpperCase();
133
+ }
134
+ function isValidRuKpp(value) {
135
+ return /^\d{4}[\dA-Z]{2}\d{3}$/.test(compactUpper(value));
136
+ }
137
+ function isValidRuBik(value) {
138
+ return /^[012]\d{8}$/.test(digitsOnly(value));
139
+ }
140
+ var ACCOUNT_W = [7, 1, 3];
141
+ function isValidRuAccount(account, bik) {
142
+ const a = digitsOnly(account);
143
+ const b = digitsOnly(bik);
144
+ if (a.length !== 20 || !isValidRuBik(b)) {
145
+ return false;
146
+ }
147
+ if (a.startsWith("03")) {
148
+ return true;
149
+ }
150
+ const rkcKeyed = a.startsWith("30101") || a.startsWith("40102");
151
+ const prefix = rkcKeyed ? "0" + b.slice(4, 6) : b.slice(6, 9);
152
+ const s = prefix + a;
153
+ let sum = 0;
154
+ for (let i = 0; i < s.length; i++) {
155
+ sum += (s.charCodeAt(i) - 48) * ACCOUNT_W[i % 3];
156
+ }
157
+ return sum % 10 === 0;
158
+ }
159
+ function isValidRuIban(value) {
160
+ const s = compactUpper(value);
161
+ if (s.length !== 33 || !s.startsWith("RU") || !/^[0-9A-Z]+$/.test(s)) {
162
+ return false;
163
+ }
164
+ return isIbanChecksumValid(s);
165
+ }
166
+ var PLATE_RE = new RegExp(
167
+ `^[${RU_PLATE_LETTERS}](\\d{3})[${RU_PLATE_LETTERS}]{2}(\\d{2}|[1-9]\\d{2})$`
168
+ );
169
+ function isValidRuPlate(value) {
170
+ const s = (value != null ? value : "").replace(/\s+/g, "").replace(/_+$/, "").split("").map(toRuPlateChar).join("");
171
+ const m = PLATE_RE.exec(s);
172
+ if (!m) {
173
+ return false;
62
174
  }
63
- return remainder === 1;
175
+ return m[1] !== "000" && Number(m[2]) !== 0;
64
176
  }
65
177
  export {
66
178
  isValidBin,
67
179
  isValidIin,
68
180
  isValidKzIban,
181
+ isValidRuAccount,
182
+ isValidRuBik,
183
+ isValidRuIban,
184
+ isValidRuInn,
185
+ isValidRuKpp,
186
+ isValidRuOgrn,
187
+ isValidRuOgrnip,
188
+ isValidRuPlate,
189
+ isValidRuSnils,
69
190
  luhn
70
191
  };
71
192
  //# sourceMappingURL=validators.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/validators/index.ts"],"sourcesContent":["function digitsOnly(value: string): string {\n return (value ?? \"\").replace(/\\D/g, \"\");\n}\n\nexport function luhn(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length === 0) {\n return false;\n }\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = digits.charCodeAt(i) - 48;\n if (double) {\n d *= 2;\n if (d > 9) {\n d -= 9;\n }\n }\n sum += d;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\nconst IIN_W1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];\nconst IIN_W2 = [3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2];\n\nfunction iinBinChecksum(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length !== 12) {\n return false;\n }\n const d = digits.split(\"\").map(c => c.charCodeAt(0) - 48);\n const weighted = (w: number[]): number =>\n w.reduce((sum, wi, i) => sum + wi * d[i], 0) % 11;\n let control = weighted(IIN_W1);\n if (control === 10) {\n control = weighted(IIN_W2);\n if (control === 10) {\n return false;\n }\n }\n return control === d[11];\n}\n\nexport function isValidIin(value: string): boolean {\n return iinBinChecksum(value);\n}\n\nexport function isValidBin(value: string): boolean {\n return iinBinChecksum(value);\n}\n\nexport function isValidKzIban(value: string): boolean {\n const s = (value ?? \"\").replace(/\\s+/g, \"\").toUpperCase();\n if (s.length !== 20 || !s.startsWith(\"KZ\") || !/^[0-9A-Z]+$/.test(s)) {\n return false;\n }\n const rearranged = s.slice(4) + s.slice(0, 4);\n let remainder = 0;\n for (let i = 0; i < rearranged.length; i++) {\n const ch = rearranged[i];\n // A→10 … Z→35, digits stay as-is\n const chunk = ch >= \"A\" && ch <= \"Z\" ? String(ch.charCodeAt(0) - 55) : ch;\n for (let j = 0; j < chunk.length; j++) {\n remainder = (remainder * 10 + (chunk.charCodeAt(j) - 48)) % 97;\n }\n }\n return remainder === 1;\n}\n"],"mappings":";AAAA,SAAS,WAAW,OAAuB;AACzC,UAAQ,wBAAS,IAAI,QAAQ,OAAO,EAAE;AACxC;AAEO,SAAS,KAAK,OAAwB;AAC3C,QAAM,SAAS,WAAW,KAAK;AAC/B,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;AAAA,EACT;AACA,MAAI,MAAM;AACV,MAAI,SAAS;AACb,WAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,QAAI,IAAI,OAAO,WAAW,CAAC,IAAI;AAC/B,QAAI,QAAQ;AACV,WAAK;AACL,UAAI,IAAI,GAAG;AACT,aAAK;AAAA,MACP;AAAA,IACF;AACA,WAAO;AACP,aAAS,CAAC;AAAA,EACZ;AACA,SAAO,MAAM,OAAO;AACtB;AAEA,IAAM,SAAS,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,EAAE;AACjD,IAAM,SAAS,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,GAAG,CAAC;AAEjD,SAAS,eAAe,OAAwB;AAC9C,QAAM,SAAS,WAAW,KAAK;AAC/B,MAAI,OAAO,WAAW,IAAI;AACxB,WAAO;AAAA,EACT;AACA,QAAM,IAAI,OAAO,MAAM,EAAE,EAAE,IAAI,OAAK,EAAE,WAAW,CAAC,IAAI,EAAE;AACxD,QAAM,WAAW,CAAC,MAChB,EAAE,OAAO,CAAC,KAAK,IAAI,MAAM,MAAM,KAAK,EAAE,CAAC,GAAG,CAAC,IAAI;AACjD,MAAI,UAAU,SAAS,MAAM;AAC7B,MAAI,YAAY,IAAI;AAClB,cAAU,SAAS,MAAM;AACzB,QAAI,YAAY,IAAI;AAClB,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,YAAY,EAAE,EAAE;AACzB;AAEO,SAAS,WAAW,OAAwB;AACjD,SAAO,eAAe,KAAK;AAC7B;AAEO,SAAS,WAAW,OAAwB;AACjD,SAAO,eAAe,KAAK;AAC7B;AAEO,SAAS,cAAc,OAAwB;AACpD,QAAM,KAAK,wBAAS,IAAI,QAAQ,QAAQ,EAAE,EAAE,YAAY;AACxD,MAAI,EAAE,WAAW,MAAM,CAAC,EAAE,WAAW,IAAI,KAAK,CAAC,cAAc,KAAK,CAAC,GAAG;AACpE,WAAO;AAAA,EACT;AACA,QAAM,aAAa,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC;AAC5C,MAAI,YAAY;AAChB,WAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC1C,UAAM,KAAK,WAAW,CAAC;AAEvB,UAAM,QAAQ,MAAM,OAAO,MAAM,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,IAAI;AACvE,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,mBAAa,YAAY,MAAM,MAAM,WAAW,CAAC,IAAI,OAAO;AAAA,IAC9D;AAAA,EACF;AACA,SAAO,cAAc;AACvB;","names":[]}
1
+ {"version":3,"sources":["../src/validators/shared.ts","../src/validators/kz.ts","../src/validators/ru.ts"],"sourcesContent":["export function digitsOnly(value: string): string {\n return (value ?? \"\").replace(/\\D/g, \"\");\n}\n\n// Remainder of an arbitrary-length digit string (es2019 target: no BigInt literals)\nexport function remainder(numeric: string, modulus: number): number {\n let r = 0;\n for (let i = 0; i < numeric.length; i++) {\n r = (r * 10 + (numeric.charCodeAt(i) - 48)) % modulus;\n }\n return r;\n}\n\n// ISO 7064 MOD-97-10; expects a compact uppercase [0-9A-Z]+ string\nexport function isIbanChecksumValid(iban: string): boolean {\n const rearranged = iban.slice(4) + iban.slice(0, 4);\n let numeric = \"\";\n for (let i = 0; i < rearranged.length; i++) {\n const ch = rearranged[i];\n // A→10 … Z→35, digits stay as-is\n numeric += ch >= \"A\" && ch <= \"Z\" ? String(ch.charCodeAt(0) - 55) : ch;\n }\n return remainder(numeric, 97) === 1;\n}\n\nexport function luhn(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length === 0) {\n return false;\n }\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = digits.charCodeAt(i) - 48;\n if (double) {\n d *= 2;\n if (d > 9) {\n d -= 9;\n }\n }\n sum += d;\n double = !double;\n }\n return sum % 10 === 0;\n}\n","import { digitsOnly, isIbanChecksumValid } from \"./shared\";\n\nconst IIN_W1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];\nconst IIN_W2 = [3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2];\n\nfunction iinBinChecksum(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length !== 12) {\n return false;\n }\n const d = digits.split(\"\").map(c => c.charCodeAt(0) - 48);\n const weighted = (w: number[]): number =>\n w.reduce((sum, wi, i) => sum + wi * d[i], 0) % 11;\n let control = weighted(IIN_W1);\n if (control === 10) {\n control = weighted(IIN_W2);\n if (control === 10) {\n return false;\n }\n }\n return control === d[11];\n}\n\nexport function isValidIin(value: string): boolean {\n return iinBinChecksum(value);\n}\n\nexport function isValidBin(value: string): boolean {\n return iinBinChecksum(value);\n}\n\nexport function isValidKzIban(value: string): boolean {\n const s = (value ?? \"\").replace(/\\s+/g, \"\").toUpperCase();\n if (s.length !== 20 || !s.startsWith(\"KZ\") || !/^[0-9A-Z]+$/.test(s)) {\n return false;\n }\n return isIbanChecksumValid(s);\n}\n","import { digitsOnly, remainder, isIbanChecksumValid } from \"./shared\";\nimport { RU_PLATE_LETTERS, toRuPlateChar } from \"../utils/ru-plate\";\n\nconst INN10_W = [2, 4, 10, 3, 5, 9, 4, 6, 8];\nconst INN12_W1 = [7, 2, 4, 10, 3, 5, 9, 4, 6, 8];\nconst INN12_W2 = [3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8];\nconst SNILS_W = [9, 8, 7, 6, 5, 4, 3, 2, 1];\n// SNILS numbers up to 001-001-998 were issued before the checksum existed\nconst SNILS_UNCHECKED_MAX = 1001998;\n\nfunction toDigits(digits: string): number[] {\n return digits.split(\"\").map(c => c.charCodeAt(0) - 48);\n}\n\nfunction weightedSum(d: number[], weights: number[]): number {\n return weights.reduce((sum, w, i) => sum + w * d[i], 0);\n}\n\nexport function isValidRuInn(value: string): boolean {\n const d = toDigits(digitsOnly(value));\n if (d.length === 10) {\n return weightedSum(d, INN10_W) % 11 % 10 === d[9];\n }\n if (d.length === 12) {\n return (\n weightedSum(d, INN12_W1) % 11 % 10 === d[10] &&\n weightedSum(d, INN12_W2) % 11 % 10 === d[11]\n );\n }\n return false;\n}\n\nexport function isValidRuSnils(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length !== 11) {\n return false;\n }\n if (Number(digits.slice(0, 9)) <= SNILS_UNCHECKED_MAX) {\n return true;\n }\n const d = toDigits(digits);\n let control = weightedSum(d, SNILS_W) % 101;\n if (control === 100) {\n control = 0;\n }\n return control === d[9] * 10 + d[10];\n}\n\nexport function isValidRuOgrn(value: string): boolean {\n const digits = digitsOnly(value);\n // 1/5 = OGRN; 2, 6-9 are ГРН record numbers\n if (digits.length !== 13 || (digits[0] !== \"1\" && digits[0] !== \"5\")) {\n return false;\n }\n return remainder(digits.slice(0, 12), 11) % 10 === Number(digits[12]);\n}\n\nexport function isValidRuOgrnip(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length !== 15 || digits[0] !== \"3\") {\n return false;\n }\n // the check digit is the last digit of the remainder (10-12 → 0-2)\n return remainder(digits.slice(0, 14), 13) % 10 === Number(digits[14]);\n}\n\nfunction compactUpper(value: string): string {\n return (value ?? \"\").replace(/\\s+/g, \"\").toUpperCase();\n}\n\nexport function isValidRuKpp(value: string): boolean {\n return /^\\d{4}[\\dA-Z]{2}\\d{3}$/.test(compactUpper(value));\n}\n\nexport function isValidRuBik(value: string): boolean {\n // 732-P: first digit 0 (direct), 1 (indirect), 2 (CBR client); legacy BIKs start with 04\n return /^[012]\\d{8}$/.test(digitsOnly(value));\n}\n\nconst ACCOUNT_W = [7, 1, 3];\n\nexport function isValidRuAccount(account: string, bik: string): boolean {\n const a = digitsOnly(account);\n const b = digitsOnly(bik);\n if (a.length !== 20 || !isValidRuBik(b)) {\n return false;\n }\n // Treasury accounts (03…) carry no control key under CBR order 515: structure only.\n if (a.startsWith(\"03\")) {\n return true;\n }\n // Correspondent accounts (30101…) and single treasury accounts (40102…, ЕКС) are keyed\n // with the RKC prefix \"0\" + BIK[4..5]; everything else with the last 3 BIK digits.\n const rkcKeyed = a.startsWith(\"30101\") || a.startsWith(\"40102\");\n const prefix = rkcKeyed ? \"0\" + b.slice(4, 6) : b.slice(6, 9);\n const s = prefix + a;\n let sum = 0;\n for (let i = 0; i < s.length; i++) {\n sum += (s.charCodeAt(i) - 48) * ACCOUNT_W[i % 3];\n }\n return sum % 10 === 0;\n}\n\nexport function isValidRuIban(value: string): boolean {\n const s = compactUpper(value);\n if (s.length !== 33 || !s.startsWith(\"RU\") || !/^[0-9A-Z]+$/.test(s)) {\n return false;\n }\n return isIbanChecksumValid(s);\n}\n\nconst PLATE_RE = new RegExp(\n `^[${RU_PLATE_LETTERS}](\\\\d{3})[${RU_PLATE_LETTERS}]{2}(\\\\d{2}|[1-9]\\\\d{2})$`\n);\n\nexport function isValidRuPlate(value: string): boolean {\n const s = (value ?? \"\").replace(/\\s+/g, \"\").replace(/_+$/, \"\").split(\"\").map(toRuPlateChar).join(\"\");\n const m = PLATE_RE.exec(s);\n if (!m) {\n return false;\n }\n // 000 is never issued; region 00 does not exist\n return m[1] !== \"000\" && Number(m[2]) !== 0;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "react-input-mask-format",
3
3
  "description": "Masked input component for React",
4
- "version": "2.3.0",
4
+ "version": "2.4.0",
5
5
  "type": "module",
6
6
  "homepage": "https://github.com/Temirtator/react-input-mask-format",
7
7
  "license": "MIT",
@@ -11,7 +11,13 @@
11
11
  "input",
12
12
  "mask",
13
13
  "masked",
14
- "react-component"
14
+ "react-component",
15
+ "presets",
16
+ "russia",
17
+ "inn",
18
+ "snils",
19
+ "ogrn",
20
+ "kazakhstan"
15
21
  ],
16
22
  "peerDependencies": {
17
23
  "react": ">=16.8.0"
@@ -82,6 +88,7 @@
82
88
  "scripts": {
83
89
  "build": "tsup",
84
90
  "demo": "vite demo",
91
+ "demo:build": "vite build demo",
85
92
  "lint": "eslint .",
86
93
  "typecheck": "tsc --noEmit",
87
94
  "test": "vitest run",