@alfalab/core-components-phone-input 5.2.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/CHANGELOG.md +316 -0
- package/dist/Component.d.ts +10 -0
- package/dist/Component.js +136 -0
- package/dist/cssm/Component.d.ts +10 -0
- package/dist/cssm/Component.js +136 -0
- package/dist/cssm/index.d.ts +1 -0
- package/dist/cssm/index.js +13 -0
- package/dist/cssm/utils/index.d.ts +17 -0
- package/dist/cssm/utils/index.js +37 -0
- package/dist/esm/Component.d.ts +10 -0
- package/dist/esm/Component.js +128 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/utils/index.d.ts +17 -0
- package/dist/esm/utils/index.js +31 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +13 -0
- package/dist/modern/Component.d.ts +10 -0
- package/dist/modern/Component.js +88 -0
- package/dist/modern/index.d.ts +1 -0
- package/dist/modern/index.js +5 -0
- package/dist/modern/utils/index.d.ts +17 -0
- package/dist/modern/utils/index.js +27 -0
- package/dist/send-stats.js +82 -0
- package/dist/utils/index.d.ts +17 -0
- package/dist/utils/index.js +37 -0
- package/package.json +27 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import React, { useRef, useImperativeHandle, useCallback } from 'react';
|
|
2
|
+
import { conformToMask } from 'text-mask-core';
|
|
3
|
+
import { MaskedInput } from '@alfalab/core-components-masked-input/dist/modern';
|
|
4
|
+
import { deleteFormatting, setCaretPosition, getInsertedNumber } from './utils/index.js';
|
|
5
|
+
|
|
6
|
+
const mask = [
|
|
7
|
+
'+',
|
|
8
|
+
'7',
|
|
9
|
+
' ',
|
|
10
|
+
/([0-6]|[8-9])/,
|
|
11
|
+
/\d/,
|
|
12
|
+
/\d/,
|
|
13
|
+
' ',
|
|
14
|
+
/\d/,
|
|
15
|
+
/\d/,
|
|
16
|
+
/\d/,
|
|
17
|
+
'-',
|
|
18
|
+
/\d/,
|
|
19
|
+
/\d/,
|
|
20
|
+
'-',
|
|
21
|
+
/\d/,
|
|
22
|
+
/\d/,
|
|
23
|
+
];
|
|
24
|
+
const countryPrefix = '+7 ';
|
|
25
|
+
const PhoneInput = React.forwardRef(({ clearableCountryCode = true, ...restProps }, ref) => {
|
|
26
|
+
const inputRef = useRef(null);
|
|
27
|
+
// Оставляет возможность прокинуть ref извне
|
|
28
|
+
useImperativeHandle(ref, () => inputRef.current);
|
|
29
|
+
const handleBeforeDisplay = useCallback((conformedValue, config) => {
|
|
30
|
+
const { rawValue, previousConformedValue, currentCaretPosition } = config;
|
|
31
|
+
/*
|
|
32
|
+
* код ниже нужен для фикса следующих багов библиотеки text-mask:
|
|
33
|
+
* 1) так как код страны указан в маске жестко как "+7",
|
|
34
|
+
* то при удалении цифры перед ним каретка устанавливается перед кодом страны
|
|
35
|
+
* 2) в номере телефона есть пробелы и дефисы,
|
|
36
|
+
* при редактировании цифр рядом с этими символами каретка перескакивает через них,
|
|
37
|
+
* а не остается на том же месте, на котором была до редактирования
|
|
38
|
+
*/
|
|
39
|
+
const previousValueWithoutFormatting = previousConformedValue
|
|
40
|
+
? deleteFormatting(previousConformedValue)
|
|
41
|
+
: '';
|
|
42
|
+
const currentValueWithoutFormatting = deleteFormatting(conformedValue) || '';
|
|
43
|
+
if (previousConformedValue &&
|
|
44
|
+
(([3, 6].includes(currentCaretPosition) &&
|
|
45
|
+
Math.abs(previousValueWithoutFormatting.length -
|
|
46
|
+
currentValueWithoutFormatting.length) === 1) ||
|
|
47
|
+
([7, 10, 13].includes(currentCaretPosition) &&
|
|
48
|
+
previousConformedValue.length > currentCaretPosition))) {
|
|
49
|
+
setCaretPosition({ position: currentCaretPosition, inputRef });
|
|
50
|
+
}
|
|
51
|
+
// Удаление цифры перед кодом страны удаляет только саму цифру, код остается ("+7 1" -> "+7 ")
|
|
52
|
+
if (rawValue === countryPrefix) {
|
|
53
|
+
return rawValue;
|
|
54
|
+
}
|
|
55
|
+
// Вставка номера с 10 цифрами без кода страны
|
|
56
|
+
if (rawValue.length === 10 && conformedValue.length === mask.length) {
|
|
57
|
+
const masked = conformToMask(`+7${rawValue}`, mask, config);
|
|
58
|
+
return masked.conformedValue;
|
|
59
|
+
}
|
|
60
|
+
const insertedNumber = getInsertedNumber({
|
|
61
|
+
rawValue,
|
|
62
|
+
clearableCountryCode,
|
|
63
|
+
countryPrefix,
|
|
64
|
+
previousConformedValue,
|
|
65
|
+
});
|
|
66
|
+
// Вставка номера, начинающегося с 8 или 7: 89990313131, 71112223344
|
|
67
|
+
if (conformedValue.length === mask.length &&
|
|
68
|
+
(insertedNumber.startsWith('8') || insertedNumber.startsWith('7'))) {
|
|
69
|
+
const masked = conformToMask(`+7${insertedNumber.slice(1)}`, mask, config);
|
|
70
|
+
return masked.conformedValue;
|
|
71
|
+
}
|
|
72
|
+
// Если ввод начат с 7 или 8 - выводит "+7 " и дает продолжить ввод со след. цифры
|
|
73
|
+
if (rawValue.length === 1 && ['7', '8'].includes(rawValue[0])) {
|
|
74
|
+
return countryPrefix;
|
|
75
|
+
}
|
|
76
|
+
const abortCountryCodeClearing = !clearableCountryCode && !conformedValue;
|
|
77
|
+
if (abortCountryCodeClearing) {
|
|
78
|
+
setCaretPosition({ position: countryPrefix.length, inputRef });
|
|
79
|
+
if (!rawValue.length)
|
|
80
|
+
return countryPrefix;
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
return conformedValue;
|
|
84
|
+
}, [clearableCountryCode]);
|
|
85
|
+
return (React.createElement(MaskedInput, Object.assign({}, restProps, { defaultValue: clearableCountryCode ? restProps.defaultValue : countryPrefix, mask: mask, onBeforeDisplay: handleBeforeDisplay, type: 'tel', ref: inputRef })));
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
export { PhoneInput };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Component";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
/**
|
|
3
|
+
* Удаляет форматирование номера телефона
|
|
4
|
+
* @param phone Номер телефона
|
|
5
|
+
*/
|
|
6
|
+
declare const deleteFormatting: (phone: string) => string;
|
|
7
|
+
declare function setCaretPosition({ position, inputRef, }: {
|
|
8
|
+
position: number;
|
|
9
|
+
inputRef: React.RefObject<HTMLInputElement>;
|
|
10
|
+
}): void;
|
|
11
|
+
declare function getInsertedNumber({ rawValue, clearableCountryCode, countryPrefix, previousConformedValue, }: {
|
|
12
|
+
rawValue: string;
|
|
13
|
+
clearableCountryCode: boolean;
|
|
14
|
+
countryPrefix: string;
|
|
15
|
+
previousConformedValue: string;
|
|
16
|
+
}): string;
|
|
17
|
+
export { deleteFormatting, setCaretPosition, getInsertedNumber };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Удаляет форматирование номера телефона
|
|
3
|
+
* @param phone Номер телефона
|
|
4
|
+
*/
|
|
5
|
+
const deleteFormatting = (phone) => phone
|
|
6
|
+
.replace('+', '')
|
|
7
|
+
.replace(/^7/, '')
|
|
8
|
+
.replace(/\s/g, '')
|
|
9
|
+
.replace(/-/g, '');
|
|
10
|
+
function setCaretPosition({ position, inputRef, }) {
|
|
11
|
+
window.requestAnimationFrame(() => {
|
|
12
|
+
if (inputRef === null || !inputRef.current)
|
|
13
|
+
return;
|
|
14
|
+
inputRef.current.setSelectionRange(position, position);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
function getInsertedNumber({ rawValue, clearableCountryCode, countryPrefix, previousConformedValue, }) {
|
|
18
|
+
if (!clearableCountryCode && previousConformedValue === countryPrefix) {
|
|
19
|
+
if (rawValue.startsWith('7') || rawValue.startsWith('8')) {
|
|
20
|
+
return rawValue;
|
|
21
|
+
}
|
|
22
|
+
return rawValue.slice(countryPrefix.length);
|
|
23
|
+
}
|
|
24
|
+
return rawValue;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { deleteFormatting, getInsertedNumber, setCaretPosition };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const http = require('http');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const { promisify } = require('util');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const readFile = promisify(fs.readFile);
|
|
7
|
+
|
|
8
|
+
async function main() {
|
|
9
|
+
const remoteHost = process.env.NIS_HOST || 'digital';
|
|
10
|
+
const remotePort = process.env.NIS_PORT || 80;
|
|
11
|
+
const remotePath = process.env.NIS_PATH || '/npm-install-stats/api/install-stats';
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const [_, node, os, arch] =
|
|
15
|
+
/node\/v(\d+\.\d+\.\d+) (\w+) (\w+)/.exec(process.env.npm_config_user_agent) || [];
|
|
16
|
+
const [__, npm] = /npm\/(\d+\.\d+\.\d+)/.exec(process.env.npm_config_user_agent) || [];
|
|
17
|
+
const [___, yarn] = /yarn\/(\d+\.\d+\.\d+)/.exec(process.env.npm_config_user_agent) || [];
|
|
18
|
+
|
|
19
|
+
let ownPackageJson, packageJson;
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
const result = await Promise.all([
|
|
23
|
+
readFile(path.join(process.cwd(), 'package.json'), 'utf-8'),
|
|
24
|
+
readFile(path.join(process.cwd(), '../../../package.json'), 'utf-8'),
|
|
25
|
+
]);
|
|
26
|
+
|
|
27
|
+
ownPackageJson = JSON.parse(result[0]);
|
|
28
|
+
packageJson = JSON.parse(result[1]);
|
|
29
|
+
} catch (err) {
|
|
30
|
+
ownPackageJson = '';
|
|
31
|
+
packageJson = '';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const data = {
|
|
35
|
+
node,
|
|
36
|
+
npm,
|
|
37
|
+
yarn,
|
|
38
|
+
os,
|
|
39
|
+
arch,
|
|
40
|
+
ownPackageJson: JSON.stringify(ownPackageJson),
|
|
41
|
+
packageJson: JSON.stringify(packageJson),
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const body = JSON.stringify(data);
|
|
45
|
+
|
|
46
|
+
const options = {
|
|
47
|
+
host: remoteHost,
|
|
48
|
+
port: remotePort,
|
|
49
|
+
path: remotePath,
|
|
50
|
+
method: 'POST',
|
|
51
|
+
headers: {
|
|
52
|
+
'Content-Type': 'application/json',
|
|
53
|
+
'Content-Length': body.length,
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
const req = http.request(options, res => {
|
|
59
|
+
res.on('end', () => {
|
|
60
|
+
resolve();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
req.on('error', () => {
|
|
65
|
+
reject();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
req.write(body);
|
|
69
|
+
req.end();
|
|
70
|
+
});
|
|
71
|
+
} catch (error) {
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
main()
|
|
77
|
+
.then(() => {
|
|
78
|
+
process.exit(0);
|
|
79
|
+
})
|
|
80
|
+
.catch(() => {
|
|
81
|
+
process.exit(0);
|
|
82
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
/**
|
|
3
|
+
* Удаляет форматирование номера телефона
|
|
4
|
+
* @param phone Номер телефона
|
|
5
|
+
*/
|
|
6
|
+
declare const deleteFormatting: (phone: string) => string;
|
|
7
|
+
declare function setCaretPosition({ position, inputRef, }: {
|
|
8
|
+
position: number;
|
|
9
|
+
inputRef: React.RefObject<HTMLInputElement>;
|
|
10
|
+
}): void;
|
|
11
|
+
declare function getInsertedNumber({ rawValue, clearableCountryCode, countryPrefix, previousConformedValue, }: {
|
|
12
|
+
rawValue: string;
|
|
13
|
+
clearableCountryCode: boolean;
|
|
14
|
+
countryPrefix: string;
|
|
15
|
+
previousConformedValue: string;
|
|
16
|
+
}): string;
|
|
17
|
+
export { deleteFormatting, setCaretPosition, getInsertedNumber };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Удаляет форматирование номера телефона
|
|
7
|
+
* @param phone Номер телефона
|
|
8
|
+
*/
|
|
9
|
+
var deleteFormatting = function (phone) {
|
|
10
|
+
return phone
|
|
11
|
+
.replace('+', '')
|
|
12
|
+
.replace(/^7/, '')
|
|
13
|
+
.replace(/\s/g, '')
|
|
14
|
+
.replace(/-/g, '');
|
|
15
|
+
};
|
|
16
|
+
function setCaretPosition(_a) {
|
|
17
|
+
var position = _a.position, inputRef = _a.inputRef;
|
|
18
|
+
window.requestAnimationFrame(function () {
|
|
19
|
+
if (inputRef === null || !inputRef.current)
|
|
20
|
+
return;
|
|
21
|
+
inputRef.current.setSelectionRange(position, position);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function getInsertedNumber(_a) {
|
|
25
|
+
var rawValue = _a.rawValue, clearableCountryCode = _a.clearableCountryCode, countryPrefix = _a.countryPrefix, previousConformedValue = _a.previousConformedValue;
|
|
26
|
+
if (!clearableCountryCode && previousConformedValue === countryPrefix) {
|
|
27
|
+
if (rawValue.startsWith('7') || rawValue.startsWith('8')) {
|
|
28
|
+
return rawValue;
|
|
29
|
+
}
|
|
30
|
+
return rawValue.slice(countryPrefix.length);
|
|
31
|
+
}
|
|
32
|
+
return rawValue;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
exports.deleteFormatting = deleteFormatting;
|
|
36
|
+
exports.getInsertedNumber = getInsertedNumber;
|
|
37
|
+
exports.setCaretPosition = setCaretPosition;
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@alfalab/core-components-phone-input",
|
|
3
|
+
"version": "5.2.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"keywords": [],
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"module": "./dist/esm/index.js",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"postinstall": "node ./dist/send-stats.js > /dev/null 2>&1 || exit 0"
|
|
14
|
+
},
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"react": "^16.9.0 || ^17.0.1"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@alfalab/core-components-masked-input": "^4.2.0",
|
|
23
|
+
"classnames": "^2.2.6",
|
|
24
|
+
"text-mask-core": "^5.1.2"
|
|
25
|
+
},
|
|
26
|
+
"gitHead": "a80a4377703da0cb8fd257612117ef3eb2d9bc42"
|
|
27
|
+
}
|