@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/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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rovula/ui",
3
- "version": "0.0.77",
3
+ "version": "0.0.78",
4
4
  "main": "dist/cjs/bundle.js",
5
5
  "module": "dist/esm/bundle.js",
6
6
  "types": "dist/index.d.ts",
@@ -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;