use-mask-input 3.10.1 → 3.10.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +7 -1
  2. package/dist/antd.cjs +1 -65
  3. package/dist/antd.cjs.map +1 -1
  4. package/dist/antd.d.cts +12 -10
  5. package/dist/{antd.d.ts → antd.d.mts} +12 -10
  6. package/dist/antd.mjs +2 -0
  7. package/dist/antd.mjs.map +1 -0
  8. package/dist/index-BmKzoe0X.d.cts +836 -0
  9. package/dist/index-BmKzoe0X.d.mts +836 -0
  10. package/dist/index.cjs +1 -173
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +18 -15
  13. package/dist/{index.d.ts → index.d.mts} +18 -15
  14. package/dist/index.mjs +2 -0
  15. package/dist/index.mjs.map +1 -0
  16. package/dist/withMask-VWeBqi_u.cjs +2 -0
  17. package/dist/withMask-VWeBqi_u.cjs.map +1 -0
  18. package/dist/withMask-jrErtLYS.mjs +2 -0
  19. package/dist/withMask-jrErtLYS.mjs.map +1 -0
  20. package/package.json +42 -22
  21. package/dist/antd.js +0 -63
  22. package/dist/antd.js.map +0 -1
  23. package/dist/chunk-PMBRAXS4.cjs +0 -5876
  24. package/dist/chunk-PMBRAXS4.cjs.map +0 -1
  25. package/dist/chunk-XSTQDKDU.js +0 -5866
  26. package/dist/chunk-XSTQDKDU.js.map +0 -1
  27. package/dist/index-D8KkaDbQ.d.cts +0 -596
  28. package/dist/index-D8KkaDbQ.d.ts +0 -596
  29. package/dist/index.js +0 -165
  30. package/dist/index.js.map +0 -1
  31. package/src/antd/useHookFormMaskAntd.spec.ts +0 -181
  32. package/src/antd/useMaskInputAntd-server.spec.tsx +0 -37
  33. package/src/antd/useMaskInputAntd.spec.tsx +0 -131
  34. package/src/api/useHookFormMask.spec.ts +0 -259
  35. package/src/api/useMaskInput-server.spec.tsx +0 -30
  36. package/src/api/useMaskInput.spec.tsx +0 -238
  37. package/src/api/withHookFormMask.spec.ts +0 -179
  38. package/src/api/withMask.spec.ts +0 -137
  39. package/src/api/withTanStackFormMask.spec.ts +0 -76
  40. package/src/core/elementResolver.spec.ts +0 -175
  41. package/src/core/inputmask.spec.ts +0 -21
  42. package/src/core/maskConfig.spec.ts +0 -208
  43. package/src/core/maskEngine.spec.ts +0 -114
  44. package/src/utils/flow.spec.ts +0 -57
  45. package/src/utils/isServer.spec.ts +0 -15
  46. package/src/utils/moduleInterop.spec.ts +0 -37
