@tecsinapse/react-core 1.13.0 → 1.14.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/dist/components/atoms/Input/InputElement/InputElement.d.ts +5 -3
- package/dist/components/atoms/Input/InputElement/InputElement.js +48 -7
- package/dist/components/atoms/Input/InputElement/InputElement.js.map +1 -1
- package/dist/components/atoms/Input/hooks/useNumberMask.d.ts +8 -0
- package/dist/components/atoms/Input/hooks/useNumberMask.js +98 -0
- package/dist/components/atoms/Input/hooks/useNumberMask.js.map +1 -0
- package/dist/components/atoms/Input/hooks/useStringMask.d.ts +8 -0
- package/dist/components/atoms/Input/hooks/useStringMask.js +109 -0
- package/dist/components/atoms/Input/hooks/useStringMask.js.map +1 -0
- package/dist/components/atoms/Input/index.d.ts +2 -3
- package/dist/components/atoms/Input/index.js +12 -26
- package/dist/components/atoms/Input/index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +8 -29
- package/dist/index.js.map +1 -1
- package/dist/utils/formatWithMask.d.ts +3 -0
- package/dist/utils/formatWithMask.js +31 -0
- package/dist/utils/formatWithMask.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +28 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/masks.d.ts +11 -0
- package/dist/utils/masks.js +19 -0
- package/dist/utils/masks.js.map +1 -0
- package/package.json +2 -2
- package/src/components/atoms/Input/InputElement/InputElement.tsx +75 -10
- package/src/components/atoms/Input/hooks/useNumberMask.ts +99 -0
- package/src/components/atoms/Input/hooks/useStringMask.ts +128 -0
- package/src/components/atoms/Input/index.ts +2 -3
- package/src/index.ts +3 -6
- package/src/utils/formatWithMask.ts +25 -0
- package/src/utils/index.ts +4 -2
- package/src/utils/masks.ts +15 -0
- package/dist/components/atoms/Input/hooks/useCurrencyMask.d.ts +0 -3
- package/dist/components/atoms/Input/hooks/useCurrencyMask.js +0 -69
- package/dist/components/atoms/Input/hooks/useCurrencyMask.js.map +0 -1
- package/dist/components/atoms/Input/hooks/useMask.d.ts +0 -9
- package/dist/components/atoms/Input/hooks/useMask.js +0 -61
- package/dist/components/atoms/Input/hooks/useMask.js.map +0 -1
- package/dist/components/atoms/Input/masks/index.d.ts +0 -10
- package/dist/components/atoms/Input/masks/index.js +0 -18
- package/dist/components/atoms/Input/masks/index.js.map +0 -1
- package/src/components/atoms/Input/hooks/useCurrencyMask.ts +0 -74
- package/src/components/atoms/Input/hooks/useMask.ts +0 -92
- package/src/components/atoms/Input/masks/index.ts +0 -12
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;AACA;;AACA;;AACA;;AAUA;;AACA;;AACA;;AACA;;AACA;;AACA;;AAOA;;AACA;;AAeA;;AACA;;AAIA;;AACA;;AACA;;AACA;;AACA;;AACA;;AAOA;;AACA;;AAIA;;AAKA;;AACA;;AACA;;AAIA;;AAKA;;AACA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AACA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AACA;;AACA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AACA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AACA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA","sourcesContent":["export { Avatar, AvatarProps } from './components/atoms/Avatar';\nexport { Badge, BadgeProps } from './components/atoms/Badge';\nexport { BoxContent, BoxContentProps } from './components/atoms/BoxContent';\nexport {\n Button,\n ButtonProps,\n ButtonSizeType,\n ButtonStateProps,\n ButtonStateType,\n Error,\n Loading,\n Success,\n} from './components/atoms/Button';\nexport { Card, CardProps } from './components/atoms/Card';\nexport { Footer, FooterProps } from './components/atoms/Card/Footer';\nexport { Header, HeaderProps } from './components/atoms/Card/Header';\nexport { Checkbox, CheckboxProps } from './components/atoms/Checkbox';\nexport { Divider, DividerProps } from './components/atoms/Divider';\nexport {\n GroupButton,\n GroupButtonOption,\n GroupButtonOptionProps,\n GroupButtonProps,\n GroupButtonValue,\n} from './components/atoms/GroupButton';\nexport { Icon, IconProps } from './components/atoms/Icon';\nexport {\n Hint,\n InputContainer,\n InputContainerProps,\n InputElement,\n InputElementProps,\n InputVariantType,\n PressableInputContainer,\n PressableInputContainerProps,\n StyledBorderKeeper,\n useInputFocus,\n useNumberMask,\n useStringMask,\n disabledInputStyles,\n} from './components/atoms/Input';\nexport { Paper, PaperProps } from './components/atoms/Paper';\nexport {\n PressableSurface,\n PressableSurfaceProps,\n} from './components/atoms/PressableSurface';\nexport { ProgressBar, ProgressBarProps } from './components/atoms/ProgressBar';\nexport { RadioButton, RadioButtonProps } from './components/atoms/RadioButton';\nexport { Switch, SwitchProps } from './components/atoms/Switch';\nexport { Tag, TagProps } from './components/atoms/Tag';\nexport { Text, TextProps } from './components/atoms/Text';\nexport {\n Calendar,\n CalendarProps,\n DateRange,\n SelectionType,\n Value,\n} from './components/molecules/Calendar';\nexport { DatePicker, DatePickerProps } from './components/molecules/DatePicker';\nexport {\n DateTimePicker,\n DateTimePickerProps,\n} from './components/molecules/DateTimePicker';\nexport {\n DateTimeSelector,\n DateTimeSelectorMode,\n DateTimeSelectorProps,\n} from './components/molecules/DateTimeSelector';\nexport { InputPasswordIcon } from './components/molecules/InputPassword';\nexport { Snackbar, SnackbarProps } from './components/molecules/Snackbar';\nexport {\n HintInputContainer,\n HintInputContainerProps,\n} from './components/molecules/HintInputContainer';\nexport {\n TextArea,\n TextAreaProps,\n TextAreaInputBase,\n} from './components/molecules/TextArea';\nexport { GridItem, Grid, IGridItem, IGrid } from './components/molecules/Grid';\nexport * from './styles/definitions';\nexport * from './styles/light';\nexport { default as ThemeProvider } from './styles/ThemeProvider';\nexport * from './types/defaults';\nexport * from './utils';\nexport * from './hooks';\n"],"file":"index.js"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.formatWithMask = void 0;
|
|
7
|
+
|
|
8
|
+
var _Input = require("../components/atoms/Input");
|
|
9
|
+
|
|
10
|
+
var _currency = _interopRequireDefault(require("currency.js"));
|
|
11
|
+
|
|
12
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
+
|
|
14
|
+
const formatWithMask = (mask, value) => {
|
|
15
|
+
if (Array.isArray(mask) || typeof mask === 'function') {
|
|
16
|
+
const selectedMask = (0, _Input.getMask)(mask, String(value));
|
|
17
|
+
const {
|
|
18
|
+
formatted
|
|
19
|
+
} = (0, _Input.mergeMask)(String(value), selectedMask);
|
|
20
|
+
return formatted || '';
|
|
21
|
+
} else {
|
|
22
|
+
const {
|
|
23
|
+
internalNumber,
|
|
24
|
+
mergedOptions
|
|
25
|
+
} = (0, _Input.getInternalNumberAndMask)(value, mask);
|
|
26
|
+
return (0, _currency.default)(internalNumber).format(mergedOptions);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
exports.formatWithMask = formatWithMask;
|
|
31
|
+
//# sourceMappingURL=formatWithMask.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/formatWithMask.ts"],"names":["formatWithMask","mask","value","Array","isArray","selectedMask","String","formatted","internalNumber","mergedOptions","format"],"mappings":";;;;;;;AAAA;;AAOA;;;;AAEO,MAAMA,cAAc,GAAG,CAC5BC,IAD4B,EAE5BC,KAF4B,KAGR;AACpB,MAAIC,KAAK,CAACC,OAAN,CAAcH,IAAd,KAAuB,OAAOA,IAAP,KAAgB,UAA3C,EAAuD;AACrD,UAAMI,YAAY,GAAG,oBAAQJ,IAAR,EAAcK,MAAM,CAACJ,KAAD,CAApB,CAArB;AACA,UAAM;AAAEK,MAAAA;AAAF,QAAgB,sBAAUD,MAAM,CAACJ,KAAD,CAAhB,EAAyBG,YAAzB,CAAtB;AACA,WAAOE,SAAS,IAAI,EAApB;AACD,GAJD,MAIO;AACL,UAAM;AAAEC,MAAAA,cAAF;AAAkBC,MAAAA;AAAlB,QAAoC,qCACxCP,KADwC,EAExCD,IAFwC,CAA1C;AAIA,WAAO,uBAASO,cAAT,EAAyBE,MAAzB,CAAgCD,aAAhC,CAAP;AACD;AACF,CAfM","sourcesContent":["import {\n MaskType,\n CurrencyOptions,\n getMask,\n mergeMask,\n getInternalNumberAndMask,\n} from '../components/atoms/Input';\nimport currency from 'currency.js';\n\nexport const formatWithMask = (\n mask: (MaskType[] | ((value: string) => MaskType[])) | CurrencyOptions,\n value: string | number\n): string | number => {\n if (Array.isArray(mask) || typeof mask === 'function') {\n const selectedMask = getMask(mask, String(value));\n const { formatted } = mergeMask(String(value), selectedMask);\n return formatted || '';\n } else {\n const { internalNumber, mergedOptions } = getInternalNumberAndMask(\n value,\n mask\n );\n return currency(internalNumber).format(mergedOptions);\n }\n};\n"],"file":"formatWithMask.js"}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -2,3 +2,5 @@ export { lightenDarkenColor } from './lightenDarkenColor';
|
|
|
2
2
|
export { extractNumbersFromString, extractDigitsFromString, } from './extractNumbersFromString';
|
|
3
3
|
export * from './IPhoneXHelper';
|
|
4
4
|
export * from './ResponsiveFontSize';
|
|
5
|
+
export * from './masks';
|
|
6
|
+
export * from './formatWithMask';
|
package/dist/utils/index.js
CHANGED
|
@@ -58,4 +58,32 @@ Object.keys(_ResponsiveFontSize).forEach(function (key) {
|
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
60
|
});
|
|
61
|
+
|
|
62
|
+
var _masks = require("./masks");
|
|
63
|
+
|
|
64
|
+
Object.keys(_masks).forEach(function (key) {
|
|
65
|
+
if (key === "default" || key === "__esModule") return;
|
|
66
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
67
|
+
if (key in exports && exports[key] === _masks[key]) return;
|
|
68
|
+
Object.defineProperty(exports, key, {
|
|
69
|
+
enumerable: true,
|
|
70
|
+
get: function () {
|
|
71
|
+
return _masks[key];
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
var _formatWithMask = require("./formatWithMask");
|
|
77
|
+
|
|
78
|
+
Object.keys(_formatWithMask).forEach(function (key) {
|
|
79
|
+
if (key === "default" || key === "__esModule") return;
|
|
80
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
81
|
+
if (key in exports && exports[key] === _formatWithMask[key]) return;
|
|
82
|
+
Object.defineProperty(exports, key, {
|
|
83
|
+
enumerable: true,
|
|
84
|
+
get: function () {
|
|
85
|
+
return _formatWithMask[key];
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
});
|
|
61
89
|
//# sourceMappingURL=index.js.map
|
package/dist/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;AACA;;AAIA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AACA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA","sourcesContent":["export { lightenDarkenColor } from './lightenDarkenColor';\nexport {\n extractNumbersFromString,\n extractDigitsFromString,\n} from './extractNumbersFromString';\nexport * from './IPhoneXHelper'
|
|
1
|
+
{"version":3,"sources":["../../src/utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;AACA;;AAIA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AACA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AACA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AACA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA","sourcesContent":["export { lightenDarkenColor } from './lightenDarkenColor';\nexport {\n extractNumbersFromString,\n extractDigitsFromString,\n} from './extractNumbersFromString';\nexport * from './IPhoneXHelper';\nexport * from './ResponsiveFontSize';\nexport * from './masks';\nexport * from './formatWithMask';\n"],"file":"index.js"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const Masks: {
|
|
2
|
+
CPF: string[];
|
|
3
|
+
CNPJ: string[];
|
|
4
|
+
DATE: string[];
|
|
5
|
+
MONTH_YEAR: string[];
|
|
6
|
+
CEP: string[];
|
|
7
|
+
PHONE: string[];
|
|
8
|
+
PHONE_EXTENDED: string[];
|
|
9
|
+
COMBINED_PHONE: (value: string) => string[];
|
|
10
|
+
COMBINED_CPF_CNPJ: (value: string) => string[];
|
|
11
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.Masks = void 0;
|
|
7
|
+
const Masks = {
|
|
8
|
+
CPF: ['999.999.999-99'],
|
|
9
|
+
CNPJ: ['99.999.999/9999-99'],
|
|
10
|
+
DATE: ['99/99/9999'],
|
|
11
|
+
MONTH_YEAR: ['99/9999'],
|
|
12
|
+
CEP: ['99999-999'],
|
|
13
|
+
PHONE: ['(99) 9999-9999'],
|
|
14
|
+
PHONE_EXTENDED: ['(99) 99999-9999'],
|
|
15
|
+
COMBINED_PHONE: value => (value === null || value === void 0 ? void 0 : value.length) <= 14 ? Masks.PHONE : Masks.PHONE_EXTENDED,
|
|
16
|
+
COMBINED_CPF_CNPJ: value => (value === null || value === void 0 ? void 0 : value.length) <= 14 ? Masks.CPF : Masks.CNPJ
|
|
17
|
+
};
|
|
18
|
+
exports.Masks = Masks;
|
|
19
|
+
//# sourceMappingURL=masks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/masks.ts"],"names":["Masks","CPF","CNPJ","DATE","MONTH_YEAR","CEP","PHONE","PHONE_EXTENDED","COMBINED_PHONE","value","length","COMBINED_CPF_CNPJ"],"mappings":";;;;;;AACO,MAAMA,KAAK,GAAG;AACnBC,EAAAA,GAAG,EAAE,CAAC,gBAAD,CADc;AAEnBC,EAAAA,IAAI,EAAE,CAAC,oBAAD,CAFa;AAGnBC,EAAAA,IAAI,EAAE,CAAC,YAAD,CAHa;AAInBC,EAAAA,UAAU,EAAE,CAAC,SAAD,CAJO;AAKnBC,EAAAA,GAAG,EAAE,CAAC,WAAD,CALc;AAMnBC,EAAAA,KAAK,EAAE,CAAC,gBAAD,CANY;AAOnBC,EAAAA,cAAc,EAAE,CAAC,iBAAD,CAPG;AAQnBC,EAAAA,cAAc,EAAGC,KAAD,IAEd,CAAAA,KAAK,SAAL,IAAAA,KAAK,WAAL,YAAAA,KAAK,CAAEC,MAAP,KAAiB,EAAjB,GAAsBV,KAAK,CAACM,KAA5B,GAAoCN,KAAK,CAACO,cAVzB;AAWnBI,EAAAA,iBAAiB,EAAGF,KAAD,IACjB,CAAAA,KAAK,SAAL,IAAAA,KAAK,WAAL,YAAAA,KAAK,CAAEC,MAAP,KAAiB,EAAjB,GAAsBV,KAAK,CAACC,GAA5B,GAAkCD,KAAK,CAACE;AAZvB,CAAd","sourcesContent":["// NOTE: Add here all individually utils, then you can use it on input components everywhere.\nexport const Masks = {\n CPF: ['999.999.999-99'],\n CNPJ: ['99.999.999/9999-99'],\n DATE: ['99/99/9999'],\n MONTH_YEAR: ['99/9999'],\n CEP: ['99999-999'],\n PHONE: ['(99) 9999-9999'],\n PHONE_EXTENDED: ['(99) 99999-9999'],\n COMBINED_PHONE: (value: string) =>\n // Value in formatted mode\n value?.length <= 14 ? Masks.PHONE : Masks.PHONE_EXTENDED,\n COMBINED_CPF_CNPJ: (value: string) =>\n value?.length <= 14 ? Masks.CPF : Masks.CNPJ,\n};\n"],"file":"masks.js"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tecsinapse/react-core",
|
|
3
3
|
"description": "TecSinapse hybrid React components",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.14.3",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -31,5 +31,5 @@
|
|
|
31
31
|
"react-native": ">=0.64.0",
|
|
32
32
|
"react-native-vector-icons": ">=8.1.0"
|
|
33
33
|
},
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "66b219caf752d5f3ed2fcbf096d530fe6c1d2938"
|
|
35
35
|
}
|
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
import { useTheme } from '@emotion/react';
|
|
2
2
|
import { ThemeProp } from '@tecsinapse/react-core';
|
|
3
|
-
import React, { FC } from 'react';
|
|
3
|
+
import React, { FC, useCallback, useEffect, useState } from 'react';
|
|
4
4
|
import { StyleProp, TextInputProps, TextStyle } from 'react-native';
|
|
5
|
-
import { IMask } from '../hooks/useMask';
|
|
6
5
|
import { StyledInputElement } from '../styled';
|
|
6
|
+
import { MaskType, useStringMask } from '../hooks/useStringMask';
|
|
7
|
+
import { CurrencyOptions, useNumberMask } from '../hooks/useNumberMask';
|
|
7
8
|
|
|
8
9
|
export interface InputElementProps
|
|
9
10
|
extends Omit<TextInputProps, 'onChange' | 'value' | 'ref'> {
|
|
10
11
|
style?: StyleProp<TextStyle>;
|
|
11
|
-
|
|
12
|
-
* TODO:
|
|
13
|
-
*/
|
|
14
|
-
value?: string | IMask;
|
|
12
|
+
value: string | number;
|
|
15
13
|
placeholder?: string;
|
|
16
14
|
disabled?: boolean;
|
|
17
|
-
onChange?: (value:
|
|
15
|
+
onChange?: (value: any) => void;
|
|
16
|
+
/**
|
|
17
|
+
To use mask for strings you have to pass a MaskType[] or ((value: string) => MaskType[])
|
|
18
|
+
A MaskType can be a string, RegExp, or Array<RegExp>.
|
|
19
|
+
In case we have a string, '9' represents digits, 'a' represents alphabet characters, and any other character represents fixed characters in the mask.
|
|
20
|
+
For example a phone mask can be represented as ['(99) \\99999-9999'], or ['(99) ', '/[9]/', '9999-9999'], or ['(', /[0-9]/, /[0-9]/, ') ', '/[9]/', '9999-9999'] and many others.
|
|
21
|
+
To use mask for numbers you have to pass a CurrencyOptions object
|
|
22
|
+
A CurrencyOptions object contains symbol, separator, decimal, precision. For example {symbol: 'R$ ', separator: '.', decimal: ',', precision: 2,}.
|
|
23
|
+
**/
|
|
24
|
+
mask?: (MaskType[] | ((value: string) => MaskType[])) | CurrencyOptions;
|
|
18
25
|
onFocus?: () => void;
|
|
19
26
|
onBlur?: () => void;
|
|
20
27
|
ref?: React.Ref<any>;
|
|
@@ -28,20 +35,78 @@ const InputElement: FC<InputElementProps> = React.forwardRef(
|
|
|
28
35
|
value,
|
|
29
36
|
disabled = false,
|
|
30
37
|
placeholderTextColor,
|
|
38
|
+
mask,
|
|
31
39
|
...rest
|
|
32
40
|
},
|
|
33
41
|
ref: React.Ref<any>
|
|
34
42
|
): JSX.Element => {
|
|
35
43
|
const theme = useTheme() as ThemeProp;
|
|
36
|
-
|
|
37
|
-
|
|
44
|
+
|
|
45
|
+
/** Check if value was reinitialized, without this state we can't total "erase" a value that was already reinitialized **/
|
|
46
|
+
const [valueReinitialized, setValueReinitialized] = useState<boolean>(
|
|
47
|
+
false
|
|
48
|
+
);
|
|
49
|
+
|
|
38
50
|
const _placeholderColor = placeholderTextColor || theme.font.color.dark;
|
|
39
51
|
|
|
52
|
+
const getInputHook = () => {
|
|
53
|
+
if (mask !== undefined) {
|
|
54
|
+
if (Array.isArray(mask) || typeof mask === 'function') {
|
|
55
|
+
return useStringMask(mask, value ?? '');
|
|
56
|
+
} else {
|
|
57
|
+
return useNumberMask(mask, value ?? '');
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
return [undefined, undefined];
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const [maskValue, setMaskValue] = getInputHook();
|
|
65
|
+
|
|
66
|
+
const _value =
|
|
67
|
+
maskValue !== undefined
|
|
68
|
+
? maskValue?.formatted ?? ''
|
|
69
|
+
: value?.toString() ?? '';
|
|
70
|
+
|
|
71
|
+
const onChangeMaskValue = useCallback(() => {
|
|
72
|
+
if (onChange) {
|
|
73
|
+
onChange(maskValue?.raw);
|
|
74
|
+
}
|
|
75
|
+
}, [maskValue]);
|
|
76
|
+
|
|
77
|
+
const onChangeValue = useCallback(
|
|
78
|
+
async (value: string | number) => {
|
|
79
|
+
if (maskValue !== undefined && setMaskValue !== undefined) {
|
|
80
|
+
await setMaskValue(value);
|
|
81
|
+
onChangeMaskValue();
|
|
82
|
+
} else onChange && onChange(value);
|
|
83
|
+
},
|
|
84
|
+
[value]
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
if (!valueReinitialized) {
|
|
89
|
+
/** Used to reinitialize maskValue with a value that was loaded after Input was rendered **/
|
|
90
|
+
if (
|
|
91
|
+
maskValue !== undefined &&
|
|
92
|
+
setMaskValue !== undefined &&
|
|
93
|
+
value !== undefined &&
|
|
94
|
+
typeof maskValue === 'object'
|
|
95
|
+
) {
|
|
96
|
+
/** Case there is a mask **/
|
|
97
|
+
if (maskValue.raw !== value.toString()) {
|
|
98
|
+
setValueReinitialized(true);
|
|
99
|
+
setMaskValue(value);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}, [value, maskValue, valueReinitialized]);
|
|
104
|
+
|
|
40
105
|
return (
|
|
41
106
|
<StyledInputElement
|
|
42
107
|
{...rest}
|
|
43
108
|
ref={ref}
|
|
44
|
-
onChangeText={
|
|
109
|
+
onChangeText={onChangeValue}
|
|
45
110
|
value={_value}
|
|
46
111
|
placeholder={placeholder}
|
|
47
112
|
placeholderTextColor={_placeholderColor}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import currency from 'currency.js';
|
|
2
|
+
import { useCallback, useState } from 'react';
|
|
3
|
+
import { extractNumbersFromString } from '../../../../utils';
|
|
4
|
+
import { MaskValue } from './useStringMask';
|
|
5
|
+
|
|
6
|
+
export type CurrencyOptions = currency.Options;
|
|
7
|
+
|
|
8
|
+
const DEFAULT_OPTIONS: CurrencyOptions = {
|
|
9
|
+
symbol: 'R$ ',
|
|
10
|
+
separator: '.',
|
|
11
|
+
decimal: ',',
|
|
12
|
+
precision: 2,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const getRegex = (precision: number) =>
|
|
16
|
+
new RegExp(`\\B(?=(\\d{${precision}})(?!\\d))`, 'g');
|
|
17
|
+
|
|
18
|
+
export const getInternalNumberAndMask = (
|
|
19
|
+
value: string | number,
|
|
20
|
+
options?: CurrencyOptions
|
|
21
|
+
): { internalNumber: number; mergedOptions: CurrencyOptions } => {
|
|
22
|
+
const mergedOptions = { ...DEFAULT_OPTIONS, ...options };
|
|
23
|
+
const { precision = -1 } = mergedOptions;
|
|
24
|
+
|
|
25
|
+
let internalNumber;
|
|
26
|
+
|
|
27
|
+
if (typeof value === 'number') {
|
|
28
|
+
if (precision) {
|
|
29
|
+
let stringValue = String(value);
|
|
30
|
+
const decimalIndex = stringValue.indexOf('.');
|
|
31
|
+
const currentPrecision = decimalIndex + precision;
|
|
32
|
+
if (decimalIndex !== -1 && currentPrecision <= stringValue.length) {
|
|
33
|
+
const zeros = stringValue.length + 1 - currentPrecision;
|
|
34
|
+
for (let i = 0; i < zeros; i++) stringValue = stringValue + `0`;
|
|
35
|
+
}
|
|
36
|
+
internalNumber = Number(stringValue);
|
|
37
|
+
} else {
|
|
38
|
+
internalNumber = value;
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
const onlyNumbers = String(extractNumbersFromString(value));
|
|
42
|
+
const padZeros = String(onlyNumbers).padStart(precision + 1, '0');
|
|
43
|
+
internalNumber = Number(padZeros.replace(getRegex(precision), '.'));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (internalNumber > Number.MAX_SAFE_INTEGER) {
|
|
47
|
+
internalNumber = Number.MAX_SAFE_INTEGER;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (internalNumber < Number.MIN_SAFE_INTEGER) {
|
|
51
|
+
internalNumber = Number.MIN_SAFE_INTEGER;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
internalNumber,
|
|
56
|
+
mergedOptions,
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* TODO:
|
|
62
|
+
* @param options
|
|
63
|
+
* @param defaultValue
|
|
64
|
+
* @returns
|
|
65
|
+
*/
|
|
66
|
+
export const useNumberMask = (
|
|
67
|
+
options?: CurrencyOptions,
|
|
68
|
+
defaultValue?: string | number
|
|
69
|
+
): [MaskValue, (value: string | number) => void] => {
|
|
70
|
+
const applyMask = useCallback(
|
|
71
|
+
(value: string | number = 0): MaskValue => {
|
|
72
|
+
const { internalNumber, mergedOptions } = getInternalNumberAndMask(
|
|
73
|
+
value,
|
|
74
|
+
options
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
raw: internalNumber,
|
|
79
|
+
formatted: currency(internalNumber).format(mergedOptions),
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
[options, getRegex]
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const [value, setValue] = useState<MaskValue>(applyMask(defaultValue));
|
|
86
|
+
|
|
87
|
+
const handleChangeValue = useCallback(
|
|
88
|
+
(formattedValue: string | number) => {
|
|
89
|
+
const { raw, formatted } = applyMask(formattedValue);
|
|
90
|
+
setValue({
|
|
91
|
+
raw,
|
|
92
|
+
formatted,
|
|
93
|
+
});
|
|
94
|
+
},
|
|
95
|
+
[applyMask, setValue]
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
return [value, handleChangeValue];
|
|
99
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { useCallback, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface MaskValue {
|
|
4
|
+
formatted?: string;
|
|
5
|
+
raw?: string | number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type MaskType = string | RegExp | Array<RegExp>;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* TODO:
|
|
12
|
+
* @param value
|
|
13
|
+
* @param mask
|
|
14
|
+
* @returns
|
|
15
|
+
*/
|
|
16
|
+
export const mergeMask = (value = '', mask: MaskType[]): MaskValue => {
|
|
17
|
+
let formatted = '';
|
|
18
|
+
let raw = '';
|
|
19
|
+
let iMask = 0;
|
|
20
|
+
let iChars = 0;
|
|
21
|
+
|
|
22
|
+
while (!(iMask === mask.length || iChars === value.length)) {
|
|
23
|
+
const maskChar = mask[iMask];
|
|
24
|
+
const valueChar = value[iChars];
|
|
25
|
+
|
|
26
|
+
if (maskChar === valueChar) {
|
|
27
|
+
formatted += maskChar;
|
|
28
|
+
iChars++;
|
|
29
|
+
iMask++;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const rawValueChar = value[iChars];
|
|
34
|
+
|
|
35
|
+
if (typeof maskChar === 'object') {
|
|
36
|
+
iChars++;
|
|
37
|
+
|
|
38
|
+
const maskCharRegex = Array.isArray(maskChar) ? maskChar[0] : maskChar;
|
|
39
|
+
const matchRegex = RegExp(maskCharRegex).test(valueChar);
|
|
40
|
+
|
|
41
|
+
if (matchRegex) {
|
|
42
|
+
formatted += valueChar;
|
|
43
|
+
raw += rawValueChar;
|
|
44
|
+
iMask++;
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
formatted += maskChar;
|
|
48
|
+
iMask++;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return { raw, formatted };
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const getMask = (
|
|
56
|
+
mask: MaskType[] | ((value: string) => MaskType[]),
|
|
57
|
+
newValue: string
|
|
58
|
+
): MaskType[] => {
|
|
59
|
+
let maskArray: MaskType[];
|
|
60
|
+
const regexArray: MaskType[] = [];
|
|
61
|
+
|
|
62
|
+
if (typeof mask === 'function') {
|
|
63
|
+
maskArray = mask(newValue);
|
|
64
|
+
} else {
|
|
65
|
+
maskArray = mask;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
maskArray.forEach(exp => {
|
|
69
|
+
if (typeof exp !== 'string') {
|
|
70
|
+
if (Array.isArray(exp)) regexArray.push(exp);
|
|
71
|
+
else regexArray.push(exp);
|
|
72
|
+
} else {
|
|
73
|
+
for (let i = 0; i < exp.length; i++) {
|
|
74
|
+
if (exp[i] === '\\') {
|
|
75
|
+
regexArray.push(exp[i + 1]);
|
|
76
|
+
i++;
|
|
77
|
+
} else {
|
|
78
|
+
if (exp[i] === '9') regexArray.push(/\d/);
|
|
79
|
+
else if (exp[i] === 'a') regexArray.push(/[a-zA-Z]/);
|
|
80
|
+
else regexArray.push(exp[i]);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
return regexArray;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* TODO:
|
|
91
|
+
* @param mask
|
|
92
|
+
* @param defaultValue
|
|
93
|
+
* @returns
|
|
94
|
+
*/
|
|
95
|
+
export const useStringMask = (
|
|
96
|
+
mask: MaskType[] | ((value: string) => MaskType[]),
|
|
97
|
+
defaultValue?: string | number
|
|
98
|
+
): [MaskValue, (text: string | number) => void] => {
|
|
99
|
+
const applyMask = useCallback(
|
|
100
|
+
(value = ''): MaskValue => {
|
|
101
|
+
const selectedMask = getMask(mask, value);
|
|
102
|
+
const { formatted, raw } = mergeMask(value, selectedMask);
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
raw,
|
|
106
|
+
formatted,
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
[mask]
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
const [value, setValue] = useState<MaskValue>(
|
|
113
|
+
applyMask(defaultValue?.toString())
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
const handleChangeValue = useCallback(
|
|
117
|
+
(formattedValue: string | number) => {
|
|
118
|
+
const { raw, formatted } = applyMask(formattedValue.toString());
|
|
119
|
+
setValue({
|
|
120
|
+
raw,
|
|
121
|
+
formatted,
|
|
122
|
+
});
|
|
123
|
+
},
|
|
124
|
+
[applyMask, setValue]
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
return [value, handleChangeValue];
|
|
128
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { default as Hint } from './Hint';
|
|
2
|
-
export * from './hooks/useCurrencyMask';
|
|
3
2
|
export * from './hooks/useInputFocus';
|
|
4
|
-
export * from './hooks/
|
|
3
|
+
export * from './hooks/useNumberMask';
|
|
4
|
+
export * from './hooks/useStringMask';
|
|
5
5
|
export {
|
|
6
6
|
default as InputContainer,
|
|
7
7
|
InputContainerProps,
|
|
@@ -11,7 +11,6 @@ export {
|
|
|
11
11
|
default as InputElement,
|
|
12
12
|
InputElementProps,
|
|
13
13
|
} from './InputElement/InputElement';
|
|
14
|
-
export * from './masks';
|
|
15
14
|
export {
|
|
16
15
|
PressableInputContainer,
|
|
17
16
|
PressableInputContainerProps,
|
package/src/index.ts
CHANGED
|
@@ -31,16 +31,13 @@ export {
|
|
|
31
31
|
InputElement,
|
|
32
32
|
InputElementProps,
|
|
33
33
|
InputVariantType,
|
|
34
|
-
Masks,
|
|
35
34
|
PressableInputContainer,
|
|
36
35
|
PressableInputContainerProps,
|
|
37
36
|
StyledBorderKeeper,
|
|
38
|
-
useCurrencyMask,
|
|
39
37
|
useInputFocus,
|
|
40
|
-
|
|
38
|
+
useNumberMask,
|
|
39
|
+
useStringMask,
|
|
41
40
|
disabledInputStyles,
|
|
42
|
-
IMask,
|
|
43
|
-
IMaskValue,
|
|
44
41
|
} from './components/atoms/Input';
|
|
45
42
|
export { Paper, PaperProps } from './components/atoms/Paper';
|
|
46
43
|
export {
|
|
@@ -57,7 +54,7 @@ export {
|
|
|
57
54
|
CalendarProps,
|
|
58
55
|
DateRange,
|
|
59
56
|
SelectionType,
|
|
60
|
-
Value
|
|
57
|
+
Value,
|
|
61
58
|
} from './components/molecules/Calendar';
|
|
62
59
|
export { DatePicker, DatePickerProps } from './components/molecules/DatePicker';
|
|
63
60
|
export {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MaskType,
|
|
3
|
+
CurrencyOptions,
|
|
4
|
+
getMask,
|
|
5
|
+
mergeMask,
|
|
6
|
+
getInternalNumberAndMask,
|
|
7
|
+
} from '../components/atoms/Input';
|
|
8
|
+
import currency from 'currency.js';
|
|
9
|
+
|
|
10
|
+
export const formatWithMask = (
|
|
11
|
+
mask: (MaskType[] | ((value: string) => MaskType[])) | CurrencyOptions,
|
|
12
|
+
value: string | number
|
|
13
|
+
): string | number => {
|
|
14
|
+
if (Array.isArray(mask) || typeof mask === 'function') {
|
|
15
|
+
const selectedMask = getMask(mask, String(value));
|
|
16
|
+
const { formatted } = mergeMask(String(value), selectedMask);
|
|
17
|
+
return formatted || '';
|
|
18
|
+
} else {
|
|
19
|
+
const { internalNumber, mergedOptions } = getInternalNumberAndMask(
|
|
20
|
+
value,
|
|
21
|
+
mask
|
|
22
|
+
);
|
|
23
|
+
return currency(internalNumber).format(mergedOptions);
|
|
24
|
+
}
|
|
25
|
+
};
|
package/src/utils/index.ts
CHANGED
|
@@ -3,5 +3,7 @@ export {
|
|
|
3
3
|
extractNumbersFromString,
|
|
4
4
|
extractDigitsFromString,
|
|
5
5
|
} from './extractNumbersFromString';
|
|
6
|
-
export * from './IPhoneXHelper'
|
|
7
|
-
export * from './ResponsiveFontSize'
|
|
6
|
+
export * from './IPhoneXHelper';
|
|
7
|
+
export * from './ResponsiveFontSize';
|
|
8
|
+
export * from './masks';
|
|
9
|
+
export * from './formatWithMask';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// NOTE: Add here all individually utils, then you can use it on input components everywhere.
|
|
2
|
+
export const Masks = {
|
|
3
|
+
CPF: ['999.999.999-99'],
|
|
4
|
+
CNPJ: ['99.999.999/9999-99'],
|
|
5
|
+
DATE: ['99/99/9999'],
|
|
6
|
+
MONTH_YEAR: ['99/9999'],
|
|
7
|
+
CEP: ['99999-999'],
|
|
8
|
+
PHONE: ['(99) 9999-9999'],
|
|
9
|
+
PHONE_EXTENDED: ['(99) 99999-9999'],
|
|
10
|
+
COMBINED_PHONE: (value: string) =>
|
|
11
|
+
// Value in formatted mode
|
|
12
|
+
value?.length <= 14 ? Masks.PHONE : Masks.PHONE_EXTENDED,
|
|
13
|
+
COMBINED_CPF_CNPJ: (value: string) =>
|
|
14
|
+
value?.length <= 14 ? Masks.CPF : Masks.CNPJ,
|
|
15
|
+
};
|