use-mask-input 3.6.0 → 3.7.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.
Files changed (58) hide show
  1. package/CHANGELOG.md +53 -76
  2. package/README.md +2 -251
  3. package/dist/antd/index.cjs +67 -0
  4. package/dist/antd/index.cjs.map +1 -0
  5. package/dist/antd/index.d.cts +37 -0
  6. package/dist/antd/index.d.ts +37 -0
  7. package/dist/antd/index.js +64 -0
  8. package/dist/antd/index.js.map +1 -0
  9. package/dist/chunk-4Y2DTPBL.cjs +3841 -0
  10. package/dist/chunk-4Y2DTPBL.cjs.map +1 -0
  11. package/dist/chunk-JGOZSJMW.js +3829 -0
  12. package/dist/chunk-JGOZSJMW.js.map +1 -0
  13. package/dist/index-F3rlTTTe.d.cts +583 -0
  14. package/dist/index-F3rlTTTe.d.ts +583 -0
  15. package/dist/index.cjs +72 -3870
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +48 -585
  18. package/dist/index.d.ts +48 -585
  19. package/dist/index.js +72 -3870
  20. package/dist/index.js.map +1 -1
  21. package/package.json +27 -21
  22. package/src/antd/index.ts +9 -0
  23. package/src/antd/useHookFormMaskAntd.spec.ts +142 -0
  24. package/src/antd/useHookFormMaskAntd.ts +57 -0
  25. package/src/antd/useMaskInputAntd-server.spec.tsx +36 -0
  26. package/src/antd/useMaskInputAntd.spec.tsx +108 -0
  27. package/src/antd/useMaskInputAntd.ts +77 -0
  28. package/src/api/index.ts +4 -0
  29. package/src/api/useHookFormMask.spec.ts +146 -0
  30. package/src/api/useHookFormMask.ts +56 -0
  31. package/src/api/useMaskInput-server.spec.tsx +30 -0
  32. package/src/api/useMaskInput.spec.tsx +220 -0
  33. package/src/api/useMaskInput.ts +73 -0
  34. package/src/api/withHookFormMask.spec.ts +155 -0
  35. package/src/api/withHookFormMask.ts +54 -0
  36. package/src/api/withMask.spec.ts +93 -0
  37. package/src/api/withMask.ts +25 -0
  38. package/src/core/elementResolver.spec.ts +175 -0
  39. package/src/core/elementResolver.ts +84 -0
  40. package/src/core/index.ts +3 -0
  41. package/src/core/maskConfig.spec.ts +183 -0
  42. package/src/core/maskConfig.ts +56 -0
  43. package/src/core/maskEngine.spec.ts +108 -0
  44. package/src/core/maskEngine.ts +47 -0
  45. package/src/index.tsx +12 -5
  46. package/src/{types.ts → types/index.ts} +13 -0
  47. package/src/utils/flow.spec.ts +27 -30
  48. package/src/utils/flow.ts +2 -2
  49. package/src/utils/index.ts +1 -1
  50. package/src/utils/isServer.spec.ts +15 -0
  51. package/src/utils/moduleInterop.spec.ts +37 -0
  52. package/src/useHookFormMask.ts +0 -47
  53. package/src/useMaskInput.ts +0 -41
  54. package/src/utils/getMaskOptions.spec.ts +0 -126
  55. package/src/utils/getMaskOptions.ts +0 -94
  56. package/src/withHookFormMask.ts +0 -34
  57. package/src/withMask.ts +0 -18
  58. /package/src/{inputmask.types.ts → types/inputmask.types.ts} +0 -0
@@ -1,4 +1,3 @@
1
- /* eslint-disable @typescript-eslint/no-unsafe-function-type */
2
1
  import {
3
2
  describe, expect, it,
4
3
  } from 'vitest';
@@ -11,50 +10,48 @@ describe('flow', () => {
11
10
  expect(typeof result).toBe('function');
12
11
  });
13
12
 
