Skip to content

Commit f8c1336

Browse files
feat: use target instead of inputRef
1 parent 82a3e42 commit f8c1336

6 files changed

Lines changed: 102 additions & 47 deletions

File tree

apps/showcase/demo/usemask/basic-demo.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
import { useMask, type UseMaskChangeEvent } from '@primereact/hooks';
2+
import { InputTextInstance } from '@primereact/types/shared/inputtext';
23
import { InputText } from 'primereact/inputtext';
34
import * as React from 'react';
45

56
export default function BasicDemo() {
6-
const ref = React.useRef(null);
77
const [value, setValue] = React.useState('');
8+
const ref = React.useRef<InputTextInstance>(null);
9+
const [target, setTarget] = React.useState<HTMLInputElement | null>(null);
10+
11+
React.useEffect(() => {
12+
if (ref.current?.elementRef?.current) {
13+
setTarget(ref.current.elementRef.current as HTMLInputElement);
14+
}
15+
}, []);
16+
817
const { onMaskInput, onMaskKeyDown, onMaskKeyPress, onMaskFocus, onMaskBlur, onMaskPaste } = useMask({
918
mask: '99-999999',
1019
onMaskChange: (event: UseMaskChangeEvent) => setValue(event.value ?? ''),
11-
inputRef: ref
20+
target: target as HTMLInputElement
1221
});
1322

1423
return (

apps/showcase/demo/usemask/format-patterns-demo.tsx

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,33 @@
11
import { useMask, type UseMaskChangeEvent } from '@primereact/hooks';
2+
import { InputTextInstance } from '@primereact/types/shared/inputtext';
23
import { InputText } from 'primereact/inputtext';
34
import { Label } from 'primereact/label';
45
import * as React from 'react';
56

67
export default function FormatPatternsDemo() {
7-
const input1 = React.useRef(null);
8-
const input2 = React.useRef(null);
9-
const input3 = React.useRef(null);
108
const [value1, setValue1] = React.useState('');
119
const [value2, setValue2] = React.useState('');
1210
const [value3, setValue3] = React.useState('');
11+
const input1 = React.useRef<InputTextInstance>(null);
12+
const input2 = React.useRef<InputTextInstance>(null);
13+
const input3 = React.useRef<InputTextInstance>(null);
14+
const [target1, setTarget1] = React.useState<HTMLInputElement | null>(null);
15+
const [target2, setTarget2] = React.useState<HTMLInputElement | null>(null);
16+
const [target3, setTarget3] = React.useState<HTMLInputElement | null>(null);
17+
18+
React.useEffect(() => {
19+
if (input1.current?.elementRef?.current) {
20+
setTarget1(input1.current.elementRef.current as HTMLInputElement);
21+
}
22+
23+
if (input2.current?.elementRef?.current) {
24+
setTarget2(input2.current.elementRef.current as HTMLInputElement);
25+
}
26+
27+
if (input3.current?.elementRef?.current) {
28+
setTarget3(input3.current.elementRef.current as HTMLInputElement);
29+
}
30+
}, []);
1331

1432
// SSN Mask
1533
const {
@@ -22,7 +40,7 @@ export default function FormatPatternsDemo() {
2240
} = useMask({
2341
mask: '999-99-9999',
2442
onMaskChange: (event: UseMaskChangeEvent) => setValue1(event.value ?? ''),
25-
inputRef: input1
43+
target: target1 as HTMLInputElement
2644
});
2745

2846
// Phone Mask
@@ -36,7 +54,7 @@ export default function FormatPatternsDemo() {
3654
} = useMask({
3755
mask: '(999) 999-9999',
3856
onMaskChange: (event: UseMaskChangeEvent) => setValue2(event.value ?? ''),
39-
inputRef: input2
57+
target: target2 as HTMLInputElement
4058
});
4159

4260
// Serial Mask
@@ -50,7 +68,7 @@ export default function FormatPatternsDemo() {
5068
} = useMask({
5169
mask: 'a*-999-a999',
5270
onMaskChange: (event: UseMaskChangeEvent) => setValue3(event.value ?? ''),
53-
inputRef: input3
71+
target: target3 as HTMLInputElement
5472
});
5573

5674
return (

apps/showcase/demo/usemask/mask-demo.tsx

Whitespace-only changes.

apps/showcase/demo/usemask/optional-demo.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
import { useMask, type UseMaskChangeEvent } from '@primereact/hooks';
2+
import { InputTextInstance } from '@primereact/types/shared/inputtext';
23
import { InputText } from 'primereact/inputtext';
34
import * as React from 'react';
45

56
export default function OptionalDemo() {
6-
const ref = React.useRef(null);
77
const [value, setValue] = React.useState('');
8+
const ref = React.useRef<InputTextInstance>(null);
9+
const [target, setTarget] = React.useState<HTMLInputElement | null>(null);
10+
11+
React.useEffect(() => {
12+
if (ref.current?.elementRef?.current) {
13+
setTarget(ref.current.elementRef.current as HTMLInputElement);
14+
}
15+
}, []);
16+
817
const { onMaskInput, onMaskKeyDown, onMaskKeyPress, onMaskFocus, onMaskBlur, onMaskPaste } = useMask({
918
mask: '(999) 999-9999? x99999',
1019
onMaskChange: (event: UseMaskChangeEvent) => setValue(event.value ?? ''),
11-
inputRef: ref
20+
target: target as HTMLInputElement
1221
});
1322

1423
return (
Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,39 @@
11
import { useMask, type UseMaskChangeEvent } from '@primereact/hooks';
2-
import { InputText } from 'primereact/inputtext';
32
import * as React from 'react';
43

54
export default function SlotCharDemo() {
6-
const ref = React.useRef(null);
75
const [value, setValue] = React.useState('');
6+
const ref = React.useRef<HTMLInputElement>(null);
7+
const [target, setTarget] = React.useState<HTMLInputElement | null>(null);
8+
9+
React.useEffect(() => {
10+
if (ref.current) {
11+
setTarget(ref.current as HTMLInputElement);
12+
}
13+
}, []);
14+
815
const { onMaskInput, onMaskKeyDown, onMaskKeyPress, onMaskFocus, onMaskBlur, onMaskPaste } = useMask({
916
mask: '99/99/9999',
1017
slotChar: 'mm/dd/yyyy',
1118
onMaskChange: (event: UseMaskChangeEvent) => setValue(event.value ?? ''),
12-
inputRef: ref
19+
target: target as HTMLInputElement
1320
});
1421

1522
return (
1623
<div className="card flex justify-center">
17-
<InputText ref={ref} placeholder="mm/dd/yyyy" value={value} onInput={onMaskInput} onKeyDown={onMaskKeyDown} onKeyPress={onMaskKeyPress} onFocus={onMaskFocus} onBlur={onMaskBlur} onPaste={onMaskPaste} />
24+
<input
25+
type="text"
26+
ref={ref}
27+
placeholder="mm/dd/yyyy"
28+
value={value}
29+
onInput={onMaskInput}
30+
onKeyDown={onMaskKeyDown}
31+
onKeyPress={onMaskKeyPress}
32+
onFocus={onMaskFocus}
33+
onBlur={onMaskBlur}
34+
onPaste={onMaskPaste}
35+
className="border border-gray-300 rounded-md px-3 py-1"
36+
/>
1837
</div>
1938
);
2039
}

packages/hooks/src/use-mask/index.ts

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export interface UseMaskOptions {
5050
/**
5151
* Reference to the mask element.
5252
*/
53-
inputRef: React.RefObject<{ elementRef: React.RefObject<HTMLInputElement> } | null>;
53+
target: HTMLInputElement;
5454
}
5555

5656
export interface UseMaskExposes {
@@ -103,7 +103,7 @@ export interface UseMaskExposes {
103103
* const { onMaskInput, onMaskKeyDown, onMaskKeyPress, onMaskFocus, onMaskBlur, onMaskPaste } = useMask({
104104
* mask: '99/99/9999',
105105
* onMaskChange: (event: UseMaskChangeEvent) => setValue(event.value ?? ''),
106-
* inputRef: ref
106+
* target: ref
107107
* });
108108
*
109109
* return (
@@ -113,7 +113,7 @@ export interface UseMaskExposes {
113113
* );
114114
*/
115115
export function useMask(options: UseMaskOptions): UseMaskExposes {
116-
const { mask, unmask, slotChar = '_', autoClear = true, readOnly = false, onMaskChange, inputRef } = options;
116+
const { mask, unmask, slotChar = '_', autoClear = true, readOnly = false, onMaskChange, target } = options;
117117

118118
const len = React.useRef(0);
119119
const tests = React.useRef<Array<RegExp | null>>([]);
@@ -149,7 +149,7 @@ export function useMask(options: UseMaskOptions): UseMaskExposes {
149149
let pos, begin, end;
150150
const iPhone = /iphone/i.test(getUserAgent());
151151

152-
oldVal.current = inputRef.current?.elementRef.current?.value as string;
152+
oldVal.current = target?.value as string;
153153

154154
//backspace, delete, and escape get special treatment
155155
if (k === 'Backspace' || k === 'Delete' || (iPhone && k === 'Escape')) {
@@ -174,12 +174,12 @@ export function useMask(options: UseMaskOptions): UseMaskExposes {
174174
event.preventDefault();
175175
} else if (k === 'Enter') {
176176
// enter
177-
inputRef.current?.elementRef.current?.blur();
177+
target.blur();
178178
updateModelValue((event.target as HTMLInputElement).value);
179179
} else if (k === 'Escape') {
180180
// escape
181-
if (inputRef.current?.elementRef.current) {
182-
inputRef.current.elementRef.current.value = focusText.current ?? '';
181+
if (target) {
182+
target.value = focusText.current ?? '';
183183
}
184184

185185
caret(0, checkVal());
@@ -251,19 +251,19 @@ export function useMask(options: UseMaskOptions): UseMaskExposes {
251251
}
252252

253253
focus.current = true;
254-
focusText.current = inputRef.current?.elementRef.current?.value as string;
254+
focusText.current = target.value as string;
255255

256-
if (!inputRef.current?.elementRef.current?.value || inputRef.current.elementRef.current.value === defaultBuffer.current) {
256+
if (!target.value || target.value === defaultBuffer.current) {
257257
requestAnimationFrame(() => {
258-
if (inputRef.current?.elementRef.current === document.activeElement) {
258+
if (target === document.activeElement) {
259259
caret(0, 0);
260260
}
261261
});
262262
} else {
263263
const pos = checkVal();
264264

265265
caretTimeoutId.current = setTimeout(() => {
266-
if (inputRef.current?.elementRef.current !== document.activeElement) {
266+
if (target !== document.activeElement) {
267267
return;
268268
}
269269

@@ -283,10 +283,10 @@ export function useMask(options: UseMaskOptions): UseMaskExposes {
283283
checkVal();
284284
updateModelValue(event.target.value);
285285

286-
if (inputRef.current?.elementRef.current?.value !== focusText.current) {
286+
if (target.value !== focusText.current) {
287287
const e = new Event('change', { bubbles: true, cancelable: false });
288288

289-
inputRef.current?.elementRef.current?.dispatchEvent(e);
289+
target.dispatchEvent(e);
290290
}
291291
};
292292

@@ -302,11 +302,11 @@ export function useMask(options: UseMaskOptions): UseMaskExposes {
302302
begin = first;
303303
end = typeof last === 'number' ? last : begin;
304304

305-
inputRef.current?.elementRef.current?.setSelectionRange(begin, end);
305+
target.setSelectionRange(begin, end);
306306
} else {
307-
if (inputRef.current?.elementRef.current) {
308-
begin = inputRef.current.elementRef.current.selectionStart ?? 0;
309-
end = inputRef.current.elementRef.current.selectionEnd ?? 0;
307+
if (target) {
308+
begin = target.selectionStart ?? 0;
309+
end = target.selectionEnd ?? 0;
310310
}
311311
}
312312

@@ -376,7 +376,7 @@ export function useMask(options: UseMaskOptions): UseMaskExposes {
376376
};
377377

378378
const handleAndroidInput = () => {
379-
const curVal = inputRef.current?.elementRef.current?.value as string;
379+
const curVal = target.value as string;
380380
const pos = caret();
381381

382382
if (!pos) {
@@ -412,14 +412,14 @@ export function useMask(options: UseMaskOptions): UseMaskExposes {
412412
};
413413

414414
const writeBuffer = () => {
415-
if (inputRef.current?.elementRef.current) {
416-
inputRef.current.elementRef.current.value = buffer.current.join('');
415+
if (target) {
416+
target.value = buffer.current.join('');
417417
}
418418
};
419419

420420
const checkVal = (allow = false): number => {
421421
//try to place characters where they belong
422-
const test = inputRef.current?.elementRef.current?.value;
422+
const test = target.value;
423423
let lastMatch = -1,
424424
i,
425425
c,
@@ -462,8 +462,8 @@ export function useMask(options: UseMaskOptions): UseMaskExposes {
462462
if (autoClear || buffer.current.join('') === defaultBuffer.current) {
463463
// Invalid value. Remove it and replace it with the
464464
// mask, which is the default behavior.
465-
if (inputRef.current?.elementRef.current?.value) {
466-
inputRef.current.elementRef.current.value = '';
465+
if (target.value) {
466+
target.value = '';
467467
}
468468

469469
clearBuffer(0, len.current);
@@ -475,8 +475,8 @@ export function useMask(options: UseMaskOptions): UseMaskExposes {
475475
} else {
476476
writeBuffer();
477477

478-
if (inputRef.current?.elementRef.current) {
479-
inputRef.current.elementRef.current.value = inputRef.current.elementRef.current.value.substring(0, lastMatch + 1);
478+
if (target) {
479+
target.value = target.value.substring(0, lastMatch + 1);
480480
}
481481
}
482482

@@ -519,8 +519,8 @@ export function useMask(options: UseMaskOptions): UseMaskExposes {
519519

520520
currentVal.current = value;
521521

522-
if (inputRef.current?.elementRef.current) {
523-
inputRef.current.elementRef.current.value = finalValue;
522+
if (target) {
523+
target.value = finalValue;
524524
}
525525

526526
// Call the onMaskChange callback to update React state
@@ -530,9 +530,9 @@ export function useMask(options: UseMaskOptions): UseMaskExposes {
530530
};
531531

532532
const updateValue = (updateModel = true) => {
533-
if (inputRef.current?.elementRef.current) {
534-
if (inputRef.current.elementRef.current.value == null) {
535-
inputRef.current.elementRef.current.value = '';
533+
if (target) {
534+
if (target.value == null) {
535+
target.value = '';
536536

537537
if (updateModel) {
538538
updateModelValue('');
@@ -541,16 +541,16 @@ export function useMask(options: UseMaskOptions): UseMaskExposes {
541541
checkVal();
542542

543543
setTimeout(() => {
544-
if (inputRef.current?.elementRef.current) {
544+
if (target) {
545545
writeBuffer();
546546
checkVal();
547547

548-
if (updateModel) updateModelValue(inputRef.current.elementRef.current.value);
548+
if (updateModel) updateModelValue(target.value);
549549
}
550550
}, 10);
551551
}
552552

553-
focusText.current = inputRef.current.elementRef.current.value;
553+
focusText.current = target.value;
554554
}
555555
};
556556

0 commit comments

Comments
 (0)