@yomologic/react-ui 0.6.2 → 0.6.3
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.d.mts +81 -1
- package/dist/index.d.ts +81 -1
- package/dist/index.js +272 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +263 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -20,6 +20,42 @@ type ButtonAsLink = ButtonBaseProps & Omit<React.AnchorHTMLAttributes<HTMLAnchor
|
|
|
20
20
|
type ButtonProps = ButtonAsButton | ButtonAsLink;
|
|
21
21
|
declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement | HTMLAnchorElement>>;
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Input formatting utilities
|
|
25
|
+
*/
|
|
26
|
+
type FormatType = "phone" | "phone-intl" | "credit-card" | "date" | "datetime";
|
|
27
|
+
/**
|
|
28
|
+
* Format US phone number: (123) 456-7890
|
|
29
|
+
*/
|
|
30
|
+
declare const formatPhoneUS: (value: string) => string;
|
|
31
|
+
/**
|
|
32
|
+
* Format international phone number: +1 (123) 456-7890
|
|
33
|
+
*/
|
|
34
|
+
declare const formatPhoneIntl: (value: string) => string;
|
|
35
|
+
/**
|
|
36
|
+
* Format credit card number: 1234 5678 9012 3456
|
|
37
|
+
*/
|
|
38
|
+
declare const formatCreditCard: (value: string) => string;
|
|
39
|
+
/**
|
|
40
|
+
* Format date: MM/DD/YYYY
|
|
41
|
+
*/
|
|
42
|
+
declare const formatDate: (value: string) => string;
|
|
43
|
+
/**
|
|
44
|
+
* Format datetime: MM/DD/YYYY HH:MM AM/PM
|
|
45
|
+
*/
|
|
46
|
+
declare const formatDateTime: (value: string) => string;
|
|
47
|
+
/**
|
|
48
|
+
* Get raw value from formatted string
|
|
49
|
+
* - For phone/credit-card: returns digits only
|
|
50
|
+
* - For date: returns YYYY-MM-DD format (ISO 8601)
|
|
51
|
+
* - For datetime: returns ISO 8601 with timezone offset
|
|
52
|
+
*/
|
|
53
|
+
declare const getRawValue: (value: string, format?: FormatType) => string;
|
|
54
|
+
/**
|
|
55
|
+
* Apply format based on format type
|
|
56
|
+
*/
|
|
57
|
+
declare const applyFormat: (value: string, format: FormatType) => string;
|
|
58
|
+
|
|
23
59
|
interface FormState {
|
|
24
60
|
values: Record<string, any>;
|
|
25
61
|
errors: Record<string, string>;
|
|
@@ -62,6 +98,8 @@ interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "
|
|
|
62
98
|
onValidationError?: (error: string | undefined) => void;
|
|
63
99
|
/** Regex pattern for validation (string or RegExp) */
|
|
64
100
|
pattern?: RegExp | string;
|
|
101
|
+
/** Format type for auto-formatting input value (phone, credit-card, date, etc.) */
|
|
102
|
+
format?: FormatType | ((value: string) => string);
|
|
65
103
|
/** Custom error messages for built-in validations */
|
|
66
104
|
errorMessages?: {
|
|
67
105
|
required?: string;
|
|
@@ -72,6 +110,7 @@ interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "
|
|
|
72
110
|
pattern?: string;
|
|
73
111
|
email?: string;
|
|
74
112
|
url?: string;
|
|
113
|
+
date?: string;
|
|
75
114
|
};
|
|
76
115
|
}
|
|
77
116
|
declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -1107,4 +1146,45 @@ type ThemeId = keyof typeof themes;
|
|
|
1107
1146
|
|
|
1108
1147
|
declare function cn(...inputs: ClassValue[]): string;
|
|
1109
1148
|
|
|
1110
|
-
|
|
1149
|
+
/**
|
|
1150
|
+
* Validation constants and regex patterns
|
|
1151
|
+
*/
|
|
1152
|
+
/**
|
|
1153
|
+
* RFC 5322 compliant email validation regex (simplified)
|
|
1154
|
+
* Matches standard email formats like: user@example.com
|
|
1155
|
+
*/
|
|
1156
|
+
declare const EMAIL_REGEX: RegExp;
|
|
1157
|
+
/**
|
|
1158
|
+
* URL validation regex
|
|
1159
|
+
* Matches http(s) URLs
|
|
1160
|
+
*/
|
|
1161
|
+
declare const URL_REGEX: RegExp;
|
|
1162
|
+
/**
|
|
1163
|
+
* Phone number validation regex (US format)
|
|
1164
|
+
* Matches formats like: (123) 456-7890, 123-456-7890, 1234567890
|
|
1165
|
+
*/
|
|
1166
|
+
declare const PHONE_REGEX: RegExp;
|
|
1167
|
+
/**
|
|
1168
|
+
* Validate email format
|
|
1169
|
+
*/
|
|
1170
|
+
declare const isValidEmail: (email: string) => boolean;
|
|
1171
|
+
/**
|
|
1172
|
+
* Validate URL format
|
|
1173
|
+
*/
|
|
1174
|
+
declare const isValidUrl: (url: string) => boolean;
|
|
1175
|
+
/**
|
|
1176
|
+
* Date validation regex (MM/DD/YYYY)
|
|
1177
|
+
* Matches formats like: 12/31/2024, 01/01/2024
|
|
1178
|
+
*/
|
|
1179
|
+
declare const DATE_REGEX: RegExp;
|
|
1180
|
+
/**
|
|
1181
|
+
* Validate phone number format
|
|
1182
|
+
*/
|
|
1183
|
+
declare const isValidPhone: (phone: string) => boolean;
|
|
1184
|
+
/**
|
|
1185
|
+
* Validate date format and value
|
|
1186
|
+
* Checks if date is in MM/DD/YYYY format and is a valid calendar date
|
|
1187
|
+
*/
|
|
1188
|
+
declare const isValidDate: (date: string) => boolean;
|
|
1189
|
+
|
|
1190
|
+
export { Alert, Badge, Button, Card, CardActionArea, CardActions, CardContent, CardDescription, CardFooter, CardHeader, CardMedia, CardTitle, Checkbox, CheckboxGroup, CodeSnippet, Container, DATE_REGEX, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Divider, Drawer, type NavItem$1 as DrawerNavItem, type NavSection$1 as DrawerNavSection, type DrawerProps, EMAIL_REGEX, EmptyState, Form, type FormContextValue, FormControl, type FormControlContextValue, FormControlLabel, type FormControlProps, type FormControlState, type FormFieldProps, FormHelperText, type FormState, type FormatType, Input, NativeSelect, type NativeSelectProps, Nav, type NavItem$2 as NavItem, type NavProps, type NavSection, PHONE_REGEX, RadioGroup, Rating, SectionLayout, Select, type SelectOption, type SelectProps, SidebarNav, type NavItem as SidebarNavItem, Slider, type SliderMark, type SliderProps, Spinner, Switch, type SwitchProps, Textarea, type TextareaProps, type ThemeId, ThemeProvider, URL_REGEX, type ValidationFunction, type ValidationRule, applyFormat, cn, formatCreditCard, formatDate, formatDateTime, formatPhoneIntl, formatPhoneUS, getRawValue, isValidDate, isValidEmail, isValidPhone, isValidUrl, themes, useForm, useFormContext, useFormControl, useFormControlContext, useFormField, useTheme };
|
package/dist/index.d.ts
CHANGED
|
@@ -20,6 +20,42 @@ type ButtonAsLink = ButtonBaseProps & Omit<React.AnchorHTMLAttributes<HTMLAnchor
|
|
|
20
20
|
type ButtonProps = ButtonAsButton | ButtonAsLink;
|
|
21
21
|
declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement | HTMLAnchorElement>>;
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Input formatting utilities
|
|
25
|
+
*/
|
|
26
|
+
type FormatType = "phone" | "phone-intl" | "credit-card" | "date" | "datetime";
|
|
27
|
+
/**
|
|
28
|
+
* Format US phone number: (123) 456-7890
|
|
29
|
+
*/
|
|
30
|
+
declare const formatPhoneUS: (value: string) => string;
|
|
31
|
+
/**
|
|
32
|
+
* Format international phone number: +1 (123) 456-7890
|
|
33
|
+
*/
|
|
34
|
+
declare const formatPhoneIntl: (value: string) => string;
|
|
35
|
+
/**
|
|
36
|
+
* Format credit card number: 1234 5678 9012 3456
|
|
37
|
+
*/
|
|
38
|
+
declare const formatCreditCard: (value: string) => string;
|
|
39
|
+
/**
|
|
40
|
+
* Format date: MM/DD/YYYY
|
|
41
|
+
*/
|
|
42
|
+
declare const formatDate: (value: string) => string;
|
|
43
|
+
/**
|
|
44
|
+
* Format datetime: MM/DD/YYYY HH:MM AM/PM
|
|
45
|
+
*/
|
|
46
|
+
declare const formatDateTime: (value: string) => string;
|
|
47
|
+
/**
|
|
48
|
+
* Get raw value from formatted string
|
|
49
|
+
* - For phone/credit-card: returns digits only
|
|
50
|
+
* - For date: returns YYYY-MM-DD format (ISO 8601)
|
|
51
|
+
* - For datetime: returns ISO 8601 with timezone offset
|
|
52
|
+
*/
|
|
53
|
+
declare const getRawValue: (value: string, format?: FormatType) => string;
|
|
54
|
+
/**
|
|
55
|
+
* Apply format based on format type
|
|
56
|
+
*/
|
|
57
|
+
declare const applyFormat: (value: string, format: FormatType) => string;
|
|
58
|
+
|
|
23
59
|
interface FormState {
|
|
24
60
|
values: Record<string, any>;
|
|
25
61
|
errors: Record<string, string>;
|
|
@@ -62,6 +98,8 @@ interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "
|
|
|
62
98
|
onValidationError?: (error: string | undefined) => void;
|
|
63
99
|
/** Regex pattern for validation (string or RegExp) */
|
|
64
100
|
pattern?: RegExp | string;
|
|
101
|
+
/** Format type for auto-formatting input value (phone, credit-card, date, etc.) */
|
|
102
|
+
format?: FormatType | ((value: string) => string);
|
|
65
103
|
/** Custom error messages for built-in validations */
|
|
66
104
|
errorMessages?: {
|
|
67
105
|
required?: string;
|
|
@@ -72,6 +110,7 @@ interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "
|
|
|
72
110
|
pattern?: string;
|
|
73
111
|
email?: string;
|
|
74
112
|
url?: string;
|
|
113
|
+
date?: string;
|
|
75
114
|
};
|
|
76
115
|
}
|
|
77
116
|
declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -1107,4 +1146,45 @@ type ThemeId = keyof typeof themes;
|
|
|
1107
1146
|
|
|
1108
1147
|
declare function cn(...inputs: ClassValue[]): string;
|
|
1109
1148
|
|
|
1110
|
-
|
|
1149
|
+
/**
|
|
1150
|
+
* Validation constants and regex patterns
|
|
1151
|
+
*/
|
|
1152
|
+
/**
|
|
1153
|
+
* RFC 5322 compliant email validation regex (simplified)
|
|
1154
|
+
* Matches standard email formats like: user@example.com
|
|
1155
|
+
*/
|
|
1156
|
+
declare const EMAIL_REGEX: RegExp;
|
|
1157
|
+
/**
|
|
1158
|
+
* URL validation regex
|
|
1159
|
+
* Matches http(s) URLs
|
|
1160
|
+
*/
|
|
1161
|
+
declare const URL_REGEX: RegExp;
|
|
1162
|
+
/**
|
|
1163
|
+
* Phone number validation regex (US format)
|
|
1164
|
+
* Matches formats like: (123) 456-7890, 123-456-7890, 1234567890
|
|
1165
|
+
*/
|
|
1166
|
+
declare const PHONE_REGEX: RegExp;
|
|
1167
|
+
/**
|
|
1168
|
+
* Validate email format
|
|
1169
|
+
*/
|
|
1170
|
+
declare const isValidEmail: (email: string) => boolean;
|
|
1171
|
+
/**
|
|
1172
|
+
* Validate URL format
|
|
1173
|
+
*/
|
|
1174
|
+
declare const isValidUrl: (url: string) => boolean;
|
|
1175
|
+
/**
|
|
1176
|
+
* Date validation regex (MM/DD/YYYY)
|
|
1177
|
+
* Matches formats like: 12/31/2024, 01/01/2024
|
|
1178
|
+
*/
|
|
1179
|
+
declare const DATE_REGEX: RegExp;
|
|
1180
|
+
/**
|
|
1181
|
+
* Validate phone number format
|
|
1182
|
+
*/
|
|
1183
|
+
declare const isValidPhone: (phone: string) => boolean;
|
|
1184
|
+
/**
|
|
1185
|
+
* Validate date format and value
|
|
1186
|
+
* Checks if date is in MM/DD/YYYY format and is a valid calendar date
|
|
1187
|
+
*/
|
|
1188
|
+
declare const isValidDate: (date: string) => boolean;
|
|
1189
|
+
|
|
1190
|
+
export { Alert, Badge, Button, Card, CardActionArea, CardActions, CardContent, CardDescription, CardFooter, CardHeader, CardMedia, CardTitle, Checkbox, CheckboxGroup, CodeSnippet, Container, DATE_REGEX, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Divider, Drawer, type NavItem$1 as DrawerNavItem, type NavSection$1 as DrawerNavSection, type DrawerProps, EMAIL_REGEX, EmptyState, Form, type FormContextValue, FormControl, type FormControlContextValue, FormControlLabel, type FormControlProps, type FormControlState, type FormFieldProps, FormHelperText, type FormState, type FormatType, Input, NativeSelect, type NativeSelectProps, Nav, type NavItem$2 as NavItem, type NavProps, type NavSection, PHONE_REGEX, RadioGroup, Rating, SectionLayout, Select, type SelectOption, type SelectProps, SidebarNav, type NavItem as SidebarNavItem, Slider, type SliderMark, type SliderProps, Spinner, Switch, type SwitchProps, Textarea, type TextareaProps, type ThemeId, ThemeProvider, URL_REGEX, type ValidationFunction, type ValidationRule, applyFormat, cn, formatCreditCard, formatDate, formatDateTime, formatPhoneIntl, formatPhoneUS, getRawValue, isValidDate, isValidEmail, isValidPhone, isValidUrl, themes, useForm, useFormContext, useFormControl, useFormControlContext, useFormField, useTheme };
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __esm = (fn, res) => function __init() {
|
|
10
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
|
+
};
|
|
9
12
|
var __export = (target, all) => {
|
|
10
13
|
for (var name in all)
|
|
11
14
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -28,6 +31,59 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
31
|
));
|
|
29
32
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
33
|
|
|
34
|
+
// src/constants/validation.ts
|
|
35
|
+
var validation_exports = {};
|
|
36
|
+
__export(validation_exports, {
|
|
37
|
+
DATE_REGEX: () => DATE_REGEX,
|
|
38
|
+
EMAIL_REGEX: () => EMAIL_REGEX,
|
|
39
|
+
PHONE_REGEX: () => PHONE_REGEX,
|
|
40
|
+
URL_REGEX: () => URL_REGEX,
|
|
41
|
+
isValidDate: () => isValidDate,
|
|
42
|
+
isValidEmail: () => isValidEmail,
|
|
43
|
+
isValidPhone: () => isValidPhone,
|
|
44
|
+
isValidUrl: () => isValidUrl
|
|
45
|
+
});
|
|
46
|
+
var EMAIL_REGEX, URL_REGEX, PHONE_REGEX, isValidEmail, isValidUrl, DATE_REGEX, isValidPhone, isValidDate;
|
|
47
|
+
var init_validation = __esm({
|
|
48
|
+
"src/constants/validation.ts"() {
|
|
49
|
+
"use strict";
|
|
50
|
+
EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
51
|
+
URL_REGEX = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/;
|
|
52
|
+
PHONE_REGEX = /^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/;
|
|
53
|
+
isValidEmail = (email) => {
|
|
54
|
+
return EMAIL_REGEX.test(email);
|
|
55
|
+
};
|
|
56
|
+
isValidUrl = (url) => {
|
|
57
|
+
return URL_REGEX.test(url);
|
|
58
|
+
};
|
|
59
|
+
DATE_REGEX = /^(0[1-9]|1[0-2])\/(0[1-9]|[12][0-9]|3[01])\/\d{4}$/;
|
|
60
|
+
isValidPhone = (phone) => {
|
|
61
|
+
return PHONE_REGEX.test(phone);
|
|
62
|
+
};
|
|
63
|
+
isValidDate = (date) => {
|
|
64
|
+
if (!DATE_REGEX.test(date)) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
const [month, day, year] = date.split("/").map(Number);
|
|
68
|
+
if (year < 1900 || year > 2100) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
if (month < 1 || month > 12) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
75
|
+
const isLeapYear = year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
|
|
76
|
+
if (isLeapYear && month === 2) {
|
|
77
|
+
daysInMonth[1] = 29;
|
|
78
|
+
}
|
|
79
|
+
if (day < 1 || day > daysInMonth[month - 1]) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
return true;
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
31
87
|
// src/index.ts
|
|
32
88
|
var index_exports = {};
|
|
33
89
|
__export(index_exports, {
|
|
@@ -47,6 +103,7 @@ __export(index_exports, {
|
|
|
47
103
|
CheckboxGroup: () => CheckboxGroup,
|
|
48
104
|
CodeSnippet: () => CodeSnippet,
|
|
49
105
|
Container: () => Container,
|
|
106
|
+
DATE_REGEX: () => DATE_REGEX,
|
|
50
107
|
Dialog: () => Dialog,
|
|
51
108
|
DialogContent: () => DialogContent,
|
|
52
109
|
DialogDescription: () => DialogDescription,
|
|
@@ -55,6 +112,7 @@ __export(index_exports, {
|
|
|
55
112
|
DialogTitle: () => DialogTitle,
|
|
56
113
|
Divider: () => Divider,
|
|
57
114
|
Drawer: () => Drawer,
|
|
115
|
+
EMAIL_REGEX: () => EMAIL_REGEX,
|
|
58
116
|
EmptyState: () => EmptyState,
|
|
59
117
|
Form: () => Form,
|
|
60
118
|
FormControl: () => FormControl,
|
|
@@ -63,6 +121,7 @@ __export(index_exports, {
|
|
|
63
121
|
Input: () => Input,
|
|
64
122
|
NativeSelect: () => NativeSelect,
|
|
65
123
|
Nav: () => Nav,
|
|
124
|
+
PHONE_REGEX: () => PHONE_REGEX,
|
|
66
125
|
RadioGroup: () => RadioGroup,
|
|
67
126
|
Rating: () => Rating,
|
|
68
127
|
SectionLayout: () => SectionLayout,
|
|
@@ -73,7 +132,19 @@ __export(index_exports, {
|
|
|
73
132
|
Switch: () => Switch,
|
|
74
133
|
Textarea: () => Textarea,
|
|
75
134
|
ThemeProvider: () => ThemeProvider,
|
|
135
|
+
URL_REGEX: () => URL_REGEX,
|
|
136
|
+
applyFormat: () => applyFormat,
|
|
76
137
|
cn: () => cn,
|
|
138
|
+
formatCreditCard: () => formatCreditCard,
|
|
139
|
+
formatDate: () => formatDate,
|
|
140
|
+
formatDateTime: () => formatDateTime,
|
|
141
|
+
formatPhoneIntl: () => formatPhoneIntl,
|
|
142
|
+
formatPhoneUS: () => formatPhoneUS,
|
|
143
|
+
getRawValue: () => getRawValue,
|
|
144
|
+
isValidDate: () => isValidDate,
|
|
145
|
+
isValidEmail: () => isValidEmail,
|
|
146
|
+
isValidPhone: () => isValidPhone,
|
|
147
|
+
isValidUrl: () => isValidUrl,
|
|
77
148
|
themes: () => themes_default,
|
|
78
149
|
useForm: () => useForm,
|
|
79
150
|
useFormContext: () => useFormContext,
|
|
@@ -234,8 +305,113 @@ Button.displayName = "Button";
|
|
|
234
305
|
// src/ui/input.tsx
|
|
235
306
|
var import_react5 = __toESM(require("react"));
|
|
236
307
|
|
|
308
|
+
// src/lib/formatting.ts
|
|
309
|
+
var formatPhoneUS = (value) => {
|
|
310
|
+
const digits = value.replace(/\D/g, "");
|
|
311
|
+
const limited = digits.slice(0, 10);
|
|
312
|
+
if (limited.length === 0) return "";
|
|
313
|
+
if (limited.length <= 3) return `(${limited}`;
|
|
314
|
+
if (limited.length <= 6)
|
|
315
|
+
return `(${limited.slice(0, 3)}) ${limited.slice(3)}`;
|
|
316
|
+
return `(${limited.slice(0, 3)}) ${limited.slice(3, 6)}-${limited.slice(6)}`;
|
|
317
|
+
};
|
|
318
|
+
var formatPhoneIntl = (value) => {
|
|
319
|
+
let cleaned = value.replace(/[^\d+]/g, "");
|
|
320
|
+
if (!cleaned.startsWith("+")) {
|
|
321
|
+
cleaned = "+" + cleaned;
|
|
322
|
+
}
|
|
323
|
+
cleaned = cleaned.slice(0, 16);
|
|
324
|
+
const digits = cleaned.slice(1);
|
|
325
|
+
if (digits.length === 0) return "+";
|
|
326
|
+
if (digits.length <= 1) return `+${digits}`;
|
|
327
|
+
if (digits.length <= 4) return `+${digits.slice(0, 1)} (${digits.slice(1)}`;
|
|
328
|
+
if (digits.length <= 7)
|
|
329
|
+
return `+${digits.slice(0, 1)} (${digits.slice(1, 4)}) ${digits.slice(4)}`;
|
|
330
|
+
return `+${digits.slice(0, 1)} (${digits.slice(1, 4)}) ${digits.slice(4, 7)}-${digits.slice(7)}`;
|
|
331
|
+
};
|
|
332
|
+
var formatCreditCard = (value) => {
|
|
333
|
+
const digits = value.replace(/\D/g, "");
|
|
334
|
+
const limited = digits.slice(0, 16);
|
|
335
|
+
return limited.replace(/(\d{4})/g, "$1 ").trim();
|
|
336
|
+
};
|
|
337
|
+
var formatDate = (value) => {
|
|
338
|
+
const digits = value.replace(/\D/g, "");
|
|
339
|
+
const limited = digits.slice(0, 8);
|
|
340
|
+
if (limited.length === 0) return "";
|
|
341
|
+
if (limited.length <= 2) return limited;
|
|
342
|
+
if (limited.length <= 4)
|
|
343
|
+
return `${limited.slice(0, 2)}/${limited.slice(2)}`;
|
|
344
|
+
return `${limited.slice(0, 2)}/${limited.slice(2, 4)}/${limited.slice(4)}`;
|
|
345
|
+
};
|
|
346
|
+
var formatDateTime = (value) => {
|
|
347
|
+
const digits = value.replace(/\D/g, "");
|
|
348
|
+
const limited = digits.slice(0, 12);
|
|
349
|
+
if (limited.length === 0) return "";
|
|
350
|
+
if (limited.length <= 2) return limited;
|
|
351
|
+
if (limited.length <= 4)
|
|
352
|
+
return `${limited.slice(0, 2)}/${limited.slice(2)}`;
|
|
353
|
+
if (limited.length <= 8)
|
|
354
|
+
return `${limited.slice(0, 2)}/${limited.slice(2, 4)}/${limited.slice(4)}`;
|
|
355
|
+
const datePart = `${limited.slice(0, 2)}/${limited.slice(2, 4)}/${limited.slice(4, 8)}`;
|
|
356
|
+
if (limited.length <= 10) return `${datePart} ${limited.slice(8)}`;
|
|
357
|
+
let hours = parseInt(limited.slice(8, 10));
|
|
358
|
+
const minutes = limited.slice(10, 12);
|
|
359
|
+
const ampm = hours >= 12 ? "PM" : "AM";
|
|
360
|
+
hours = hours % 12 || 12;
|
|
361
|
+
return `${datePart} ${hours}:${minutes} ${ampm}`;
|
|
362
|
+
};
|
|
363
|
+
var getRawValue = (value, format) => {
|
|
364
|
+
if (format === "date") {
|
|
365
|
+
const digits = value.replace(/\D/g, "");
|
|
366
|
+
if (digits.length === 8) {
|
|
367
|
+
const month = digits.slice(0, 2);
|
|
368
|
+
const day = digits.slice(2, 4);
|
|
369
|
+
const year = digits.slice(4, 8);
|
|
370
|
+
return `${year}-${month}-${day}`;
|
|
371
|
+
}
|
|
372
|
+
return digits;
|
|
373
|
+
}
|
|
374
|
+
if (format === "datetime") {
|
|
375
|
+
const digits = value.replace(/\D/g, "");
|
|
376
|
+
if (digits.length === 12) {
|
|
377
|
+
const month = digits.slice(0, 2);
|
|
378
|
+
const day = digits.slice(2, 4);
|
|
379
|
+
const year = digits.slice(4, 8);
|
|
380
|
+
const hours = digits.slice(8, 10);
|
|
381
|
+
const minutes = digits.slice(10, 12);
|
|
382
|
+
const date = new Date(
|
|
383
|
+
parseInt(year),
|
|
384
|
+
parseInt(month) - 1,
|
|
385
|
+
parseInt(day),
|
|
386
|
+
parseInt(hours),
|
|
387
|
+
parseInt(minutes)
|
|
388
|
+
);
|
|
389
|
+
return date.toISOString();
|
|
390
|
+
}
|
|
391
|
+
return digits;
|
|
392
|
+
}
|
|
393
|
+
return value.replace(/\D/g, "");
|
|
394
|
+
};
|
|
395
|
+
var applyFormat = (value, format) => {
|
|
396
|
+
switch (format) {
|
|
397
|
+
case "phone":
|
|
398
|
+
return formatPhoneUS(value);
|
|
399
|
+
case "phone-intl":
|
|
400
|
+
return formatPhoneIntl(value);
|
|
401
|
+
case "credit-card":
|
|
402
|
+
return formatCreditCard(value);
|
|
403
|
+
case "date":
|
|
404
|
+
return formatDate(value);
|
|
405
|
+
case "datetime":
|
|
406
|
+
return formatDateTime(value);
|
|
407
|
+
default:
|
|
408
|
+
return value;
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
|
|
237
412
|
// src/ui/hooks/useFormField.ts
|
|
238
413
|
var import_react4 = require("react");
|
|
414
|
+
init_validation();
|
|
239
415
|
|
|
240
416
|
// src/ui/form.tsx
|
|
241
417
|
var import_react2 = require("react");
|
|
@@ -807,7 +983,7 @@ function useFormField2(options) {
|
|
|
807
983
|
return errorMessages?.required || "This field is required";
|
|
808
984
|
}
|
|
809
985
|
if (value) {
|
|
810
|
-
if (type === "email" && !
|
|
986
|
+
if (type === "email" && !EMAIL_REGEX.test(value)) {
|
|
811
987
|
return errorMessages?.email || "Please enter a valid email address";
|
|
812
988
|
}
|
|
813
989
|
if (type === "url") {
|
|
@@ -864,7 +1040,7 @@ function useFormField2(options) {
|
|
|
864
1040
|
return errorMessages?.required || "This field is required";
|
|
865
1041
|
}
|
|
866
1042
|
if (value) {
|
|
867
|
-
if (type === "email" && !
|
|
1043
|
+
if (type === "email" && !EMAIL_REGEX.test(value)) {
|
|
868
1044
|
return errorMessages?.email || "Please enter a valid email address";
|
|
869
1045
|
}
|
|
870
1046
|
if (type === "url") {
|
|
@@ -981,12 +1157,31 @@ var Input = import_react5.default.forwardRef(
|
|
|
981
1157
|
validate,
|
|
982
1158
|
onValidationError,
|
|
983
1159
|
pattern,
|
|
1160
|
+
format,
|
|
984
1161
|
errorMessages,
|
|
985
1162
|
...props
|
|
986
1163
|
}, ref) => {
|
|
1164
|
+
const [internalValue, setInternalValue] = import_react5.default.useState("");
|
|
1165
|
+
const dateValidate = import_react5.default.useCallback(
|
|
1166
|
+
async (value) => {
|
|
1167
|
+
if (validate) {
|
|
1168
|
+
const customError = await validate(value);
|
|
1169
|
+
if (customError) return customError;
|
|
1170
|
+
}
|
|
1171
|
+
if (format === "date" && value && value.length === 8) {
|
|
1172
|
+
const { isValidDate: isValidDate2 } = await Promise.resolve().then(() => (init_validation(), validation_exports));
|
|
1173
|
+
const formatted = `${value.slice(0, 2)}/${value.slice(2, 4)}/${value.slice(4, 8)}`;
|
|
1174
|
+
if (!isValidDate2(formatted)) {
|
|
1175
|
+
return errorMessages?.date || "Please enter a valid date";
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
return void 0;
|
|
1179
|
+
},
|
|
1180
|
+
[validate, format, errorMessages]
|
|
1181
|
+
);
|
|
987
1182
|
const {
|
|
988
1183
|
fieldId,
|
|
989
|
-
value:
|
|
1184
|
+
value: hookValue,
|
|
990
1185
|
error: inputError,
|
|
991
1186
|
isDisabled,
|
|
992
1187
|
isRequired,
|
|
@@ -1008,19 +1203,71 @@ var Input = import_react5.default.forwardRef(
|
|
|
1008
1203
|
min: props.min,
|
|
1009
1204
|
max: props.max,
|
|
1010
1205
|
pattern,
|
|
1011
|
-
validate,
|
|
1206
|
+
validate: format === "date" ? dateValidate : validate,
|
|
1012
1207
|
onValidationError,
|
|
1013
1208
|
errorMessages,
|
|
1014
1209
|
idPrefix: "input"
|
|
1015
1210
|
});
|
|
1211
|
+
const inputValue = hookValue !== void 0 ? hookValue : internalValue;
|
|
1212
|
+
const [cursorPosition, setCursorPosition] = import_react5.default.useState(null);
|
|
1016
1213
|
const handleChange = (e) => {
|
|
1017
|
-
|
|
1214
|
+
const input = e.target;
|
|
1215
|
+
const newValue = input.value;
|
|
1216
|
+
const cursorPos = input.selectionStart || 0;
|
|
1217
|
+
if (format && typeof format === "string") {
|
|
1218
|
+
const cleaned = newValue.replace(/\D/g, "");
|
|
1219
|
+
const formatted = applyFormat(cleaned, format);
|
|
1220
|
+
if (hookValue !== void 0) {
|
|
1221
|
+
hookHandleChange(cleaned);
|
|
1222
|
+
} else {
|
|
1223
|
+
setInternalValue(cleaned);
|
|
1224
|
+
}
|
|
1225
|
+
let formattedPos = 0;
|
|
1226
|
+
let digitCount = 0;
|
|
1227
|
+
const targetDigits = cleaned.slice(
|
|
1228
|
+
0,
|
|
1229
|
+
Math.min(cleaned.length, cursorPos)
|
|
1230
|
+
);
|
|
1231
|
+
for (let i = 0; i < formatted.length && digitCount < targetDigits.length; i++) {
|
|
1232
|
+
if (/\d/.test(formatted[i])) {
|
|
1233
|
+
digitCount++;
|
|
1234
|
+
}
|
|
1235
|
+
formattedPos = i + 1;
|
|
1236
|
+
}
|
|
1237
|
+
setCursorPosition(formattedPos);
|
|
1238
|
+
} else {
|
|
1239
|
+
if (hookValue !== void 0) {
|
|
1240
|
+
hookHandleChange(newValue);
|
|
1241
|
+
} else {
|
|
1242
|
+
setInternalValue(newValue);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1018
1245
|
onChange?.(e);
|
|
1019
1246
|
};
|
|
1020
1247
|
const handleBlur = (e) => {
|
|
1021
|
-
|
|
1248
|
+
const value = e.target.value;
|
|
1249
|
+
const blurValue = format && typeof format === "string" ? value.replace(/\D/g, "") : value;
|
|
1250
|
+
hookHandleBlur(blurValue);
|
|
1022
1251
|
onBlur?.(e);
|
|
1023
1252
|
};
|
|
1253
|
+
const displayValue = import_react5.default.useMemo(() => {
|
|
1254
|
+
if (format && inputValue) {
|
|
1255
|
+
if (typeof format === "function") {
|
|
1256
|
+
return format(inputValue);
|
|
1257
|
+
}
|
|
1258
|
+
return applyFormat(inputValue, format);
|
|
1259
|
+
}
|
|
1260
|
+
return inputValue;
|
|
1261
|
+
}, [format, inputValue]);
|
|
1262
|
+
import_react5.default.useEffect(() => {
|
|
1263
|
+
if (cursorPosition !== null && internalRef.current) {
|
|
1264
|
+
internalRef.current.setSelectionRange(
|
|
1265
|
+
cursorPosition,
|
|
1266
|
+
cursorPosition
|
|
1267
|
+
);
|
|
1268
|
+
setCursorPosition(null);
|
|
1269
|
+
}
|
|
1270
|
+
}, [cursorPosition, displayValue]);
|
|
1024
1271
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1025
1272
|
"div",
|
|
1026
1273
|
{
|
|
@@ -1053,7 +1300,7 @@ var Input = import_react5.default.forwardRef(
|
|
|
1053
1300
|
},
|
|
1054
1301
|
type,
|
|
1055
1302
|
id: fieldId,
|
|
1056
|
-
value:
|
|
1303
|
+
value: displayValue,
|
|
1057
1304
|
onChange: handleChange,
|
|
1058
1305
|
onBlur: handleBlur,
|
|
1059
1306
|
disabled: isDisabled,
|
|
@@ -5247,6 +5494,9 @@ function useTheme() {
|
|
|
5247
5494
|
}
|
|
5248
5495
|
return context;
|
|
5249
5496
|
}
|
|
5497
|
+
|
|
5498
|
+
// src/index.ts
|
|
5499
|
+
init_validation();
|
|
5250
5500
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5251
5501
|
0 && (module.exports = {
|
|
5252
5502
|
Alert,
|
|
@@ -5265,6 +5515,7 @@ function useTheme() {
|
|
|
5265
5515
|
CheckboxGroup,
|
|
5266
5516
|
CodeSnippet,
|
|
5267
5517
|
Container,
|
|
5518
|
+
DATE_REGEX,
|
|
5268
5519
|
Dialog,
|
|
5269
5520
|
DialogContent,
|
|
5270
5521
|
DialogDescription,
|
|
@@ -5273,6 +5524,7 @@ function useTheme() {
|
|
|
5273
5524
|
DialogTitle,
|
|
5274
5525
|
Divider,
|
|
5275
5526
|
Drawer,
|
|
5527
|
+
EMAIL_REGEX,
|
|
5276
5528
|
EmptyState,
|
|
5277
5529
|
Form,
|
|
5278
5530
|
FormControl,
|
|
@@ -5281,6 +5533,7 @@ function useTheme() {
|
|
|
5281
5533
|
Input,
|
|
5282
5534
|
NativeSelect,
|
|
5283
5535
|
Nav,
|
|
5536
|
+
PHONE_REGEX,
|
|
5284
5537
|
RadioGroup,
|
|
5285
5538
|
Rating,
|
|
5286
5539
|
SectionLayout,
|
|
@@ -5291,7 +5544,19 @@ function useTheme() {
|
|
|
5291
5544
|
Switch,
|
|
5292
5545
|
Textarea,
|
|
5293
5546
|
ThemeProvider,
|
|
5547
|
+
URL_REGEX,
|
|
5548
|
+
applyFormat,
|
|
5294
5549
|
cn,
|
|
5550
|
+
formatCreditCard,
|
|
5551
|
+
formatDate,
|
|
5552
|
+
formatDateTime,
|
|
5553
|
+
formatPhoneIntl,
|
|
5554
|
+
formatPhoneUS,
|
|
5555
|
+
getRawValue,
|
|
5556
|
+
isValidDate,
|
|
5557
|
+
isValidEmail,
|
|
5558
|
+
isValidPhone,
|
|
5559
|
+
isValidUrl,
|
|
5295
5560
|
themes,
|
|
5296
5561
|
useForm,
|
|
5297
5562
|
useFormContext,
|