use-mask-input 3.6.0 → 3.6.1

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 (39) hide show
  1. package/CHANGELOG.md +47 -76
  2. package/README.md +2 -251
  3. package/dist/index.cjs +157 -84
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +52 -11
  6. package/dist/index.d.ts +52 -11
  7. package/dist/index.js +158 -85
  8. package/dist/index.js.map +1 -1
  9. package/package.json +21 -21
  10. package/src/api/index.ts +4 -0
  11. package/src/api/useHookFormMask.spec.ts +146 -0
  12. package/src/api/useHookFormMask.ts +56 -0
  13. package/src/api/useMaskInput-server.spec.tsx +30 -0
  14. package/src/api/useMaskInput.spec.tsx +220 -0
  15. package/src/api/useMaskInput.ts +64 -0
  16. package/src/api/withHookFormMask.spec.ts +155 -0
  17. package/src/api/withHookFormMask.ts +54 -0
  18. package/src/api/withMask.spec.ts +93 -0
  19. package/src/api/withMask.ts +25 -0
  20. package/src/core/elementResolver.spec.ts +175 -0
  21. package/src/core/elementResolver.ts +84 -0
  22. package/src/core/index.ts +3 -0
  23. package/src/core/maskConfig.spec.ts +183 -0
  24. package/src/{utils/getMaskOptions.ts → core/maskConfig.ts} +12 -3
  25. package/src/core/maskEngine.spec.ts +108 -0
  26. package/src/core/maskEngine.ts +47 -0
  27. package/src/index.tsx +12 -5
  28. package/src/{types.ts → types/index.ts} +13 -0
  29. package/src/utils/flow.spec.ts +27 -30
  30. package/src/utils/flow.ts +2 -2
  31. package/src/utils/index.ts +1 -1
  32. package/src/utils/isServer.spec.ts +15 -0
  33. package/src/utils/moduleInterop.spec.ts +37 -0
  34. package/src/useHookFormMask.ts +0 -47
  35. package/src/useMaskInput.ts +0 -41
  36. package/src/utils/getMaskOptions.spec.ts +0 -126
  37. package/src/withHookFormMask.ts +0 -34
  38. package/src/withMask.ts +0 -18
  39. /package/src/{inputmask.types.ts → types/inputmask.types.ts} +0 -0
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { UseFormRegisterReturn, FieldValues, RegisterOptions, UseFormRegister, Path } from 'react-hook-form';
1
+ import { RefCallback } from 'react';
2
+ import { FieldValues, UseFormRegisterReturn, Path, RegisterOptions, UseFormRegister } from 'react-hook-form';
2
3
  export { UseFormRegister, UseFormRegisterReturn } from 'react-hook-form';
3
- import { RefObject } from 'react';
4
4
 
