mfk-mask-input 1.0.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.
package/README.md ADDED
@@ -0,0 +1,283 @@
1
+ # mfk-mask-input
2
+
3
+ A lightweight and flexible vanilla React masked input component built with [IMask](https://imask.js.org/).
4
+
5
+ ## Features
6
+
7
+ - 🎭 **Flexible Masking** - Supports various mask patterns (phone, credit card, date, custom)
8
+ - 🪶 **Lightweight** - Vanilla React input, no UI framework dependencies
9
+ - 📝 **TypeScript Support** - Full TypeScript support with type definitions
10
+ - ⚡ **Minimal Dependencies** - Only React and IMask as peer dependencies
11
+ - 🔧 **Customizable** - Extensive IMask options support
12
+ - 🎯 **Developer Friendly** - Access both masked and unmasked values in onChange
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install mfk-mask-input
18
+ # or
19
+ yarn add mfk-mask-input
20
+ # or
21
+ pnpm add mfk-mask-input
22
+ # or
23
+ bun add mfk-mask-input
24
+ ```
25
+
26
+ ### Peer Dependencies
27
+
28
+ This package requires the following peer dependencies:
29
+
30
+ ```json
31
+ {
32
+ "react": "^18.0.0 || ^19.0.0",
33
+ "react-dom": "^18.0.0 || ^19.0.0",
34
+ "imask": "^6.0.0 || ^7.0.0"
35
+ }
36
+ ```
37
+
38
+ ## Quick Start
39
+
40
+ ```tsx
41
+ import { InputMask } from "mfk-mask-input";
42
+
43
+ function MyComponent() {
44
+ return (
45
+ <InputMask
46
+ mask="(000) 000-0000"
47
+ placeholder="Enter phone number"
48
+ onChange={(e) => {
49
+ console.log("Masked:", e.maskedValue); // "(555) 123-4567"
50
+ console.log("Unmasked:", e.unmaskedValue); // "5551234567"
51
+ }}
52
+ />
53
+ );
54
+ }
55
+ ```
56
+
57
+ ## Usage Examples
58
+
59
+ ### Phone Number
60
+
61
+ ```tsx
62
+ <InputMask mask="(000) 000-0000" placeholder="(555) 123-4567" />
63
+ ```
64
+
65
+ ### Credit Card
66
+
67
+ ```tsx
68
+ <InputMask mask="0000 0000 0000 0000" placeholder="1234 5678 9012 3456" />
69
+ ```
70
+
71
+ ### Date
72
+
73
+ ```tsx
74
+ <InputMask mask="00/00/0000" placeholder="DD/MM/YYYY" />
75
+ ```
76
+
77
+ ### Custom Patterns
78
+
79
+ ```tsx
80
+ <InputMask
81
+ mask="AAA-000"
82
+ definitions={{
83
+ A: /[A-Z]/,
84
+ "0": /[0-9]/,
85
+ }}
86
+ placeholder="ABC-123"
87
+ />
88
+ ```
89
+
90
+ ### Multiple Masks (Dynamic)
91
+
92
+ ```tsx
93
+ <InputMask
94
+ mask={[
95
+ { mask: "(000) 000-0000" },
96
+ { mask: "+0 (000) 000-0000" },
97
+ { mask: "+00 (000) 000-0000" },
98
+ ]}
99
+ placeholder="Phone number"
100
+ />
101
+ ```
102
+
103
+ ### Controlled Component
104
+
105
+ ```tsx
106
+ import { useState } from "react";
107
+ import { InputMask } from "mfk-mask-input";
108
+
109
+ function ControlledExample() {
110
+ const [value, setValue] = useState("");
111
+
112
+ return (
113
+ <InputMask
114
+ mask="0000-0000-0000-0000"
115
+ value={value}
116
+ onChange={(e) => setValue(e.maskedValue)}
117
+ />
118
+ );
119
+ }
120
+ ```
121
+
122
+ ### With Advanced IMask Options
123
+
124
+ ```tsx
125
+ <InputMask
126
+ mask={Number}
127
+ maskOptions={{
128
+ scale: 2,
129
+ thousandsSeparator: ",",
130
+ radix: ".",
131
+ mapToRadix: ["."],
132
+ min: 0,
133
+ max: 999999,
134
+ }}
135
+ placeholder="0.00"
136
+ />
137
+ ```
138
+
139
+ ### With Custom Styling
140
+
141
+ ```tsx
142
+ <InputMask
143
+ mask="(000) 000-0000"
144
+ className="my-input-class"
145
+ style={{ padding: "8px", border: "1px solid #ccc" }}
146
+ />
147
+ ```
148
+
149
+ ## API
150
+
151
+ ### Props
152
+
153
+ All standard HTML input props are supported, plus the following:
154
+
155
+ | Prop | Type | Required | Description |
156
+ | -------------- | -------------------------------- | -------- | -------------------------------------------------------------------------------------------------------- |
157
+ | `mask` | `MaskType` | Yes | Mask pattern or configuration. Can be a string, RegExp, Date, Number, function, or array of mask objects |
158
+ | `maskOptions` | `InputMaskOptions` | No | Additional IMask configuration options |
159
+ | `definitions` | `object` | No | Custom character definitions (e.g., `{ 'A': /[A-Z]/ }`) |
160
+ | `onChange` | `(event: OnChangeEvent) => void` | No | Change handler with extended event object |
161
+ | `value` | `string` | No | Controlled component value |
162
+ | `defaultValue` | `string` | No | Default value for uncontrolled usage |
163
+
164
+ ### Types
165
+
166
+ #### OnChangeEvent
167
+
168
+ The extended onChange event includes:
169
+
170
+ ```tsx
171
+ interface OnChangeEvent {
172
+ target: HTMLInputElement;
173
+ maskedValue: string; // Formatted value with mask
174
+ unmaskedValue: string; // Raw value without mask
175
+ // ... standard event properties
176
+ }
177
+ ```
178
+
179
+ #### MaskType
180
+
181
+ ```tsx
182
+ type MaskType =
183
+ | string
184
+ | RegExp
185
+ | typeof Number
186
+ | typeof Date
187
+ | ((value: string) => string)
188
+ | Array<{ mask: string | RegExp /* other options */ }>;
189
+ ```
190
+
191
+ ## Advanced Usage
192
+
193
+ ### Custom Definitions
194
+
195
+ Define custom placeholder characters:
196
+
197
+ ```tsx
198
+ <InputMask
199
+ mask="00/00/0000"
200
+ definitions={{
201
+ "0": /[0-9]/, // Digit
202
+ A: /[A-Z]/, // Uppercase letter
203
+ a: /[a-z]/, // Lowercase letter
204
+ "*": /[A-Za-z0-9]/, // Alphanumeric
205
+ }}
206
+ />
207
+ ```
208
+
209
+ ### With Form Libraries
210
+
211
+ #### React Hook Form
212
+
213
+ ```tsx
214
+ import { useForm, Controller } from "react-hook-form";
215
+ import { InputMask } from "mfk-mask-input";
216
+
217
+ function FormExample() {
218
+ const { control } = useForm();
219
+
220
+ return (
221
+ <Controller
222
+ name="phone"
223
+ control={control}
224
+ render={({ field }) => (
225
+ <InputMask
226
+ mask="(000) 000-0000"
227
+ {...field}
228
+ onChange={(e) => field.onChange(e.maskedValue)}
229
+ />
230
+ )}
231
+ />
232
+ );
233
+ }
234
+ ```
235
+
236
+ #### Formik
237
+
238
+ ```tsx
239
+ import { Formik, Field } from "formik";
240
+ import { InputMask } from "mfk-mask-input";
241
+
242
+ function FormikExample() {
243
+ return (
244
+ <Formik initialValues={{ phone: "" }}>
245
+ {({ setFieldValue }) => (
246
+ <Field name="phone">
247
+ {({ field }) => (
248
+ <InputMask
249
+ mask="(000) 000-0000"
250
+ value={field.value}
251
+ onChange={(e) => setFieldValue("phone", e.maskedValue)}
252
+ />
253
+ )}
254
+ </Field>
255
+ )}
256
+ </Formik>
257
+ );
258
+ }
259
+ ```
260
+
261
+ ## IMask Documentation
262
+
263
+ For complete IMask options and patterns, see the [official IMask documentation](https://imask.js.org/guide.html).
264
+
265
+ ## TypeScript
266
+
267
+ This package includes TypeScript definitions. Import types as needed:
268
+
269
+ ```tsx
270
+ import type {
271
+ MaskedInputProps,
272
+ OnChangeEvent,
273
+ InputMaskOptions,
274
+ } from "mfk-mask-input";
275
+ ```
276
+
277
+ ## License
278
+
279
+ MIT
280
+
281
+ ## Contributing
282
+
283
+ Contributions are welcome! Please feel free to submit a Pull Request.
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const O=require("react/jsx-runtime"),d=require("imask"),n=require("react"),E=n.forwardRef(function(y,a){const{mask:l,maskOptions:c,value:s,defaultValue:M,definitions:f,onChange:k,...I}=y,p=n.useRef(null),e=n.useRef(null),r=(typeof s=="string"?s:M)||"",[V,i]=n.useState(r),o=n.useMemo(()=>({mask:l,lazy:!0,definitions:{0:/[0-9]/,...c?.definitions,...f},...c}),[l,c,f]),m=n.useCallback(()=>{const t=p.current;if(!t)return;if(e.current){e.current.updateOptions(o);return}const u=d(t,o);e.current=u,u.on("accept",()=>{const v=u.value,h=u.unmaskedValue;i(v),k?.({target:t,maskedValue:v,unmaskedValue:h})}),r&&(u.value=r,t.value=u.value,i(u.value))},[o,k,r]);n.useEffect(()=>(m(),()=>{e.current?.destroy(),e.current=null}),[m]),n.useEffect(()=>{e.current&&s!==void 0&&e.current.value!==s&&(e.current.value=s,i(e.current.value))},[s]);const g=t=>{p.current=t,a&&(typeof a=="function"?a(t):a.current=t)};return O.jsx("input",{...I,ref:g,value:V,onChange:()=>{}})});exports.IMask=d;exports.InputMask=E;
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/InputMask.tsx"],"sourcesContent":["import IMask from 'imask';\r\nimport { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';\r\nimport type { IMaskOptions, MaskedInputProps, OnChangeEvent } from './types';\r\n\r\n/**\r\n * InputMask - A vanilla masked input component\r\n * \r\n * @example\r\n * ```tsx\r\n * <InputMask\r\n * mask=\"(000) 000-0000\"\r\n * placeholder=\"Phone number\"\r\n * onChange={(e) => console.log(e.maskedValue, e.unmaskedValue)}\r\n * />\r\n * ```\r\n */\r\nconst InputMask = forwardRef<HTMLInputElement, MaskedInputProps>(function MaskedInput(props, forwardedRef) {\r\n const {\r\n mask,\r\n maskOptions: _maskOptions,\r\n value: controlledValue,\r\n defaultValue,\r\n definitions,\r\n onChange,\r\n ...defaultInputProps\r\n } = props;\r\n\r\n const inputRef = useRef<HTMLInputElement | null>(null);\r\n const maskRef = useRef<ReturnType<typeof IMask> | null>(null);\r\n\r\n const initialValue = (typeof controlledValue === 'string' ? controlledValue : defaultValue) || '';\r\n const [value, setValue] = useState(initialValue);\r\n\r\n const maskOptions = useMemo(() => {\r\n return {\r\n mask,\r\n lazy: true,\r\n definitions: {\r\n 0: /[0-9]/,\r\n ..._maskOptions?.definitions,\r\n ...definitions,\r\n },\r\n ..._maskOptions,\r\n } as IMaskOptions;\r\n }, [mask, _maskOptions, definitions]);\r\n\r\n const initMask = useCallback(() => {\r\n const el = inputRef.current;\r\n if (!el) return;\r\n\r\n if (maskRef.current) {\r\n maskRef.current.updateOptions(maskOptions as any);\r\n return;\r\n }\r\n\r\n const maskInstance = IMask(el, maskOptions as any);\r\n maskRef.current = maskInstance;\r\n\r\n maskInstance.on('accept', () => {\r\n const masked = maskInstance.value;\r\n const unmasked = maskInstance.unmaskedValue;\r\n setValue(masked);\r\n\r\n const syntheticEvent = {\r\n target: el,\r\n maskedValue: masked,\r\n unmaskedValue: unmasked,\r\n } as OnChangeEvent;\r\n onChange?.(syntheticEvent);\r\n });\r\n\r\n if (initialValue) {\r\n maskInstance.value = initialValue;\r\n el.value = maskInstance.value;\r\n setValue(maskInstance.value);\r\n }\r\n }, [maskOptions, onChange, initialValue]);\r\n\r\n useEffect(() => {\r\n initMask();\r\n return () => {\r\n maskRef.current?.destroy();\r\n maskRef.current = null;\r\n };\r\n }, [initMask]);\r\n\r\n useEffect(() => {\r\n if (maskRef.current && controlledValue !== undefined) {\r\n if (maskRef.current.value !== controlledValue) {\r\n maskRef.current.value = controlledValue;\r\n setValue(maskRef.current.value);\r\n }\r\n }\r\n }, [controlledValue]);\r\n\r\n const handleRef = (ref: HTMLInputElement | null) => {\r\n inputRef.current = ref;\r\n if (forwardedRef) {\r\n if (typeof forwardedRef === 'function') forwardedRef(ref);\r\n else forwardedRef.current = ref;\r\n }\r\n };\r\n\r\n return <input {...defaultInputProps} ref={handleRef} value={value} onChange={() => {}} />;\r\n});\r\n\r\nexport default InputMask;\r\n"],"names":["InputMask","forwardRef","props","forwardedRef","mask","_maskOptions","controlledValue","defaultValue","definitions","onChange","defaultInputProps","inputRef","useRef","maskRef","initialValue","value","setValue","useState","maskOptions","useMemo","initMask","useCallback","el","maskInstance","IMask","masked","unmasked","useEffect","handleRef","ref","jsx"],"mappings":"2JAgBMA,EAAYC,EAAAA,WAA+C,SAAqBC,EAAOC,EAAc,CACzG,KAAM,CACJ,KAAAC,EACA,YAAaC,EACb,MAAOC,EACP,aAAAC,EACA,YAAAC,EACA,SAAAC,EACA,GAAGC,CAAA,EACDR,EAEES,EAAWC,EAAAA,OAAgC,IAAI,EAC/CC,EAAUD,EAAAA,OAAwC,IAAI,EAEtDE,GAAgB,OAAOR,GAAoB,SAAWA,EAAkBC,IAAiB,GACzF,CAACQ,EAAOC,CAAQ,EAAIC,EAAAA,SAASH,CAAY,EAEzCI,EAAcC,EAAAA,QAAQ,KACnB,CACL,KAAAf,EACA,KAAM,GACN,YAAa,CACX,EAAG,QACH,GAAGC,GAAc,YACjB,GAAGG,CAAA,EAEL,GAAGH,CAAA,GAEJ,CAACD,EAAMC,EAAcG,CAAW,CAAC,EAE9BY,EAAWC,EAAAA,YAAY,IAAM,CACjC,MAAMC,EAAKX,EAAS,QACpB,GAAI,CAACW,EAAI,OAET,GAAIT,EAAQ,QAAS,CACnBA,EAAQ,QAAQ,cAAcK,CAAkB,EAChD,MACF,CAEA,MAAMK,EAAeC,EAAMF,EAAIJ,CAAkB,EACjDL,EAAQ,QAAUU,EAElBA,EAAa,GAAG,SAAU,IAAM,CAC9B,MAAME,EAASF,EAAa,MACtBG,EAAWH,EAAa,cAC9BP,EAASS,CAAM,EAOfhB,IALuB,CACrB,OAAQa,EACR,YAAaG,EACb,cAAeC,CAAA,CAEQ,CAC3B,CAAC,EAEGZ,IACFS,EAAa,MAAQT,EACrBQ,EAAG,MAAQC,EAAa,MACxBP,EAASO,EAAa,KAAK,EAE/B,EAAG,CAACL,EAAaT,EAAUK,CAAY,CAAC,EAExCa,EAAAA,UAAU,KACRP,EAAA,EACO,IAAM,CACXP,EAAQ,SAAS,QAAA,EACjBA,EAAQ,QAAU,IACpB,GACC,CAACO,CAAQ,CAAC,EAEbO,EAAAA,UAAU,IAAM,CACVd,EAAQ,SAAWP,IAAoB,QACrCO,EAAQ,QAAQ,QAAUP,IAC5BO,EAAQ,QAAQ,MAAQP,EACxBU,EAASH,EAAQ,QAAQ,KAAK,EAGpC,EAAG,CAACP,CAAe,CAAC,EAEpB,MAAMsB,EAAaC,GAAiC,CAClDlB,EAAS,QAAUkB,EACf1B,IACE,OAAOA,GAAiB,WAAYA,EAAa0B,CAAG,IACtC,QAAUA,EAEhC,EAEA,OAAOC,EAAAA,IAAC,SAAO,GAAGpB,EAAmB,IAAKkB,EAAW,MAAAb,EAAc,SAAU,IAAM,CAAC,EAAG,CACzF,CAAC"}
@@ -0,0 +1,80 @@
1
+ import { ForwardRefExoticComponent } from 'react';
2
+ import { default as IMask } from 'imask';
3
+ import { RefAttributes } from 'react';
4
+
5
+ declare type GeneralInputProps = React.InputHTMLAttributes<HTMLInputElement>;
6
+
7
+ export { IMask }
8
+
9
+ /**
10
+ * IMask options with mask field
11
+ */
12
+ export declare interface IMaskOptions extends Omit<InputMaskOptions, 'mask'> {
13
+ mask: MaskFieldType;
14
+ }
15
+
16
+ declare type IMaskOptionsBase = any;
17
+
18
+ /**
19
+ * InputMask - A vanilla masked input component
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * <InputMask
24
+ * mask="(000) 000-0000"
25
+ * placeholder="Phone number"
26
+ * onChange={(e) => console.log(e.maskedValue, e.unmaskedValue)}
27
+ * />
28
+ * ```
29
+ */
30
+ export declare const InputMask: ForwardRefExoticComponent<MaskedInputProps & RefAttributes<HTMLInputElement>>;
31
+
32
+ /**
33
+ * IMask options configuration
34
+ */
35
+ export declare type InputMaskOptions = {
36
+ [K in keyof IMaskOptionsBase]?: IMaskOptionsBase[K];
37
+ };
38
+
39
+ declare type InputOnChangeParam = Parameters<Exclude<React.InputHTMLAttributes<HTMLInputElement>['onChange'], undefined>>[0];
40
+
41
+ /**
42
+ * Props for the InputMask component
43
+ */
44
+ export declare interface MaskedInputProps extends Omit<GeneralInputProps, 'onChange' | 'value' | 'defaultValue'> {
45
+ /** Mask pattern or configuration */
46
+ mask: MaskType;
47
+ /** Custom character definitions for the mask */
48
+ definitions?: InputMaskOptions['definitions'];
49
+ /** Controlled value */
50
+ value?: string;
51
+ /** Default value for uncontrolled usage */
52
+ defaultValue?: string;
53
+ /** Additional IMask options */
54
+ maskOptions?: InputMaskOptions;
55
+ /** Change handler with masked and unmasked values */
56
+ onChange?: (event: OnChangeEvent) => void;
57
+ }
58
+
59
+ declare type MaskFieldType = string | RegExp | ((...args: never) => unknown) | Date | InputMaskOptions;
60
+
61
+ declare type MaskOptionsList = Array<IMaskOptions>;
62
+
63
+ /**
64
+ * Supported mask types
65
+ */
66
+ export declare type MaskType = MaskFieldType | MaskOptionsList;
67
+
68
+ /**
69
+ * Extended onChange event with masked and unmasked values
70
+ */
71
+ export declare interface OnChangeEvent extends OnChangeParam {
72
+ /** The formatted value with mask applied */
73
+ maskedValue: string;
74
+ /** The raw value without mask */
75
+ unmaskedValue: string;
76
+ }
77
+
78
+ declare type OnChangeParam = InputOnChangeParam;
79
+
80
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,53 @@
1
+ import { jsx as g } from "react/jsx-runtime";
2
+ import O from "imask";
3
+ import { default as D } from "imask";
4
+ import { forwardRef as x, useRef as d, useState as C, useMemo as E, useCallback as R, useEffect as v } from "react";
5
+ const q = x(function(V, s) {
6
+ const {
7
+ mask: i,
8
+ maskOptions: r,
9
+ value: u,
10
+ defaultValue: h,
11
+ definitions: l,
12
+ onChange: f,
13
+ ...y
14
+ } = V, m = d(null), e = d(null), a = (typeof u == "string" ? u : h) || "", [I, o] = C(a), c = E(() => ({
15
+ mask: i,
16
+ lazy: !0,
17
+ definitions: {
18
+ 0: /[0-9]/,
19
+ ...r?.definitions,
20
+ ...l
21
+ },
22
+ ...r
23
+ }), [i, r, l]), p = R(() => {
24
+ const t = m.current;
25
+ if (!t) return;
26
+ if (e.current) {
27
+ e.current.updateOptions(c);
28
+ return;
29
+ }
30
+ const n = O(t, c);
31
+ e.current = n, n.on("accept", () => {
32
+ const k = n.value, M = n.unmaskedValue;
33
+ o(k), f?.({
34
+ target: t,
35
+ maskedValue: k,
36
+ unmaskedValue: M
37
+ });
38
+ }), a && (n.value = a, t.value = n.value, o(n.value));
39
+ }, [c, f, a]);
40
+ return v(() => (p(), () => {
41
+ e.current?.destroy(), e.current = null;
42
+ }), [p]), v(() => {
43
+ e.current && u !== void 0 && e.current.value !== u && (e.current.value = u, o(e.current.value));
44
+ }, [u]), /* @__PURE__ */ g("input", { ...y, ref: (t) => {
45
+ m.current = t, s && (typeof s == "function" ? s(t) : s.current = t);
46
+ }, value: I, onChange: () => {
47
+ } });
48
+ });
49
+ export {
50
+ D as IMask,
51
+ q as InputMask
52
+ };
53
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/InputMask.tsx"],"sourcesContent":["import IMask from 'imask';\r\nimport { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';\r\nimport type { IMaskOptions, MaskedInputProps, OnChangeEvent } from './types';\r\n\r\n/**\r\n * InputMask - A vanilla masked input component\r\n * \r\n * @example\r\n * ```tsx\r\n * <InputMask\r\n * mask=\"(000) 000-0000\"\r\n * placeholder=\"Phone number\"\r\n * onChange={(e) => console.log(e.maskedValue, e.unmaskedValue)}\r\n * />\r\n * ```\r\n */\r\nconst InputMask = forwardRef<HTMLInputElement, MaskedInputProps>(function MaskedInput(props, forwardedRef) {\r\n const {\r\n mask,\r\n maskOptions: _maskOptions,\r\n value: controlledValue,\r\n defaultValue,\r\n definitions,\r\n onChange,\r\n ...defaultInputProps\r\n } = props;\r\n\r\n const inputRef = useRef<HTMLInputElement | null>(null);\r\n const maskRef = useRef<ReturnType<typeof IMask> | null>(null);\r\n\r\n const initialValue = (typeof controlledValue === 'string' ? controlledValue : defaultValue) || '';\r\n const [value, setValue] = useState(initialValue);\r\n\r\n const maskOptions = useMemo(() => {\r\n return {\r\n mask,\r\n lazy: true,\r\n definitions: {\r\n 0: /[0-9]/,\r\n ..._maskOptions?.definitions,\r\n ...definitions,\r\n },\r\n ..._maskOptions,\r\n } as IMaskOptions;\r\n }, [mask, _maskOptions, definitions]);\r\n\r\n const initMask = useCallback(() => {\r\n const el = inputRef.current;\r\n if (!el) return;\r\n\r\n if (maskRef.current) {\r\n maskRef.current.updateOptions(maskOptions as any);\r\n return;\r\n }\r\n\r\n const maskInstance = IMask(el, maskOptions as any);\r\n maskRef.current = maskInstance;\r\n\r\n maskInstance.on('accept', () => {\r\n const masked = maskInstance.value;\r\n const unmasked = maskInstance.unmaskedValue;\r\n setValue(masked);\r\n\r\n const syntheticEvent = {\r\n target: el,\r\n maskedValue: masked,\r\n unmaskedValue: unmasked,\r\n } as OnChangeEvent;\r\n onChange?.(syntheticEvent);\r\n });\r\n\r\n if (initialValue) {\r\n maskInstance.value = initialValue;\r\n el.value = maskInstance.value;\r\n setValue(maskInstance.value);\r\n }\r\n }, [maskOptions, onChange, initialValue]);\r\n\r\n useEffect(() => {\r\n initMask();\r\n return () => {\r\n maskRef.current?.destroy();\r\n maskRef.current = null;\r\n };\r\n }, [initMask]);\r\n\r\n useEffect(() => {\r\n if (maskRef.current && controlledValue !== undefined) {\r\n if (maskRef.current.value !== controlledValue) {\r\n maskRef.current.value = controlledValue;\r\n setValue(maskRef.current.value);\r\n }\r\n }\r\n }, [controlledValue]);\r\n\r\n const handleRef = (ref: HTMLInputElement | null) => {\r\n inputRef.current = ref;\r\n if (forwardedRef) {\r\n if (typeof forwardedRef === 'function') forwardedRef(ref);\r\n else forwardedRef.current = ref;\r\n }\r\n };\r\n\r\n return <input {...defaultInputProps} ref={handleRef} value={value} onChange={() => {}} />;\r\n});\r\n\r\nexport default InputMask;\r\n"],"names":["InputMask","forwardRef","props","forwardedRef","mask","_maskOptions","controlledValue","defaultValue","definitions","onChange","defaultInputProps","inputRef","useRef","maskRef","initialValue","value","setValue","useState","maskOptions","useMemo","initMask","useCallback","el","maskInstance","IMask","masked","unmasked","useEffect","jsx","ref"],"mappings":";;;;AAgBA,MAAMA,IAAYC,EAA+C,SAAqBC,GAAOC,GAAc;AACzG,QAAM;AAAA,IACJ,MAAAC;AAAA,IACA,aAAaC;AAAA,IACb,OAAOC;AAAA,IACP,cAAAC;AAAA,IACA,aAAAC;AAAA,IACA,UAAAC;AAAA,IACA,GAAGC;AAAA,EAAA,IACDR,GAEES,IAAWC,EAAgC,IAAI,GAC/CC,IAAUD,EAAwC,IAAI,GAEtDE,KAAgB,OAAOR,KAAoB,WAAWA,IAAkBC,MAAiB,IACzF,CAACQ,GAAOC,CAAQ,IAAIC,EAASH,CAAY,GAEzCI,IAAcC,EAAQ,OACnB;AAAA,IACL,MAAAf;AAAA,IACA,MAAM;AAAA,IACN,aAAa;AAAA,MACX,GAAG;AAAA,MACH,GAAGC,GAAc;AAAA,MACjB,GAAGG;AAAA,IAAA;AAAA,IAEL,GAAGH;AAAA,EAAA,IAEJ,CAACD,GAAMC,GAAcG,CAAW,CAAC,GAE9BY,IAAWC,EAAY,MAAM;AACjC,UAAMC,IAAKX,EAAS;AACpB,QAAI,CAACW,EAAI;AAET,QAAIT,EAAQ,SAAS;AACnB,MAAAA,EAAQ,QAAQ,cAAcK,CAAkB;AAChD;AAAA,IACF;AAEA,UAAMK,IAAeC,EAAMF,GAAIJ,CAAkB;AACjD,IAAAL,EAAQ,UAAUU,GAElBA,EAAa,GAAG,UAAU,MAAM;AAC9B,YAAME,IAASF,EAAa,OACtBG,IAAWH,EAAa;AAC9B,MAAAP,EAASS,CAAM,GAOfhB,IALuB;AAAA,QACrB,QAAQa;AAAA,QACR,aAAaG;AAAA,QACb,eAAeC;AAAA,MAAA,CAEQ;AAAA,IAC3B,CAAC,GAEGZ,MACFS,EAAa,QAAQT,GACrBQ,EAAG,QAAQC,EAAa,OACxBP,EAASO,EAAa,KAAK;AAAA,EAE/B,GAAG,CAACL,GAAaT,GAAUK,CAAY,CAAC;AAExC,SAAAa,EAAU,OACRP,EAAA,GACO,MAAM;AACX,IAAAP,EAAQ,SAAS,QAAA,GACjBA,EAAQ,UAAU;AAAA,EACpB,IACC,CAACO,CAAQ,CAAC,GAEbO,EAAU,MAAM;AACd,IAAId,EAAQ,WAAWP,MAAoB,UACrCO,EAAQ,QAAQ,UAAUP,MAC5BO,EAAQ,QAAQ,QAAQP,GACxBU,EAASH,EAAQ,QAAQ,KAAK;AAAA,EAGpC,GAAG,CAACP,CAAe,CAAC,GAUb,gBAAAsB,EAAC,WAAO,GAAGlB,GAAmB,KARnB,CAACmB,MAAiC;AAClD,IAAAlB,EAAS,UAAUkB,GACf1B,MACE,OAAOA,KAAiB,aAAYA,EAAa0B,CAAG,MACtC,UAAUA;AAAA,EAEhC,GAEqD,OAAAd,GAAc,UAAU,MAAM;AAAA,EAAC,GAAG;AACzF,CAAC;"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "mfk-mask-input",
3
+ "version": "1.0.0",
4
+ "description": "A vanilla React masked input component using IMask",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "require": "./dist/index.cjs",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc && vite build",
21
+ "prepublishOnly": "npm run build"
22
+ },
23
+ "keywords": [
24
+ "react",
25
+ "input",
26
+ "mask",
27
+ "masked-input",
28
+ "imask",
29
+ "form",
30
+ "component"
31
+ ],
32
+ "author": "",
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": ""
37
+ },
38
+ "peerDependencies": {
39
+ "imask": "^6.0.0 || ^7.0.0",
40
+ "react": "^18.0.0 || ^19.0.0",
41
+ "react-dom": "^18.0.0 || ^19.0.0"
42
+ },
43
+ "devDependencies": {
44
+ "@types/node": "^24.10.0",
45
+ "@types/react": "^19.2.2",
46
+ "@types/react-dom": "^19.2.2",
47
+ "@vitejs/plugin-react": "^5.1.0",
48
+ "typescript": "~5.9.3",
49
+ "vite": "^7.2.2",
50
+ "vite-plugin-dts": "^4.3.0"
51
+ }
52
+ }