14
- it('returns undefined value if no return funcion provided', () => {
15
- const result = flow(() => {})(42);
16
- expect(result).toBe(undefined);
13
+ it('returns undefined value if no return function provided', () => {
14
+ const result = flow(() => { });
15
+ expect(result(42)).toBe(undefined);
17
16
  });
18
17
 
19
18
  it('throws an error if any argument is not a function', () => {
20
19
  // @ts-expect-error - null is not a function
21
20
  expect(() => flow(null)).toThrow(TypeError);
22
21
  // @ts-expect-error - null is not a function
23
- expect(() => flow(() => {}, null)).toThrow(TypeError);
22
+ expect(() => flow(() => { }, null)).toThrow(TypeError);
23
+ expect(() => {
24
+ flow(1 as unknown as () => void, () => { });
25
+ }).toThrow(TypeError);
24
26
  });
25
27
 
26
28
  it('returns the original value if no functions are provided', () => {
27
- const result = flow()(42);
28
- expect(result).toBe(42);
29
+ const result = flow();
30
+ expect(result(42)).toBe(42);
31
+ expect(result('test')).toBe('test');
29
32
  });
30
33
 
31
- it.todo('binds the functions to the correct context', () => {
32
- const context = { value: 42 };
33
- const fn1 = function (this: { value: number }) {
34
- return this.value;
35
- };
36
- const fn2 = function (this: { value: number }, n: number) {
37
- return this.value + n;
38
- };
39
- const fn = flow(fn1, fn2).bind(context);
40
- const result = fn(10);
41
- expect(result).toBe(52);
42
- });
34
+ it('composes functions correctly', () => {
35
+ const addOne = (x: number) => x + 1;
36
+ const multiplyByTwo = (x: number) => x * 2;
37
+ const subtractThree = (x: number) => x - 3;
43
38
 
44
- it('should return a function', () => {
45
- const result = flow();
46
- expect(typeof result).toBe('function');
39
+ const composed = flow(addOne, multiplyByTwo, subtractThree);
40
+ expect(composed(5)).toBe(9); // (5 + 1) * 2 - 3 = 9
47
41
  });
48
42
 
49
- it('should throw an error if any argument is not a function', () => {
50
- expect(() => {
51
- flow(1 as unknown as Function, () => {});
52
- }).toThrow(TypeError);
43
+ it('works with single function', () => {
44
+ const double = (x: number) => x * 2;
45
+ const fn = flow(double);
46
+ expect(fn(5)).toBe(10);
53
47
  });
54
48
 
55
- it('should return the input argument if no functions are provided', () => {
56
- const input = 'test';
57
- const result = flow()(input);
58
- expect(result).toBe(input);
49
+ it('works with multiple functions', () => {
50
+ const fn1 = (n: number) => n + 1;
51
+ const fn2 = (n: number) => n * 2;
52
+ const fn3 = (n: number) => n - 1;
53
+
54
+ const composed = flow(fn1, fn2, fn3);
55
+ expect(composed(5)).toBe(11); // ((5 + 1) * 2) - 1 = 11
59
56
  });
60
57
  });
package/src/utils/flow.ts CHANGED
@@ -11,10 +11,10 @@ export default function flow(...funcs: Function[]): Function {
11
11
  }
12
12
  return (...args: Function[]) => {
13
13
  let i = 0;
14
- let result = length ? funcs[i].apply(this, args) : args[0];
14
+ let result = length ? funcs[i].apply(undefined, args) : args[0];
15
15
  while (i + 1 < length) {
16
16
  i += 1;
17
- result = funcs[i].call(this, result);
17
+ result = funcs[i].call(undefined, result);
18
18
  }
19
19
  return result;
20
20
  };
@@ -1,3 +1,3 @@
1
1
  export { default as flow } from './flow';
2
2
  export { default as isServer } from './isServer';
3
- export { default as getMaskOptions } from './getMaskOptions';
3
+ export { default as moduleInterop } from './moduleInterop';
@@ -0,0 +1,15 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ describe('isServer', () => {
4
+ it('returns boolean value', async () => {
5
+ const { default: isServer } = await import('./isServer');
6
+ expect(typeof isServer).toBe('boolean');
7
+ });
8
+
9
+ it('returns false in browser environment', async () => {
10
+ // in jsdom environment, window and document exist
11
+ const { default: isServer } = await import('./isServer');
12
+ // in test environment with jsdom, it should be false
13
+ expect(isServer).toBe(false);
14
+ });
15
+ });
@@ -0,0 +1,37 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import interopDefaultSync from './moduleInterop';
4
+
5
+ describe('interopDefaultSync', () => {
6
+ it('returns module with default export', () => {
7
+ const module = { default: 'test' };
8
+ expect(interopDefaultSync(module)).toBe('test');
9
+ });
10
+
11
+ it('returns module without default export', () => {
12
+ const module = { foo: 'bar' };
13
+ expect(interopDefaultSync(module)).toBe(module);
14
+ });
15
+
16
+ it('returns non-object values as-is', () => {
17
+ expect(interopDefaultSync('string')).toBe('string');
18
+ expect(interopDefaultSync(123)).toBe(123);
19
+ expect(interopDefaultSync(null)).toBe(null);
20
+ // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
21
+ expect(interopDefaultSync(undefined)).toBe(undefined);
22
+ });
23
+
24
+ it('handles null module', () => {
25
+ expect(interopDefaultSync(null)).toBe(null);
26
+ });
27
+
28
+ it('handles module with null default', () => {
29
+ const module = { default: null };
30
+ expect(interopDefaultSync(module)).toBe(null);
31
+ });
32
+
33
+ it('handles module with undefined default', () => {
34
+ const module = { default: undefined };
35
+ expect(interopDefaultSync(module)).toBe(undefined);
36
+ });
37
+ });
@@ -1,47 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- /* eslint-disable import-x/no-extraneous-dependencies */
3
- import inputmask from 'inputmask';
4
-
5
- import { flow, getMaskOptions } from './utils';
6
- import interopDefaultSync from './utils/moduleInterop';
7
-
8
- import type { RefCallback } from 'react';
9
- import type {
10
- FieldValues, Path,
11
- RegisterOptions,
12
- UseFormRegister,
13
- UseFormRegisterReturn,
14
- } from 'react-hook-form';
15
-
16
- import type { Mask, Options } from './types';
17
-
18
- export default function useHookFormMask<
19
- T extends FieldValues, D extends RegisterOptions,
20
- >(registerFn: UseFormRegister<T>) {
21
- return (fieldName: Path<T>, mask: Mask, options?: (
22
- D & Options) | Options | D): UseFormRegisterReturn<Path<T>> => {
23
- if (!registerFn) throw new Error('registerFn is required');
24
-
25
- const { ref, ...restRegister } = registerFn(fieldName, options as any);
26
-
27
- const maskInput = interopDefaultSync(inputmask)(getMaskOptions(mask, options as any));
28
-
29
- const newRef = flow((_ref: HTMLElement) => {
30
- if (_ref) {
31
- const { nodeName } = _ref;
32
-
33
- if (nodeName !== 'INPUT') {
34
- maskInput.mask(_ref.querySelector('input') as HTMLElement);
35
- } else {
36
- maskInput.mask(_ref);
37
- }
38
- }
39
- return _ref;
40
- }, ref) as RefCallback<HTMLElement>;
41
-
42
- return {
43
- ...restRegister,
44
- ref: newRef,
45
- };
46
- };
47
- }
@@ -1,41 +0,0 @@
1
- /* eslint-disable import-x/no-extraneous-dependencies */
2
- import { useEffect, useRef } from 'react';
3
-
4
- import inputmask from 'inputmask';
5
-
6
- import { getMaskOptions } from './utils';
7
- import isServer from './utils/isServer';
8
- import interopDefaultSync from './utils/moduleInterop';
9
-
10
- import type { RefObject } from 'react';
11
-
12
- import type { Mask, Options } from './types';
13
-
14
- interface UseInputMaskOptions {
15
- mask: Mask;
16
- register?: (element: HTMLElement) => void;
17
- options?: Options;
18
- }
19
-
20
- export default function useInputMask(props: UseInputMaskOptions): RefObject<HTMLInputElement> {
21
- const { mask, register, options } = props;
22
- const ref = useRef<HTMLInputElement>(null);
23
- if (isServer) return ref;
24
-
25
- // eslint-disable-next-line react-hooks/rules-of-hooks
26
- useEffect(() => {
27
- if (!isServer && ref.current) {
28
- if (!ref.current) return;
29
-
30
- const maskInput = interopDefaultSync(inputmask)(getMaskOptions(mask, options));
31
-
32
- maskInput.mask(ref.current);
33
-
34
- if (register && ref.current) {
35
- register(ref.current);
36
- }
37
- }
38
- }, [mask, register, options]);
39
-
40
- return ref;
41
- }
@@ -1,126 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
-
3
- import getMaskOptions from './getMaskOptions';
4
-
5
- describe('getMaskOptions', () => {
6
- it('returns default options when no mask is provided', () => {
7
- const options = getMaskOptions();
8
- expect(options).toEqual({
9
- jitMasking: false,
10
- });
11
- });
12
-
13
- it('returns options for datetime mask', () => {
14
- const options = getMaskOptions('datetime');
15
- expect(options).toEqual({
16
- alias: 'datetime',
17
- jitMasking: false,
18
- });
19
- });
20
-
21
- it('returns options for cpf mask', () => {
22
- const options = getMaskOptions('cpf');
23
- expect(options).toEqual({
24
- mask: '999.999.999-99',
25
- placeholder: '___.___.___-__',
26
- jitMasking: false,
27
- });
28
- });
29
-
30
- it('returns options for email mask', () => {
31
- const options = getMaskOptions('email');
32
- expect(options).toEqual({
33
- alias: 'email',
34
- placeholder: '',
35
- jitMasking: false,
36
- });
37
- });
38
-
39
- it('returns options for numeric mask', () => {
40
- const options = getMaskOptions('numeric');
41
- expect(options).toEqual({
42
- alias: 'numeric',
43
- placeholder: '',
44
- jitMasking: false,
45
- });
46
- });
47
-
48
- it('returns options for currency mask', () => {
49
- const options = getMaskOptions('currency');
50
- expect(options).toEqual({
51
- alias: 'currency',
52
- prefix: '$ ',
53
- placeholder: '',
54
- jitMasking: false,
55
- });
56
- });
57
-
58
- it('returns options for decimal mask', () => {
59
- const options = getMaskOptions('decimal');
60
- expect(options).toEqual({
61
- alias: 'decimal',
62
- placeholder: '',
63
- jitMasking: false,
64
- });
65
- });
66
-
67
- it('returns options for integer mask', () => {
68
- const options = getMaskOptions('integer');
69
- expect(options).toEqual({
70
- alias: 'integer',
71
- placeholder: '',
72
- jitMasking: false,
73
- });
74
- });
75
-
76
- it('returns options for percentage mask', () => {
77
- const options = getMaskOptions('percentage');
78
- expect(options).toEqual({
79
- alias: 'percentage',
80
- placeholder: ' %',
81
- suffix: ' %',
82
- jitMasking: false,
83
- });
84
- });
85
-
86
- it('returns options for url mask', () => {
87
- const options = getMaskOptions('url');
88
- expect(options).toEqual({
89
- alias: 'url',
90
- placeholder: 'https://',
91
- jitMasking: false,
92
- });
93
- });
94
-
95
- it('returns options for ip mask', () => {
96
- const options = getMaskOptions('ip');
97
- expect(options).toEqual({
98
- alias: 'ip',
99
- jitMasking: false,
100
- });
101
- });
102
-
103
- it('returns options for mac mask', () => {
104
- const options = getMaskOptions('mac');
105
- expect(options).toEqual({
106
- alias: 'mac',
107
- jitMasking: false,
108
- });
109
- });
110
-
111
- it('returns options for ssn mask', () => {
112
- const options = getMaskOptions('ssn');
113
- expect(options).toEqual({
114
- alias: 'ssn',
115
- jitMasking: false,
116
- });
117
- });
118
-
119
- it('returns options for custom mask', () => {
120
- const options = getMaskOptions('999-999');
121
- expect(options).toEqual({
122
- mask: '999-999',
123
- jitMasking: false,
124
- });
125
- });
126
- });
@@ -1,94 +0,0 @@
1
- import type { Mask, Options } from '../types';
2
-
3
- export default function getMaskOptions(mask?: Mask, _options?: Options): Options {
4
- const options: Options = {
5
- jitMasking: false,
6
- ..._options,
7
- };
8
- if (!mask) return options;
9
-
10
- const masks: Record<string, Inputmask.Options> = {
11
- datetime: {
12
- alias: 'datetime',
13
- ...options,
14
- },
15
- email: {
16
- alias: 'email',
17
- placeholder: '',
18
- ...options,
19
- },
20
- numeric: {
21
- alias: 'numeric',
22
- placeholder: '',
23
- ...options,
24
- },
25
- currency: {
26
- alias: 'currency',
27
- prefix: '$ ',
28
- placeholder: '',
29
- ...options,
30
- },
31
- decimal: {
32
- alias: 'decimal',
33
- placeholder: '',
34
- ...options,
35
- },
36
- integer: {
37
- alias: 'integer',
38
- placeholder: '',
39
- ...options,
40
- },
41
- percentage: {
42
- alias: 'percentage',
43
- placeholder: ' %',
44
- suffix: ' %',
45
- ...options,
46
- },
47
- url: {
48
- alias: 'url',
49
- placeholder: 'https://',
50
- ...options,
51
- },
52
- ip: {
53
- alias: 'ip',
54
- ...options,
55
- },
56
- mac: {
57
- alias: 'mac',
58
- ...options,
59
- },
60
- ssn: {
61
- alias: 'ssn',
62
- ...options,
63
- },
64
-
65
- // alias for brazilians <3
66
- // ty <3
67
- 'brl-currency': {
68
- alias: 'currency',
69
- prefix: 'R$ ',
70
- placeholder: '0,00',
71
- displayFormat: 'currency',
72
- radixPoint: ',',
73
- autoUnmask: true,
74
- ...options,
75
- },
76
- cpf: {
77
- mask: '999.999.999-99',
78
- placeholder: '___.___.___-__',
79
- ...options,
80
- },
81
- cnpj: {
82
- mask: ['A|9{2}.A|9{3}.A|9{3}/A|9{4}-9{2}'],
83
- placeholder: '__.___.___/____-__',
84
- ...options,
85
- },
86
- };
87
-
88
- if (typeof mask === 'string' && masks[mask]) return masks[mask];
89
-
90
- return {
91
- mask,
92
- ...options,
93
- };
94
- }
@@ -1,34 +0,0 @@
1
- /* eslint-disable import-x/no-extraneous-dependencies */
2
- import inputmask from 'inputmask';
3
-
4
- import { flow, getMaskOptions } from './utils';
5
- import interopDefaultSync from './utils/moduleInterop';
6
-
7
- import type { RefCallback } from 'react';
8
-
9
- import type { Mask, Options, UseFormRegisterReturn } from './types';
10
-
11
- export default function withHookFormMask(
12
- register: UseFormRegisterReturn,
13
- mask: Mask,
14
- options?: Options,
15
- ): UseFormRegisterReturn {
16
- //
17
- let newRef;
18
-
19
- if (register) {
20
- const { ref } = register;
21
-
22
- const maskInput = interopDefaultSync(inputmask)(getMaskOptions(mask, options));
23
-
24
- newRef = flow((_ref: HTMLElement) => {
25
- if (_ref) maskInput.mask(_ref);
26
- return _ref;
27
- }, ref) as RefCallback<HTMLElement>;
28
- }
29
-
30
- return {
31
- ...register,
32
- ref: newRef as RefCallback<HTMLElement>,
33
- };
34
- }
package/src/withMask.ts DELETED
@@ -1,18 +0,0 @@
1
- /* eslint-disable import-x/no-extraneous-dependencies */
2
- import inputmask from 'inputmask';
3
-
4
- import { getMaskOptions } from './utils';
5
- import isServer from './utils/isServer';
6
- import interopDefaultSync from './utils/moduleInterop';
7
-
8
- import type { Input, Mask, Options } from './types';
9
-
10
- export default function withMask(mask: Mask, options?: Options) {
11
- return (input: Input | null): void => {
12
- if (isServer || mask === null || !input) return;
13
-
14
- const maskInput = interopDefaultSync(inputmask)(getMaskOptions(mask, options));
15
-
16
- maskInput.mask(input);
17
- };
18
- }