form-input-fields 1.0.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.
package/README.md ADDED
@@ -0,0 +1,826 @@
1
+ # Form Fields Components
2
+
3
+ A collection of Material-UI form field components with Formik integration.
4
+
5
+ ## FormDateField
6
+
7
+ A date input field component with Material-UI and Formik integration, powered by MUI X Date Pickers.
8
+
9
+ ### Features
10
+
11
+ - **Material-UI Integration**: Consistent styling with other form components
12
+ - **Formik Integration**: Seamless form state management with error handling
13
+ - **Day.js Support**: Lightweight date library for date manipulation
14
+ - **Custom Date Formatting**: Flexible date display formats
15
+ - **Date Validation**: Built-in min/max date validation
16
+ - **Read-Only Support**: Can be configured as read-only
17
+ - **TypeScript Support**: Full type safety with exported interfaces
18
+ - **Helper Text Display**: Show date format or custom helper text
19
+ - **Today Button**: Optional today button in date picker
20
+
21
+ ### Available Date Formats
22
+
23
+ The component uses predefined date format constants from `date.ts`:
24
+
25
+ #### FORM_DATE_FORMAT
26
+
27
+ ```typescript
28
+ export const FORM_DATE_FORMAT = {
29
+ short: "YYYY-MM-DD",
30
+ long: "MM/DD/YYYY hh:mm A",
31
+ custom: "DD MMMM YYYY hh:mm A",
32
+ };
33
+ ```
34
+
35
+ #### DATE_PICKER_DATE_FORMAT
36
+
37
+ ```typescript
38
+ export const DATE_PICKER_DATE_FORMAT = {
39
+ short: "DD/MM/YYYY",
40
+ };
41
+ ```
42
+
43
+ #### DATE_PICKER_MONTH_YEAR_FORMAT
44
+
45
+ ```typescript
46
+ export const DATE_PICKER_MONTH_YEAR_FORMAT = {
47
+ short: "MM/YYYY",
48
+ long: "MMMM YYYY",
49
+ };
50
+ ```
51
+
52
+ ### Importing Date Constants
53
+
54
+ ```tsx
55
+ import {
56
+ FORM_DATE_FORMAT,
57
+ DATE_PICKER_DATE_FORMAT,
58
+ DATE_PICKER_MONTH_YEAR_FORMAT
59
+ } from "form-input-mask-field/date";
60
+
61
+ // Use predefined formats
62
+ <Field
63
+ component={FormDateField}
64
+ name="birthDate"
65
+ format={FORM_DATE_FORMAT.short} // 'YYYY-MM-DD'
66
+ />
67
+
68
+ // Or use custom format
69
+ <Field
70
+ component={FormDateField}
71
+ name="eventDate"
72
+ format="DD/MM/YYYY HH:mm" // Custom format
73
+ />
74
+ ```
75
+
76
+ ### Usage with Formik
77
+
78
+ ```tsx
79
+ import { Formik, Field } from "formik";
80
+ import { FormDateField, FormDateFieldProps } from "form-input-mask-field";
81
+ import { FORM_DATE_FORMAT } from "form-input-mask-field/date";
82
+ import dayjs from "dayjs";
83
+
84
+ <Formik
85
+ initialValues={{ birthDate: null, appointmentDate: null }}
86
+ onSubmit={(values) => console.log(values)}
87
+ >
88
+ {/* Basic usage */}
89
+ <Field
90
+ component={FormDateField}
91
+ name="birthDate"
92
+ label="Birth Date"
93
+ format={FORM_DATE_FORMAT.short}
94
+ />
95
+
96
+ {/* Advanced usage with validation */}
97
+ <Field
98
+ component={FormDateField}
99
+ name="appointmentDate"
100
+ label="Appointment Date"
101
+ format="DD/MM/YYYY"
102
+ minDate={dayjs()}
103
+ disablePast={true}
104
+ showTodayButton={true}
105
+ showDateFormat={true}
106
+ onChange={(value, context) => {
107
+ console.log("Selected date:", value);
108
+ console.log("Formatted value:", context.formattedValue);
109
+ }}
110
+ />
111
+ </Formik>;
112
+ ```
113
+
114
+ ### Props
115
+
116
+ The FormDateField component accepts all props from `FormDateFieldProps`, `FieldProps`, and `TextFieldProps`.
117
+
118
+ #### FormDateFieldProps Interface
119
+
120
+ | Prop | Type | Default | Description |
121
+ | ----------------- | ---------- | ------------------------ | --------------------------------------------- |
122
+ | `format` | `string` | `FORM_DATE_FORMAT.short` | Date format string using dayjs format tokens |
123
+ | `minDate` | `Dayjs` | - | Minimum selectable date |
124
+ | `maxDate` | `Dayjs` | - | Maximum selectable date |
125
+ | `disablePast` | `boolean` | `false` | Disable past dates |
126
+ | `disableFuture` | `boolean` | `false` | Disable future dates |
127
+ | `showTodayButton` | `boolean` | `false` | Show today button in the picker |
128
+ | `readOnly` | `boolean` | `false` | Make the field read-only |
129
+ | `showDateFormat` | `boolean` | `false` | Show the date format as helper text |
130
+ | `onChange` | `function` | - | Custom change handler with additional context |
131
+
132
+ #### Common Props (from FieldProps & TextFieldProps)
133
+
134
+ | Prop | Type | Required | Description |
135
+ | ------------ | ---------------- | -------- | --------------------------------------------- |
136
+ | `name` | `string` | Yes | Field name in Formik values |
137
+ | `label` | `string` | No | Field label |
138
+ | `helperText` | `string` | No | Custom helper text |
139
+ | `error` | `boolean` | No | Error state |
140
+ | `disabled` | `boolean` | No | Disabled state |
141
+ | Other | `TextFieldProps` | No | All Material-UI TextField props are supported |
142
+
143
+ ### Examples
144
+
145
+ #### Basic Date Input
146
+
147
+ ```tsx
148
+ <Field
149
+ component={FormDateField}
150
+ name="birthDate"
151
+ label="Birth Date"
152
+ format="DD/MM/YYYY"
153
+ />
154
+ ```
155
+
156
+ #### Date with Validation
157
+
158
+ ```tsx
159
+ <Field
160
+ component={FormDateField}
161
+ name="startDate"
162
+ label="Start Date"
163
+ minDate={dayjs()}
164
+ disablePast={true}
165
+ showDateFormat={true}
166
+ helperText="Select a future date"
167
+ />
168
+ ```
169
+
170
+ #### Appointment Scheduler
171
+
172
+ ```tsx
173
+ <Field
174
+ component={FormDateField}
175
+ name="appointmentDate"
176
+ label="Appointment Date"
177
+ format="DD MMMM YYYY"
178
+ minDate={dayjs().add(1, "day")}
179
+ maxDate={dayjs().add(3, "month")}
180
+ showTodayButton={true}
181
+ showDateFormat={true}
182
+ />
183
+ ```
184
+
185
+ #### Read-Only Date Display
186
+
187
+ ```tsx
188
+ <Field
189
+ component={FormDateField}
190
+ name="createdDate"
191
+ label="Created Date"
192
+ format="DD/MM/YYYY HH:mm"
193
+ readOnly={true}
194
+ />
195
+ ```
196
+
197
+ #### Custom Change Handler
198
+
199
+ ```tsx
200
+ <Field
201
+ component={FormDateField}
202
+ name="eventDate"
203
+ label="Event Date"
204
+ format="YYYY-MM-DD"
205
+ onChange={(value, context) => {
206
+ console.log("Selected date:", value);
207
+ console.log("Formatted value:", context.formattedValue);
208
+ console.log("Validation error:", context.validationError);
209
+
210
+ // Custom logic here
211
+ if (value && value.day() === 0) {
212
+ alert("Events cannot be scheduled on Sundays");
213
+ }
214
+ }}
215
+ />
216
+ ```
217
+
218
+ #### Date Range (Start/End Dates)
219
+
220
+ ```tsx
221
+ <Field
222
+ component={FormDateField}
223
+ name="startDate"
224
+ label="Start Date"
225
+ format="DD/MM/YYYY"
226
+ maxDate={values.endDate ? dayjs(values.endDate) : undefined}
227
+ />
228
+
229
+ <Field
230
+ component={FormDateField}
231
+ name="endDate"
232
+ label="End Date"
233
+ format="DD/MM/YYYY"
234
+ minDate={values.startDate ? dayjs(values.startDate) : undefined}
235
+ />
236
+ ```
237
+
238
+ ## FormMaskField
239
+
240
+ A flexible form field component with advanced text masking capabilities.
241
+
242
+ ### Features
243
+
244
+ - **Material-UI Integration**: Consistent styling with other form components
245
+ - **Formik Integration**: Seamless form state management
246
+ - **Flexible Masking**: Pattern-based input masking with multiple character types
247
+ - **Uppercase Conversion**: Automatic text transformation
248
+ - **TypeScript Support**: Full type safety and IntelliSense
249
+ - **Clean Value Option**: Return masked or unmasked values to form state
250
+
251
+ ### Usage with Formik
252
+
253
+ ```tsx
254
+ import { Formik, Field } from "formik";
255
+ import { FormMaskField } from "form-input-mask-field";
256
+
257
+ <Formik
258
+ initialValues={{ phoneNumber: "", gameCode: "" }}
259
+ onSubmit={(values) => console.log(values)}
260
+ >
261
+ <Field
262
+ component={FormMaskField}
263
+ name="phoneNumber"
264
+ label="Phone Number"
265
+ mask="(999) 999-9999"
266
+ placeholder="Enter phone number"
267
+ />
268
+
269
+ <Field
270
+ component={FormMaskField}
271
+ name="gameCode"
272
+ label="Game Code"
273
+ mask="AAAAA"
274
+ toUpperCase={true}
275
+ returnCleanValue={true}
276
+ />
277
+ </Formik>;
278
+ ```
279
+
280
+ ### Mask Pattern Characters
281
+
282
+ | Character | Description | Example |
283
+ | --------- | ---------------------------- | ------------------------ |
284
+ | `9` | Digit (0-9) | `999-99-9999` for SSN |
285
+ | `A` | Letter (a-z, A-Z) | `AAA` for country code |
286
+ | `*` | Alphanumeric (a-z, A-Z, 0-9) | `***-***` for mixed code |
287
+ | `a` | Lowercase letter (a-z) | `aaa` for lowercase only |
288
+ | `Z` | Uppercase letter (A-Z) | `ZZZ` for uppercase only |
289
+ | `#` | Hexadecimal (0-9, A-F, a-f) | `######` for hex color |
290
+ | Any other | Literal character | `-`, `(`, `)`, `/`, etc. |
291
+
292
+ ### Props
293
+
294
+ | Prop | Type | Default | Description |
295
+ | ------------------ | ---------- | ------- | -------------------------------------------------------------- |
296
+ | `mask` | `string` | - | Mask pattern using the characters above |
297
+ | `placeholderChar` | `string` | `'_'` | Character shown in placeholder for mask positions |
298
+ | `toUpperCase` | `boolean` | `false` | Convert input to uppercase automatically |
299
+ | `returnCleanValue` | `boolean` | `false` | Return unmasked value to Formik (true) or masked value (false) |
300
+ | `showMaskPattern` | `boolean` | `false` | Show the mask pattern as helper text below the input field |
301
+ | `showPlaceholder` | `boolean` | `false` | Show placeholder text with mask pattern in the input field |
302
+ | `onChange` | `function` | - | Custom change handler with masked, clean, and raw values |
303
+
304
+ Plus all standard Material-UI TextField props and Formik FieldProps.
305
+
306
+ ### Examples
307
+
308
+ #### Phone Number
309
+
310
+ ```tsx
311
+ <Field
312
+ component={FormMaskField}
313
+ name="phone"
314
+ label="Phone Number"
315
+ mask="(999) 999-9999"
316
+ placeholder="(555) 123-4567"
317
+ />
318
+ ```
319
+
320
+ #### Date Input
321
+
322
+ ```tsx
323
+ <Field
324
+ component={FormMaskField}
325
+ name="date"
326
+ label="Date"
327
+ mask="99/99/9999"
328
+ placeholder="MM/DD/YYYY"
329
+ />
330
+ ```
331
+
332
+ #### Product Code (Uppercase)
333
+
334
+ ```tsx
335
+ <Field
336
+ component={FormMaskField}
337
+ name="productCode"
338
+ label="Product Code"
339
+ mask="AAA-999-AAA"
340
+ toUpperCase={true}
341
+ returnCleanValue={true}
342
+ />
343
+ ```
344
+
345
+ #### Credit Card
346
+
347
+ ```tsx
348
+ <Field
349
+ component={FormMaskField}
350
+ name="creditCard"
351
+ label="Credit Card"
352
+ mask="9999 9999 9999 9999"
353
+ placeholder="1234 5678 9012 3456"
354
+ />
355
+ ```
356
+
357
+ #### Custom Change Handler
358
+
359
+ ```tsx
360
+ <Field
361
+ component={FormMaskField}
362
+ name="customField"
363
+ label="Custom Field"
364
+ mask="999-AAA"
365
+ onChange={(event) => {
366
+ console.log("Masked value:", event.target.value);
367
+ console.log("Clean value:", event.target.cleanValue);
368
+ console.log("Raw input:", event.target.rawValue);
369
+ }}
370
+ />
371
+ ```
372
+
373
+ #### Show Mask Pattern
374
+
375
+ ```tsx
376
+ <Field
377
+ component={FormMaskField}
378
+ name="gameCode"
379
+ label="Game Code"
380
+ mask="AAA-999"
381
+ showMaskPattern={true}
382
+ toUpperCase={true}
383
+ />
384
+ // This will show "Pattern: AAA-999" as helper text below the input
385
+ ```
386
+
387
+ #### Show Placeholder
388
+
389
+ ```tsx
390
+ <Field
391
+ component={FormMaskField}
392
+ name="phoneNumber"
393
+ label="Phone Number"
394
+ mask="(999) 999-9999"
395
+ showPlaceholder={true}
396
+ />
397
+ // This will show "(___) ___-____" as placeholder text in the input field
398
+ ```
399
+
400
+ ## Complete Example Application
401
+
402
+ Here's a comprehensive example showing how to build a complete form application using FormMaskField with Material-UI and Formik:
403
+
404
+ ### App.tsx
405
+
406
+ ```tsx
407
+ import React from "react";
408
+ import { Formik, Form, Field, FormikHelpers, FormikErrors } from "formik";
409
+ import Container from "@mui/material/Container";
410
+ import Typography from "@mui/material/Typography";
411
+ import Box from "@mui/material/Box";
412
+ import Button from "@mui/material/Button";
413
+ import { Grid } from "@mui/material";
414
+ import Paper from "@mui/material/Paper";
415
+ import Alert from "@mui/material/Alert";
416
+ import { ThemeProvider, createTheme } from "@mui/material/styles";
417
+ import CssBaseline from "@mui/material/CssBaseline";
418
+ import { FormMaskField } from "form-input-mask-field";
419
+ import "./App.css";
420
+
421
+ interface FormValues {
422
+ phone: string;
423
+ date: string;
424
+ creditCard: string;
425
+ licensePlate: string;
426
+ hexColor: string;
427
+ customCode: string;
428
+ socialSecurity: string;
429
+ postalCode: string;
430
+ }
431
+
432
+ interface FormFieldEvent
433
+ extends Omit<React.ChangeEvent<HTMLInputElement>, "target"> {
434
+ target: HTMLInputElement & {
435
+ value: string;
436
+ cleanValue: string;
437
+ rawValue: string;
438
+ name: string;
439
+ };
440
+ }
441
+
442
+ // Create a Material-UI theme
443
+ const theme = createTheme({
444
+ palette: {
445
+ primary: {
446
+ main: "#1976d2",
447
+ },
448
+ secondary: {
449
+ main: "#dc004e",
450
+ },
451
+ },
452
+ });
453
+
454
+ // Validation schema
455
+ const validateForm = (values: FormValues): FormikErrors<FormValues> => {
456
+ const errors: Partial<FormValues> = {};
457
+
458
+ if (!values.phone) {
459
+ errors.phone = "Phone number is required";
460
+ } else if (values.phone.replace(/\D/g, "").length < 10) {
461
+ errors.phone = "Phone number must be 10 digits";
462
+ }
463
+
464
+ if (!values.date) {
465
+ errors.date = "Date is required";
466
+ }
467
+
468
+ if (!values.creditCard) {
469
+ errors.creditCard = "Credit card is required";
470
+ } else if (values.creditCard.replace(/\D/g, "").length < 16) {
471
+ errors.creditCard = "Credit card must be 16 digits";
472
+ }
473
+
474
+ if (!values.licensePlate) {
475
+ errors.licensePlate = "License plate is required";
476
+ }
477
+
478
+ return errors;
479
+ };
480
+
481
+ function App() {
482
+ const initialValues: FormValues = {
483
+ phone: "",
484
+ date: "",
485
+ creditCard: "",
486
+ licensePlate: "",
487
+ hexColor: "",
488
+ customCode: "",
489
+ socialSecurity: "",
490
+ postalCode: "",
491
+ };
492
+
493
+ const handleSubmit = (
494
+ values: FormValues,
495
+ { setSubmitting }: FormikHelpers<FormValues>
496
+ ) => {
497
+ console.log("Form Values:", values);
498
+ setTimeout(() => {
499
+ alert("Form submitted! Check console for values.");
500
+ setSubmitting(false);
501
+ }, 400);
502
+ };
503
+
504
+ const handleCustomChange =
505
+ (fieldName: keyof FormValues) => (event: FormFieldEvent) => {
506
+ console.log(`${fieldName} changed:`, {
507
+ masked: event.target.value,
508
+ clean: event.target.cleanValue,
509
+ raw: event.target.rawValue,
510
+ });
511
+ return event;
512
+ };
513
+
514
+ return (
515
+ <ThemeProvider theme={theme}>
516
+ <CssBaseline />
517
+ <Container maxWidth="lg" sx={{ py: 4 }}>
518
+ <Typography variant="h3" component="h1" gutterBottom align="center">
519
+ FormMaskField Demo
520
+ </Typography>
521
+
522
+ <Typography
523
+ variant="subtitle1"
524
+ align="center"
525
+ color="text.secondary"
526
+ paragraph
527
+ >
528
+ A comprehensive example showcasing the FormMaskField component with
529
+ various mask patterns and configurations
530
+ </Typography>
531
+
532
+ <Formik
533
+ initialValues={initialValues}
534
+ validate={validateForm}
535
+ onSubmit={handleSubmit}
536
+ >
537
+ {({ values, isSubmitting, errors, touched }) => (
538
+ <Form>
539
+ <Grid container spacing={3}>
540
+ {/* Basic Masks Section */}
541
+ <Grid>
542
+ <Paper elevation={2} sx={{ p: 3 }}>
543
+ <Typography variant="h5" gutterBottom>
544
+ Basic Input Masks
545
+ </Typography>
546
+
547
+ <Grid container spacing={2}>
548
+ <Grid>
549
+ <Field
550
+ name="phone"
551
+ component={FormMaskField}
552
+ label="Phone Number"
553
+ mask="(999) 999-9999"
554
+ showMaskPattern={true}
555
+ showPlaceholder={true}
556
+ helperText="US phone number format"
557
+ onChange={handleCustomChange("phone")}
558
+ />
559
+ </Grid>
560
+
561
+ <Grid>
562
+ <Field
563
+ name="date"
564
+ component={FormMaskField}
565
+ label="Date"
566
+ mask="99/99/9999"
567
+ showMaskPattern={true}
568
+ showPlaceholder={true}
569
+ helperText="MM/DD/YYYY format"
570
+ />
571
+ </Grid>
572
+
573
+ <Grid>
574
+ <Field
575
+ name="socialSecurity"
576
+ component={FormMaskField}
577
+ label="Social Security Number"
578
+ mask="999-99-9999"
579
+ showMaskPattern={true}
580
+ showPlaceholder={true}
581
+ returnCleanValue={true}
582
+ helperText="Clean value returned (no dashes)"
583
+ />
584
+ </Grid>
585
+
586
+ <Grid>
587
+ <Field
588
+ name="postalCode"
589
+ component={FormMaskField}
590
+ label="ZIP Code"
591
+ mask="99999-9999"
592
+ showMaskPattern={true}
593
+ showPlaceholder={true}
594
+ helperText="US ZIP+4 format"
595
+ />
596
+ </Grid>
597
+ </Grid>
598
+ </Paper>
599
+ </Grid>
600
+
601
+ {/* Advanced Masks Section */}
602
+ <Grid>
603
+ <Paper elevation={2} sx={{ p: 3 }}>
604
+ <Typography variant="h5" gutterBottom>
605
+ Advanced Input Masks
606
+ </Typography>
607
+
608
+ <Grid container spacing={2}>
609
+ <Grid>
610
+ <Field
611
+ name="creditCard"
612
+ component={FormMaskField}
613
+ label="Credit Card Number"
614
+ mask="9999-9999-9999-9999"
615
+ showMaskPattern={true}
616
+ showPlaceholder={true}
617
+ helperText="16-digit credit card number"
618
+ onChange={handleCustomChange("creditCard")}
619
+ />
620
+ </Grid>
621
+
622
+ <Grid>
623
+ <Field
624
+ name="licensePlate"
625
+ component={FormMaskField}
626
+ label="License Plate"
627
+ mask="AAA-999"
628
+ toUpperCase={true}
629
+ showMaskPattern={true}
630
+ showPlaceholder={true}
631
+ helperText="3 letters + 3 numbers (auto uppercase)"
632
+ onChange={handleCustomChange("licensePlate")}
633
+ />
634
+ </Grid>
635
+
636
+ <Grid>
637
+ <Field
638
+ name="hexColor"
639
+ component={FormMaskField}
640
+ label="Hex Color Code"
641
+ mask="#######"
642
+ toUpperCase={true}
643
+ showMaskPattern={true}
644
+ showPlaceholder={true}
645
+ placeholderChar="0"
646
+ helperText="6-digit hex color code"
647
+ />
648
+ </Grid>
649
+
650
+ <Grid>
651
+ <Field
652
+ name="customCode"
653
+ component={FormMaskField}
654
+ label="Custom Code"
655
+ mask="**-999-AA"
656
+ toUpperCase={true}
657
+ returnCleanValue={true}
658
+ showMaskPattern={true}
659
+ showPlaceholder={true}
660
+ helperText="Alphanumeric + digits + letters"
661
+ onChange={handleCustomChange("customCode")}
662
+ />
663
+ </Grid>
664
+ </Grid>
665
+ </Paper>
666
+ </Grid>
667
+
668
+ {/* Current Values Display */}
669
+ <Grid>
670
+ <Paper elevation={2} sx={{ p: 3 }}>
671
+ <Typography variant="h5" gutterBottom>
672
+ Current Form Values
673
+ </Typography>
674
+
675
+ <Box sx={{ mt: 2 }}>
676
+ <Typography
677
+ variant="body2"
678
+ component="pre"
679
+ sx={{
680
+ backgroundColor: "#f5f5f5",
681
+ p: 2,
682
+ borderRadius: 1,
683
+ overflow: "auto",
684
+ fontSize: "0.875rem",
685
+ }}
686
+ >
687
+ {JSON.stringify(values, null, 2)}
688
+ </Typography>
689
+ </Box>
690
+ </Paper>
691
+ </Grid>
692
+
693
+ {/* Form Errors Display */}
694
+ {Object.keys(errors).length > 0 &&
695
+ Object.keys(touched).length > 0 && (
696
+ <Grid>
697
+ <Alert severity="error">
698
+ <Typography variant="h6" gutterBottom>
699
+ Form Validation Errors:
700
+ </Typography>
701
+ <ul>
702
+ {Object.entries(errors).map(
703
+ ([field, error]) =>
704
+ touched[field] && (
705
+ <li key={field}>
706
+ <strong>{field}:</strong> {error}
707
+ </li>
708
+ )
709
+ )}
710
+ </ul>
711
+ </Alert>
712
+ </Grid>
713
+ )}
714
+
715
+ {/* Submit Button */}
716
+ <Grid>
717
+ <Box
718
+ sx={{ display: "flex", justifyContent: "center", mt: 2 }}
719
+ >
720
+ <Button
721
+ type="submit"
722
+ variant="contained"
723
+ size="large"
724
+ disabled={isSubmitting}
725
+ sx={{ minWidth: 200 }}
726
+ >
727
+ {isSubmitting ? "Submitting..." : "Submit Form"}
728
+ </Button>
729
+ </Box>
730
+ </Grid>
731
+ </Grid>
732
+ </Form>
733
+ )}
734
+ </Formik>
735
+ </Container>
736
+ </ThemeProvider>
737
+ );
738
+ }
739
+
740
+ export default App;
741
+ ```
742
+
743
+ ### App.css
744
+
745
+ ```css
746
+ #root {
747
+ max-width: 1280px;
748
+ margin: 0 auto;
749
+ padding: 2rem;
750
+ text-align: center;
751
+ }
752
+
753
+ .logo {
754
+ height: 6em;
755
+ padding: 1.5em;
756
+ will-change: filter;
757
+ transition: filter 300ms;
758
+ }
759
+
760
+ .logo:hover {
761
+ filter: drop-shadow(0 0 2em #646cffaa);
762
+ }
763
+
764
+ .logo.react:hover {
765
+ filter: drop-shadow(0 0 2em #61dafbaa);
766
+ }
767
+
768
+ @keyframes logo-spin {
769
+ from {
770
+ transform: rotate(0deg);
771
+ }
772
+ to {
773
+ transform: rotate(360deg);
774
+ }
775
+ }
776
+
777
+ @media (prefers-reduced-motion: no-preference) {
778
+ a:nth-of-type(2) .logo {
779
+ animation: logo-spin infinite 20s linear;
780
+ }
781
+ }
782
+
783
+ .card {
784
+ padding: 2em;
785
+ }
786
+
787
+ .read-the-docs {
788
+ color: #888;
789
+ }
790
+ ```
791
+
792
+ ### Key Features Demonstrated
793
+
794
+ This example application showcases:
795
+
796
+ 1. **Complete Form Integration**: Full Formik integration with validation and error handling
797
+ 2. **Multiple Mask Types**: Phone numbers, dates, credit cards, license plates, hex colors, and custom codes
798
+ 3. **Advanced Features**:
799
+ - Uppercase conversion (`toUpperCase`)
800
+ - Clean value return (`returnCleanValue`)
801
+ - Custom placeholder characters (`placeholderChar`)
802
+ - Pattern display (`showMaskPattern`)
803
+ - Placeholder display (`showPlaceholder`)
804
+ 4. **Custom Event Handling**: onChange handlers that provide masked, clean, and raw values
805
+ 5. **Material-UI Integration**: Consistent styling with Material-UI theme and components
806
+ 6. **Real-time Validation**: Form validation with error display
807
+ 7. **Live Value Display**: Real-time display of current form values
808
+ 8. **Responsive Layout**: Grid-based responsive layout
809
+
810
+ ### Running the Example
811
+
812
+ To run this example:
813
+
814
+ 1. Install dependencies: `npm install`
815
+ 2. Start the development server: `npm run dev`
816
+ 3. Open your browser and navigate to the local development URL
817
+ 4. Interact with the form fields to see the masking in action
818
+ 5. Open browser console to see custom onChange event data
819
+
820
+ The example demonstrates how FormMaskField seamlessly integrates with existing Material-UI and Formik workflows while providing powerful input masking capabilities.
821
+
822
+ ## Support
823
+
824
+ If you like my work, you can support me here:
825
+
826
+ [![Buy Me a book](https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png)](https://coff.ee/vavanv)