@catalystsoftware/ui 1.0.5 → 1.0.7

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 (155) hide show
  1. package/dist/data/data.tsx +29 -29
  2. package/dist/data/tailwind.config.js +3821 -261
  3. package/dist/data.tsx +29 -29
  4. package/package.json +4 -3
  5. package/components/catalyst-ui/buttons/burger.tsx +0 -207
  6. package/components/catalyst-ui/core/data-display/timeline.tsx +0 -210
  7. package/components/catalyst-ui/core/feedback/alert.tsx +0 -491
  8. package/components/catalyst-ui/core/feedback/spinner-1.tsx +0 -65
  9. package/components/catalyst-ui/core/feedback/toast.tsx +0 -1857
  10. package/components/catalyst-ui/core/navigation/menu.tsx +0 -164
  11. package/components/catalyst-ui/forms/toggle-class.tsx +0 -176
  12. package/components/catalyst-ui/hooks/use-copy-to-clipboard.tsx +0 -419
  13. package/components/catalyst-ui/hooks/use-counter.tsx +0 -13
  14. package/components/catalyst-ui/hooks/use-event-listener.tsx +0 -23
  15. package/components/catalyst-ui/hooks/use-export-markdown.tsx +0 -47
  16. package/components/catalyst-ui/hooks/use-focus.tsx +0 -17
  17. package/components/catalyst-ui/hooks/use-interval.tsx +0 -23
  18. package/components/catalyst-ui/hooks/use-is-client.tsx +0 -16
  19. package/components/catalyst-ui/hooks/use-media-query.tsx +0 -19
  20. package/components/catalyst-ui/hooks/use-mobile.tsx +0 -19
  21. package/components/catalyst-ui/hooks/use-resize-observer.tsx +0 -81
  22. package/components/catalyst-ui/hooks/use-timeout.tsx +0 -21
  23. package/components/catalyst-ui/hooks/use-timer.tsx +0 -209
  24. package/components/catalyst-ui/hooks/use-toggle.tsx +0 -12
  25. package/components/catalyst-ui/media/image.tsx +0 -13
  26. package/components/catalyst-ui/overlays/dual-sidebar.tsx +0 -4142
  27. package/components/catalyst-ui/overlays/sidebar-original.tsx +0 -726
  28. package/components/catalyst-ui/primitives/accordion.tsx +0 -250
  29. package/components/catalyst-ui/primitives/alert-dialog.tsx +0 -126
  30. package/components/catalyst-ui/primitives/aspect-ratio.tsx +0 -9
  31. package/components/catalyst-ui/primitives/avatar.tsx +0 -296
  32. package/components/catalyst-ui/primitives/badge.tsx +0 -57
  33. package/components/catalyst-ui/primitives/breadcrumb.tsx +0 -101
  34. package/components/catalyst-ui/primitives/button.tsx +0 -265
  35. package/components/catalyst-ui/primitives/calendar-v4.tsx +0 -208
  36. package/components/catalyst-ui/primitives/calendar.tsx +0 -295
  37. package/components/catalyst-ui/primitives/card.tsx +0 -618
  38. package/components/catalyst-ui/primitives/carousel.tsx +0 -238
  39. package/components/catalyst-ui/primitives/chart.tsx +0 -347
  40. package/components/catalyst-ui/primitives/checkbox.tsx +0 -225
  41. package/components/catalyst-ui/primitives/collapsible.tsx +0 -212
  42. package/components/catalyst-ui/primitives/command.tsx +0 -393
  43. package/components/catalyst-ui/primitives/context-menu.tsx +0 -236
  44. package/components/catalyst-ui/primitives/dialog.tsx +0 -471
  45. package/components/catalyst-ui/primitives/drawer.tsx +0 -761
  46. package/components/catalyst-ui/primitives/dropdown-menu.tsx +0 -290
  47. package/components/catalyst-ui/primitives/empty.tsx +0 -104
  48. package/components/catalyst-ui/primitives/field.tsx +0 -244
  49. package/components/catalyst-ui/primitives/hover-card.tsx +0 -124
  50. package/components/catalyst-ui/primitives/input-otp.tsx +0 -76
  51. package/components/catalyst-ui/primitives/input.tsx +0 -64
  52. package/components/catalyst-ui/primitives/item.tsx +0 -196
  53. package/components/catalyst-ui/primitives/kbd.tsx +0 -75
  54. package/components/catalyst-ui/primitives/label.tsx +0 -24
  55. package/components/catalyst-ui/primitives/navigation-menu.tsx +0 -150
  56. package/components/catalyst-ui/primitives/pagination.tsx +0 -198
  57. package/components/catalyst-ui/primitives/popover.tsx +0 -232
  58. package/components/catalyst-ui/primitives/progress.tsx +0 -34
  59. package/components/catalyst-ui/primitives/radio-group.tsx +0 -43
  60. package/components/catalyst-ui/primitives/resizable.tsx +0 -56
  61. package/components/catalyst-ui/primitives/select.tsx +0 -155
  62. package/components/catalyst-ui/primitives/separator.tsx +0 -74
  63. package/components/catalyst-ui/primitives/sheet.tsx +0 -126
  64. package/components/catalyst-ui/primitives/skeleton.tsx +0 -15
  65. package/components/catalyst-ui/primitives/slider.tsx +0 -27
  66. package/components/catalyst-ui/primitives/switch.tsx +0 -187
  67. package/components/catalyst-ui/primitives/tabs.tsx +0 -335
  68. package/components/catalyst-ui/primitives/textarea.tsx +0 -24
  69. package/components/catalyst-ui/primitives/toggle-group.tsx +0 -55
  70. package/components/catalyst-ui/primitives/toggle.tsx +0 -42
  71. package/components/catalyst-ui/primitives/tooltip.tsx +0 -116
  72. package/components/catalyst-ui/utils/basic-auth.tsx +0 -40
  73. package/components/catalyst-ui/utils/context-storage.tsx +0 -19
  74. package/components/catalyst-ui/utils/cors-middleware.tsx +0 -71
  75. package/components/catalyst-ui/utils/deferred-content.tsx +0 -595
  76. package/components/catalyst-ui/utils/honeypot-middleware.tsx +0 -38
  77. package/components/catalyst-ui/utils/incId.tsx +0 -75
  78. package/components/catalyst-ui/utils/jwk-auth.tsx +0 -36
  79. package/components/catalyst-ui/utils/request-id.tsx +0 -14
  80. package/components/catalyst-ui/utils/secure-headers.tsx +0 -37
  81. package/components/catalyst-ui/utils/server-timing.tsx +0 -23
  82. package/components/catalyst-ui/utils/utils.ts +0 -43
  83. package/components/catalyst-ui/utils/with-cookie.tsx +0 -43
  84. package/components/catalyst-ui/x/accordian-x.tsx +0 -428
  85. package/components/catalyst-ui/x/alert-x.tsx +0 -413
  86. package/components/catalyst-ui/x/animated-text-x.tsx +0 -2242
  87. package/components/catalyst-ui/x/avatar-x.tsx +0 -515
  88. package/components/catalyst-ui/x/badge-x.tsx +0 -670
  89. package/components/catalyst-ui/x/button-X.tsx +0 -2857
  90. package/components/catalyst-ui/x/button-group-x.tsx +0 -847
  91. package/components/catalyst-ui/x/calendar-x.tsx +0 -1910
  92. package/components/catalyst-ui/x/card-x.tsx +0 -2597
  93. package/components/catalyst-ui/x/checkbox-x.tsx +0 -656
  94. package/components/catalyst-ui/x/collapsible-x.tsx +0 -1360
  95. package/components/catalyst-ui/x/combobox-x.tsx +0 -911
  96. package/components/catalyst-ui/x/data-table-x.tsx +0 -1753
  97. package/components/catalyst-ui/x/date-picker-x.tsx +0 -648
  98. package/components/catalyst-ui/x/dialog-x.tsx +0 -659
  99. package/components/catalyst-ui/x/dropdown-menu-x.tsx +0 -612
  100. package/components/catalyst-ui/x/hover-card-x.tsx +0 -375
  101. package/components/catalyst-ui/x/icon-x.tsx +0 -840
  102. package/components/catalyst-ui/x/input-mask-x.tsx +0 -981
  103. package/components/catalyst-ui/x/input-otp-x.tsx +0 -659
  104. package/components/catalyst-ui/x/loader-x.tsx +0 -1757
  105. package/components/catalyst-ui/x/pagination-x.tsx +0 -622
  106. package/components/catalyst-ui/x/popover-x.tsx +0 -744
  107. package/components/catalyst-ui/x/radio-group-x.tsx +0 -499
  108. package/components/catalyst-ui/x/select-x.tsx +0 -1127
  109. package/components/catalyst-ui/x/sheet-x.tsx +0 -668
  110. package/components/catalyst-ui/x/switch-x.tsx +0 -681
  111. package/components/catalyst-ui/x/table-x.tsx +0 -574
  112. package/components/catalyst-ui/x/tabs-x.tsx +0 -839
  113. package/components/catalyst-ui/x/textarea-x.tsx +0 -1263
  114. package/components/catalyst-ui/x/tooltip-x.tsx +0 -396
  115. package/components/catalyst-ui/x/tracker-x.tsx +0 -560
  116. package/data/bg-data.tsx +0 -901
  117. package/data/buttons-data.tsx +0 -2327
  118. package/data/charts-data.tsx +0 -102
  119. package/data/chat-data.tsx +0 -83
  120. package/data/code-data.tsx +0 -1040
  121. package/data/comboboxes-data.tsx +0 -1843
  122. package/data/command-data.tsx +0 -1381
  123. package/data/core-data.tsx +0 -15953
  124. package/data/crm-data.tsx +0 -47
  125. package/data/data.tsx +0 -159
  126. package/data/date-and-time-data.tsx +0 -554
  127. package/data/dependencies.tsx +0 -7
  128. package/data/ecommerce-data.tsx +0 -1387
  129. package/data/forms-data.tsx +0 -7890
  130. package/data/hooks-data.tsx +0 -5487
  131. package/data/index.ts +0 -34
  132. package/data/inputs-data.tsx +0 -557
  133. package/data/interactive-data.tsx +0 -5394
  134. package/data/lofi-data.tsx +0 -18295
  135. package/data/marketing-data.tsx +0 -2546
  136. package/data/media-data.tsx +0 -1510
  137. package/data/motion-data.tsx +0 -5801
  138. package/data/overlay-data.tsx +0 -4136
  139. package/data/pdf-data.tsx +0 -124
  140. package/data/pos-data.tsx +0 -213
  141. package/data/postcss.config.js +0 -6
  142. package/data/primitive-data.tsx +0 -5170
  143. package/data/prompt-data.tsx +0 -1226
  144. package/data/requiredLibs.ts +0 -4
  145. package/data/sandbox-data.tsx +0 -1
  146. package/data/sidebars-data.tsx +0 -5421
  147. package/data/stacks-data.tsx +0 -32
  148. package/data/table-data.tsx +0 -706
  149. package/data/tailwind.config.js +0 -270
  150. package/data/tailwind.config.ngin.js +0 -3830
  151. package/data/tailwind.css +0 -431
  152. package/data/tools-data.tsx +0 -6910
  153. package/data/typography-data.tsx +0 -2050
  154. package/data/utils-data.tsx +0 -6500
  155. package/data/x-data.tsx +0 -1171
