Skip to content

Commit

Permalink
🔀 Merge branch 'main' of github.com:codermarcos/simple-mask-money int…
Browse files Browse the repository at this point in the history
…o fix/#63/readonly-inputs

Conflicts:
	src/set-mask.ts

On branch fix/#63/readonly-inputs
All conflicts fixed but you are still merging.

Changes to be committed:
	modified:   package-lock.json
	modified:   package.json
	modified:   src/get-base-configuration.ts
	modified:   src/set-mask.ts
	modified:   src/types.ts
	modified:   tests/get-base-configuration.test.ts
  • Loading branch information
codermarcos committed Jan 28, 2024
2 parents e049ac3 + a87ea75 commit 73d707d
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 51 deletions.
3 changes: 2 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "simple-mask-money",
"version": "4.0.7",
"version": "4.1.0",
"private": false,
"description": "Simple money mask developed with pure JavaScript. To run on Client Side and Server Side",
"types": "./lib/simple-mask-money.d.ts",
Expand Down
1 change: 1 addition & 0 deletions src/get-base-configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const configuration: SimpleMaskMoneyConfiguration = {
suffix : '',
thousandsSeparator: '.',
cursor : 'end',
allowEmpty : false,
};

function getBaseConfiguration(
Expand Down
66 changes: 38 additions & 28 deletions src/set-mask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import getBaseConfiguration from 'src/get-base-configuration';
const numbers = '0123456789'.split('');

/**
* It applies a mask to an input element, formatting its value as a currency.
* It takes an input element and an optional configuration object as parameters.
* The function listens for keyboard events on the input element and updates its value accordingly.
* It applies a mask to an input element, formatting its value as a currency.
* It takes an input element and an optional configuration object as parameters.
* The function listens for keyboard events on the input element and updates its value accordingly.
* It also handles caret positioning and allows for undoing changes. The function returns a method to remove the mask from the input element.
*
*
* @remarks
* This method is part of the {@link https://github.com/codermarcos/simple-mask-money/ | SimpleMaskMoney} to see the full documentation check {@link https://github.com/codermarcos/simple-mask-money/tree/main/examples/4.x.x#simplemaskmoneysetmask | SimpleMaskMoney.setMask}
*
Expand All @@ -24,23 +24,23 @@ const numbers = '0123456789'.split('');
* Here's an example using from cdn with CSSSelector:
* ```html
* <script src=""></script>
*
*
* <input id="my-input" />
*
*
* <script>
* const remove = SimpleMaskMoney.setMask('#my-input');
* remove(); // To remove the mask and listeners
* remove(); // To remove the mask and listeners
* </script>
* ```
*
*
* @example
* Here's an example using from npm to React with CSSSelector:
* ```jsx
* import { setMask } from 'simple-mask-money';
*
*
* function InputMoney() {
* useEffect(() => setMask('#my-input'), []);
*
*
* return <input id="my-input" />;
* }
* ```
Expand All @@ -66,6 +66,7 @@ function setMask(
prefix,
suffix,
cursor,
allowEmpty,
} = currentConfiguration;

if (typeof document === 'undefined') return () => void 0;
Expand Down Expand Up @@ -114,7 +115,7 @@ function setMask(
[actionName] = action;
const [, actionParams] = action;
const [start, end] = actionParams;

// Add or remove characters
const characteresRemoved = characteres.splice(...(actionParams as [number, number]));

Expand All @@ -132,9 +133,9 @@ function setMask(
let isNegative = false;

for (let character; (character = characteres.pop()); ) {
if (character === '-') {
if (character === '-') {
isNegative = true;
continue;
continue;
}

if (character === decimalSeparator && decimalSeparatorAdded && trimExtraDecimals) {
Expand All @@ -145,7 +146,7 @@ function setMask(

if (fractionDigitsNumbers.length < result.length)
thousandsCounter += result.length - fractionDigitsNumbers.length;

result = [
decimalSeparator,
...fractionDigitsNumbers,
Expand All @@ -169,9 +170,9 @@ function setMask(
}

result.unshift(character);

if (result.length !== fractionDigits || decimalSeparatorAdded) continue;

result.unshift(decimalSeparator);
decimalSeparatorAdded = true;
}
Expand All @@ -186,7 +187,7 @@ function setMask(
result = [completer, decimalSeparator, result.join('').padStart(fractionDigits, completer)];
else if (result.length === fractionDigits + decimalSeparator.length) // ,00
result.unshift(completer);

if (isNegative)
result[negativeSignAfter ? 'push' : 'unshift']('-');

Expand All @@ -200,12 +201,12 @@ function setMask(
let position = positionDefault;

if (cursor === 'move' && force)
position = typeof force[1] === 'number'
position = typeof force[1] === 'number'
? [force[0], force[1]] as const
: [force[0], force[0]] as const;

element.setSelectionRange(...position);

return position;
};

Expand All @@ -214,11 +215,11 @@ function setMask(
const initialValue = formatToMask(element.value.split(''), true);

let lastValue = initialValue;

const onKeyDown = (e: KeyboardEvent) => {
beforeFormat?.(element.value);
const lastPositionToNumber = getLastPositionToNumber();

let start = element.selectionStart ?? lastPositionToNumber;
let end = element.selectionEnd ?? lastPositionToNumber;

Expand All @@ -227,12 +228,12 @@ function setMask(

// Undo to first value
if (e.ctrlKey && e.key === 'z') return triggerInputChanges(initialValue);

// Allow move caret after or before the prefix or suffix
if (cursor === 'move' && (
(e.key === 'ArrowLeft' && start > firstPositionToNumber) ||
(e.key === 'ArrowRight' && start < lastPositionToNumber)
)) return;
)) return;

e.preventDefault();

Expand All @@ -251,6 +252,11 @@ function setMask(
// No allow erase the prefix
if (isBackspace && start === 0) return;

if (allowEmpty && isBackspace && element.value.length <= prefix.length + 1) {
triggerInputChanges(prefix);
return;
}

const characteres = element.value.split('');

const length = Math.abs(end - start);
Expand All @@ -275,7 +281,7 @@ function setMask(
start = start - characteresRemoved <= firstPositionToNumber ? firstPositionToNumber : start - characteresRemoved;
end = end - characteresRemoved <= firstPositionToNumber ? firstPositionToNumber : end - characteresRemoved;
}

triggerInputChanges(newValue, [start, end]);
};

Expand All @@ -302,12 +308,16 @@ function setMask(

// Only set position if is on prefix or suffix
if (!position) return;

setCaretPosition(position);
};

triggerInputChanges(initialValue);

if (allowEmpty && initialValue === `${prefix}0`) {
triggerInputChanges('');
} else {
triggerInputChanges(initialValue);
}

if (element.hasAttribute('readonly') || element.hasAttribute('disabled')) return () => void 0;

element.addEventListener('keydown', onKeyDown);
Expand All @@ -332,7 +342,7 @@ function setMask(
export default setMask;
/**
* Check the {@link https://github.com/codermarcos/simple-mask-money/tree/main/examples/4.x.x#SimpleMaskMoney.setMask | SimpleMaskMoney.setMask} method to get more information about this type
*
*
* @remarks
* This type is part of the {@link https://github.com/codermarcos/simple-mask-money/ | SimpleMaskMoney} to see the full documentation check {@link https://github.com/codermarcos/simple-mask-money/tree/main/examples/4.x.x#SimpleMaskMoney.setMask | SimpleMaskMoney.setMask}
*/
Expand Down
25 changes: 14 additions & 11 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,28 @@
* This is the full configuration for the mask.
*
* @interface SimpleMaskMoneyConfiguration
*
*
* @field {(value: string) => void} afterFormat is used for get the value when the mask is already applied
* @field {(value: string) => string} beforeFormat is used for get the value when the mask will be applied
*
*
* @field {boolean} allowNegative is used for define if allow values less than zero
* @field {boolean} negativeSignAfter is used for define if negative sign should be after the number
*
*
* @field {string} decimalSeparator is used for define the separator of decimals digits
* @field {string} thousandsSeparator is used for define the separator of thousands digits
*
*
* @field {boolean} fixed is used for define if your value can be empty or always should have value
*
*
* @field {number} fractionDigits is used for define the quantity of decimals digits
*
*
* @field {string} prefix is used for define a string that always precedes its value
* @field {string} suffix is used for define a string that always follows its value
*
*
* @field {'move' | 'end'} cursor is used for define the position of the cursor when the user focus the input
*/
export type SimpleMaskMoneyConfiguration = {
/** Called after format the value when the mask is already applied */
afterFormat?(value: string): void;
afterFormat?(value: string): void;
/** Called before format the value when the mask will be applied */
beforeFormat?(value: string): string;

Expand All @@ -47,14 +47,17 @@ export type SimpleMaskMoneyConfiguration = {
prefix: string;
/** **Default:** `''` - This string always follows its value */
suffix: string;

/** **Default:** `'end'` - Define the position of the cursor when the user focus the input */
cursor: 'move' | 'end';

/** **Default:** `false` - Define if allow empty value */
allowEmpty: boolean;
}

export type OptionalSimpleMaskMoneyConfiguration = Partial<SimpleMaskMoneyConfiguration>;

export type HTMLInputElementMasked = HTMLInputElement & {
/** This method remove the input mask */
removeMask?: () => void;
/** This method remove the input mask */
removeMask?: () => void;
};
22 changes: 12 additions & 10 deletions tests/get-base-configuration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { describe, expect, it } from '@jest/globals';
import getBaseConfiguration from 'src/get-base-configuration';

describe(
'getBaseConfiguration',
'getBaseConfiguration',
() => {

it(
'should have base configuration',
'should have base configuration',
() => {
expect(getBaseConfiguration()).toEqual({
allowNegative : false,
expect(getBaseConfiguration()).toEqual({
allowNegative : false,
negativeSignAfter : false,
decimalSeparator : ',',
fixed : true,
Expand All @@ -19,29 +19,30 @@ describe(
suffix : '',
thousandsSeparator : '.',
cursor : 'end',
allowEmpty : false,
});
},
);

it(
'should have base configuration',
'should have base configuration',
() => {
const fractionDigits = 4;
const decimalSeparator = '.';
const prefix = 'R$';
const allowNegative = true;
const cursor = 'move';

const result = getBaseConfiguration({
allowNegative,
decimalSeparator,
const result = getBaseConfiguration({
allowNegative,
decimalSeparator,
fractionDigits,
prefix,
cursor
});

expect(result).toEqual({
allowNegative,
expect(result).toEqual({
allowNegative,
negativeSignAfter : false,
decimalSeparator,
fixed : true,
Expand All @@ -50,6 +51,7 @@ describe(
prefix,
thousandsSeparator : '.',
cursor,
allowEmpty : false,
});
},
);
Expand Down

0 comments on commit 73d707d

Please sign in to comment.