@elliemae/ds-form-helpers-mask-hooks 3.52.1 → 3.53.0-alpha.2
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/dist/cjs/hooks/useNumberMask.js +33 -5
- package/dist/cjs/hooks/useNumberMask.js.map +2 -2
- package/dist/esm/hooks/useNumberMask.js +33 -5
- package/dist/esm/hooks/useNumberMask.js.map +2 -2
- package/dist/types/hooks/useNumberMask.d.ts +1 -1
- package/dist/types/hooks/usePhoneMask.d.ts +1 -1
- package/dist/types/react-desc-prop-types.d.ts +0 -1
- package/package.json +9 -8
|
@@ -40,7 +40,7 @@ var import_utils = require("../utils/index.js");
|
|
|
40
40
|
var import_react_desc_prop_types = require("../react-desc-prop-types.js");
|
|
41
41
|
var import_DSMaskDefinitions = require("../DSMaskDefinitions.js");
|
|
42
42
|
const addThousandsSeparator = (n, separator) => n.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
|
|
43
|
-
const conformValue = (rawValue, cursorPos, lastKeyCode, opts) => {
|
|
43
|
+
const conformValue = (rawValue, cursorPos, lastKeyCode, opts, finalize = false) => {
|
|
44
44
|
const {
|
|
45
45
|
includeThousandsSeparator = true,
|
|
46
46
|
allowNegative = false,
|
|
@@ -52,10 +52,20 @@ const conformValue = (rawValue, cursorPos, lastKeyCode, opts) => {
|
|
|
52
52
|
const THOUSANDSSEPARATOR = ",";
|
|
53
53
|
let dotIdx = -1;
|
|
54
54
|
let finalPrefix = [prefix?.length, 0].includes(rawValue.indexOf("-")) && allowNegative ? "-" : "";
|
|
55
|
+
let seenInvalidDot = false;
|
|
55
56
|
let maskedValue = String(rawValue).split("").filter((char, idx) => {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
if (seenInvalidDot) return false;
|
|
58
|
+
const isDigit = char >= "0" && char <= "9";
|
|
59
|
+
if (char === ".") {
|
|
60
|
+
if (decimalPlaces) {
|
|
61
|
+
const validChar = dotIdx === -1;
|
|
62
|
+
if (validChar) dotIdx = idx;
|
|
63
|
+
return validChar;
|
|
64
|
+
}
|
|
65
|
+
seenInvalidDot = true;
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
return isDigit;
|
|
59
69
|
});
|
|
60
70
|
if (prefix && maskedValue.length) finalPrefix += prefix;
|
|
61
71
|
while (maskedValue.length >= 2 && maskedValue[0] === "0" && maskedValue[1] !== ".") {
|
|
@@ -89,6 +99,24 @@ const conformValue = (rawValue, cursorPos, lastKeyCode, opts) => {
|
|
|
89
99
|
if (maskedValue[maskedPos] === rawValue[i]) maskedPos += 1;
|
|
90
100
|
}
|
|
91
101
|
maskedPos += finalPrefix.length;
|
|
102
|
+
if (finalize && decimalPlaces > 0 && decimalRequired) {
|
|
103
|
+
const hasDot = maskedValue.includes(".");
|
|
104
|
+
if (!hasDot) {
|
|
105
|
+
if (maskedValue.length !== 0) {
|
|
106
|
+
maskedValue = [...maskedValue, ".", ...Array(decimalPlaces).fill("0")];
|
|
107
|
+
if (cursorPos >= 0) maskedPos += 1 + decimalPlaces;
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
const dotAt = maskedValue.indexOf(".");
|
|
111
|
+
const decimalsCount = maskedValue.length - dotAt - 1;
|
|
112
|
+
if (decimalsCount < decimalPlaces) {
|
|
113
|
+
const toAdd = decimalPlaces - decimalsCount;
|
|
114
|
+
maskedValue = [...maskedValue, ...Array(toAdd).fill("0")];
|
|
115
|
+
} else if (decimalsCount > decimalPlaces) {
|
|
116
|
+
maskedValue = [...maskedValue.slice(0, dotAt + 1 + decimalPlaces)];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
92
120
|
const finalSuffix = maskedValue.length ? suffix : "";
|
|
93
121
|
const maskedValueString = finalPrefix + maskedValue.join("") + finalSuffix;
|
|
94
122
|
return [maskedValueString, maskedPos];
|
|
@@ -180,7 +208,7 @@ const useNumberMask = (props) => {
|
|
|
180
208
|
};
|
|
181
209
|
};
|
|
182
210
|
const getNumberMaskedValue = (value, opts) => {
|
|
183
|
-
const [maskedValue] = conformValue(value, value.length - 1, "", opts);
|
|
211
|
+
const [maskedValue] = conformValue(value, value.length - 1, "", opts, true);
|
|
184
212
|
return maskedValue;
|
|
185
213
|
};
|
|
186
214
|
useNumberMask.displayName = import_DSMaskDefinitions.useNumberMaskName;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/hooks/useNumberMask.ts", "../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable max-lines */\n/* eslint-disable max-params */\n/* eslint-disable max-statements */\n/* eslint-disable complexity */\nimport type React from 'react';\nimport { useCallback, useRef, useState } from 'react';\nimport {\n describe,\n PropTypes,\n useMemoMergePropsWithDefault,\n useValidateTypescriptPropTypes,\n} from '@elliemae/ds-props-helpers';\nimport { setCursorPosition, useCallbackAfterRender } from '../utils/index.js';\nimport { useNumberMaskDefaultProps, useNumberMaskPropTypes, type UseNumberMaskT } from '../react-desc-prop-types.js';\nimport { useNumberMaskName } from '../DSMaskDefinitions.js';\n\nconst addThousandsSeparator = (n: string, separator: string) => n.replace(/\\B(?=(\\d{3})+(?!\\d))/g, separator);\n\nconst conformValue = (\n rawValue: string,\n cursorPos: number,\n lastKeyCode: string,\n opts: Omit<UseNumberMaskT.Props, 'valueSetter'>,\n): [string, number] => {\n const {\n includeThousandsSeparator = true,\n allowNegative = false,\n prefix = '',\n suffix = '',\n decimalPlaces = 2,\n decimalRequired = false,\n } = opts;\n const THOUSANDSSEPARATOR = ',';\n\n let dotIdx = -1;\n // allow minus sign before and after the preffix\n let finalPrefix = [prefix?.length, 0].includes(rawValue.indexOf('-')) && allowNegative ? '-' : '';\n\n let maskedValue = String(rawValue)\n .split('')\n .filter((char, idx) => {\n // we take only the first dot\n const validChar = (char >= '0' && char <= '9') || (char === '.' && dotIdx === -1 && decimalPlaces);\n if (char === '.' && validChar) dotIdx = idx;\n return validChar;\n });\n\n if (prefix && maskedValue.length) finalPrefix += prefix;\n\n // REMOVE FOLLOWING ZEROS IN INTEGER PART AFTER LEADER ZERO NUMBER\n while (maskedValue.length >= 2 && maskedValue[0] === '0' && maskedValue[1] !== '.') {\n maskedValue = maskedValue.splice(1);\n }\n dotIdx = maskedValue.findIndex((char) => char === '.');\n\n let integer = maskedValue.slice(0, dotIdx !== -1 ? dotIdx : maskedValue.length);\n const decimal = maskedValue.slice(dotIdx, dotIdx + decimalPlaces + 1);\n // ADDING THOUSANDS SEPARATOR\n if (includeThousandsSeparator) {\n integer = addThousandsSeparator(integer.join(''), THOUSANDSSEPARATOR).split('');\n }\n\n let zeroWasAdded = false;\n\n // MERGIN INT AND DECIMAL IF NECCESSARY\n if (dotIdx !== -1 && !(lastKeyCode === 'Backspace' && decimal.length === 1)) {\n if (integer.length) {\n maskedValue = [...integer, ...decimal];\n } else {\n // if theres no integer add a zero to the left of the dot to cover .23 => 0.23 case\n maskedValue = ['0', ...decimal];\n zeroWasAdded = true;\n }\n } else {\n // If decimal is required we add a dot after integer if exists\n maskedValue = decimalRequired && integer.length ? [...integer, '.'] : integer;\n }\n\n // remove orphans prefix for example \"-$\"\n if (lastKeyCode === 'Backspace' && maskedValue.length === 0) {\n finalPrefix = '';\n }\n\n // SET REAL CURSOR POSITION AFTER ADDING DOT and COMMAS SEPARATORS\n let maskedPos = 0;\n\n // 0 leading case we move the cursor to continue typing\n if (maskedValue[maskedPos] === '0' && cursorPos === 1 + prefix.length) maskedPos += 1;\n\n if (zeroWasAdded) maskedPos += 1;\n\n for (let i = 0; i < cursorPos; i += 1) {\n if (maskedValue[maskedPos] === THOUSANDSSEPARATOR) maskedPos += 1;\n if (maskedValue[maskedPos] === rawValue[i]) maskedPos += 1;\n }\n\n maskedPos += finalPrefix.length;\n\n const finalSuffix = maskedValue.length ? suffix : '';\n\n const maskedValueString = finalPrefix + maskedValue.join('') + finalSuffix;\n return [maskedValueString, maskedPos];\n};\n\nexport const useNumberMask: ((args: UseNumberMaskT.Props) => UseNumberMaskT.OutputT) & { displayName: string } = (\n props,\n) => {\n const propsWithDefault = useMemoMergePropsWithDefault<UseNumberMaskT.InternalProps>(props, useNumberMaskDefaultProps);\n useValidateTypescriptPropTypes(propsWithDefault, useNumberMaskPropTypes, useNumberMaskName);\n\n const {\n valueSetter,\n onChange: userOnChange,\n onKeyDown: userOnKeyDown,\n onBlur: userOnBlur,\n ...opts\n } = propsWithDefault;\n\n const lastKeyCode = useRef('Unidentified');\n\n const scheduleAfterRender = useCallbackAfterRender(true);\n\n // Some times, the value of the mask is not gonna change (user types invalid char for example)\n // This makes the input to go from \"correct\" -> \"incorrect\" -> \"correct\"\n // But since the input is controlled, the input does not re-render\n // This makes the input go mumbo-jumbo and places the cursor in the end, because we kinda changed the value async\n // Solution for this is to trigger a re-render, we do this with a set state call in the on change event\n const [, setKey] = useState(0);\n\n const onBlur: React.FocusEventHandler<HTMLInputElement> = useCallback(\n (e) => {\n const maskedValue = e.target.value;\n\n const {\n decimalRequired = true,\n decimalPlaces = 2,\n suffix = '',\n // prefix = '',\n // min = -Infinity,\n // max = Infinity,\n } = opts;\n // const value = Number(e.target.value.replace(/[,`${prefix}${suffix}`]/g, ''));\n // if (value < min) valueSetter(`${prefix}${min.toString()}${suffix}`);\n // if (value > max) valueSetter(`${prefix}${max.toString()}${suffix}`);\n const dotIdx = maskedValue.indexOf('.');\n const minusIndex = maskedValue.indexOf('-');\n\n const suffixIndex = suffix.length ? maskedValue.indexOf(suffix) : -1;\n\n if (decimalRequired) {\n if (dotIdx > -1) {\n const decimal = maskedValue.slice(dotIdx + 1, suffix.length ? -suffix.length : maskedValue.length);\n\n let zerosRest = '';\n while (decimal.length + zerosRest.length !== decimalPlaces) {\n zerosRest += '0';\n }\n\n valueSetter((suffix.length ? maskedValue.slice(0, suffixIndex) : maskedValue) + zerosRest + suffix);\n }\n } else if (maskedValue.length - suffix.length - 1 === dotIdx) {\n // removing orphans dots\n valueSetter(maskedValue.replace('.', ''));\n } else if (maskedValue.length - 1 === minusIndex) {\n // removing orphans minus\n valueSetter(maskedValue.replace('-', ''));\n }\n if (userOnBlur) userOnBlur(e);\n },\n [userOnBlur, valueSetter, opts],\n );\n\n const onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = useCallback(\n (e) => {\n lastKeyCode.current = e.code;\n if (userOnKeyDown) userOnKeyDown(e);\n },\n [userOnKeyDown],\n );\n\n const onChange: React.ChangeEventHandler<HTMLInputElement> = useCallback(\n (e) => {\n const [mask, cursorPos] = conformValue(\n e.target.value,\n e.target.selectionEnd ?? 0,\n lastKeyCode.current,\n opts as UseNumberMaskT.Props,\n );\n\n // Strip formatting characters and prefix/suffix\n const numericValue = Number(mask.replace(opts.prefix, '').replace(opts.suffix, '').replace(/,/g, ''));\n\n // If the value is below min or above max, do not update to that value.\n if (opts.min !== undefined && numericValue < opts.min) {\n // Option 1: Force the value to the minimum\n valueSetter(`${opts.prefix}${opts.min}${opts.suffix}`);\n scheduleAfterRender(() => setCursorPosition(e.target, cursorPos));\n return;\n // Option 2: Prevent the update (i.e. ignore the change) until a valid number is entered.\n // return;\n }\n if (opts.max !== undefined && numericValue > opts.max) {\n // Force the value to the maximum\n valueSetter(`${opts.prefix}${opts.max}${opts.suffix}`);\n scheduleAfterRender(() => setCursorPosition(e.target, cursorPos));\n return;\n }\n\n // Only update if the numeric value is within the valid range.\n valueSetter((prevMask) => {\n if (mask === prevMask) setKey((key) => key + 1);\n return mask;\n });\n if (userOnChange) userOnChange(e, mask);\n scheduleAfterRender(() => setCursorPosition(e.target, cursorPos));\n },\n [valueSetter, scheduleAfterRender, userOnChange, opts],\n );\n\n return {\n onKeyDown,\n onChange,\n onBlur,\n };\n};\n\nexport const getNumberMaskedValue = (value: string, opts: Omit<UseNumberMaskT.Props, 'valueSetter'>) => {\n const [maskedValue] = conformValue(value, value.length - 1, '', opts);\n return maskedValue;\n};\n\nuseNumberMask.displayName = useNumberMaskName;\nexport const UseNumberMaskWithSchema = describe(useNumberMask);\nUseNumberMaskWithSchema.propTypes = useNumberMaskPropTypes;\nUseNumberMaskWithSchema.returnType = {\n onKeyDown: PropTypes.func.description('On key down event for input').isRequired,\n onChange: PropTypes.func.description('On change event for input').isRequired,\n onBlur: PropTypes.func.description('On blur event for input').isRequired,\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADKvB,mBAA8C;AAC9C,8BAKO;AACP,mBAA0D;AAC1D,mCAAuF;AACvF,+BAAkC;AAElC,MAAM,wBAAwB,CAAC,GAAW,cAAsB,EAAE,QAAQ,yBAAyB,SAAS;AAE5G,MAAM,eAAe,CACnB,UACA,WACA,aACA,
|
|
4
|
+
"sourcesContent": ["/* eslint-disable max-lines */\n/* eslint-disable max-params */\n/* eslint-disable max-statements */\n/* eslint-disable complexity */\nimport type React from 'react';\nimport { useCallback, useRef, useState } from 'react';\nimport {\n describe,\n PropTypes,\n useMemoMergePropsWithDefault,\n useValidateTypescriptPropTypes,\n} from '@elliemae/ds-props-helpers';\nimport { setCursorPosition, useCallbackAfterRender } from '../utils/index.js';\nimport { useNumberMaskDefaultProps, useNumberMaskPropTypes, type UseNumberMaskT } from '../react-desc-prop-types.js';\nimport { useNumberMaskName } from '../DSMaskDefinitions.js';\n\nconst addThousandsSeparator = (n: string, separator: string) => n.replace(/\\B(?=(\\d{3})+(?!\\d))/g, separator);\n\nconst conformValue = (\n rawValue: string,\n cursorPos: number,\n lastKeyCode: string,\n opts: Omit<UseNumberMaskT.Props, 'valueSetter'>,\n finalize = false,\n): [string, number] => {\n const {\n includeThousandsSeparator = true,\n allowNegative = false,\n prefix = '',\n suffix = '',\n decimalPlaces = 2,\n decimalRequired = false,\n } = opts;\n const THOUSANDSSEPARATOR = ',';\n\n let dotIdx = -1;\n // allow minus sign before and after the preffix\n let finalPrefix = [prefix?.length, 0].includes(rawValue.indexOf('-')) && allowNegative ? '-' : '';\n\n // CHANGE: when decimals are not allowed (decimalPlaces === 0), ignore everything after the first dot\n let seenInvalidDot = false;\n\n let maskedValue = String(rawValue)\n .split('')\n .filter((char, idx) => {\n if (seenInvalidDot) return false;\n\n const isDigit = char >= '0' && char <= '9';\n\n if (char === '.') {\n if (decimalPlaces) {\n const validChar = dotIdx === -1;\n if (validChar) dotIdx = idx;\n return validChar;\n }\n // decimals not allowed: drop the dot and everything after it\n seenInvalidDot = true;\n return false;\n }\n\n // we take only the first dot (handled above); otherwise only digits\n return isDigit;\n });\n\n if (prefix && maskedValue.length) finalPrefix += prefix;\n\n // REMOVE FOLLOWING ZEROS IN INTEGER PART AFTER LEADER ZERO NUMBER\n while (maskedValue.length >= 2 && maskedValue[0] === '0' && maskedValue[1] !== '.') {\n maskedValue = maskedValue.splice(1);\n }\n dotIdx = maskedValue.findIndex((char) => char === '.');\n\n let integer = maskedValue.slice(0, dotIdx !== -1 ? dotIdx : maskedValue.length);\n const decimal = maskedValue.slice(dotIdx, dotIdx + decimalPlaces + 1);\n // ADDING THOUSANDS SEPARATOR\n if (includeThousandsSeparator) {\n integer = addThousandsSeparator(integer.join(''), THOUSANDSSEPARATOR).split('');\n }\n\n let zeroWasAdded = false;\n\n // MERGIN INT AND DECIMAL IF NECCESSARY\n if (dotIdx !== -1 && !(lastKeyCode === 'Backspace' && decimal.length === 1)) {\n if (integer.length) {\n maskedValue = [...integer, ...decimal];\n } else {\n // if theres no integer add a zero to the left of the dot to cover .23 => 0.23 case\n maskedValue = ['0', ...decimal];\n zeroWasAdded = true;\n }\n } else {\n // If decimal is required we add a dot after integer if exists\n maskedValue = decimalRequired && integer.length ? [...integer, '.'] : integer;\n }\n\n // remove orphans prefix for example \"-$\"\n if (lastKeyCode === 'Backspace' && maskedValue.length === 0) {\n finalPrefix = '';\n }\n\n // SET REAL CURSOR POSITION AFTER ADDING DOT and COMMAS SEPARATORS\n let maskedPos = 0;\n\n // 0 leading case we move the cursor to continue typing\n if (maskedValue[maskedPos] === '0' && cursorPos === 1 + prefix.length) maskedPos += 1;\n\n if (zeroWasAdded) maskedPos += 1;\n\n for (let i = 0; i < cursorPos; i += 1) {\n if (maskedValue[maskedPos] === THOUSANDSSEPARATOR) maskedPos += 1;\n if (maskedValue[maskedPos] === rawValue[i]) maskedPos += 1;\n }\n\n maskedPos += finalPrefix.length;\n\n // --- FINALIZATION STEP (pads decimals if requested) ---\n if (finalize && decimalPlaces > 0 && decimalRequired) {\n const hasDot = maskedValue.includes('.');\n if (!hasDot) {\n if (maskedValue.length !== 0) {\n maskedValue = [...maskedValue, '.', ...Array<string>(decimalPlaces).fill('0')];\n if (cursorPos >= 0) maskedPos += 1 + decimalPlaces;\n }\n } else {\n const dotAt = maskedValue.indexOf('.');\n const decimalsCount = maskedValue.length - dotAt - 1;\n if (decimalsCount < decimalPlaces) {\n const toAdd = decimalPlaces - decimalsCount;\n maskedValue = [...maskedValue, ...Array<string>(toAdd).fill('0')];\n } else if (decimalsCount > decimalPlaces) {\n maskedValue = [...maskedValue.slice(0, dotAt + 1 + decimalPlaces)];\n }\n }\n }\n\n const finalSuffix = maskedValue.length ? suffix : '';\n const maskedValueString = finalPrefix + maskedValue.join('') + finalSuffix;\n return [maskedValueString, maskedPos];\n};\n\nexport const useNumberMask: ((args: UseNumberMaskT.Props) => UseNumberMaskT.OutputT) & { displayName: string } = (\n props,\n) => {\n const propsWithDefault = useMemoMergePropsWithDefault<UseNumberMaskT.InternalProps>(props, useNumberMaskDefaultProps);\n useValidateTypescriptPropTypes(propsWithDefault, useNumberMaskPropTypes, useNumberMaskName);\n\n const {\n valueSetter,\n onChange: userOnChange,\n onKeyDown: userOnKeyDown,\n onBlur: userOnBlur,\n ...opts\n } = propsWithDefault;\n\n const lastKeyCode = useRef('Unidentified');\n\n const scheduleAfterRender = useCallbackAfterRender(true);\n\n // Some times, the value of the mask is not gonna change (user types invalid char for example)\n // This makes the input to go from \"correct\" -> \"incorrect\" -> \"correct\"\n // But since the input is controlled, the input does not re-render\n // This makes the input go mumbo-jumbo and places the cursor in the end, because we kinda changed the value async\n // Solution for this is to trigger a re-render, we do this with a set state call in the on change event\n const [, setKey] = useState(0);\n\n const onBlur: React.FocusEventHandler<HTMLInputElement> = useCallback(\n (e) => {\n const maskedValue = e.target.value;\n\n const {\n decimalRequired = true,\n decimalPlaces = 2,\n suffix = '',\n // prefix = '',\n // min = -Infinity,\n // max = Infinity,\n } = opts;\n // const value = Number(e.target.value.replace(/[,`${prefix}${suffix}`]/g, ''));\n // if (value < min) valueSetter(`${prefix}${min.toString()}${suffix}`);\n // if (value > max) valueSetter(`${prefix}${max.toString()}${suffix}`);\n const dotIdx = maskedValue.indexOf('.');\n const minusIndex = maskedValue.indexOf('-');\n\n const suffixIndex = suffix.length ? maskedValue.indexOf(suffix) : -1;\n\n if (decimalRequired) {\n if (dotIdx > -1) {\n const decimal = maskedValue.slice(dotIdx + 1, suffix.length ? -suffix.length : maskedValue.length);\n\n let zerosRest = '';\n while (decimal.length + zerosRest.length !== decimalPlaces) {\n zerosRest += '0';\n }\n\n valueSetter((suffix.length ? maskedValue.slice(0, suffixIndex) : maskedValue) + zerosRest + suffix);\n }\n } else if (maskedValue.length - suffix.length - 1 === dotIdx) {\n // removing orphans dots\n valueSetter(maskedValue.replace('.', ''));\n } else if (maskedValue.length - 1 === minusIndex) {\n // removing orphans minus\n valueSetter(maskedValue.replace('-', ''));\n }\n if (userOnBlur) userOnBlur(e);\n },\n [userOnBlur, valueSetter, opts],\n );\n\n const onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = useCallback(\n (e) => {\n lastKeyCode.current = e.code;\n if (userOnKeyDown) userOnKeyDown(e);\n },\n [userOnKeyDown],\n );\n\n const onChange: React.ChangeEventHandler<HTMLInputElement> = useCallback(\n (e) => {\n const [mask, cursorPos] = conformValue(\n e.target.value,\n e.target.selectionEnd ?? 0,\n lastKeyCode.current,\n opts as UseNumberMaskT.Props,\n );\n\n // Strip formatting characters and prefix/suffix\n const numericValue = Number(mask.replace(opts.prefix, '').replace(opts.suffix, '').replace(/,/g, ''));\n\n // If the value is below min or above max, do not update to that value.\n if (opts.min !== undefined && numericValue < opts.min) {\n // Option 1: Force the value to the minimum\n valueSetter(`${opts.prefix}${opts.min}${opts.suffix}`);\n scheduleAfterRender(() => setCursorPosition(e.target, cursorPos));\n return;\n // Option 2: Prevent the update (i.e. ignore the change) until a valid number is entered.\n // return;\n }\n if (opts.max !== undefined && numericValue > opts.max) {\n // Force the value to the maximum\n valueSetter(`${opts.prefix}${opts.max}${opts.suffix}`);\n scheduleAfterRender(() => setCursorPosition(e.target, cursorPos));\n return;\n }\n\n // Only update if the numeric value is within the valid range.\n valueSetter((prevMask) => {\n if (mask === prevMask) setKey((key) => key + 1);\n return mask;\n });\n if (userOnChange) userOnChange(e, mask);\n scheduleAfterRender(() => setCursorPosition(e.target, cursorPos));\n },\n [valueSetter, scheduleAfterRender, userOnChange, opts],\n );\n\n return {\n onKeyDown,\n onChange,\n onBlur,\n };\n};\n\nexport const getNumberMaskedValue = (value: string, opts: Omit<UseNumberMaskT.Props, 'valueSetter'>) => {\n const [maskedValue] = conformValue(value, value.length - 1, '', opts, true);\n return maskedValue;\n};\n\nuseNumberMask.displayName = useNumberMaskName;\nexport const UseNumberMaskWithSchema = describe(useNumberMask);\nUseNumberMaskWithSchema.propTypes = useNumberMaskPropTypes;\nUseNumberMaskWithSchema.returnType = {\n onKeyDown: PropTypes.func.description('On key down event for input').isRequired,\n onChange: PropTypes.func.description('On change event for input').isRequired,\n onBlur: PropTypes.func.description('On blur event for input').isRequired,\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -10,7 +10,7 @@ import { setCursorPosition, useCallbackAfterRender } from "../utils/index.js";
|
|
|
10
10
|
import { useNumberMaskDefaultProps, useNumberMaskPropTypes } from "../react-desc-prop-types.js";
|
|
11
11
|
import { useNumberMaskName } from "../DSMaskDefinitions.js";
|
|
12
12
|
const addThousandsSeparator = (n, separator) => n.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
|
|
13
|
-
const conformValue = (rawValue, cursorPos, lastKeyCode, opts) => {
|
|
13
|
+
const conformValue = (rawValue, cursorPos, lastKeyCode, opts, finalize = false) => {
|
|
14
14
|
const {
|
|
15
15
|
includeThousandsSeparator = true,
|
|
16
16
|
allowNegative = false,
|
|
@@ -22,10 +22,20 @@ const conformValue = (rawValue, cursorPos, lastKeyCode, opts) => {
|
|
|
22
22
|
const THOUSANDSSEPARATOR = ",";
|
|
23
23
|
let dotIdx = -1;
|
|
24
24
|
let finalPrefix = [prefix?.length, 0].includes(rawValue.indexOf("-")) && allowNegative ? "-" : "";
|
|
25
|
+
let seenInvalidDot = false;
|
|
25
26
|
let maskedValue = String(rawValue).split("").filter((char, idx) => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
if (seenInvalidDot) return false;
|
|
28
|
+
const isDigit = char >= "0" && char <= "9";
|
|
29
|
+
if (char === ".") {
|
|
30
|
+
if (decimalPlaces) {
|
|
31
|
+
const validChar = dotIdx === -1;
|
|
32
|
+
if (validChar) dotIdx = idx;
|
|
33
|
+
return validChar;
|
|
34
|
+
}
|
|
35
|
+
seenInvalidDot = true;
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return isDigit;
|
|
29
39
|
});
|
|
30
40
|
if (prefix && maskedValue.length) finalPrefix += prefix;
|
|
31
41
|
while (maskedValue.length >= 2 && maskedValue[0] === "0" && maskedValue[1] !== ".") {
|
|
@@ -59,6 +69,24 @@ const conformValue = (rawValue, cursorPos, lastKeyCode, opts) => {
|
|
|
59
69
|
if (maskedValue[maskedPos] === rawValue[i]) maskedPos += 1;
|
|
60
70
|
}
|
|
61
71
|
maskedPos += finalPrefix.length;
|
|
72
|
+
if (finalize && decimalPlaces > 0 && decimalRequired) {
|
|
73
|
+
const hasDot = maskedValue.includes(".");
|
|
74
|
+
if (!hasDot) {
|
|
75
|
+
if (maskedValue.length !== 0) {
|
|
76
|
+
maskedValue = [...maskedValue, ".", ...Array(decimalPlaces).fill("0")];
|
|
77
|
+
if (cursorPos >= 0) maskedPos += 1 + decimalPlaces;
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
const dotAt = maskedValue.indexOf(".");
|
|
81
|
+
const decimalsCount = maskedValue.length - dotAt - 1;
|
|
82
|
+
if (decimalsCount < decimalPlaces) {
|
|
83
|
+
const toAdd = decimalPlaces - decimalsCount;
|
|
84
|
+
maskedValue = [...maskedValue, ...Array(toAdd).fill("0")];
|
|
85
|
+
} else if (decimalsCount > decimalPlaces) {
|
|
86
|
+
maskedValue = [...maskedValue.slice(0, dotAt + 1 + decimalPlaces)];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
62
90
|
const finalSuffix = maskedValue.length ? suffix : "";
|
|
63
91
|
const maskedValueString = finalPrefix + maskedValue.join("") + finalSuffix;
|
|
64
92
|
return [maskedValueString, maskedPos];
|
|
@@ -150,7 +178,7 @@ const useNumberMask = (props) => {
|
|
|
150
178
|
};
|
|
151
179
|
};
|
|
152
180
|
const getNumberMaskedValue = (value, opts) => {
|
|
153
|
-
const [maskedValue] = conformValue(value, value.length - 1, "", opts);
|
|
181
|
+
const [maskedValue] = conformValue(value, value.length - 1, "", opts, true);
|
|
154
182
|
return maskedValue;
|
|
155
183
|
};
|
|
156
184
|
useNumberMask.displayName = useNumberMaskName;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/hooks/useNumberMask.ts"],
|
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable max-lines */\n/* eslint-disable max-params */\n/* eslint-disable max-statements */\n/* eslint-disable complexity */\nimport type React from 'react';\nimport { useCallback, useRef, useState } from 'react';\nimport {\n describe,\n PropTypes,\n useMemoMergePropsWithDefault,\n useValidateTypescriptPropTypes,\n} from '@elliemae/ds-props-helpers';\nimport { setCursorPosition, useCallbackAfterRender } from '../utils/index.js';\nimport { useNumberMaskDefaultProps, useNumberMaskPropTypes, type UseNumberMaskT } from '../react-desc-prop-types.js';\nimport { useNumberMaskName } from '../DSMaskDefinitions.js';\n\nconst addThousandsSeparator = (n: string, separator: string) => n.replace(/\\B(?=(\\d{3})+(?!\\d))/g, separator);\n\nconst conformValue = (\n rawValue: string,\n cursorPos: number,\n lastKeyCode: string,\n opts: Omit<UseNumberMaskT.Props, 'valueSetter'>,\n): [string, number] => {\n const {\n includeThousandsSeparator = true,\n allowNegative = false,\n prefix = '',\n suffix = '',\n decimalPlaces = 2,\n decimalRequired = false,\n } = opts;\n const THOUSANDSSEPARATOR = ',';\n\n let dotIdx = -1;\n // allow minus sign before and after the preffix\n let finalPrefix = [prefix?.length, 0].includes(rawValue.indexOf('-')) && allowNegative ? '-' : '';\n\n let maskedValue = String(rawValue)\n .split('')\n .filter((char, idx) => {\n // we take only the first dot\n const validChar = (char >= '0' && char <= '9') || (char === '.' && dotIdx === -1 && decimalPlaces);\n if (char === '.' && validChar) dotIdx = idx;\n return validChar;\n });\n\n if (prefix && maskedValue.length) finalPrefix += prefix;\n\n // REMOVE FOLLOWING ZEROS IN INTEGER PART AFTER LEADER ZERO NUMBER\n while (maskedValue.length >= 2 && maskedValue[0] === '0' && maskedValue[1] !== '.') {\n maskedValue = maskedValue.splice(1);\n }\n dotIdx = maskedValue.findIndex((char) => char === '.');\n\n let integer = maskedValue.slice(0, dotIdx !== -1 ? dotIdx : maskedValue.length);\n const decimal = maskedValue.slice(dotIdx, dotIdx + decimalPlaces + 1);\n // ADDING THOUSANDS SEPARATOR\n if (includeThousandsSeparator) {\n integer = addThousandsSeparator(integer.join(''), THOUSANDSSEPARATOR).split('');\n }\n\n let zeroWasAdded = false;\n\n // MERGIN INT AND DECIMAL IF NECCESSARY\n if (dotIdx !== -1 && !(lastKeyCode === 'Backspace' && decimal.length === 1)) {\n if (integer.length) {\n maskedValue = [...integer, ...decimal];\n } else {\n // if theres no integer add a zero to the left of the dot to cover .23 => 0.23 case\n maskedValue = ['0', ...decimal];\n zeroWasAdded = true;\n }\n } else {\n // If decimal is required we add a dot after integer if exists\n maskedValue = decimalRequired && integer.length ? [...integer, '.'] : integer;\n }\n\n // remove orphans prefix for example \"-$\"\n if (lastKeyCode === 'Backspace' && maskedValue.length === 0) {\n finalPrefix = '';\n }\n\n // SET REAL CURSOR POSITION AFTER ADDING DOT and COMMAS SEPARATORS\n let maskedPos = 0;\n\n // 0 leading case we move the cursor to continue typing\n if (maskedValue[maskedPos] === '0' && cursorPos === 1 + prefix.length) maskedPos += 1;\n\n if (zeroWasAdded) maskedPos += 1;\n\n for (let i = 0; i < cursorPos; i += 1) {\n if (maskedValue[maskedPos] === THOUSANDSSEPARATOR) maskedPos += 1;\n if (maskedValue[maskedPos] === rawValue[i]) maskedPos += 1;\n }\n\n maskedPos += finalPrefix.length;\n\n const finalSuffix = maskedValue.length ? suffix : '';\n\n const maskedValueString = finalPrefix + maskedValue.join('') + finalSuffix;\n return [maskedValueString, maskedPos];\n};\n\nexport const useNumberMask: ((args: UseNumberMaskT.Props) => UseNumberMaskT.OutputT) & { displayName: string } = (\n props,\n) => {\n const propsWithDefault = useMemoMergePropsWithDefault<UseNumberMaskT.InternalProps>(props, useNumberMaskDefaultProps);\n useValidateTypescriptPropTypes(propsWithDefault, useNumberMaskPropTypes, useNumberMaskName);\n\n const {\n valueSetter,\n onChange: userOnChange,\n onKeyDown: userOnKeyDown,\n onBlur: userOnBlur,\n ...opts\n } = propsWithDefault;\n\n const lastKeyCode = useRef('Unidentified');\n\n const scheduleAfterRender = useCallbackAfterRender(true);\n\n // Some times, the value of the mask is not gonna change (user types invalid char for example)\n // This makes the input to go from \"correct\" -> \"incorrect\" -> \"correct\"\n // But since the input is controlled, the input does not re-render\n // This makes the input go mumbo-jumbo and places the cursor in the end, because we kinda changed the value async\n // Solution for this is to trigger a re-render, we do this with a set state call in the on change event\n const [, setKey] = useState(0);\n\n const onBlur: React.FocusEventHandler<HTMLInputElement> = useCallback(\n (e) => {\n const maskedValue = e.target.value;\n\n const {\n decimalRequired = true,\n decimalPlaces = 2,\n suffix = '',\n // prefix = '',\n // min = -Infinity,\n // max = Infinity,\n } = opts;\n // const value = Number(e.target.value.replace(/[,`${prefix}${suffix}`]/g, ''));\n // if (value < min) valueSetter(`${prefix}${min.toString()}${suffix}`);\n // if (value > max) valueSetter(`${prefix}${max.toString()}${suffix}`);\n const dotIdx = maskedValue.indexOf('.');\n const minusIndex = maskedValue.indexOf('-');\n\n const suffixIndex = suffix.length ? maskedValue.indexOf(suffix) : -1;\n\n if (decimalRequired) {\n if (dotIdx > -1) {\n const decimal = maskedValue.slice(dotIdx + 1, suffix.length ? -suffix.length : maskedValue.length);\n\n let zerosRest = '';\n while (decimal.length + zerosRest.length !== decimalPlaces) {\n zerosRest += '0';\n }\n\n valueSetter((suffix.length ? maskedValue.slice(0, suffixIndex) : maskedValue) + zerosRest + suffix);\n }\n } else if (maskedValue.length - suffix.length - 1 === dotIdx) {\n // removing orphans dots\n valueSetter(maskedValue.replace('.', ''));\n } else if (maskedValue.length - 1 === minusIndex) {\n // removing orphans minus\n valueSetter(maskedValue.replace('-', ''));\n }\n if (userOnBlur) userOnBlur(e);\n },\n [userOnBlur, valueSetter, opts],\n );\n\n const onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = useCallback(\n (e) => {\n lastKeyCode.current = e.code;\n if (userOnKeyDown) userOnKeyDown(e);\n },\n [userOnKeyDown],\n );\n\n const onChange: React.ChangeEventHandler<HTMLInputElement> = useCallback(\n (e) => {\n const [mask, cursorPos] = conformValue(\n e.target.value,\n e.target.selectionEnd ?? 0,\n lastKeyCode.current,\n opts as UseNumberMaskT.Props,\n );\n\n // Strip formatting characters and prefix/suffix\n const numericValue = Number(mask.replace(opts.prefix, '').replace(opts.suffix, '').replace(/,/g, ''));\n\n // If the value is below min or above max, do not update to that value.\n if (opts.min !== undefined && numericValue < opts.min) {\n // Option 1: Force the value to the minimum\n valueSetter(`${opts.prefix}${opts.min}${opts.suffix}`);\n scheduleAfterRender(() => setCursorPosition(e.target, cursorPos));\n return;\n // Option 2: Prevent the update (i.e. ignore the change) until a valid number is entered.\n // return;\n }\n if (opts.max !== undefined && numericValue > opts.max) {\n // Force the value to the maximum\n valueSetter(`${opts.prefix}${opts.max}${opts.suffix}`);\n scheduleAfterRender(() => setCursorPosition(e.target, cursorPos));\n return;\n }\n\n // Only update if the numeric value is within the valid range.\n valueSetter((prevMask) => {\n if (mask === prevMask) setKey((key) => key + 1);\n return mask;\n });\n if (userOnChange) userOnChange(e, mask);\n scheduleAfterRender(() => setCursorPosition(e.target, cursorPos));\n },\n [valueSetter, scheduleAfterRender, userOnChange, opts],\n );\n\n return {\n onKeyDown,\n onChange,\n onBlur,\n };\n};\n\nexport const getNumberMaskedValue = (value: string, opts: Omit<UseNumberMaskT.Props, 'valueSetter'>) => {\n const [maskedValue] = conformValue(value, value.length - 1, '', opts);\n return maskedValue;\n};\n\nuseNumberMask.displayName = useNumberMaskName;\nexport const UseNumberMaskWithSchema = describe(useNumberMask);\nUseNumberMaskWithSchema.propTypes = useNumberMaskPropTypes;\nUseNumberMaskWithSchema.returnType = {\n onKeyDown: PropTypes.func.description('On key down event for input').isRequired,\n onChange: PropTypes.func.description('On change event for input').isRequired,\n onBlur: PropTypes.func.description('On blur event for input').isRequired,\n};\n"],
|
|
5
|
-
"mappings": "AAAA,YAAY,WAAW;ACKvB,SAAS,aAAa,QAAQ,gBAAgB;AAC9C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,mBAAmB,8BAA8B;AAC1D,SAAS,2BAA2B,8BAAmD;AACvF,SAAS,yBAAyB;AAElC,MAAM,wBAAwB,CAAC,GAAW,cAAsB,EAAE,QAAQ,yBAAyB,SAAS;AAE5G,MAAM,eAAe,CACnB,UACA,WACA,aACA,
|
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable max-lines */\n/* eslint-disable max-params */\n/* eslint-disable max-statements */\n/* eslint-disable complexity */\nimport type React from 'react';\nimport { useCallback, useRef, useState } from 'react';\nimport {\n describe,\n PropTypes,\n useMemoMergePropsWithDefault,\n useValidateTypescriptPropTypes,\n} from '@elliemae/ds-props-helpers';\nimport { setCursorPosition, useCallbackAfterRender } from '../utils/index.js';\nimport { useNumberMaskDefaultProps, useNumberMaskPropTypes, type UseNumberMaskT } from '../react-desc-prop-types.js';\nimport { useNumberMaskName } from '../DSMaskDefinitions.js';\n\nconst addThousandsSeparator = (n: string, separator: string) => n.replace(/\\B(?=(\\d{3})+(?!\\d))/g, separator);\n\nconst conformValue = (\n rawValue: string,\n cursorPos: number,\n lastKeyCode: string,\n opts: Omit<UseNumberMaskT.Props, 'valueSetter'>,\n finalize = false,\n): [string, number] => {\n const {\n includeThousandsSeparator = true,\n allowNegative = false,\n prefix = '',\n suffix = '',\n decimalPlaces = 2,\n decimalRequired = false,\n } = opts;\n const THOUSANDSSEPARATOR = ',';\n\n let dotIdx = -1;\n // allow minus sign before and after the preffix\n let finalPrefix = [prefix?.length, 0].includes(rawValue.indexOf('-')) && allowNegative ? '-' : '';\n\n // CHANGE: when decimals are not allowed (decimalPlaces === 0), ignore everything after the first dot\n let seenInvalidDot = false;\n\n let maskedValue = String(rawValue)\n .split('')\n .filter((char, idx) => {\n if (seenInvalidDot) return false;\n\n const isDigit = char >= '0' && char <= '9';\n\n if (char === '.') {\n if (decimalPlaces) {\n const validChar = dotIdx === -1;\n if (validChar) dotIdx = idx;\n return validChar;\n }\n // decimals not allowed: drop the dot and everything after it\n seenInvalidDot = true;\n return false;\n }\n\n // we take only the first dot (handled above); otherwise only digits\n return isDigit;\n });\n\n if (prefix && maskedValue.length) finalPrefix += prefix;\n\n // REMOVE FOLLOWING ZEROS IN INTEGER PART AFTER LEADER ZERO NUMBER\n while (maskedValue.length >= 2 && maskedValue[0] === '0' && maskedValue[1] !== '.') {\n maskedValue = maskedValue.splice(1);\n }\n dotIdx = maskedValue.findIndex((char) => char === '.');\n\n let integer = maskedValue.slice(0, dotIdx !== -1 ? dotIdx : maskedValue.length);\n const decimal = maskedValue.slice(dotIdx, dotIdx + decimalPlaces + 1);\n // ADDING THOUSANDS SEPARATOR\n if (includeThousandsSeparator) {\n integer = addThousandsSeparator(integer.join(''), THOUSANDSSEPARATOR).split('');\n }\n\n let zeroWasAdded = false;\n\n // MERGIN INT AND DECIMAL IF NECCESSARY\n if (dotIdx !== -1 && !(lastKeyCode === 'Backspace' && decimal.length === 1)) {\n if (integer.length) {\n maskedValue = [...integer, ...decimal];\n } else {\n // if theres no integer add a zero to the left of the dot to cover .23 => 0.23 case\n maskedValue = ['0', ...decimal];\n zeroWasAdded = true;\n }\n } else {\n // If decimal is required we add a dot after integer if exists\n maskedValue = decimalRequired && integer.length ? [...integer, '.'] : integer;\n }\n\n // remove orphans prefix for example \"-$\"\n if (lastKeyCode === 'Backspace' && maskedValue.length === 0) {\n finalPrefix = '';\n }\n\n // SET REAL CURSOR POSITION AFTER ADDING DOT and COMMAS SEPARATORS\n let maskedPos = 0;\n\n // 0 leading case we move the cursor to continue typing\n if (maskedValue[maskedPos] === '0' && cursorPos === 1 + prefix.length) maskedPos += 1;\n\n if (zeroWasAdded) maskedPos += 1;\n\n for (let i = 0; i < cursorPos; i += 1) {\n if (maskedValue[maskedPos] === THOUSANDSSEPARATOR) maskedPos += 1;\n if (maskedValue[maskedPos] === rawValue[i]) maskedPos += 1;\n }\n\n maskedPos += finalPrefix.length;\n\n // --- FINALIZATION STEP (pads decimals if requested) ---\n if (finalize && decimalPlaces > 0 && decimalRequired) {\n const hasDot = maskedValue.includes('.');\n if (!hasDot) {\n if (maskedValue.length !== 0) {\n maskedValue = [...maskedValue, '.', ...Array<string>(decimalPlaces).fill('0')];\n if (cursorPos >= 0) maskedPos += 1 + decimalPlaces;\n }\n } else {\n const dotAt = maskedValue.indexOf('.');\n const decimalsCount = maskedValue.length - dotAt - 1;\n if (decimalsCount < decimalPlaces) {\n const toAdd = decimalPlaces - decimalsCount;\n maskedValue = [...maskedValue, ...Array<string>(toAdd).fill('0')];\n } else if (decimalsCount > decimalPlaces) {\n maskedValue = [...maskedValue.slice(0, dotAt + 1 + decimalPlaces)];\n }\n }\n }\n\n const finalSuffix = maskedValue.length ? suffix : '';\n const maskedValueString = finalPrefix + maskedValue.join('') + finalSuffix;\n return [maskedValueString, maskedPos];\n};\n\nexport const useNumberMask: ((args: UseNumberMaskT.Props) => UseNumberMaskT.OutputT) & { displayName: string } = (\n props,\n) => {\n const propsWithDefault = useMemoMergePropsWithDefault<UseNumberMaskT.InternalProps>(props, useNumberMaskDefaultProps);\n useValidateTypescriptPropTypes(propsWithDefault, useNumberMaskPropTypes, useNumberMaskName);\n\n const {\n valueSetter,\n onChange: userOnChange,\n onKeyDown: userOnKeyDown,\n onBlur: userOnBlur,\n ...opts\n } = propsWithDefault;\n\n const lastKeyCode = useRef('Unidentified');\n\n const scheduleAfterRender = useCallbackAfterRender(true);\n\n // Some times, the value of the mask is not gonna change (user types invalid char for example)\n // This makes the input to go from \"correct\" -> \"incorrect\" -> \"correct\"\n // But since the input is controlled, the input does not re-render\n // This makes the input go mumbo-jumbo and places the cursor in the end, because we kinda changed the value async\n // Solution for this is to trigger a re-render, we do this with a set state call in the on change event\n const [, setKey] = useState(0);\n\n const onBlur: React.FocusEventHandler<HTMLInputElement> = useCallback(\n (e) => {\n const maskedValue = e.target.value;\n\n const {\n decimalRequired = true,\n decimalPlaces = 2,\n suffix = '',\n // prefix = '',\n // min = -Infinity,\n // max = Infinity,\n } = opts;\n // const value = Number(e.target.value.replace(/[,`${prefix}${suffix}`]/g, ''));\n // if (value < min) valueSetter(`${prefix}${min.toString()}${suffix}`);\n // if (value > max) valueSetter(`${prefix}${max.toString()}${suffix}`);\n const dotIdx = maskedValue.indexOf('.');\n const minusIndex = maskedValue.indexOf('-');\n\n const suffixIndex = suffix.length ? maskedValue.indexOf(suffix) : -1;\n\n if (decimalRequired) {\n if (dotIdx > -1) {\n const decimal = maskedValue.slice(dotIdx + 1, suffix.length ? -suffix.length : maskedValue.length);\n\n let zerosRest = '';\n while (decimal.length + zerosRest.length !== decimalPlaces) {\n zerosRest += '0';\n }\n\n valueSetter((suffix.length ? maskedValue.slice(0, suffixIndex) : maskedValue) + zerosRest + suffix);\n }\n } else if (maskedValue.length - suffix.length - 1 === dotIdx) {\n // removing orphans dots\n valueSetter(maskedValue.replace('.', ''));\n } else if (maskedValue.length - 1 === minusIndex) {\n // removing orphans minus\n valueSetter(maskedValue.replace('-', ''));\n }\n if (userOnBlur) userOnBlur(e);\n },\n [userOnBlur, valueSetter, opts],\n );\n\n const onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = useCallback(\n (e) => {\n lastKeyCode.current = e.code;\n if (userOnKeyDown) userOnKeyDown(e);\n },\n [userOnKeyDown],\n );\n\n const onChange: React.ChangeEventHandler<HTMLInputElement> = useCallback(\n (e) => {\n const [mask, cursorPos] = conformValue(\n e.target.value,\n e.target.selectionEnd ?? 0,\n lastKeyCode.current,\n opts as UseNumberMaskT.Props,\n );\n\n // Strip formatting characters and prefix/suffix\n const numericValue = Number(mask.replace(opts.prefix, '').replace(opts.suffix, '').replace(/,/g, ''));\n\n // If the value is below min or above max, do not update to that value.\n if (opts.min !== undefined && numericValue < opts.min) {\n // Option 1: Force the value to the minimum\n valueSetter(`${opts.prefix}${opts.min}${opts.suffix}`);\n scheduleAfterRender(() => setCursorPosition(e.target, cursorPos));\n return;\n // Option 2: Prevent the update (i.e. ignore the change) until a valid number is entered.\n // return;\n }\n if (opts.max !== undefined && numericValue > opts.max) {\n // Force the value to the maximum\n valueSetter(`${opts.prefix}${opts.max}${opts.suffix}`);\n scheduleAfterRender(() => setCursorPosition(e.target, cursorPos));\n return;\n }\n\n // Only update if the numeric value is within the valid range.\n valueSetter((prevMask) => {\n if (mask === prevMask) setKey((key) => key + 1);\n return mask;\n });\n if (userOnChange) userOnChange(e, mask);\n scheduleAfterRender(() => setCursorPosition(e.target, cursorPos));\n },\n [valueSetter, scheduleAfterRender, userOnChange, opts],\n );\n\n return {\n onKeyDown,\n onChange,\n onBlur,\n };\n};\n\nexport const getNumberMaskedValue = (value: string, opts: Omit<UseNumberMaskT.Props, 'valueSetter'>) => {\n const [maskedValue] = conformValue(value, value.length - 1, '', opts, true);\n return maskedValue;\n};\n\nuseNumberMask.displayName = useNumberMaskName;\nexport const UseNumberMaskWithSchema = describe(useNumberMask);\nUseNumberMaskWithSchema.propTypes = useNumberMaskPropTypes;\nUseNumberMaskWithSchema.returnType = {\n onKeyDown: PropTypes.func.description('On key down event for input').isRequired,\n onChange: PropTypes.func.description('On change event for input').isRequired,\n onBlur: PropTypes.func.description('On blur event for input').isRequired,\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -2,5 +2,5 @@ import { type UseNumberMaskT } from '../react-desc-prop-types.js';
|
|
|
2
2
|
export declare const useNumberMask: ((args: UseNumberMaskT.Props) => UseNumberMaskT.OutputT) & {
|
|
3
3
|
displayName: string;
|
|
4
4
|
};
|
|
5
|
-
export declare const getNumberMaskedValue: (value: string, opts: Omit<UseNumberMaskT.Props,
|
|
5
|
+
export declare const getNumberMaskedValue: (value: string, opts: Omit<UseNumberMaskT.Props, "valueSetter">) => string;
|
|
6
6
|
export declare const UseNumberMaskWithSchema: import("@elliemae/ds-props-helpers/dist/types/propTypes/types.js").DocumentedReactComponent<UseNumberMaskT.Props>;
|
|
@@ -2,5 +2,5 @@ import { type UsePhoneMaskT } from '../react-desc-prop-types.js';
|
|
|
2
2
|
export declare const usePhoneMask: ((args: UsePhoneMaskT.Props) => UsePhoneMaskT.OutputT) & {
|
|
3
3
|
displayName: string;
|
|
4
4
|
};
|
|
5
|
-
export declare const getPhoneMaskedValue: (value: string, opts?: Omit<UsePhoneMaskT.Props,
|
|
5
|
+
export declare const getPhoneMaskedValue: (value: string, opts?: Omit<UsePhoneMaskT.Props, "valueSetter">) => string;
|
|
6
6
|
export declare const UsePhoneMaskWithSchema: import("@elliemae/ds-props-helpers/dist/types/propTypes/types.js").DocumentedReactComponent<UsePhoneMaskT.Props>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elliemae/ds-form-helpers-mask-hooks",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.53.0-alpha.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "ICE MT - Dimsum - Controlled Form Helpers - Text Masks Hooks",
|
|
6
6
|
"files": [
|
|
@@ -36,20 +36,21 @@
|
|
|
36
36
|
"indent": 4
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@elliemae/ds-props-helpers": "3.
|
|
40
|
-
"@elliemae/ds-system": "3.
|
|
39
|
+
"@elliemae/ds-props-helpers": "3.53.0-alpha.2",
|
|
40
|
+
"@elliemae/ds-system": "3.53.0-alpha.2"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@elliemae/pui-cli": "9.0.0-next.
|
|
44
|
-
"@elliemae/pui-theme": "~2.
|
|
43
|
+
"@elliemae/pui-cli": "9.0.0-next.65",
|
|
44
|
+
"@elliemae/pui-theme": "~2.13.0",
|
|
45
45
|
"jest": "~29.7.0",
|
|
46
46
|
"styled-components": "~5.3.9",
|
|
47
47
|
"styled-system": "^5.1.5",
|
|
48
|
-
"@elliemae/ds-form-input-text": "3.
|
|
49
|
-
"@elliemae/ds-monorepo-devops": "3.
|
|
48
|
+
"@elliemae/ds-form-input-text": "3.53.0-alpha.2",
|
|
49
|
+
"@elliemae/ds-monorepo-devops": "3.53.0-alpha.2",
|
|
50
|
+
"@elliemae/ds-test-utils": "3.53.0-alpha.2"
|
|
50
51
|
},
|
|
51
52
|
"peerDependencies": {
|
|
52
|
-
"@elliemae/pui-theme": "~2.
|
|
53
|
+
"@elliemae/pui-theme": "~2.13.0",
|
|
53
54
|
"react": "^18.3.1",
|
|
54
55
|
"react-dom": "^18.3.1",
|
|
55
56
|
"styled-components": "~5.3.9",
|