@@ -1,981 +0,0 @@
1
- 'use client'
2
-
3
- import React, { useId } from 'react'
4
- import { withMask } from 'use-mask-input'
5
- import { cva } from 'class-variance-authority'
6
- import { CreditCard } from 'lucide-react'
7
- import { cn } from '~/components/catalyst-ui'
8
- import { Input, useValidateCreditCard } from '~/components/catalyst-ui'
9
- import { Field, FieldLabel, FieldDescription, FieldError } from '~/components/catalyst-ui'
10
-
11
- /**
12
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ InputMaskX Component ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
13
- * ★ ━━━━ ☆ ━━━━ ━━━━ ☆ ━━━━ ★
14
- * InputMaskX: A collection of input components with various masking patterns for structured data entry
15
- *
16
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Basic Input Mask ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
17
- * ```jsx
18
- * // Default input
19
- * <InputMaskX label="Default Input" placeholder="Enter text" />
20
- *
21
- * // Custom mask pattern
22
- * <InputMaskX
23
- * inputMask="WithMask"
24
- * label="License Plate"
25
- * mask="AA99 AAA"
26
- * placeholder="AB12 CDE"
27
- * />
28
- *
29
- * // Time input with mask
30
- * <InputMaskX
31
- * inputMask="Time"
32
- * label="Time"
33
- * placeholder="HH:MM:SS"
34
- * />
35
- * ```
36
- *
37
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Credit Card Inputs ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
38
- * ```jsx
39
- * // Card number with auto-detection
40
- * <InputMaskX
41
- * inputMask="CardNumber"
42
- * label="Credit Card Number"
43
- * placeholder="1234 5678 9012 3456"
44
- * />
45
- *
46
- * // Expiry date
47
- * <InputMaskX
48
- * inputMask="ExpiryDate"
49
- * label="Expiration Date"
50
- * placeholder="MM/YY"
51
- * />
52
- *
53
- * // CVC code
54
- * <InputMaskX
55
- * inputMask="CVCCode"
56
- * label="CVC"
57
- * placeholder="123"
58
- * />
59
- *
60
- * // Complete card form
61
- * <InputMaskX
62
- * inputMask="CardDetails"
63
- * label="Card Information"
64
- * />
65
- * ```
66
- *
67
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Custom Mask Patterns ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
68
- * ```jsx
69
- * // Phone number
70
- * <InputMaskX
71
- * inputMask="WithMask"
72
- * label="Phone Number"
73
- * mask="(999) 999-9999"
74
- * placeholder="(123) 456-7890"
75
- * />
76
- *
77
- * // Social Security Number
78
- * <InputMaskX
79
- * inputMask="WithMask"
80
- * label="SSN"
81
- * mask="999-99-9999"
82
- * placeholder="123-45-6789"
83
- * />
84
- *
85
- * // Postal/ZIP Code
86
- * <InputMaskX
87
- * inputMask="WithMask"
88
- * label="ZIP Code"
89
- * mask="99999-9999"
90
- * placeholder="12345-6789"
91
- * />
92
- *
93
- * // Date
94
- * <InputMaskX
95
- * inputMask="WithMask"
96
- * label="Date"
97
- * mask="99/99/9999"
98
- * placeholder="MM/DD/YYYY"
99
- * />
100
- * ```
101
- *
102
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Custom Styling Variations ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
103
- * ```jsx
104
- * // Filled variant
105
- * <InputMaskX
106
- * inputMask="CardNumber"
107
- * variant="filled"
108
- * label="Card Number"
109
- * />
110
- *
111
- * // Small size
112
- * <InputMaskX
113
- * inputMask="CVCCode"
114
- * size="sm"
115
- * label="CVC"
116
- * />
117
- *
118
- * // Large size
119
- * <InputMaskX
120
- * inputMask="ExpiryDate"
121
- * size="lg"
122
- * label="Expiry"
123
- * />
124
- *
125
- * // Error state
126
- * <InputMaskX
127
- * inputMask="CardNumber"
128
- * state="error"
129
- * label="Invalid Card"
130
- * error="Please enter a valid card number"
131
- * />
132
- *
133
- * // Success state
134
- * <InputMaskX
135
- * inputMask="CardNumber"
136
- * state="success"
137
- * label="Valid Card"
138
- * />
139
- *
140
- * // Rounded variants
141
- * <InputMaskX
142
- * inputMask="WithMask"
143
- * rounded="lg"
144
- * label="Rounded Input"
145
- * mask="AAA-999"
146
- * />
147
- * ```
148
- *
149
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ With Icons and Visuals ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
150
- * ```jsx
151
- * // Card number with icon
152
- * <InputMaskX
153
- * inputMask="CardNumber"
154
- * label="Card Number"
155
- * // Shows card type icon (Visa, Mastercard, etc.) automatically
156
- * />
157
- *
158
- * // Custom icon placement
159
- * <div className="relative">
160
- * <InputMaskX
161
- * inputMask="WithMask"
162
- * label="Phone"
163
- * mask="(999) 999-9999"
164
- * className="pl-10" // Space for icon
165
- * />
166
- * <Phone className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2" />
167
- * </div>
168
- * ```
169
- *
170
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Complete Payment Form ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
171
- * ```jsx
172
- * function PaymentForm() {
173
- * const [cardNumber, setCardNumber] = useState('')
174
- * const [expiry, setExpiry] = useState('')
175
- * const [cvc, setCVC] = useState('')
176
- *
177
- * return (
178
- * <div className="space-y-4 max-w-md">
179
- * <InputMaskX
180
- * inputMask="CardNumber"
181
- * label="Card Number"
182
- * value={cardNumber}
183
- * onChange={(e) => setCardNumber(e.target.value)}
184
- * />
185
- *
186
- * <div className="grid grid-cols-2 gap-4">
187
- * <InputMaskX
188
- * inputMask="ExpiryDate"
189
- * label="Expiry Date"
190
- * value={expiry}
191
- * onChange={(e) => setExpiry(e.target.value)}
192
- * />
193
- * <InputMaskX
194
- * inputMask="CVCCode"
195
- * label="CVC"
196
- * value={cvc}
197
- * onChange={(e) => setCVC(e.target.value)}
198
- * />
199
- * </div>
200
- *
201
- * <button className="w-full bg-blue-600 text-white py-2 rounded">
202
- * Pay Now
203
- * </button>
204
- * </div>
205
- * )
206
- * }
207
- * ```
208
- *
209
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Available Input Mask Types ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
210
- * 1. **default** - Regular input without mask
211
- * 2. **WithMask** - Custom mask pattern
212
- * 3. **Time** - Time input (HH:MM:SS format)
213
- * 4. **CardNumber** - Credit card number with validation
214
- * 5. **ExpiryDate** - Card expiry date (MM/YY)
215
- * 6. **CVCCode** - Card security code
216
- * 7. **CardDetails** - Combined card form (number + expiry + CVC)
217
- *
218
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Mask Pattern Syntax ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
219
- * ```jsx
220
- * // Common mask patterns
221
- * <InputMaskX
222
- * inputMask="WithMask"
223
- * mask="999-999-9999" // Numbers only
224
- * />
225
- *
226
- * <InputMaskX
227
- * inputMask="WithMask"
228
- * mask="AAA-999" // Letters then numbers
229
- * />
230
- *
231
- * <InputMaskX
232
- * inputMask="WithMask"
233
- * mask="**** **** **** 9999" // Fixed characters with numbers
234
- * />
235
- *
236
- * // Date/time patterns
237
- * <InputMaskX
238
- * inputMask="Time"
239
- * // Automatically uses HH:MM:SS format
240
- * />
241
- *
242
- * // Custom datetime
243
- * <InputMaskX
244
- * inputMask="WithMask"
245
- * mask="datetime"
246
- * // Additional props: inputFormat, outputFormat
247
- * />
248
- * ```
249
- *
250
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Props Reference ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
251
- * - **Common Props**:
252
- * - `inputMask`: string - Type of mask to apply
253
- * - `label`: string - Input field label
254
- * - `description`: string - Helper text
255
- * - `error`: string - Error message
256
- * - `placeholder`: string - Placeholder text
257
- * - `value`: string - Controlled value
258
- * - `onChange`: (e: React.ChangeEvent) => void - Change handler
259
- *
260
- * - **WithMask Specific Props**:
261
- * - `mask`: string - Mask pattern (e.g., "999-999-9999")
262
- * - `showMaskOnHover`: boolean - Show mask on hover
263
- *
264
- * - **Time Specific Props**:
265
- * - `inputFormat`: string - Input format (default: "HH:MM:ss")
266
- * - `outputFormat`: string - Output format (default: "HH:MM:ss")
267
- *
268
- * - **Styling Props** (via inputMaskVariants):
269
- * - `variant`: 'default' | 'filled' | 'ghost'
270
- * - `size`: 'sm' | 'default' | 'lg'
271
- * - `rounded`: 'sm' | 'default' | 'lg' | 'full' | 'none'
272
- * - `state`: 'default' | 'error' | 'success'
273
- * - `className`: string - Additional CSS classes
274
- *
275
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Validation Features ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
276
- * ```jsx
277
- * // Card number validation
278
- * <InputMaskX
279
- * inputMask="CardNumber"
280
- * label="Card Number"
281
- * // Automatically validates: Luhn algorithm, card type detection
282
- * />
283
- *
284
- * // Expiry date validation
285
- * <InputMaskX
286
- * inputMask="ExpiryDate"
287
- * label="Expiry"
288
- * // Validates: Not expired, valid month/year format
289
- * />
290
- *
291
- * // Custom validation
292
- * function CustomValidationExample() {
293
- * const [value, setValue] = useState('')
294
- * const [error, setError] = useState('')
295
- *
296
- * const validate = (input: string) => {
297
- * if (!input.match(/^AB\d{2} CDE$/)) {
298
- * setError('Invalid format')
299
- * } else {
300
- * setError('')
301
- * }
302
- * }
303
- *
304
- * return (
305
- * <InputMaskX
306
- * inputMask="WithMask"
307
- * label="Custom Pattern"
308
- * mask="AB99 CDE"
309
- * value={value}
310
- * onChange={(e) => {
311
- * setValue(e.target.value)
312
- * validate(e.target.value)
313
- * }}
314
- * error={error}
315
- * />
316
- * )
317
- * }
318
- * ```
319
- *
320
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Accessibility Features ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
321
- * - **Auto IDs**: Automatic ID generation for label association
322
- * - **Screen Reader**: All labels and descriptions accessible
323
- * - **Keyboard Navigation**: Full keyboard support
324
- * - **Focus Management**: Clear focus indicators
325
- * - **ARIA Attributes**: Proper role and state attributes
326
- *
327
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Usage Examples ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
328
- * ```jsx
329
- * // Registration form
330
- * function RegistrationForm() {
331
- * return (
332
- * <div className="space-y-4">
333
- * <InputMaskX label="Full Name" placeholder="John Doe" />
334
- * <InputMaskX
335
- * inputMask="WithMask"
336
- * label="Phone"
337
- * mask="(999) 999-9999"
338
- * placeholder="(123) 456-7890"
339
- * />
340
- * <InputMaskX
341
- * inputMask="WithMask"
342
- * label="SSN"
343
- * mask="999-99-9999"
344
- * placeholder="123-45-6789"
345
- * />
346
- * </div>
347
- * )
348
- * }
349
- *
350
- * // Booking system
351
- * function BookingForm() {
352
- * return (
353
- * <div className="space-y-4">
354
- * <InputMaskX
355
- * inputMask="WithMask"
356
- * label="Booking Reference"
357
- * mask="AAA-9999"
358
- * placeholder="ABC-1234"
359
- * />
360
- * <InputMaskX
361
- * inputMask="Time"
362
- * label="Check-in Time"
363
- * placeholder="14:00:00"
364
- * />
365
- * <InputMaskX
366
- * inputMask="CardDetails"
367
- * label="Payment Information"
368
- * />
369
- * </div>
370
- * )
371
- * }
372
- *
373
- * // Settings form
374
- * function SettingsForm() {
375
- * return (
376
- * <div className="space-y-4">
377
- * <InputMaskX
378
- * inputMask="WithMask"
379
- * label="API Key"
380
- * mask="****-****-****-****"
381
- * placeholder="••••-••••-••••-••••"
382
- * />
383
- * <InputMaskX
384
- * inputMask="Time"
385
- * label="Schedule Time"
386
- * placeholder="09:00:00"
387
- * />
388
- * <InputMaskX
389
- * variant="filled"
390
- * size="sm"
391
- * label="Short Code"
392
- * placeholder="ABC123"
393
- * />
394
- * </div>
395
- * )
396
- * }
397
- * ```
398
- *
399
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Integration with Form Libraries ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
400
- * ```jsx
401
- * // With React Hook Form
402
- * import { useForm } from 'react-hook-form'
403
- *
404
- * function HookFormExample() {
405
- * const { register, handleSubmit } = useForm()
406
- *
407
- * return (
408
- * <form onSubmit={handleSubmit(data => console.log(data))}>
409
- * <InputMaskX
410
- * inputMask="CardNumber"
411
- * label="Card Number"
412
- * {...register('cardNumber', { required: true })}
413
- * />
414
- * <InputMaskX
415
- * inputMask="ExpiryDate"
416
- * label="Expiry"
417
- * {...register('expiry', { required: true })}
418
- * />
419
- * <button type="submit">Submit</button>
420
- * </form>
421
- * )
422
- * }
423
- *
424
- * // With Formik
425
- * import { useField } from 'formik'
426
- *
427
- * function FormikField({ label, ...props }) {
428
- * const [field, meta] = useField(props)
429
- *
430
- * return (
431
- * <InputMaskX
432
- * label={label}
433
- * {...field}
434
- * error={meta.touched && meta.error ? meta.error : ''}
435
- * {...props}
436
- * />
437
- * )
438
- * }
439
- * ```
440
- *
441
- */
442
-
443
- // #region CVA VARIANTS
444
- export const inputMaskVariants = cva(
445
- 'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
446
- {
447
- variants: {
448
- variant: {
449
- default: '',
450
- filled: 'bg-muted border-transparent shadow-none',
451
- ghost: 'border-transparent shadow-none',
452
- },
453
- size: {
454
- sm: 'h-8 text-xs',
455
- default: 'h-10',
456
- lg: 'h-12 text-base',
457
- },
458
- rounded: {
459
- default: 'rounded-md',
460
- sm: 'rounded-sm',
461
- lg: 'rounded-lg',
462
- full: 'rounded-full',
463
- none: 'rounded-none',
464
- },
465
- state: {
466
- default: '',
467
- error: 'border-destructive focus-visible:ring-destructive',
468
- success: 'border-green-500 focus-visible:ring-green-500',
469
- },
470
- },
471
- defaultVariants: {
472
- variant: 'default',
473
- size: 'default',
474
- rounded: 'default',
475
- state: 'default',
476
- },
477
- }
478
- )
479
- // #endregion
480
-
481
- // #region PARENT FUNCTION
482
- export function InputMaskX({ inputMask = 'default', ...props }: any) {
483
- switch (inputMask) {
484
- case 'WithMask':
485
- return <WithMask {...props} />
486
- case 'Time':
487
- return <Time {...props} />
488
- case 'CardNumber':
489
- return <CardNumber {...props} />
490
- case 'ExpiryDate':
491
- return <ExpiryDate {...props} />
492
- case 'CVCCode':
493
- return <CVCCode {...props} />
494
- case 'CardDetails':
495
- return <CardDetails {...props} />
496
- default:
497
- return <DefaultInputMask {...props} />
498
- }
499
- }
500
- // #endregion
501
-
502
- // #region SUPPORTING FUNCTIONS
503
- const DefaultInputMask = ({ label, description, error, variant, size, rounded, state, className, ...props }: any) => {
504
- const id = useId()
505
- return (
506
- <Field className='w-full max-w-xs space-y-2'>
507
- {label && <FieldLabel htmlFor={id}>{label}</FieldLabel>}
508
- <Input
509
- id={id}
510
- className={cn(inputMaskVariants({ variant, size, rounded, state }), className)}
511
- {...props}
512
- />
513
- {description && <FieldDescription>{description}</FieldDescription>}
514
- {error && <FieldError>{error}</FieldError>}
515
- </Field>
516
- )
517
- }
518
-
519
- const WithMask = ({ label = 'Input with mask', description, error, variant, size, rounded, state, className, mask = 'AA99 AAA', placeholder = 'AB12 CDE', ...props }: any) => {
520
- const id = useId()
521
- return (
522
- <Field className='w-full max-w-xs space-y-2'>
523
- <FieldLabel htmlFor={id}>{label}</FieldLabel>
524
- <Input
525
- id={id}
526
- type='text'
527
- placeholder={placeholder}
528
- ref={withMask(mask, {
529
- placeholder: '_',
530
- showMaskOnHover: false
531
- })}
532
- className={cn(inputMaskVariants({ variant, size, rounded, state }), className)}
533
- {...props}
534
- />
535
- {description && <FieldDescription>{description}</FieldDescription>}
536
- {error && <FieldError>{error}</FieldError>}
537
- <p className='text-muted-foreground text-xs'>
538
- Built with{' '}
539
- <a
540
- className='hover:text-foreground underline'
541
- href='https://github.com/eduardoborges/use-mask-input'
542
- target='_blank'
543
- rel='noopener noreferrer'
544
- >
545
- use-mask-input
546
- </a>
547
- </p>
548
- </Field>
549
- )
550
- }
551
-
552
- const Time = ({ label = 'Input time', description, error, variant, size, rounded, state, className, placeholder = '00:00:00', ...props }: any) => {
553
- const id = useId()
554
- return (
555
- <Field className='w-full max-w-xs space-y-2'>
556
- <FieldLabel htmlFor={id}>{label}</FieldLabel>
557
- <Input
558
- id={id}
559
- type='text'
560
- placeholder={placeholder}
561
- ref={withMask('datetime', {
562
- placeholder: '_',
563
- inputFormat: 'HH:MM:ss',
564
- outputFormat: 'HH:MM:ss',
565
- showMaskOnHover: false
566
- })}
567
- className={cn(inputMaskVariants({ variant, size, rounded, state }), className)}
568
- {...props}
569
- />
570
- {description && <FieldDescription>{description}</FieldDescription>}
571
- {error && <FieldError>{error}</FieldError>}
572
- <p className='text-muted-foreground text-xs'>
573
- Built with{' '}
574
- <a
575
- className='hover:text-foreground underline'
576
- href='https://github.com/eduardoborges/use-mask-input'
577
- target='_blank'
578
- rel='noopener noreferrer'
579
- >
580
- use-mask-input
581
- </a>
582
- </p>
583
- </Field>
584
- )
585
- }
586
-
587
- const CardNumber = ({ label = 'Card number', description, error, variant, size, rounded, state, className, ...props }: any) => {
588
- const id = useId()
589
- const { getCardNumberProps, getCardIcon } = useValidateCreditCard()
590
- const CardIcon = getCardIcon()
591
-
592
- return (
593
- <Field className='w-full max-w-xs space-y-2'>
594
- <FieldLabel htmlFor={id}>{label}</FieldLabel>
595
- <div className='relative'>
596
- <Input
597
- {...getCardNumberProps()}
598
- id={id}
599
- className={cn(inputMaskVariants({ variant, size, rounded, state }), 'peer pr-11', className)}
600
- {...props}
601
- />
602
- <div className='text-muted-foreground pointer-events-none absolute inset-y-0 right-0 flex items-center justify-center pr-3 peer-disabled:opacity-50'>
603
- <CardIcon className='size-6' />
604
- <span className='sr-only'>Card Provider</span>
605
- </div>
606
- </div>
607
- {description && <FieldDescription>{description}</FieldDescription>}
608
- {error && <FieldError>{error}</FieldError>}
609
- <p className='text-muted-foreground text-xs'>
610
- Built with custom validation
611
- </p>
612
- </Field>
613
- )
614
- }
615
-
616
- const ExpiryDate = ({ label = 'Expiry date', description, error, variant, size, rounded, state, className, placeholder = 'MM/YY', ...props }: any) => {
617
- const id = useId()
618
- return (
619
- <Field className='w-full max-w-xs space-y-2'>
620
- <FieldLabel htmlFor={id}>{label}</FieldLabel>
621
- <Input
622
- id={id}
623
- type='text'
624
- placeholder={placeholder}
625
- ref={withMask('99/99', {
626
- placeholder: '_',
627
- showMaskOnHover: false
628
- })}
629
- className={cn(inputMaskVariants({ variant, size, rounded, state }), className)}
630
- {...props}
631
- />
632
- {description && <FieldDescription>{description}</FieldDescription>}
633
- {error && <FieldError>{error}</FieldError>}
634
- </Field>
635
- )
636
- }
637
-
638
- const CVCCode = ({ label = 'CVC code', description, error, variant, size, rounded, state, className, placeholder = '123', ...props }: any) => {
639
- const id = useId()
640
- return (
641
- <Field className='w-full max-w-xs space-y-2'>
642
- <FieldLabel htmlFor={id}>{label}</FieldLabel>
643
- <Input
644
- id={id}
645
- type='text'
646
- placeholder={placeholder}
647
- ref={withMask('999', {
648
- placeholder: '_',
649
- showMaskOnHover: false
650
- })}
651
- className={cn(inputMaskVariants({ variant, size, rounded, state }), className)}
652
- {...props}
653
- />
654
- {description && <FieldDescription>{description}</FieldDescription>}
655
- {error && <FieldError>{error}</FieldError>}
656
- </Field>
657
- )
658
- }
659
-
660
- const CardDetails = ({ label = 'Card details', description, error, variant, size, rounded, state, className, ...props }: any) => {
661
- const id = useId()
662
- const { getCardNumberProps, getCardIcon } = useValidateCreditCard()
663
- const CardIcon = getCardIcon()
664
-
665
- return (
666
- <Field className='w-full max-w-xs space-y-2'>
667
- <FieldLabel>{label}</FieldLabel>
668
- <div>
669
- <div className='relative focus-within:z-1'>
670
- <Input
671
- {...getCardNumberProps()}
672
- id={`number-${id}`}
673
- className={cn(inputMaskVariants({ variant, size, rounded, state }), 'peer rounded-b-none pr-9 shadow-none', className)}
674
- {...props}
675
- />
676
- <div className='text-muted-foreground pointer-events-none absolute inset-y-0 right-0 flex items-center justify-center pr-3 peer-disabled:opacity-50'>
677
- <CardIcon className='size-6' />
678
- <span className='sr-only'>Card Provider</span>
679
- </div>
680
- </div>
681
- <div className='-mt-px flex'>
682
- <div className='min-w-0 flex-1 focus-within:z-1'>
683
- <Input
684
- type='text'
685
- placeholder='MM/YY'
686
- ref={withMask('99/99', {
687
- placeholder: '_',
688
- showMaskOnHover: false
689
- })}
690
- id={`expiry-${id}`}
691
- className={cn(inputMaskVariants({ variant, size, rounded, state }), 'rounded-t-none rounded-r-none shadow-none')}
692
- />
693
- </div>
694
- <div className='-ms-px min-w-0 flex-1 focus-within:z-1'>
695
- <Input
696
- type='text'
697
- placeholder='123'
698
- ref={withMask('999', {
699
- placeholder: '_',
700
- showMaskOnHover: false
701
- })}
702
- id={`cvc-${id}`}
703
- className={cn(inputMaskVariants({ variant, size, rounded, state }), 'rounded-t-none rounded-l-none shadow-none')}
704
- />
705
- </div>
706
- </div>
707
- </div>
708
- {description && <FieldDescription>{description}</FieldDescription>}
709
- {error && <FieldError>{error}</FieldError>}
710
- <p className='text-muted-foreground text-xs'>
711
- Built with custom validation
712
- </p>
713
- </Field>
714
- )
715
- }
716
- // #endregion
717
-
718
- // #region DEMO
719
- export function InputMaskXDemo() {
720
- return (
721
- <div className='space-y-12 p-6 max-w-3xl mx-auto'>
722
- <div>
723
- <h3 className='text-lg font-semibold mb-4'>Default</h3>
724
- <InputMaskX label='Default Input' placeholder='Enter text' />
725
- </div>
726
-
727
- <div>
728
- <h3 className='text-lg font-semibold mb-4'>With Mask</h3>
729
- <InputMaskX inputMask='WithMask' />
730
- </div>
731
-
732
- <div>
733
- <h3 className='text-lg font-semibold mb-4'>Time Input</h3>
734
- <InputMaskX inputMask='Time' />
735
- </div>
736
-
737
- <div>
738
- <h3 className='text-lg font-semibold mb-4'>Card Number</h3>
739
- <InputMaskX inputMask='CardNumber' />
740
- </div>
741
-
742
- <div>
743
- <h3 className='text-lg font-semibold mb-4'>Expiry Date</h3>
744
- <InputMaskX inputMask='ExpiryDate' />
745
- </div>
746
-
747
- <div>
748
- <h3 className='text-lg font-semibold mb-4'>CVC Code</h3>
749
- <InputMaskX inputMask='CVCCode' />
750
- </div>
751
-
752
- <div>
753
- <h3 className='text-lg font-semibold mb-4'>Card Details (Combined)</h3>
754
- <InputMaskX inputMask='CardDetails' />
755
- </div>
756
- </div>
757
- )
758
- }
759
- // #endregion
760
-
761
-
762
- /**
763
-
764
-
765
-
766
-
767
-
768
-
769
- export function InputMaskX({ inputMask = 'default', children, ...props }: any) {
770
- switch (inputMask) {
771
- case 'Closable':
772
- break
773
- default:
774
- break;
775
- }
776
- }
777
-
778
- const InputWithMaskDemo = () => {
779
- const id = useId()
780
-
781
- return (
782
- <div className='w-full max-w-xs space-y-2'>
783
- <Label htmlFor={id}>Input with mask</Label>
784
- <Input
785
- id={id}
786
- type='text'
787
- placeholder='AB12 CDE'
788
- ref={withMask('AA99 AAA', {
789
- placeholder: '_',
790
- showMaskOnHover: false
791
- })}
792
- />
793
- <p className='text-muted-foreground text-xs'>
794
- Built with{' '}
795
- <a
796
- className='hover:text-foreground underline'
797
- href='https://github.com/eduardoborges/use-mask-input'
798
- target='_blank'
799
- rel='noopener noreferrer'
800
- >
801
- use-mask-input
802
- </a>
803
- </p>
804
- </div>
805
- )
806
- }
807
-
808
- const InputTimeDemo = () => {
809
- const id = useId()
810
-
811
- return (
812
- <div className='w-full max-w-xs space-y-2'>
813
- <Label htmlFor={id}>Input time</Label>
814
- <Input
815
- id={id}
816
- type='text'
817
- placeholder='00:00:00'
818
- ref={withMask('datetime', {
819
- placeholder: '_',
820
- inputFormat: 'HH:MM:ss',
821
- outputFormat: 'HH:MM:ss',
822
- showMaskOnHover: false
823
- })}
824
- />
825
- <p className='text-muted-foreground text-xs'>
826
- Built with{' '}
827
- <a
828
- className='hover:text-foreground underline'
829
- href='https://github.com/eduardoborges/use-mask-input'
830
- target='_blank'
831
- rel='noopener noreferrer'
832
- >
833
- use-mask-input
834
- </a>
835
- </p>
836
- </div>
837
- )
838
- }
839
-
840
- const InputCardNumberDemo = () => {
841
- const id = useId()
842
- const { meta, getCardNumberProps, getCardImageProps } = usePaymentInputs()
843
-
844
- return (
845
- <div className='w-full max-w-xs space-y-2'>
846
- <Label htmlFor={id}>Card number</Label>
847
- <div className='relative'>
848
- <Input {...getCardNumberProps()} id={id} className='peer pr-11' />
849
- <div className='text-muted-foreground pointer-events-none absolute inset-y-0 right-0 flex items-center justify-center pr-3 peer-disabled:opacity-50'>
850
- {meta.cardType ? (
851
- <svg
852
- className='w-6 overflow-hidden'
853
- {...getCardImageProps({
854
- images: images as unknown as CardImages
855
- })}
856
- />
857
- ) : (
858
- <CreditCardIcon className='size-4' />
859
- )}
860
- <span className='sr-only'>Card Provider</span>
861
- </div>
862
- </div>
863
- <p className='text-muted-foreground text-xs'>
864
- Built with{' '}
865
- <a
866
- className='hover:text-foreground underline'
867
- href='https://github.com/medipass/react-payment-inputs'
868
- target='_blank'
869
- rel='noopener noreferrer'
870
- >
871
- React Payment Inputs
872
- </a>
873
- </p>
874
- </div>
875
- )
876
- }
877
-
878
- const InputExpiryDateDemo = () => {
879
- const id = useId()
880
- const { getExpiryDateProps } = usePaymentInputs()
881
-
882
- return (
883
- <div className='w-full max-w-xs space-y-2'>
884
- <Label htmlFor={id}>Expiry date</Label>
885
- <Input {...getExpiryDateProps()} id={id} />
886
- <p className='text-muted-foreground text-xs'>
887
- Built with{' '}
888
- <a
889
- className='hover:text-foreground underline'
890
- href='https://github.com/medipass/react-payment-inputs'
891
- target='_blank'
892
- rel='noopener noreferrer'
893
- >
894
- React Payment Inputs
895
- </a>
896
- </p>
897
- </div>
898
- )
899
- }
900
-
901
- const InputCVCCodeDemo = () => {
902
- const id = useId()
903
- const { getCVCProps } = usePaymentInputs()
904
-
905
- return (
906
- <div className='w-full max-w-xs space-y-2'>
907
- <Label htmlFor={id}>CVC code</Label>
908
- <Input {...getCVCProps()} id={id} />
909
- <p className='text-muted-foreground text-xs'>
910
- Built with{' '}
911
- <a
912
- className='hover:text-foreground underline'
913
- href='https://github.com/medipass/react-payment-inputs'
914
- target='_blank'
915
- rel='noopener noreferrer'
916
- >
917
- React Payment Inputs
918
- </a>
919
- </p>
920
- </div>
921
- )
922
- }
923
-
924
- const InputCardDetailsDemo = () => {
925
- const id = useId()
926
- const { meta, getCardNumberProps, getExpiryDateProps, getCVCProps, getCardImageProps } = usePaymentInputs()
927
-
928
- return (
929
- <div className='w-full max-w-xs space-y-2'>
930
- <Label>Card details</Label>
931
- <div>
932
- <div className='relative focus-within:z-1'>
933
- <Input {...getCardNumberProps()} id={`number-${id}`} className='peer rounded-b-none pr-9 shadow-none' />
934
- <div className='text-muted-foreground pointer-events-none absolute inset-y-0 right-0 flex items-center justify-center pr-3 peer-disabled:opacity-50'>
935
- {meta.cardType ? (
936
- <svg
937
- className='w-6 overflow-hidden'
938
- {...getCardImageProps({
939
- images: images as unknown as CardImages
940
- })}
941
- />
942
- ) : (
943
- <CreditCardIcon className='size-4' />
944
- )}
945
- <span className='sr-only'>Card Provider</span>
946
- </div>
947
- </div>
948
- <div className='-mt-px flex'>
949
- <div className='min-w-0 flex-1 focus-within:z-1'>
950
- <Input
951
- {...getExpiryDateProps()}
952
- id={`expiry-${id}`}
953
- className='rounded-t-none rounded-r-none shadow-none'
954
- />
955
- </div>
956
- <div className='-ms-px min-w-0 flex-1 focus-within:z-1'>
957
- <Input {...getCVCProps()} id={`cvc-${id}`} className='rounded-t-none rounded-l-none shadow-none' />
958
- </div>
959
- </div>
960
- </div>
961
- <p className='text-muted-foreground text-xs'>
962
- Built with{' '}
963
- <a
964
- className='hover:text-foreground underline'
965
- href='https://github.com/medipass/react-payment-inputs'
966
- target='_blank'
967
- rel='noopener noreferrer'
968
- >
969
- React Payment Inputs
970
- </a>
971
- </p>
972
- </div>
973
- )
974
- } */
975
-
976
-
977
-
978
-
979
-
980
-
981
-