@@ -1,259 +0,0 @@
1
- import { act, renderHook } from '@testing-library/react';
2
- import inputmask from '../core/inputmask';
3
- import {
4
- beforeEach,
5
- describe, expect, it, vi,
6
- } from 'vitest';
7
-
8
- import useHookFormMask from './useHookFormMask';
9
-
10
- import type { FieldValues, UseFormRegister } from 'react-hook-form';
11
-
12
- vi.mock('../core/inputmask', () => ({
13
- default: vi.fn((options) => ({
14
- mask: vi.fn(),
15
- options,
16
- })),
17
- }));
18
-
19
- function makeRegisterFn(name = 'test') {
20
- return vi.fn(() => ({
21
- ref: vi.fn(),
22
- prevRef: vi.fn(),
23
- onChange: vi.fn(),
24
- onBlur: vi.fn(),
25
- name,
26
- }));
27
- }
28
-
29
- describe('useHookFormMask', () => {
30
- beforeEach(() => {
31
- vi.clearAllMocks();
32
- });
33
-
34
- it('returns a function', () => {
35
- const registerFn = makeRegisterFn();
36
- const { result } = renderHook(
37
- () => useHookFormMask(registerFn as UseFormRegister<FieldValues>),
38
- );
39
- expect(typeof result.current).toBe('function');
40
- });
41
-
42
- it('registers field with mask', () => {
43
- const input = document.createElement('input');
44
- const refCallback = vi.fn();
45
- const registerFn = vi.fn(() => ({
46
- ref: refCallback,
47
- prevRef: vi.fn(),
48
- onChange: vi.fn(),
49
- onBlur: vi.fn(),
50
- name: 'phone',
51
- }));
52
- const maskFn = vi.fn();
53
- vi.mocked(inputmask).mockReturnValue({ mask: maskFn } as any);
54
-
55
- const { result } = renderHook(
56
- () => useHookFormMask(registerFn as UseFormRegister<FieldValues>),
57
- );
58
- const registration = result.current('phone', '999-999');
59
-
60
- expect(registerFn).toHaveBeenCalledWith('phone', undefined);
61
- expect(registration.ref).toBeDefined();
62
- expect(typeof registration.ref).toBe('function');
63
-
64
- registration.ref?.(input);
65
-
66
- expect(maskFn).toHaveBeenCalled();
67
- });
68
-
69
- it('merges register options with mask options', () => {
70
- const registerFn = makeRegisterFn('phone');
71
- vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any);
72
-
73
- const { result } = renderHook(
74
- () => useHookFormMask(registerFn as UseFormRegister<FieldValues>),
75
- );
76
- result.current('phone', '999-999', { required: true });
77
-
78
- expect(registerFn).toHaveBeenCalledWith('phone', { required: true });
79
- });
80
-
81
- it('works with alias masks', () => {
82
- const registerFn = makeRegisterFn('cpf');
83
- vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any);
84
-
85
- const { result } = renderHook(
86
- () => useHookFormMask(registerFn as UseFormRegister<FieldValues>),
87
- );
88
- const registration = result.current('cpf', 'cpf');
89
-
90
- expect(registration.ref).toBeDefined();
91
- });
92
-
93
- it('works with array masks', () => {
94
- const registerFn = makeRegisterFn('phone');
95
- vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any);
96
-
97
- const { result } = renderHook(
98
- () => useHookFormMask(registerFn as UseFormRegister<FieldValues>),
99
- );
100
- const registration = result.current('phone', ['999-999', '9999-9999']);
101
-
102
- expect(registration.ref).toBeDefined();
103
- });
104
-
105
- it('preserves all register return properties', () => {
106
- const onChange = vi.fn();
107
- const onBlur = vi.fn();
108
- const registerFn = vi.fn(() => ({
109
- ref: vi.fn(),
110
- prevRef: vi.fn(),
111
- onChange,
112
- onBlur,
113
- name: 'phone',
114
- }));
115
-
116
- const { result } = renderHook(
117
- () => useHookFormMask(registerFn as UseFormRegister<FieldValues>),
118
- );
119
- const registration = result.current('phone', '999-999');
120
-
121
- expect(registration.onChange).toBe(onChange);
122
- expect(registration.onBlur).toBe(onBlur);
123
- expect(registration.name).toBe('phone');
124
- });
125
-
126
- it('handles null ref from register', () => {
127
- const registerFn = vi.fn(() => ({
128
- ref: undefined,
129
- prevRef: vi.fn(),
130
- onChange: vi.fn(),
131
- onBlur: vi.fn(),
132
- name: 'phone',
133
- }));
134
-
135
- const { result } = renderHook(
136
- () => useHookFormMask(registerFn as unknown as UseFormRegister<FieldValues>),
137
- );
138
- const registration = result.current('phone', '999-999');
139
-
140
- expect(registration.ref).toBeDefined();
141
- });
142
-
143
- it('returns the same ref callback reference across multiple calls (stable identity)', () => {
144
- const registerFn = makeRegisterFn('phone');
145
-
146
- const { result } = renderHook(
147
- () => useHookFormMask(registerFn as UseFormRegister<FieldValues>),
148
- );
149
-
150
- const first = result.current('phone', '999-999');
151
- const second = result.current('phone', '999-999');
152
-
153
- expect(first.ref).toBe(second.ref);
154
- });
155
-
156
- it('returns different ref callbacks for different field/mask combinations', () => {
157
- const registerFn = vi.fn((name: string) => ({
158
- ref: vi.fn(),
159
- prevRef: vi.fn(),
160
- onChange: vi.fn(),
161
- onBlur: vi.fn(),
162
- name,
163
- }));
164
-
165
- const { result } = renderHook(
166
- () => useHookFormMask(registerFn as unknown as UseFormRegister<FieldValues>),
167
- );
168
-
169
- const phone = result.current('phone', '999-999');
170
- const cpf = result.current('cpf', 'cpf');
171
-
172
- expect(phone.ref).not.toBe(cpf.ref);
173
- });
174
-
175
- it('invalidates the ref cache when registerFn changes (rerender with new registerFn)', () => {
176
- const registerFn1 = makeRegisterFn('phone');
177
- const registerFn2 = makeRegisterFn('phone');
178
-
179
- const { result, rerender } = renderHook(
180
- ({ fn }) => useHookFormMask(fn as UseFormRegister<FieldValues>),
181
- { initialProps: { fn: registerFn1 } },
182
- );
183
-
184
- const refBefore = result.current('phone', '999-999').ref;
185
-
186
- rerender({ fn: registerFn2 });
187
-
188
- const refAfter = result.current('phone', '999-999').ref;
189
-
190
- expect(refBefore).not.toBe(refAfter);
191
- });
192
-
193
- it('calls the latest RHF ref with the element after re-render (reset() regression)', async () => {
194
- // Simulate react-hook-form's reset() behaviour: it clears _fields and
195
- // returns a brand-new ref callback from register() on the next render.
196
- // The cached stable ref must still forward to the new RHF ref so that
197
- // RHF's internal T()/Z() logic can sync the DOM value to the reset value.
198
- const input = document.createElement('input');
199
- const refFn1 = vi.fn();
200
- const refFn2 = vi.fn(); // "new" ref returned after reset()
201
-
202
- const makeRegisterReturn = (ref: ReturnType<typeof vi.fn>) => ({
203
- ref,
204
- prevRef: vi.fn(),
205
- onChange: vi.fn(),
206
- onBlur: vi.fn(),
207
- name: 'phone',
208
- });
209
-
210
- let currentRef = refFn1;
211
- const registerFn = vi.fn(() => makeRegisterReturn(currentRef));
212
-
213
- vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any);
214
-
215
- // Mimic a real component: the registration function is called on every
216
- // render (which is what triggers the queue-push logic for reset support).
217
- const { result, rerender } = renderHook(
218
- () => {
219
- const registerWithMask = useHookFormMask(registerFn as UseFormRegister<FieldValues>);
220
- return registerWithMask('phone', '999-999');
221
- },
222
- );
223
-
224
- // Mount the element – stable cached ref is called once
225
- result.current.ref?.(input);
226
- expect(refFn1).toHaveBeenCalledWith(input);
227
-
228
- // Simulate reset(): register() now returns a different ref (refFn2)
229
- currentRef = refFn2;
230
-
231
- await act(async () => {
232
- rerender();
233
- });
234
-
235
- // After the re-render + useLayoutEffect, the new RHF ref must have been
236
- // called with the stored element so RHF can re-register it and sync values.
237
- expect(refFn2).toHaveBeenCalledWith(input);
238
- });
239
-
240
- it('defines prevRef as a non-enumerable property', () => {
241
- const prevRef = vi.fn();
242
- const registerFn = vi.fn(() => ({
243
- ref: prevRef,
244
- prevRef: vi.fn(),
245
- onChange: vi.fn(),
246
- onBlur: vi.fn(),
247
- name: 'phone',
248
- }));
249
-
250
- const { result } = renderHook(
251
- () => useHookFormMask(registerFn as UseFormRegister<FieldValues>),
252
- );
253
- const registration = result.current('phone', '999-999');
254
-
255
- const descriptor = Object.getOwnPropertyDescriptor(registration, 'prevRef');
256
- expect(descriptor?.enumerable).toBe(false);
257
- expect((registration as unknown as { prevRef: typeof prevRef }).prevRef).toBe(prevRef);
258
- });
259
- });
@@ -1,30 +0,0 @@
1
- import { act, renderHook } from '@testing-library/react';
2
- import {
3
- beforeEach,
4
- describe, expect, it, vi,
5
- } from 'vitest';
6
-
7
- vi.mock('../utils/isServer', () => ({
8
- default: true,
9
- }));
10
-
11
- describe('useMaskInput server-side', () => {
12
- beforeEach(() => {
13
- vi.clearAllMocks();
14
- vi.resetModules();
15
- });
16
-
17
- it('returns no-op function on server', async () => {
18
- const { default: useMaskInput } = await import('./useMaskInput');
19
- const { result } = renderHook(() => useMaskInput({ mask: '999-999' }));
20
-
21
- expect(typeof result.current).toBe('function');
22
-
23
- act(() => {
24
- result.current(document.createElement('input'));
25
- });
26
-
27
- // should do nothing on server
28
- expect(result.current).toBeDefined();
29
- });
30
- });
@@ -1,238 +0,0 @@
1
- import { act, renderHook } from '@testing-library/react';
2
- import inputmask from '../core/inputmask';
3
- import {
4
- beforeEach,
5
- describe, expect, it, vi,
6
- } from 'vitest';
7
-
8
- import useMaskInput from './useMaskInput';
9
- import * as core from '../core';
10
-
11
- import type { Input } from '../types';
12
-
13
- vi.mock('../core/inputmask', () => ({
14
- default: vi.fn((options) => ({
15
- mask: vi.fn(),
16
- options,
17
- })),
18
- }));
19
-
20
- vi.mock('../utils/isServer', () => ({
21
- default: false,
22
- }));
23
-
24
- describe('useMaskInput', () => {
25
- beforeEach(() => {
26
- vi.clearAllMocks();
27
- });
28
-
29
- it('returns a ref callback function', () => {
30
- const { result } = renderHook(() => useMaskInput({ mask: '999-999' }));
31
- expect(typeof result.current).toBe('function');
32
- expect(typeof result.current.unmaskedValue).toBe('function');
33
- });
34
-
35
- it('handles null input', () => {
36
- const { result } = renderHook(() => useMaskInput({ mask: '999-999' }));
37
-
38
- act(() => {
39
- result.current(null);
40
- });
41
-
42
- expect(result.current).toBeDefined();
43
- });
44
-
45
- it('handles direct input element', () => {
46
- const input = document.createElement('input');
47
- vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any);
48
-
49
- const { result, rerender } = renderHook(() => useMaskInput({ mask: '999-999' }));
50
-
51
- act(() => {
52
- result.current(input);
53
- });
54
-
55
- rerender();
56
-
57
- expect(inputmask).toHaveBeenCalled();
58
- });
59
-
60
- it('exposes the unmasked value from the masked input', () => {
61
- const input = document.createElement('input');
62
- vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any);
63
-
64
- const { result } = renderHook(() => useMaskInput({ mask: '999-999' }));
65
-
66
- act(() => {
67
- result.current(input);
68
- });
69
-
70
- input.inputmask = {
71
- unmaskedvalue: vi.fn(() => '2026-04-01'),
72
- } as any;
73
-
74
- expect(result.current.unmaskedValue()).toBe('2026-04-01');
75
- });
76
-
77
- it('handles ref object', () => {
78
- const input = document.createElement('input');
79
- const ref = { current: input };
80
- vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any);
81
-
82
- const { result, rerender } = renderHook(() => useMaskInput({ mask: '999-999' }));
83
-
84
- act(() => {
85
- result.current(ref as unknown as Input);
86
- });
87
-
88
- rerender();
89
-
90
- expect(inputmask).toHaveBeenCalled();
91
- });
92
-
93
- it('handles wrapper element with input inside', () => {
94
- const wrapper = document.createElement('div');
95
- const input = document.createElement('input');
96
- wrapper.appendChild(input);
97
- vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any);
98
-
99
- const { result, rerender } = renderHook(() => useMaskInput({ mask: '999-999' }));
100
-
101
- act(() => {
102
- result.current(wrapper);
103
- });
104
-
105
- rerender();
106
-
107
- expect(inputmask).toHaveBeenCalled();
108
- });
109
-
110
- it('handles invalid element in ref', () => {
111
- const invalidRef = { current: 'not an element' };
112
- vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any);
113
-
114
- const { result } = renderHook(() => useMaskInput({ mask: '999-999' }));
115
-
116
- act(() => {
117
- result.current(invalidRef as unknown as Input);
118
- });
119
-
120
- expect(result.current).toBeDefined();
121
- });
122
-
123
- it('handles element that is not HTMLElement in useEffect', () => {
124
- vi.spyOn(core, 'isHTMLElement').mockReturnValueOnce(false);
125
-
126
- const invalidElement = { nodeType: 1 } as unknown as Input;
127
- vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any);
128
-
129
- const { result, rerender } = renderHook(() => useMaskInput({ mask: '999-999' }));
130
-
131
- act(() => {
132
- result.current(invalidElement as unknown as Input);
133
- });
134
-
135
- rerender();
136
-
137
- expect(result.current).toBeDefined();
138
- });
139
-
140
- it('handles wrapper without input inside', () => {
141
- const wrapper = document.createElement('div');
142
- vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any);
143
-
144
- const { result, rerender } = renderHook(() => useMaskInput({ mask: '999-999' }));
145
-
146
- act(() => {
147
- result.current(wrapper);
148
- });
149
-
150
- rerender();
151
-
152
- expect(inputmask).toHaveBeenCalled();
153
- });
154
-
155
- it('works with custom options', () => {
156
- const input = document.createElement('input');
157
- vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any);
158
-
159
- const { result, rerender } = renderHook(() => useMaskInput({
160
- mask: '999-999',
161
- options: { placeholder: '_' },
162
- }));
163
-
164
- act(() => {
165
- result.current(input);
166
- });
167
-
168
- rerender();
169
-
170
- expect(inputmask).toHaveBeenCalled();
171
- });
172
-
173
- it('works with alias masks', () => {
174
- const input = document.createElement('input');
175
- vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any);
176
-
177
- const { result, rerender } = renderHook(() => useMaskInput({ mask: 'cpf' }));
178
-
179
- act(() => {
180
- result.current(input);
181
- });
182
-
183
- rerender();
184
-
185
- expect(inputmask).toHaveBeenCalled();
186
- });
187
-
188
- it('calls register callback when provided', () => {
189
- const input = document.createElement('input');
190
- const register = vi.fn();
191
- vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any);
192
-
193
- const { result, rerender } = renderHook(() => useMaskInput({
194
- mask: '999-999',
195
- register,
196
- }));
197
-
198
- act(() => {
199
- result.current(input);
200
- });
201
-
202
- rerender();
203
-
204
- expect(inputmask).toHaveBeenCalled();
205
- });
206
-
207
- it('handles textarea element', () => {
208
- const textarea = document.createElement('textarea');
209
- vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any);
210
-
211
- const { result, rerender } = renderHook(() => useMaskInput({ mask: '999-999' }));
212
-
213
- act(() => {
214
- result.current(textarea);
215
- });
216
-
217
- rerender();
218
-
219
- expect(inputmask).toHaveBeenCalled();
220
- });
221
-
222
- it('handles case where findInputElement returns valid element', () => {
223
- const wrapper = document.createElement('div');
224
- const input = document.createElement('input');
225
- wrapper.appendChild(input);
226
- vi.mocked(inputmask).mockReturnValue({ mask: vi.fn() } as any);
227
-
228
- const { result, rerender } = renderHook(() => useMaskInput({ mask: '999-999' }));
229
-
230
- act(() => {
231
- result.current(wrapper);
232
- });
233
-
234
- rerender();
235
-
236
- expect(inputmask).toHaveBeenCalled();
237
- });
238
- });
@@ -1,179 +0,0 @@
1
- import inputmask from '../core/inputmask';
2
- import {
3
- beforeEach,
4
- describe, expect, it, vi,
5
- } from 'vitest';
6
-
7
- import withHookFormMask from './withHookFormMask';
8
-
9
- import type { RefCallback } from 'react';
10
- import type { FieldValues } from 'react-hook-form';
11
-
12
- import type { UseHookFormMaskReturn } from '../types';
13
-
14
- vi.mock('../core/inputmask', () => ({
15
- default: vi.fn((options) => ({
16
- mask: vi.fn(),
17
- options,
18
- })),
19
- }));
20
-
21
- const createRegister = (
22
- overrides: Partial<UseHookFormMaskReturn<FieldValues>> = {},
23
- ): UseHookFormMaskReturn<FieldValues> => ({
24
- prevRef: vi.fn(),
25
- ref: vi.fn(),
26
- onChange: vi.fn(),
27
- onBlur: vi.fn(),
28
- name: 'phone',
29
- unmaskedValue: vi.fn(() => ''),
30
- ...overrides,
31
- });
32
-
33
- describe('withHookFormMask', () => {
34
- beforeEach(() => {
35
- vi.clearAllMocks();
36
- });
37
-
38
- it('returns register object with masked ref', () => {
39
- const originalRef = vi.fn();
40
- const register = createRegister({ ref: originalRef });
41
- const maskFn = vi.fn();
42
- vi.mocked(inputmask).mockReturnValue({ mask: maskFn } as any);
43
-
44
- const result = withHookFormMask(register, '999-999');
45
-
46
- expect(result.ref).toBeDefined();
47
- expect(typeof result.ref).toBe('function');
48
- expect(result.onChange).toBe(register.onChange);
49
- expect(result.onBlur).toBe(register.onBlur);
50
- expect(result.name).toBe(register.name);
51
- expect(typeof result.unmaskedValue).toBe('function');
52
- });
53
-
54
- it('applies mask when ref is called', () => {
55
- const input = document.createElement('input');
56
- const originalRef = vi.fn();
57
- const register = createRegister({ ref: originalRef });
58
- const maskFn = vi.fn();
59
- vi.mocked(inputmask).mockReturnValue({ mask: maskFn } as any);
60
-
61
- const result = withHookFormMask(register, '999-999');
62
- result.ref?.(input);
63
-
64
- expect(maskFn).toHaveBeenCalled();
65
- });
66
-
67
- it('exposes the unmasked value from the masked input', () => {
68
- const input = document.createElement('input');
69
- const originalRef = vi.fn();
70
- const register = createRegister({ ref: originalRef });
71
- const maskFn = vi.fn();
72
- vi.mocked(inputmask).mockReturnValue({ mask: maskFn } as any);
73
-
74
- const result = withHookFormMask(register, '999-999');
75
- result.ref?.(input);
76
-
77
- input.inputmask = {
78
- unmaskedvalue: vi.fn(() => '2026-04-01'),
79
- } as any;
80
-
81
- expect(result.unmaskedValue()).toBe('2026-04-01');
82
- });
83
-
84
- it('calls original ref after applying mask', () => {
85
- const input = document.createElement('input');
86
- const originalRef = vi.fn();
87
- const register = createRegister({ ref: originalRef });
88
- const maskFn = vi.fn();
89
- vi.mocked(inputmask).mockReturnValue({ mask: maskFn } as any);
90
-
91
- const result = withHookFormMask(register, '999-999');
92
- result.ref?.(input);
93
-
94
- expect(originalRef).toHaveBeenCalled();
95
- });
96
-
97
- it('works with alias masks', () => {
98
- const input = document.createElement('input');
99
- const originalRef = vi.fn();
100
- const register = createRegister({ ref: originalRef, name: 'cpf' });
101
- const maskFn = vi.fn();
102
- vi.mocked(inputmask).mockReturnValue({ mask: maskFn } as any);
103
-
104
- const result = withHookFormMask(register, 'cpf');
105
- result.ref?.(input);
106
-
107
- expect(maskFn).toHaveBeenCalled();
108
- });
109
-
110
- it('works with custom options', () => {
111
- const input = document.createElement('input');
112
- const originalRef = vi.fn();
113
- const register = createRegister({ ref: originalRef });
114
- const maskFn = vi.fn();
115
- vi.mocked(inputmask).mockReturnValue({ mask: maskFn } as any);
116
-
117
- const result = withHookFormMask(register, '999-999', { placeholder: '_' });
118
- result.ref?.(input);
119
-
120
- expect(maskFn).toHaveBeenCalled();
121
- });
122
-
123
- it('handles null ref gracefully', () => {
124
- const register = createRegister({
125
- prevRef: null as unknown as RefCallback<HTMLElement | null>,
126
- ref: null as unknown as RefCallback<HTMLElement | null>,
127
- });
128
-
129
- const result = withHookFormMask(register, '999-999');
130
- expect(result.ref).toBeNull();
131
- expect(result.onChange).toBe(register.onChange);
132
- expect(result.onBlur).toBe(register.onBlur);
133
- });
134
-
135
- it('handles null input in ref callback', () => {
136
- const originalRef = vi.fn();
137
- const register = createRegister({ ref: originalRef });
138
- const maskFn = vi.fn();
139
- vi.mocked(inputmask).mockReturnValue({ mask: maskFn } as any);
140
-
141
- const result = withHookFormMask(register, '999-999');
142
- result.ref?.(null as unknown as HTMLElement);
143
-
144
- expect(maskFn).not.toHaveBeenCalled();
145
- });
146
-
147
- it('returns the same ref callback reference across multiple calls (stable identity)', () => {
148
- const originalRef = vi.fn();
149
- const register = createRegister({ ref: originalRef });
150
-
151
- const first = withHookFormMask(register, '999-999');
152
- const second = withHookFormMask(register, '999-999');
153
-
154
- expect(first.ref).toBe(second.ref);
155
- });
156
-
157
- it('returns different ref callbacks for different field/mask combinations', () => {
158
- const originalRef = vi.fn();
159
- const registerPhone = createRegister({ ref: originalRef, name: 'phone' });
160
- const registerCpf = createRegister({ ref: originalRef, name: 'cpf' });
161
-
162
- const phone = withHookFormMask(registerPhone, '999-999');
163
- const cpf = withHookFormMask(registerCpf, 'cpf');
164
-
165
- expect(phone.ref).not.toBe(cpf.ref);
166
- });
167
-
168
- it('returns a new ref callback when the original ref changes', () => {
169
- const ref1 = vi.fn();
170
- const ref2 = vi.fn();
171
- const register1 = createRegister({ prevRef: vi.fn(), ref: ref1 });
172
- const register2 = createRegister({ prevRef: vi.fn(), ref: ref2 });
173
-
174
- const result1 = withHookFormMask(register1, '999-999');
175
- const result2 = withHookFormMask(register2, '999-999');
176
-
177
- expect(result1.ref).not.toBe(result2.ref);
178
- });
179
- });