5
5
  type Range = {
6
6
  start: string;
@@ -576,18 +576,59 @@ interface CommandObject {
576
576
  type Mask = 'datetime' | 'email' | 'numeric' | 'currency' | 'decimal' | 'integer' | 'percentage' | 'url' | 'ip' | 'mac' | 'ssn' | 'brl-currency' | 'cpf' | 'cnpj' | (string & {}) | (string[] & {}) | null;
577
577
  type Options = Options$1;
578
578
  type Input = HTMLInputElement | HTMLTextAreaElement | HTMLElement;
579
+ interface UseHookFormMaskReturn<T extends FieldValues> extends UseFormRegisterReturn<Path<T>> {
580
+ ref: RefCallback<HTMLElement | null>;
581
+ prevRef: RefCallback<HTMLElement | null>;
582
+ }
579
583
 
580
- declare function withHookFormMask(register: UseFormRegisterReturn, mask: Mask, options?: Options): UseFormRegisterReturn;
581
-
582
- declare function withMask(mask: Mask, options?: Options): (input: Input | null) => void;
583
-
584
- declare function useHookFormMask<T extends FieldValues, D extends RegisterOptions>(registerFn: UseFormRegister<T>): (fieldName: Path<T>, mask: Mask, options?: (D & Options) | Options | D) => UseFormRegisterReturn<Path<T>>;
585
-
586
- interface UseInputMaskOptions {
584
+ interface UseMaskInputOptions {
587
585
  mask: Mask;
588
586
  register?: (element: HTMLElement) => void;
589
587
  options?: Options;
590
588
  }
591
- declare function useInputMask(props: UseInputMaskOptions): RefObject<HTMLInputElement>;
589
+ /**
590
+ * React hook for applying input masks to form elements.
591
+ * Works with Ant Design and other wrapped components too.
592
+ *
593
+ * @param props - Configuration object
594
+ * @param props.mask - The mask pattern to apply
595
+ * @param props.register - Optional callback that receives the element
596
+ * @param props.options - Optional mask configuration options
597
+ * @returns A ref callback function to attach to the input element
598
+ */
599
+ declare function useMaskInput(props: UseMaskInputOptions): ((input: Input | null) => void);
600
+
601
+ /**
602
+ * Creates a masked version of React Hook Form's register function.
603
+ * Takes react-hook-form's register and adds automatic masking. Like an upgrade.
604
+ *
605
+ * @template T - The form data type
606
+ * @template D - The register options type
607
+ * @param registerFn - The register function from useForm hook
608
+ * @returns A function that registers a field with mask support
609
+ */
610
+ declare function useHookFormMask<T extends FieldValues, D extends RegisterOptions>(registerFn: UseFormRegister<T>): (fieldName: Path<T>, mask: Mask, options?: (D & Options) | Options | D) => UseHookFormMaskReturn<T>;
611
+
612
+ /**
613
+ * Higher-order function that creates a ref callback for applying input masks.
614
+ * Simple function to apply mask via ref. No hooks, no drama.
615
+ *
616
+ * @param mask - The mask pattern to apply
617
+ * @param options - Optional mask configuration options
618
+ * @returns A ref callback function that applies the mask
619
+ */
620
+ declare function withMask(mask: Mask, options?: Options): (input: Input | null) => void;
621
+
622
+ /**
623
+ * Enhances a React Hook Form register return object with mask support.
624
+ * Takes an already registered field and adds mask to it.
625
+ * Useful when you registered the field before.
626
+ *
627
+ * @param register - The register return object from React Hook Form
628
+ * @param mask - The mask pattern to apply
629
+ * @param options - Optional mask configuration options
630
+ * @returns A new register return object with mask applied
631
+ */
632
+ declare function withHookFormMask(register: UseFormRegisterReturn, mask: Mask, options?: Options): UseHookFormMaskReturn<FieldValues>;
592
633
 
593
- export { type Mask, type Options, useHookFormMask, useInputMask as useMaskInput, withHookFormMask, withMask };
634
+ export { type Input, type Mask, type Options, useHookFormMask, useMaskInput, withHookFormMask, withMask };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { UseFormRegisterReturn, FieldValues, RegisterOptions, UseFormRegister, Path } from 'react-hook-form';
1
+ import { RefCallback } from 'react';
2
+ import { FieldValues, UseFormRegisterReturn, Path, RegisterOptions, UseFormRegister } from 'react-hook-form';
2
3
  export { UseFormRegister, UseFormRegisterReturn } from 'react-hook-form';
3
- import { RefObject } from 'react';
4
4
 
5
5
  type Range = {
6
6
  start: string;
@@ -576,18 +576,59 @@ interface CommandObject {
576
576
  type Mask = 'datetime' | 'email' | 'numeric' | 'currency' | 'decimal' | 'integer' | 'percentage' | 'url' | 'ip' | 'mac' | 'ssn' | 'brl-currency' | 'cpf' | 'cnpj' | (string & {}) | (string[] & {}) | null;
577
577
  type Options = Options$1;
578
578
  type Input = HTMLInputElement | HTMLTextAreaElement | HTMLElement;
579
+ interface UseHookFormMaskReturn<T extends FieldValues> extends UseFormRegisterReturn<Path<T>> {
580
+ ref: RefCallback<HTMLElement | null>;
581
+ prevRef: RefCallback<HTMLElement | null>;
582
+ }
579
583
 
580
- declare function withHookFormMask(register: UseFormRegisterReturn, mask: Mask, options?: Options): UseFormRegisterReturn;
581
-
582
- declare function withMask(mask: Mask, options?: Options): (input: Input | null) => void;
583
-
584
- declare function useHookFormMask<T extends FieldValues, D extends RegisterOptions>(registerFn: UseFormRegister<T>): (fieldName: Path<T>, mask: Mask, options?: (D & Options) | Options | D) => UseFormRegisterReturn<Path<T>>;
585
-
586
- interface UseInputMaskOptions {
584
+ interface UseMaskInputOptions {
587
585
  mask: Mask;
588
586
  register?: (element: HTMLElement) => void;
589
587
  options?: Options;
590
588
  }
591
- declare function useInputMask(props: UseInputMaskOptions): RefObject<HTMLInputElement>;
589
+ /**
590
+ * React hook for applying input masks to form elements.
591
+ * Works with Ant Design and other wrapped components too.
592
+ *
593
+ * @param props - Configuration object
594
+ * @param props.mask - The mask pattern to apply
595
+ * @param props.register - Optional callback that receives the element
596
+ * @param props.options - Optional mask configuration options
597
+ * @returns A ref callback function to attach to the input element
598
+ */
599
+ declare function useMaskInput(props: UseMaskInputOptions): ((input: Input | null) => void);
600
+
601
+ /**
602
+ * Creates a masked version of React Hook Form's register function.
603
+ * Takes react-hook-form's register and adds automatic masking. Like an upgrade.
604
+ *
605
+ * @template T - The form data type
606
+ * @template D - The register options type
607
+ * @param registerFn - The register function from useForm hook
608
+ * @returns A function that registers a field with mask support
609
+ */
610
+ declare function useHookFormMask<T extends FieldValues, D extends RegisterOptions>(registerFn: UseFormRegister<T>): (fieldName: Path<T>, mask: Mask, options?: (D & Options) | Options | D) => UseHookFormMaskReturn<T>;
611
+
612
+ /**
613
+ * Higher-order function that creates a ref callback for applying input masks.
614
+ * Simple function to apply mask via ref. No hooks, no drama.
615
+ *
616
+ * @param mask - The mask pattern to apply
617
+ * @param options - Optional mask configuration options
618
+ * @returns A ref callback function that applies the mask
619
+ */
620
+ declare function withMask(mask: Mask, options?: Options): (input: Input | null) => void;
621
+
622
+ /**
623
+ * Enhances a React Hook Form register return object with mask support.
624
+ * Takes an already registered field and adds mask to it.
625
+ * Useful when you registered the field before.
626
+ *
627
+ * @param register - The register return object from React Hook Form
628
+ * @param mask - The mask pattern to apply
629
+ * @param options - Optional mask configuration options
630
+ * @returns A new register return object with mask applied
631
+ */
632
+ declare function withHookFormMask(register: UseFormRegisterReturn, mask: Mask, options?: Options): UseHookFormMaskReturn<FieldValues>;
592
633
 
593
- export { type Mask, type Options, useHookFormMask, useInputMask as useMaskInput, withHookFormMask, withMask };
634
+ export { type Input, type Mask, type Options, useHookFormMask, useMaskInput, withHookFormMask, withMask };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { useRef, useEffect } from 'react';
1
+ import { useRef, useMemo, useEffect } from 'react';
2
2
 
3
3
  var __create = Object.create;
4
4
  var __defProp = Object.defineProperty;
@@ -26,17 +26,17 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  mod
27
27
  ));
28
28
 
29
- // node_modules/inputmask/dist/inputmask.js
29
+ // ../../node_modules/.pnpm/inputmask@5.0.10-beta.61/node_modules/inputmask/dist/inputmask.js
30
30
  var require_inputmask = __commonJS({
31
- "node_modules/inputmask/dist/inputmask.js"(exports, module) {
31
+ "../../node_modules/.pnpm/inputmask@5.0.10-beta.61/node_modules/inputmask/dist/inputmask.js"(exports$1, module) {
32
32
  !(function(e, t) {
33
- if ("object" == typeof exports && "object" == typeof module) module.exports = t();
33
+ if ("object" == typeof exports$1 && "object" == typeof module) module.exports = t();
34
34
  else if ("function" == typeof define && define.amd) define([], t);
35
35
  else {
36
36
  var n = t();
37
- for (var i in n) ("object" == typeof exports ? exports : e)[i] = n[i];
37
+ for (var i in n) ("object" == typeof exports$1 ? exports$1 : e)[i] = n[i];
38
38
  }
39
- })("undefined" != typeof self ? self : exports, function() {
39
+ })("undefined" != typeof self ? self : exports$1, function() {
40
40
  return (function() {
41
41
  var e = {
42
42
  340: function(e2, t2) {
@@ -3677,35 +3677,52 @@ var require_inputmask = __commonJS({
3677
3677
  }
3678
3678
  });
3679
3679
 
3680
- // src/withHookFormMask.ts
3681
- var import_inputmask = __toESM(require_inputmask());
3682
-
3683
- // src/utils/flow.ts
3684
- function flow(...funcs) {
3685
- const { length } = funcs;
3686
- let index = length;
3687
- while (index > 0) {
3688
- index -= 1;
3689
- if (typeof funcs[index] !== "function") {
3690
- throw new TypeError("Expected a function");
3680
+ // src/core/elementResolver.ts
3681
+ function isHTMLElement(element) {
3682
+ return element !== null && typeof element === "object" && "nodeType" in element && "querySelector" in element && typeof element.querySelector === "function";
3683
+ }
3684
+ function findInputElement(element) {
3685
+ if (!element) return null;
3686
+ if (!isHTMLElement(element)) {
3687
+ return null;
3688
+ }
3689
+ if (element.nodeName === "INPUT" || element.nodeName === "TEXTAREA") {
3690
+ return element;
3691
+ }
3692
+ if (!("querySelector" in element) || typeof element.querySelector !== "function") {
3693
+ return null;
3694
+ }
3695
+ try {
3696
+ const inputElement = element.querySelector("input") ?? element.querySelector("textarea");
3697
+ if (inputElement && isHTMLElement(inputElement)) {
3698
+ return inputElement;
3691
3699
  }
3700
+ } catch {
3701
+ return null;
3692
3702
  }
3693
- return (...args) => {
3694
- let i = 0;
3695
- let result = length ? funcs[i].apply(this, args) : args[0];
3696
- while (i + 1 < length) {
3697
- i += 1;
3698
- result = funcs[i].call(this, result);
3703
+ return null;
3704
+ }
3705
+ function resolveInputRef(input) {
3706
+ if (!input) {
3707
+ return null;
3708
+ }
3709
+ if (typeof input === "object" && "current" in input) {
3710
+ const refValue = input.current;
3711
+ if (isHTMLElement(refValue)) {
3712
+ return refValue;
3699
3713
  }
3700
- return result;
3701
- };
3714
+ return null;
3715
+ }
3716
+ if (isHTMLElement(input)) {
3717
+ return input;
3718
+ }
3719
+ return null;
3702
3720
  }
3703
3721
 
3704
- // src/utils/isServer.ts
3705
- var isServer = !(typeof window !== "undefined" && window.document?.createElement);
3706
- var isServer_default = isServer;
3722
+ // src/core/maskEngine.ts
3723
+ var import_inputmask = __toESM(require_inputmask());
3707
3724
 
3708
- // src/utils/getMaskOptions.ts
3725
+ // src/core/maskConfig.ts
3709
3726
  function getMaskOptions(mask, _options) {
3710
3727
  const options = {
3711
3728
  jitMasking: false,
@@ -3767,7 +3784,6 @@ function getMaskOptions(mask, _options) {
3767
3784
  ...options
3768
3785
  },
3769
3786
  // alias for brazilians <3
3770
- // ty <3
3771
3787
  "brl-currency": {
3772
3788
  alias: "currency",
3773
3789
  prefix: "R$ ",
@@ -3795,6 +3811,31 @@ function getMaskOptions(mask, _options) {
3795
3811
  };
3796
3812
  }
3797
3813
 
3814
+ // src/utils/flow.ts
3815
+ function flow(...funcs) {
3816
+ const { length } = funcs;
3817
+ let index = length;
3818
+ while (index > 0) {
3819
+ index -= 1;
3820
+ if (typeof funcs[index] !== "function") {
3821
+ throw new TypeError("Expected a function");
3822
+ }
3823
+ }
3824
+ return (...args) => {
3825
+ let i = 0;
3826
+ let result = length ? funcs[i].apply(void 0, args) : args[0];
3827
+ while (i + 1 < length) {
3828
+ i += 1;
3829
+ result = funcs[i].call(void 0, result);
3830
+ }
3831
+ return result;
3832
+ };
3833
+ }
3834
+
3835
+ // src/utils/isServer.ts
3836
+ var isServer = !(typeof window !== "undefined" && window.document?.createElement);
3837
+ var isServer_default = isServer;
3838
+
3798
3839
  // src/utils/moduleInterop.ts
3799
3840
  function interopDefaultSync(module) {
3800
3841
  if (typeof module === "object" && module !== null) {
@@ -3806,75 +3847,107 @@ function interopDefaultSync(module) {
3806
3847
  return module;
3807
3848
  }
3808
3849
 
3809
- // src/withHookFormMask.ts
3810
- function withHookFormMask(register, mask, options) {
3811
- let newRef;
3812
- if (register) {
3813
- const { ref } = register;
3814
- const maskInput = interopDefaultSync(import_inputmask.default)(getMaskOptions(mask, options));
3815
- newRef = flow((_ref) => {
3816
- if (_ref) maskInput.mask(_ref);
3817
- return _ref;
3818
- }, ref);
3850
+ // src/core/maskEngine.ts
3851
+ function createMaskInstance(mask, options) {
3852
+ const inputmaskInstance = interopDefaultSync(import_inputmask.default);
3853
+ return inputmaskInstance(getMaskOptions(mask, options));
3854
+ }
3855
+ function applyMaskToElement(element, mask, options) {
3856
+ if (!element) return;
3857
+ const maskInstance = createMaskInstance(mask, options);
3858
+ const inputElement = element.nodeName === "INPUT" ? element : element.querySelector("input");
3859
+ if (inputElement) {
3860
+ maskInstance.mask(inputElement);
3861
+ } else {
3862
+ maskInstance.mask(element);
3819
3863
  }
3820
- return {
3821
- ...register,
3822
- ref: newRef
3823
- };
3824
3864
  }
3825
3865
 
3826
- // src/withMask.ts
3827
- var import_inputmask2 = __toESM(require_inputmask());
3828
- function withMask(mask, options) {
3866
+ // src/api/useMaskInput.ts
3867
+ function useMaskInput(props) {
3868
+ const { mask, register, options } = props;
3869
+ const ref = useRef(null);
3870
+ const maskInput = useMemo(() => createMaskInstance(mask, options), [mask, options]);
3871
+ if (isServer_default) {
3872
+ return () => {
3873
+ };
3874
+ }
3875
+ useEffect(() => {
3876
+ if (isServer_default || !ref.current) return;
3877
+ if (!isHTMLElement(ref.current)) {
3878
+ return;
3879
+ }
3880
+ const inputElement = findInputElement(ref.current);
3881
+ if (inputElement && isHTMLElement(inputElement)) {
3882
+ maskInput.mask(inputElement);
3883
+ }
3884
+ if (register && isHTMLElement(ref.current)) {
3885
+ register(ref.current);
3886
+ }
3887
+ }, [mask, register, options, maskInput, ref]);
3829
3888
  return (input) => {
3830
- if (isServer_default || mask === null || !input) return;
3831
- const maskInput = interopDefaultSync(import_inputmask2.default)(getMaskOptions(mask, options));
3832
- maskInput.mask(input);
3889
+ if (!input) {
3890
+ ref.current = null;
3891
+ return;
3892
+ }
3893
+ ref.current = resolveInputRef(input);
3833
3894
  };
3834
3895
  }
3835
3896
 
3836
- // src/useHookFormMask.ts
3837
- var import_inputmask3 = __toESM(require_inputmask());
3897
+ // src/api/useHookFormMask.ts
3838
3898
  function useHookFormMask(registerFn) {
3839
3899
  return (fieldName, mask, options) => {
3840
3900
  if (!registerFn) throw new Error("registerFn is required");
3841
- const { ref, ...restRegister } = registerFn(fieldName, options);
3842
- const maskInput = interopDefaultSync(import_inputmask3.default)(getMaskOptions(mask, options));
3843
- const newRef = flow((_ref) => {
3844
- if (_ref) {
3845
- const { nodeName } = _ref;
3846
- if (nodeName !== "INPUT") {
3847
- maskInput.mask(_ref.querySelector("input"));
3848
- } else {
3849
- maskInput.mask(_ref);
3850
- }
3851
- }
3901
+ const registerReturn = registerFn(fieldName, options);
3902
+ const { ref } = registerReturn;
3903
+ const applyMaskToRef = (_ref) => {
3904
+ if (_ref) applyMaskToElement(_ref, mask, options);
3852
3905
  return _ref;
3853
- }, ref);
3854
- return {
3855
- ...restRegister,
3856
- ref: newRef
3857
3906
  };
3907
+ const refWithMask = ref ? flow(applyMaskToRef, ref) : applyMaskToRef;
3908
+ const result = {
3909
+ ...registerReturn,
3910
+ ref: refWithMask
3911
+ };
3912
+ Object.defineProperty(result, "prevRef", {
3913
+ value: ref,
3914
+ enumerable: false,
3915
+ writable: true,
3916
+ configurable: true
3917
+ });
3918
+ return result;
3858
3919
  };
3859
3920
  }
3860
3921
 
3861
- // src/useMaskInput.ts
3862
- var import_inputmask4 = __toESM(require_inputmask());
3863
- function useInputMask(props) {
3864
- const { mask, register, options } = props;
3865
- const ref = useRef(null);
3866
- if (isServer_default) return ref;
3867
- useEffect(() => {
3868
- if (!isServer_default && ref.current) {
3869
- if (!ref.current) return;
3870
- const maskInput = interopDefaultSync(import_inputmask4.default)(getMaskOptions(mask, options));
3871
- maskInput.mask(ref.current);
3872
- if (register && ref.current) {
3873
- register(ref.current);
3874
- }
3875
- }
3876
- }, [mask, register, options]);
3877
- return ref;
3922
+ // src/api/withMask.ts
3923
+ var import_inputmask2 = __toESM(require_inputmask());
3924
+ function withMask(mask, options) {
3925
+ return (input) => {
3926
+ if (isServer_default || mask === null || !input) return;
3927
+ const maskInput = interopDefaultSync(import_inputmask2.default)(getMaskOptions(mask, options));
3928
+ maskInput.mask(input);
3929
+ };
3930
+ }
3931
+
3932
+ // src/api/withHookFormMask.ts
3933
+ function withHookFormMask(register, mask, options) {
3934
+ const { ref } = register;
3935
+ const applyMaskToRef = (_ref) => {
3936
+ if (_ref) applyMaskToElement(_ref, mask, options);
3937
+ return _ref;
3938
+ };
3939
+ const refWithMask = ref === null ? null : ref ? flow(applyMaskToRef, ref) : null;
3940
+ const result = {
3941
+ ...register,
3942
+ ref: refWithMask
3943
+ };
3944
+ Object.defineProperty(result, "prevRef", {
3945
+ value: ref,
3946
+ enumerable: false,
3947
+ writable: true,
3948
+ configurable: true
3949
+ });
3950
+ return result;
3878
3951
  }
3879
3952
  /*! Bundled license information:
3880
3953
 
@@ -3889,6 +3962,6 @@ inputmask/dist/inputmask.js:
3889
3962
  (*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE *)
3890
3963
  */
3891
3964
 
3892
- export { useHookFormMask, useInputMask as useMaskInput, withHookFormMask, withMask };
3965
+ export { useHookFormMask, useMaskInput, withHookFormMask, withMask };
3893
3966
  //# sourceMappingURL=index.js.map
3894
3967
  //# sourceMappingURL=index.js.map