@rovula/ui 0.0.77 → 0.0.78
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/dist/cjs/bundle.css +28 -0
- package/dist/cjs/bundle.js +3 -3
- package/dist/cjs/bundle.js.map +1 -1
- package/dist/cjs/types/components/MaskedTextInput/MaskedTextInput.d.ts +75 -0
- package/dist/cjs/types/components/MaskedTextInput/MaskedTextInput.stories.d.ts +491 -0
- package/dist/cjs/types/components/MaskedTextInput/index.d.ts +3 -0
- package/dist/cjs/types/index.d.ts +2 -0
- package/dist/components/MaskedTextInput/MaskedTextInput.js +267 -0
- package/dist/components/MaskedTextInput/MaskedTextInput.stories.js +167 -0
- package/dist/components/MaskedTextInput/index.js +2 -0
- package/dist/components/Toast/Toast.styles.js +1 -1
- package/dist/esm/bundle.css +28 -0
- package/dist/esm/bundle.js +3 -3
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/types/components/MaskedTextInput/MaskedTextInput.d.ts +75 -0
- package/dist/esm/types/components/MaskedTextInput/MaskedTextInput.stories.d.ts +491 -0
- package/dist/esm/types/components/MaskedTextInput/index.d.ts +3 -0
- package/dist/esm/types/index.d.ts +2 -0
- package/dist/index.d.ts +59 -1
- package/dist/index.js +1 -0
- package/dist/src/theme/global.css +35 -0
- package/package.json +1 -1
- package/src/components/MaskedTextInput/MaskedTextInput.stories.tsx +414 -0
- package/src/components/MaskedTextInput/MaskedTextInput.tsx +391 -0
- package/src/components/MaskedTextInput/README.md +202 -0
- package/src/components/MaskedTextInput/index.ts +3 -0
- package/src/components/Toast/Toast.styles.tsx +1 -1
- package/src/index.ts +5 -0
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import "./theme/global.css";
|
|
|
4
4
|
import "./icons/iconConfig";
|
|
5
5
|
export { default as Button } from "./components/Button/Button";
|
|
6
6
|
export { default as TextInput } from "./components/TextInput/TextInput";
|
|
7
|
+
export { default as MaskedTextInput } from "./components/MaskedTextInput";
|
|
7
8
|
export { NumberInput } from "./components/NumberInput/NumberInput";
|
|
8
9
|
export { default as TextArea } from "./components/TextArea/TextArea";
|
|
9
10
|
export { default as Text } from "./components/Text/Text";
|
|
@@ -2348,6 +2348,10 @@ input[type=number] {
|
|
|
2348
2348
|
z-index: 50;
|
|
2349
2349
|
}
|
|
2350
2350
|
|
|
2351
|
+
.z-\[1000\] {
|
|
2352
|
+
z-index: 1000;
|
|
2353
|
+
}
|
|
2354
|
+
|
|
2351
2355
|
.z-\[100\] {
|
|
2352
2356
|
z-index: 100;
|
|
2353
2357
|
}
|
|
@@ -2778,6 +2782,10 @@ input[type=number] {
|
|
|
2778
2782
|
min-width: fit-content;
|
|
2779
2783
|
}
|
|
2780
2784
|
|
|
2785
|
+
.max-w-2xl {
|
|
2786
|
+
max-width: 42rem;
|
|
2787
|
+
}
|
|
2788
|
+
|
|
2781
2789
|
.max-w-\[300px\] {
|
|
2782
2790
|
max-width: 300px;
|
|
2783
2791
|
}
|
|
@@ -2790,6 +2798,10 @@ input[type=number] {
|
|
|
2790
2798
|
max-width: 32rem;
|
|
2791
2799
|
}
|
|
2792
2800
|
|
|
2801
|
+
.max-w-md {
|
|
2802
|
+
max-width: 28rem;
|
|
2803
|
+
}
|
|
2804
|
+
|
|
2793
2805
|
.flex-1 {
|
|
2794
2806
|
flex: 1 1 0%;
|
|
2795
2807
|
}
|
|
@@ -3891,6 +3903,11 @@ input[type=number] {
|
|
|
3891
3903
|
background-color: color-mix(in srgb, var(--function-default-stroke) calc(100% * var(--tw-bg-opacity, 1)), transparent);
|
|
3892
3904
|
}
|
|
3893
3905
|
|
|
3906
|
+
.bg-gray-100 {
|
|
3907
|
+
--tw-bg-opacity: 1;
|
|
3908
|
+
background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
|
|
3909
|
+
}
|
|
3910
|
+
|
|
3894
3911
|
.bg-gray-200 {
|
|
3895
3912
|
--tw-bg-opacity: 1;
|
|
3896
3913
|
background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));
|
|
@@ -5527,6 +5544,11 @@ input[type=number] {
|
|
|
5527
5544
|
font-weight: var(--label-label2-weight, 400);
|
|
5528
5545
|
}
|
|
5529
5546
|
|
|
5547
|
+
.text-lg {
|
|
5548
|
+
font-size: 1.125rem;
|
|
5549
|
+
line-height: 1.75rem;
|
|
5550
|
+
}
|
|
5551
|
+
|
|
5530
5552
|
.text-sm {
|
|
5531
5553
|
font-size: 0.875rem;
|
|
5532
5554
|
line-height: 1.25rem;
|
|
@@ -5640,6 +5662,10 @@ input[type=number] {
|
|
|
5640
5662
|
font-weight: 500;
|
|
5641
5663
|
}
|
|
5642
5664
|
|
|
5665
|
+
.font-semibold {
|
|
5666
|
+
font-weight: 600;
|
|
5667
|
+
}
|
|
5668
|
+
|
|
5643
5669
|
.uppercase {
|
|
5644
5670
|
text-transform: uppercase;
|
|
5645
5671
|
}
|
|
@@ -5893,6 +5919,11 @@ input[type=number] {
|
|
|
5893
5919
|
color: rgb(107 114 128 / var(--tw-text-opacity, 1));
|
|
5894
5920
|
}
|
|
5895
5921
|
|
|
5922
|
+
.text-gray-700 {
|
|
5923
|
+
--tw-text-opacity: 1;
|
|
5924
|
+
color: rgb(55 65 81 / var(--tw-text-opacity, 1));
|
|
5925
|
+
}
|
|
5926
|
+
|
|
5896
5927
|
.text-green-500 {
|
|
5897
5928
|
--tw-text-opacity: 1;
|
|
5898
5929
|
color: rgb(34 197 94 / var(--tw-text-opacity, 1));
|
|
@@ -8870,6 +8901,10 @@ input[type=number] {
|
|
|
8870
8901
|
.md\:right-\[40px\] {
|
|
8871
8902
|
right: 40px;
|
|
8872
8903
|
}
|
|
8904
|
+
|
|
8905
|
+
.md\:grid-cols-2 {
|
|
8906
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
8907
|
+
}
|
|
8873
8908
|
}
|
|
8874
8909
|
|
|
8875
8910
|
.\[\&\:has\(\[role\=checkbox\]\)\]\:w-4:has([role=checkbox]) {
|
package/package.json
CHANGED
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import MaskedTextInput, { MASK_PATTERNS } from "./MaskedTextInput";
|
|
4
|
+
|
|
5
|
+
// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
|
|
6
|
+
const meta = {
|
|
7
|
+
title: "Components/MaskedTextInput",
|
|
8
|
+
component: MaskedTextInput,
|
|
9
|
+
tags: ["autodocs"],
|
|
10
|
+
parameters: {
|
|
11
|
+
// More on how to position stories at: https://storybook.js.org/docs/7.0/react/configure/story-layout
|
|
12
|
+
layout: "fullscreen",
|
|
13
|
+
},
|
|
14
|
+
decorators: [
|
|
15
|
+
(Story) => (
|
|
16
|
+
<div className="p-5 flex w-full bg-[rgb(var(--base-bg-2))] ">
|
|
17
|
+
<Story />
|
|
18
|
+
</div>
|
|
19
|
+
),
|
|
20
|
+
],
|
|
21
|
+
} satisfies Meta<typeof MaskedTextInput>;
|
|
22
|
+
|
|
23
|
+
export default meta;
|
|
24
|
+
|
|
25
|
+
export const Default = {
|
|
26
|
+
args: {
|
|
27
|
+
label: "Phone Number",
|
|
28
|
+
mask: MASK_PATTERNS.PHONE,
|
|
29
|
+
fullwidth: true,
|
|
30
|
+
},
|
|
31
|
+
render: (args) => {
|
|
32
|
+
return (
|
|
33
|
+
<div className="flex flex-row gap-4 w-full">
|
|
34
|
+
<MaskedTextInput id="1" size="lg" {...args} />
|
|
35
|
+
<MaskedTextInput id="2" size="md" {...args} />
|
|
36
|
+
<MaskedTextInput id="3" size="sm" {...args} />
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
},
|
|
40
|
+
} satisfies StoryObj;
|
|
41
|
+
|
|
42
|
+
export const PhoneNumber = {
|
|
43
|
+
args: {
|
|
44
|
+
label: "Phone Number",
|
|
45
|
+
mask: MASK_PATTERNS.PHONE,
|
|
46
|
+
fullwidth: true,
|
|
47
|
+
},
|
|
48
|
+
render: (args) => {
|
|
49
|
+
return (
|
|
50
|
+
<div className="flex flex-col gap-4 w-full max-w-md">
|
|
51
|
+
<MaskedTextInput {...args} />
|
|
52
|
+
<MaskedTextInput
|
|
53
|
+
{...args}
|
|
54
|
+
label="International Phone"
|
|
55
|
+
mask={MASK_PATTERNS.PHONE_INTL}
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
},
|
|
60
|
+
} satisfies StoryObj;
|
|
61
|
+
|
|
62
|
+
export const CreditCard = {
|
|
63
|
+
args: {
|
|
64
|
+
label: "Credit Card Number",
|
|
65
|
+
mask: MASK_PATTERNS.CREDIT_CARD,
|
|
66
|
+
fullwidth: true,
|
|
67
|
+
},
|
|
68
|
+
render: (args) => {
|
|
69
|
+
return (
|
|
70
|
+
<div className="flex flex-col gap-4 w-full max-w-md">
|
|
71
|
+
<MaskedTextInput {...args} />
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
},
|
|
75
|
+
} satisfies StoryObj;
|
|
76
|
+
|
|
77
|
+
export const DateAndTime = {
|
|
78
|
+
args: {
|
|
79
|
+
label: "Date",
|
|
80
|
+
mask: MASK_PATTERNS.DATE,
|
|
81
|
+
fullwidth: true,
|
|
82
|
+
},
|
|
83
|
+
render: (args) => {
|
|
84
|
+
return (
|
|
85
|
+
<div className="flex flex-col gap-4 w-full max-w-md">
|
|
86
|
+
<MaskedTextInput {...args} />
|
|
87
|
+
<MaskedTextInput {...args} label="Time" mask={MASK_PATTERNS.TIME} />
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
},
|
|
91
|
+
} satisfies StoryObj;
|
|
92
|
+
|
|
93
|
+
export const SocialSecurityNumber = {
|
|
94
|
+
args: {
|
|
95
|
+
label: "Social Security Number",
|
|
96
|
+
mask: MASK_PATTERNS.SSN,
|
|
97
|
+
fullwidth: true,
|
|
98
|
+
},
|
|
99
|
+
render: (args) => {
|
|
100
|
+
return (
|
|
101
|
+
<div className="flex flex-col gap-4 w-full max-w-md">
|
|
102
|
+
<MaskedTextInput {...args} />
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
},
|
|
106
|
+
} satisfies StoryObj;
|
|
107
|
+
|
|
108
|
+
export const ZipCode = {
|
|
109
|
+
args: {
|
|
110
|
+
label: "ZIP Code",
|
|
111
|
+
mask: MASK_PATTERNS.ZIP_CODE,
|
|
112
|
+
fullwidth: true,
|
|
113
|
+
},
|
|
114
|
+
render: (args) => {
|
|
115
|
+
return (
|
|
116
|
+
<div className="flex flex-col gap-4 w-full max-w-md">
|
|
117
|
+
<MaskedTextInput {...args} />
|
|
118
|
+
<MaskedTextInput
|
|
119
|
+
{...args}
|
|
120
|
+
label="ZIP Code + 4"
|
|
121
|
+
mask={MASK_PATTERNS.ZIP_CODE_EXT}
|
|
122
|
+
/>
|
|
123
|
+
</div>
|
|
124
|
+
);
|
|
125
|
+
},
|
|
126
|
+
} satisfies StoryObj;
|
|
127
|
+
|
|
128
|
+
export const Currency = {
|
|
129
|
+
args: {
|
|
130
|
+
label: "Amount",
|
|
131
|
+
mask: MASK_PATTERNS.CURRENCY,
|
|
132
|
+
fullwidth: true,
|
|
133
|
+
},
|
|
134
|
+
render: (args) => {
|
|
135
|
+
return (
|
|
136
|
+
<div className="flex flex-col gap-4 w-full max-w-md">
|
|
137
|
+
<MaskedTextInput {...args} />
|
|
138
|
+
</div>
|
|
139
|
+
);
|
|
140
|
+
},
|
|
141
|
+
} satisfies StoryObj;
|
|
142
|
+
|
|
143
|
+
export const CustomMask = {
|
|
144
|
+
args: {
|
|
145
|
+
label: "Custom Pattern",
|
|
146
|
+
mask: "AAA-999-AAA",
|
|
147
|
+
fullwidth: true,
|
|
148
|
+
},
|
|
149
|
+
render: (args) => {
|
|
150
|
+
return (
|
|
151
|
+
<div className="flex flex-col gap-4 w-full max-w-md">
|
|
152
|
+
<MaskedTextInput {...args} />
|
|
153
|
+
<MaskedTextInput {...args} label="License Plate" mask="999-AAA" />
|
|
154
|
+
<MaskedTextInput {...args} label="Product Code" mask="AA-9999-AA" />
|
|
155
|
+
<MaskedTextInput {...args} label="Time" mask="00:00:00" />
|
|
156
|
+
</div>
|
|
157
|
+
);
|
|
158
|
+
},
|
|
159
|
+
} satisfies StoryObj;
|
|
160
|
+
|
|
161
|
+
export const MaskOptions = {
|
|
162
|
+
args: {
|
|
163
|
+
label: "Phone with Options",
|
|
164
|
+
mask: MASK_PATTERNS.PHONE,
|
|
165
|
+
fullwidth: true,
|
|
166
|
+
},
|
|
167
|
+
render: (args) => {
|
|
168
|
+
return (
|
|
169
|
+
<div className="flex flex-col gap-4 w-full max-w-md">
|
|
170
|
+
<MaskedTextInput
|
|
171
|
+
{...args}
|
|
172
|
+
label="With Guide"
|
|
173
|
+
guide={true}
|
|
174
|
+
showMask={true}
|
|
175
|
+
/>
|
|
176
|
+
<MaskedTextInput
|
|
177
|
+
{...args}
|
|
178
|
+
label="Without Guide"
|
|
179
|
+
guide={false}
|
|
180
|
+
showMask={true}
|
|
181
|
+
/>
|
|
182
|
+
<MaskedTextInput
|
|
183
|
+
{...args}
|
|
184
|
+
label="Custom Mask Char"
|
|
185
|
+
maskChar="*"
|
|
186
|
+
guide={true}
|
|
187
|
+
showMask={true}
|
|
188
|
+
/>
|
|
189
|
+
</div>
|
|
190
|
+
);
|
|
191
|
+
},
|
|
192
|
+
} satisfies StoryObj;
|
|
193
|
+
|
|
194
|
+
export const WithCallbacks = {
|
|
195
|
+
args: {
|
|
196
|
+
label: "Phone with Callbacks",
|
|
197
|
+
mask: MASK_PATTERNS.PHONE,
|
|
198
|
+
fullwidth: true,
|
|
199
|
+
},
|
|
200
|
+
render: (args) => {
|
|
201
|
+
const [maskedValue, setMaskedValue] = useState("");
|
|
202
|
+
const [rawValue, setRawValue] = useState("");
|
|
203
|
+
|
|
204
|
+
return (
|
|
205
|
+
<div className="flex flex-col gap-4 w-full max-w-md">
|
|
206
|
+
<MaskedTextInput
|
|
207
|
+
{...args}
|
|
208
|
+
onChange={(e) => {
|
|
209
|
+
setMaskedValue(e.target.value);
|
|
210
|
+
setRawValue(e.target.value);
|
|
211
|
+
}}
|
|
212
|
+
onMaskedChange={(masked: string, raw: string) => {
|
|
213
|
+
setMaskedValue(masked);
|
|
214
|
+
setRawValue(raw);
|
|
215
|
+
}}
|
|
216
|
+
/>
|
|
217
|
+
<div className="p-4 bg-gray-100 rounded">
|
|
218
|
+
<p>
|
|
219
|
+
<strong>Masked Value:</strong> {maskedValue}
|
|
220
|
+
</p>
|
|
221
|
+
<p>
|
|
222
|
+
<strong>Raw Value:</strong> {rawValue}
|
|
223
|
+
</p>
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
);
|
|
227
|
+
},
|
|
228
|
+
} satisfies StoryObj;
|
|
229
|
+
|
|
230
|
+
export const AllPatterns = {
|
|
231
|
+
args: {
|
|
232
|
+
fullwidth: true,
|
|
233
|
+
},
|
|
234
|
+
render: (args) => {
|
|
235
|
+
return (
|
|
236
|
+
<div className="flex flex-col gap-4 w-full max-w-2xl">
|
|
237
|
+
<h3 className="text-lg font-semibold">All Mask Patterns</h3>
|
|
238
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
239
|
+
<MaskedTextInput {...args} label="Phone" mask={MASK_PATTERNS.PHONE} />
|
|
240
|
+
<MaskedTextInput
|
|
241
|
+
{...args}
|
|
242
|
+
label="International Phone"
|
|
243
|
+
mask={MASK_PATTERNS.PHONE_INTL}
|
|
244
|
+
/>
|
|
245
|
+
<MaskedTextInput
|
|
246
|
+
{...args}
|
|
247
|
+
label="Credit Card"
|
|
248
|
+
mask={MASK_PATTERNS.CREDIT_CARD}
|
|
249
|
+
/>
|
|
250
|
+
<MaskedTextInput {...args} label="Date" mask={MASK_PATTERNS.DATE} />
|
|
251
|
+
<MaskedTextInput {...args} label="Time" mask={MASK_PATTERNS.TIME} />
|
|
252
|
+
<MaskedTextInput {...args} label="SSN" mask={MASK_PATTERNS.SSN} />
|
|
253
|
+
<MaskedTextInput
|
|
254
|
+
{...args}
|
|
255
|
+
label="ZIP Code"
|
|
256
|
+
mask={MASK_PATTERNS.ZIP_CODE}
|
|
257
|
+
/>
|
|
258
|
+
<MaskedTextInput
|
|
259
|
+
{...args}
|
|
260
|
+
label="ZIP Code + 4"
|
|
261
|
+
mask={MASK_PATTERNS.ZIP_CODE_EXT}
|
|
262
|
+
/>
|
|
263
|
+
<MaskedTextInput
|
|
264
|
+
{...args}
|
|
265
|
+
label="Currency"
|
|
266
|
+
mask={MASK_PATTERNS.CURRENCY}
|
|
267
|
+
/>
|
|
268
|
+
<MaskedTextInput
|
|
269
|
+
{...args}
|
|
270
|
+
label="Percentage"
|
|
271
|
+
mask={MASK_PATTERNS.PERCENTAGE}
|
|
272
|
+
/>
|
|
273
|
+
</div>
|
|
274
|
+
</div>
|
|
275
|
+
);
|
|
276
|
+
},
|
|
277
|
+
} satisfies StoryObj;
|
|
278
|
+
|
|
279
|
+
export const KendoRules = {
|
|
280
|
+
args: {
|
|
281
|
+
label: "Kendo UI Rules",
|
|
282
|
+
fullwidth: true,
|
|
283
|
+
},
|
|
284
|
+
render: (args) => {
|
|
285
|
+
return (
|
|
286
|
+
<div className="flex flex-col gap-4 w-full max-w-md">
|
|
287
|
+
<h3 className="text-sm font-semibold text-gray-700">
|
|
288
|
+
Kendo UI Mask Rules Examples
|
|
289
|
+
</h3>
|
|
290
|
+
<MaskedTextInput
|
|
291
|
+
{...args}
|
|
292
|
+
label="Rule: 0 (Digits Only)"
|
|
293
|
+
mask="000-000-0000"
|
|
294
|
+
helperText="0 = Required digit (0-9)"
|
|
295
|
+
/>
|
|
296
|
+
<MaskedTextInput
|
|
297
|
+
{...args}
|
|
298
|
+
label="Rule: L (Letters Only)"
|
|
299
|
+
mask="LLL-LLLL"
|
|
300
|
+
helperText="L = Required letter (a-z, A-Z)"
|
|
301
|
+
/>
|
|
302
|
+
<MaskedTextInput
|
|
303
|
+
{...args}
|
|
304
|
+
label="Rule: A (Alphanumeric)"
|
|
305
|
+
mask="AAAA-0000"
|
|
306
|
+
helperText="A = Letter or digit"
|
|
307
|
+
/>
|
|
308
|
+
<MaskedTextInput
|
|
309
|
+
{...args}
|
|
310
|
+
label="Rule: # (Number with sign)"
|
|
311
|
+
mask="###"
|
|
312
|
+
helperText="# = Digit, space, + or -"
|
|
313
|
+
/>
|
|
314
|
+
<MaskedTextInput
|
|
315
|
+
{...args}
|
|
316
|
+
label="Mixed Pattern Example"
|
|
317
|
+
mask="(000) LLL-0000"
|
|
318
|
+
helperText="Format: (123) ABC-4567"
|
|
319
|
+
/>
|
|
320
|
+
</div>
|
|
321
|
+
);
|
|
322
|
+
},
|
|
323
|
+
} satisfies StoryObj;
|
|
324
|
+
|
|
325
|
+
export const OptionalRules = {
|
|
326
|
+
args: {
|
|
327
|
+
label: "Optional Rules (with space)",
|
|
328
|
+
fullwidth: true,
|
|
329
|
+
},
|
|
330
|
+
render: (args) => {
|
|
331
|
+
return (
|
|
332
|
+
<div className="flex flex-col gap-4 w-full max-w-md">
|
|
333
|
+
<h3 className="text-sm font-semibold text-gray-700">
|
|
334
|
+
Rules that accept space (optional input)
|
|
335
|
+
</h3>
|
|
336
|
+
<p className="text-xs text-gray-500">
|
|
337
|
+
Note: These rules allow space, making the position optional
|
|
338
|
+
</p>
|
|
339
|
+
<MaskedTextInput
|
|
340
|
+
{...args}
|
|
341
|
+
label="Rule: 9 (Digit or Space)"
|
|
342
|
+
mask="999-999-9999"
|
|
343
|
+
helperText="9 = Optional digit (press space to skip)"
|
|
344
|
+
guide={false}
|
|
345
|
+
/>
|
|
346
|
+
<MaskedTextInput
|
|
347
|
+
{...args}
|
|
348
|
+
label="Rule: ? (Letter or Space)"
|
|
349
|
+
mask="???-????"
|
|
350
|
+
helperText="? = Optional letter (press space to skip)"
|
|
351
|
+
guide={false}
|
|
352
|
+
/>
|
|
353
|
+
<MaskedTextInput
|
|
354
|
+
{...args}
|
|
355
|
+
label="Rule: a (Alphanumeric or Space)"
|
|
356
|
+
mask="aaaa-aaaa"
|
|
357
|
+
helperText="a = Optional alphanumeric (press space to skip)"
|
|
358
|
+
guide={false}
|
|
359
|
+
/>
|
|
360
|
+
</div>
|
|
361
|
+
);
|
|
362
|
+
},
|
|
363
|
+
} satisfies StoryObj;
|
|
364
|
+
|
|
365
|
+
export const CustomRules = {
|
|
366
|
+
args: {
|
|
367
|
+
label: "Custom Rules",
|
|
368
|
+
fullwidth: true,
|
|
369
|
+
},
|
|
370
|
+
render: (args) => {
|
|
371
|
+
return (
|
|
372
|
+
<div className="flex flex-col gap-4 w-full max-w-md">
|
|
373
|
+
<h3 className="text-sm font-semibold text-gray-700">
|
|
374
|
+
Custom Validation Rules
|
|
375
|
+
</h3>
|
|
376
|
+
<div className="space-y-2">
|
|
377
|
+
<MaskedTextInput
|
|
378
|
+
{...args}
|
|
379
|
+
label="Custom Rule: Digits 3-9 only"
|
|
380
|
+
mask="~-~-~"
|
|
381
|
+
rules={{
|
|
382
|
+
"~": /[3-9]/,
|
|
383
|
+
}}
|
|
384
|
+
helperText="Type only digits 3, 4, 5, 6, 7, 8, or 9"
|
|
385
|
+
/>
|
|
386
|
+
</div>
|
|
387
|
+
<div className="space-y-2">
|
|
388
|
+
<MaskedTextInput
|
|
389
|
+
{...args}
|
|
390
|
+
label="Custom Rule: Uppercase letters only"
|
|
391
|
+
mask="***"
|
|
392
|
+
rules={{
|
|
393
|
+
"*": (char: string) =>
|
|
394
|
+
char === char.toUpperCase() && /[A-Z]/.test(char),
|
|
395
|
+
}}
|
|
396
|
+
helperText="Type only uppercase letters (A-Z)"
|
|
397
|
+
/>
|
|
398
|
+
</div>
|
|
399
|
+
<div className="space-y-2">
|
|
400
|
+
<MaskedTextInput
|
|
401
|
+
{...args}
|
|
402
|
+
label="Mixed Custom Rules"
|
|
403
|
+
mask="~*-~*"
|
|
404
|
+
rules={{
|
|
405
|
+
"~": /[0-9]/,
|
|
406
|
+
"*": /[A-Z]/,
|
|
407
|
+
}}
|
|
408
|
+
helperText="Format: Digit-Letter-Digit-Letter"
|
|
409
|
+
/>
|
|
410
|
+
</div>
|
|
411
|
+
</div>
|
|
412
|
+
);
|
|
413
|
+
},
|
|
414
|
+
} satisfies StoryObj;
|