@yomologic/react-ui 0.6.2 → 0.6.4
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 +83 -1
- package/dist/index.d.ts +83 -1
- package/dist/index.js +283 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +274 -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,47 @@ 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
|
+
* Email validation regex
|
|
1154
|
+
* Matches standard email formats like: user@example.com
|
|
1155
|
+
* Requires @ symbol, domain name, and TLD (like .com, .org, etc.)
|
|
1156
|
+
*/
|
|
1157
|
+
declare const EMAIL_REGEX: RegExp;
|
|
1158
|
+
/**
|
|
1159
|
+
* URL validation regex
|
|
1160
|
+
* Matches http(s) URLs
|
|
1161
|
+
*/
|
|
1162
|
+
declare const URL_REGEX: RegExp;
|
|
1163
|
+
/**
|
|
1164
|
+
* Phone number validation regex (US format)
|
|
1165
|
+
* Matches formats like: (123) 456-7890, 123-456-7890, 1234567890
|
|
1166
|
+
*/
|
|
1167
|
+
declare const PHONE_REGEX: RegExp;
|
|
1168
|
+
/**
|
|
1169
|
+
* Validate email format
|
|
1170
|
+
*/
|
|
1171
|
+
declare const isValidEmail: (email: string) => boolean;
|
|
1172
|
+
/**
|
|
1173
|
+
* Validate URL format and security
|
|
1174
|
+
* Checks for valid http/https protocol and blocks dangerous protocols
|
|
1175
|
+
*/
|
|
1176
|
+
declare const isValidUrl: (url: string) => boolean;
|
|
1177
|
+
/**
|
|
1178
|
+
* Date validation regex (MM/DD/YYYY)
|
|
1179
|
+
* Matches formats like: 12/31/2024, 01/01/2024
|
|
1180
|
+
*/
|
|
1181
|
+
declare const DATE_REGEX: RegExp;
|
|
1182
|
+
/**
|
|
1183
|
+
* Validate phone number format
|
|
1184
|
+
*/
|
|
1185
|
+
declare const isValidPhone: (phone: string) => boolean;
|
|
1186
|
+
/**
|
|
1187
|
+
* Validate date format and value
|
|
1188
|
+
* Checks if date is in MM/DD/YYYY format and is a valid calendar date
|
|
1189
|
+
*/
|
|
1190
|
+
declare const isValidDate: (date: string) => boolean;
|
|
1191
|
+
|
|
1192
|
+
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,47 @@ 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
|
+
* Email validation regex
|
|
1154
|
+
* Matches standard email formats like: user@example.com
|
|
1155
|
+
* Requires @ symbol, domain name, and TLD (like .com, .org, etc.)
|
|
1156
|
+
*/
|
|
1157
|
+
declare const EMAIL_REGEX: RegExp;
|
|
1158
|
+
/**
|
|
1159
|
+
* URL validation regex
|
|
1160
|
+
* Matches http(s) URLs
|
|
1161
|
+
*/
|
|
1162
|
+
declare const URL_REGEX: RegExp;
|
|
1163
|
+
/**
|
|
1164
|
+
* Phone number validation regex (US format)
|
|
1165
|
+
* Matches formats like: (123) 456-7890, 123-456-7890, 1234567890
|
|
1166
|
+
*/
|
|
1167
|
+
declare const PHONE_REGEX: RegExp;
|
|
1168
|
+
/**
|
|
1169
|
+
* Validate email format
|
|
1170
|
+
*/
|
|
1171
|
+
declare const isValidEmail: (email: string) => boolean;
|
|
1172
|
+
/**
|
|
1173
|
+
* Validate URL format and security
|
|
1174
|
+
* Checks for valid http/https protocol and blocks dangerous protocols
|
|
1175
|
+
*/
|
|
1176
|
+
declare const isValidUrl: (url: string) => boolean;
|
|
1177
|
+
/**
|
|
1178
|
+
* Date validation regex (MM/DD/YYYY)
|
|
1179
|
+
* Matches formats like: 12/31/2024, 01/01/2024
|
|
1180
|
+
*/
|
|
1181
|
+
declare const DATE_REGEX: RegExp;
|
|
1182
|
+
/**
|
|
1183
|
+
* Validate phone number format
|
|
1184
|
+
*/
|
|
1185
|
+
declare const isValidPhone: (phone: string) => boolean;
|
|
1186
|
+
/**
|
|
1187
|
+
* Validate date format and value
|
|
1188
|
+
* Checks if date is in MM/DD/YYYY format and is a valid calendar date
|
|
1189
|
+
*/
|
|
1190
|
+
declare const isValidDate: (date: string) => boolean;
|
|
1191
|
+
|
|
1192
|
+
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,62 @@ 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-]+)*\.[a-zA-Z]{2,}$/;
|
|
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
|
+
if (/^(javascript|data|vbscript|file|about):/i.test(url)) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
return URL_REGEX.test(url);
|
|
61
|
+
};
|
|
62
|
+
DATE_REGEX = /^(0[1-9]|1[0-2])\/(0[1-9]|[12][0-9]|3[01])\/\d{4}$/;
|
|
63
|
+
isValidPhone = (phone) => {
|
|
64
|
+
return PHONE_REGEX.test(phone);
|
|
65
|
+
};
|
|
66
|
+
isValidDate = (date) => {
|
|
67
|
+
if (!DATE_REGEX.test(date)) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
const [month, day, year] = date.split("/").map(Number);
|
|
71
|
+
if (year < 1900 || year > 2100) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
if (month < 1 || month > 12) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
78
|
+
const isLeapYear = year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
|
|
79
|
+
if (isLeapYear && month === 2) {
|
|
80
|
+
daysInMonth[1] = 29;
|
|
81
|
+
}
|
|
82
|
+
if (day < 1 || day > daysInMonth[month - 1]) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
return true;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
31
90
|
// src/index.ts
|
|
32
91
|
var index_exports = {};
|
|
33
92
|
__export(index_exports, {
|
|
@@ -47,6 +106,7 @@ __export(index_exports, {
|
|
|
47
106
|
CheckboxGroup: () => CheckboxGroup,
|
|
48
107
|
CodeSnippet: () => CodeSnippet,
|
|
49
108
|
Container: () => Container,
|
|
109
|
+
DATE_REGEX: () => DATE_REGEX,
|
|
50
110
|
Dialog: () => Dialog,
|
|
51
111
|
DialogContent: () => DialogContent,
|
|
52
112
|
DialogDescription: () => DialogDescription,
|
|
@@ -55,6 +115,7 @@ __export(index_exports, {
|
|
|
55
115
|
DialogTitle: () => DialogTitle,
|
|
56
116
|
Divider: () => Divider,
|
|
57
117
|
Drawer: () => Drawer,
|
|
118
|
+
EMAIL_REGEX: () => EMAIL_REGEX,
|
|
58
119
|
EmptyState: () => EmptyState,
|
|
59
120
|
Form: () => Form,
|
|
60
121
|
FormControl: () => FormControl,
|
|
@@ -63,6 +124,7 @@ __export(index_exports, {
|
|
|
63
124
|
Input: () => Input,
|
|
64
125
|
NativeSelect: () => NativeSelect,
|
|
65
126
|
Nav: () => Nav,
|
|
127
|
+
PHONE_REGEX: () => PHONE_REGEX,
|
|
66
128
|
RadioGroup: () => RadioGroup,
|
|
67
129
|
Rating: () => Rating,
|
|
68
130
|
SectionLayout: () => SectionLayout,
|
|
@@ -73,7 +135,19 @@ __export(index_exports, {
|
|
|
73
135
|
Switch: () => Switch,
|
|
74
136
|
Textarea: () => Textarea,
|
|
75
137
|
ThemeProvider: () => ThemeProvider,
|
|
138
|
+
URL_REGEX: () => URL_REGEX,
|
|
139
|
+
applyFormat: () => applyFormat,
|
|
76
140
|
cn: () => cn,
|
|
141
|
+
formatCreditCard: () => formatCreditCard,
|
|
142
|
+
formatDate: () => formatDate,
|
|
143
|
+
formatDateTime: () => formatDateTime,
|
|
144
|
+
formatPhoneIntl: () => formatPhoneIntl,
|
|
145
|
+
formatPhoneUS: () => formatPhoneUS,
|
|
146
|
+
getRawValue: () => getRawValue,
|
|
147
|
+
isValidDate: () => isValidDate,
|
|
148
|
+
isValidEmail: () => isValidEmail,
|
|
149
|
+
isValidPhone: () => isValidPhone,
|
|
150
|
+
isValidUrl: () => isValidUrl,
|
|
77
151
|
themes: () => themes_default,
|
|
78
152
|
useForm: () => useForm,
|
|
79
153
|
useFormContext: () => useFormContext,
|
|
@@ -234,8 +308,113 @@ Button.displayName = "Button";
|
|
|
234
308
|
// src/ui/input.tsx
|
|
235
309
|
var import_react5 = __toESM(require("react"));
|
|
236
310
|
|
|
311
|
+
// src/lib/formatting.ts
|
|
312
|
+
var formatPhoneUS = (value) => {
|
|
313
|
+
const digits = value.replace(/\D/g, "");
|
|
314
|
+
const limited = digits.slice(0, 10);
|
|
315
|
+
if (limited.length === 0) return "";
|
|
316
|
+
if (limited.length <= 3) return `(${limited}`;
|
|
317
|
+
if (limited.length <= 6)
|
|
318
|
+
return `(${limited.slice(0, 3)}) ${limited.slice(3)}`;
|
|
319
|
+
return `(${limited.slice(0, 3)}) ${limited.slice(3, 6)}-${limited.slice(6)}`;
|
|
320
|
+
};
|
|
321
|
+
var formatPhoneIntl = (value) => {
|
|
322
|
+
let cleaned = value.replace(/[^\d+]/g, "");
|
|
323
|
+
if (!cleaned.startsWith("+")) {
|
|
324
|
+
cleaned = "+" + cleaned;
|
|
325
|
+
}
|
|
326
|
+
cleaned = cleaned.slice(0, 16);
|
|
327
|
+
const digits = cleaned.slice(1);
|
|
328
|
+
if (digits.length === 0) return "+";
|
|
329
|
+
if (digits.length <= 1) return `+${digits}`;
|
|
330
|
+
if (digits.length <= 4) return `+${digits.slice(0, 1)} (${digits.slice(1)}`;
|
|
331
|
+
if (digits.length <= 7)
|
|
332
|
+
return `+${digits.slice(0, 1)} (${digits.slice(1, 4)}) ${digits.slice(4)}`;
|
|
333
|
+
return `+${digits.slice(0, 1)} (${digits.slice(1, 4)}) ${digits.slice(4, 7)}-${digits.slice(7)}`;
|
|
334
|
+
};
|
|
335
|
+
var formatCreditCard = (value) => {
|
|
336
|
+
const digits = value.replace(/\D/g, "");
|
|
337
|
+
const limited = digits.slice(0, 16);
|
|
338
|
+
return limited.replace(/(\d{4})/g, "$1 ").trim();
|
|
339
|
+
};
|
|
340
|
+
var formatDate = (value) => {
|
|
341
|
+
const digits = value.replace(/\D/g, "");
|
|
342
|
+
const limited = digits.slice(0, 8);
|
|
343
|
+
if (limited.length === 0) return "";
|
|
344
|
+
if (limited.length <= 2) return limited;
|
|
345
|
+
if (limited.length <= 4)
|
|
346
|
+
return `${limited.slice(0, 2)}/${limited.slice(2)}`;
|
|
347
|
+
return `${limited.slice(0, 2)}/${limited.slice(2, 4)}/${limited.slice(4)}`;
|
|
348
|
+
};
|
|
349
|
+
var formatDateTime = (value) => {
|
|
350
|
+
const digits = value.replace(/\D/g, "");
|
|
351
|
+
const limited = digits.slice(0, 12);
|
|
352
|
+
if (limited.length === 0) return "";
|
|
353
|
+
if (limited.length <= 2) return limited;
|
|
354
|
+
if (limited.length <= 4)
|
|
355
|
+
return `${limited.slice(0, 2)}/${limited.slice(2)}`;
|
|
356
|
+
if (limited.length <= 8)
|
|
357
|
+
return `${limited.slice(0, 2)}/${limited.slice(2, 4)}/${limited.slice(4)}`;
|
|
358
|
+
const datePart = `${limited.slice(0, 2)}/${limited.slice(2, 4)}/${limited.slice(4, 8)}`;
|
|
359
|
+
if (limited.length <= 10) return `${datePart} ${limited.slice(8)}`;
|
|
360
|
+
let hours = parseInt(limited.slice(8, 10));
|
|
361
|
+
const minutes = limited.slice(10, 12);
|
|
362
|
+
const ampm = hours >= 12 ? "PM" : "AM";
|
|
363
|
+
hours = hours % 12 || 12;
|
|
364
|
+
return `${datePart} ${hours}:${minutes} ${ampm}`;
|
|
365
|
+
};
|
|
366
|
+
var getRawValue = (value, format) => {
|
|
367
|
+
if (format === "date") {
|
|
368
|
+
const digits = value.replace(/\D/g, "");
|
|
369
|
+
if (digits.length === 8) {
|
|
370
|
+
const month = digits.slice(0, 2);
|
|
371
|
+
const day = digits.slice(2, 4);
|
|
372
|
+
const year = digits.slice(4, 8);
|
|
373
|
+
return `${year}-${month}-${day}`;
|
|
374
|
+
}
|
|
375
|
+
return digits;
|
|
376
|
+
}
|
|
377
|
+
if (format === "datetime") {
|
|
378
|
+
const digits = value.replace(/\D/g, "");
|
|
379
|
+
if (digits.length === 12) {
|
|
380
|
+
const month = digits.slice(0, 2);
|
|
381
|
+
const day = digits.slice(2, 4);
|
|
382
|
+
const year = digits.slice(4, 8);
|
|
383
|
+
const hours = digits.slice(8, 10);
|
|
384
|
+
const minutes = digits.slice(10, 12);
|
|
385
|
+
const date = new Date(
|
|
386
|
+
parseInt(year),
|
|
387
|
+
parseInt(month) - 1,
|
|
388
|
+
parseInt(day),
|
|
389
|
+
parseInt(hours),
|
|
390
|
+
parseInt(minutes)
|
|
391
|
+
);
|
|
392
|
+
return date.toISOString();
|
|
393
|
+
}
|
|
394
|
+
return digits;
|
|
395
|
+
}
|
|
396
|
+
return value.replace(/\D/g, "");
|
|
397
|
+
};
|
|
398
|
+
var applyFormat = (value, format) => {
|
|
399
|
+
switch (format) {
|
|
400
|
+
case "phone":
|
|
401
|
+
return formatPhoneUS(value);
|
|
402
|
+
case "phone-intl":
|
|
403
|
+
return formatPhoneIntl(value);
|
|
404
|
+
case "credit-card":
|
|
405
|
+
return formatCreditCard(value);
|
|
406
|
+
case "date":
|
|
407
|
+
return formatDate(value);
|
|
408
|
+
case "datetime":
|
|
409
|
+
return formatDateTime(value);
|
|
410
|
+
default:
|
|
411
|
+
return value;
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
|
|
237
415
|
// src/ui/hooks/useFormField.ts
|
|
238
416
|
var import_react4 = require("react");
|
|
417
|
+
init_validation();
|
|
239
418
|
|
|
240
419
|
// src/ui/form.tsx
|
|
241
420
|
var import_react2 = require("react");
|
|
@@ -807,10 +986,13 @@ function useFormField2(options) {
|
|
|
807
986
|
return errorMessages?.required || "This field is required";
|
|
808
987
|
}
|
|
809
988
|
if (value) {
|
|
810
|
-
if (type === "email" && !
|
|
989
|
+
if (type === "email" && !EMAIL_REGEX.test(value)) {
|
|
811
990
|
return errorMessages?.email || "Please enter a valid email address";
|
|
812
991
|
}
|
|
813
992
|
if (type === "url") {
|
|
993
|
+
if (/^(javascript|data|vbscript|file|about):/i.test(value)) {
|
|
994
|
+
return errorMessages?.url || "Invalid URL protocol";
|
|
995
|
+
}
|
|
814
996
|
try {
|
|
815
997
|
new URL(value);
|
|
816
998
|
} catch {
|
|
@@ -864,10 +1046,15 @@ function useFormField2(options) {
|
|
|
864
1046
|
return errorMessages?.required || "This field is required";
|
|
865
1047
|
}
|
|
866
1048
|
if (value) {
|
|
867
|
-
if (type === "email" && !
|
|
1049
|
+
if (type === "email" && !EMAIL_REGEX.test(value)) {
|
|
868
1050
|
return errorMessages?.email || "Please enter a valid email address";
|
|
869
1051
|
}
|
|
870
1052
|
if (type === "url") {
|
|
1053
|
+
if (/^(javascript|data|vbscript|file|about):/i.test(
|
|
1054
|
+
value
|
|
1055
|
+
)) {
|
|
1056
|
+
return errorMessages?.url || "Invalid URL protocol";
|
|
1057
|
+
}
|
|
871
1058
|
try {
|
|
872
1059
|
new URL(value);
|
|
873
1060
|
} catch {
|
|
@@ -981,12 +1168,31 @@ var Input = import_react5.default.forwardRef(
|
|
|
981
1168
|
validate,
|
|
982
1169
|
onValidationError,
|
|
983
1170
|
pattern,
|
|
1171
|
+
format,
|
|
984
1172
|
errorMessages,
|
|
985
1173
|
...props
|
|
986
1174
|
}, ref) => {
|
|
1175
|
+
const [internalValue, setInternalValue] = import_react5.default.useState("");
|
|
1176
|
+
const dateValidate = import_react5.default.useCallback(
|
|
1177
|
+
async (value) => {
|
|
1178
|
+
if (validate) {
|
|
1179
|
+
const customError = await validate(value);
|
|
1180
|
+
if (customError) return customError;
|
|
1181
|
+
}
|
|
1182
|
+
if (format === "date" && value && value.length === 8) {
|
|
1183
|
+
const { isValidDate: isValidDate2 } = await Promise.resolve().then(() => (init_validation(), validation_exports));
|
|
1184
|
+
const formatted = `${value.slice(0, 2)}/${value.slice(2, 4)}/${value.slice(4, 8)}`;
|
|
1185
|
+
if (!isValidDate2(formatted)) {
|
|
1186
|
+
return errorMessages?.date || "Please enter a valid date";
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
return void 0;
|
|
1190
|
+
},
|
|
1191
|
+
[validate, format, errorMessages]
|
|
1192
|
+
);
|
|
987
1193
|
const {
|
|
988
1194
|
fieldId,
|
|
989
|
-
value:
|
|
1195
|
+
value: hookValue,
|
|
990
1196
|
error: inputError,
|
|
991
1197
|
isDisabled,
|
|
992
1198
|
isRequired,
|
|
@@ -1008,19 +1214,71 @@ var Input = import_react5.default.forwardRef(
|
|
|
1008
1214
|
min: props.min,
|
|
1009
1215
|
max: props.max,
|
|
1010
1216
|
pattern,
|
|
1011
|
-
validate,
|
|
1217
|
+
validate: format === "date" ? dateValidate : validate,
|
|
1012
1218
|
onValidationError,
|
|
1013
1219
|
errorMessages,
|
|
1014
1220
|
idPrefix: "input"
|
|
1015
1221
|
});
|
|
1222
|
+
const inputValue = hookValue !== void 0 ? hookValue : internalValue;
|
|
1223
|
+
const [cursorPosition, setCursorPosition] = import_react5.default.useState(null);
|
|
1016
1224
|
const handleChange = (e) => {
|
|
1017
|
-
|
|
1225
|
+
const input = e.target;
|
|
1226
|
+
const newValue = input.value;
|
|
1227
|
+
const cursorPos = input.selectionStart || 0;
|
|
1228
|
+
if (format && typeof format === "string") {
|
|
1229
|
+
const cleaned = newValue.replace(/\D/g, "");
|
|
1230
|
+
const formatted = applyFormat(cleaned, format);
|
|
1231
|
+
if (hookValue !== void 0) {
|
|
1232
|
+
hookHandleChange(cleaned);
|
|
1233
|
+
} else {
|
|
1234
|
+
setInternalValue(cleaned);
|
|
1235
|
+
}
|
|
1236
|
+
let formattedPos = 0;
|
|
1237
|
+
let digitCount = 0;
|
|
1238
|
+
const targetDigits = cleaned.slice(
|
|
1239
|
+
0,
|
|
1240
|
+
Math.min(cleaned.length, cursorPos)
|
|
1241
|
+
);
|
|
1242
|
+
for (let i = 0; i < formatted.length && digitCount < targetDigits.length; i++) {
|
|
1243
|
+
if (/\d/.test(formatted[i])) {
|
|
1244
|
+
digitCount++;
|
|
1245
|
+
}
|
|
1246
|
+
formattedPos = i + 1;
|
|
1247
|
+
}
|
|
1248
|
+
setCursorPosition(formattedPos);
|
|
1249
|
+
} else {
|
|
1250
|
+
if (hookValue !== void 0) {
|
|
1251
|
+
hookHandleChange(newValue);
|
|
1252
|
+
} else {
|
|
1253
|
+
setInternalValue(newValue);
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1018
1256
|
onChange?.(e);
|
|
1019
1257
|
};
|
|
1020
1258
|
const handleBlur = (e) => {
|
|
1021
|
-
|
|
1259
|
+
const value = e.target.value;
|
|
1260
|
+
const blurValue = format && typeof format === "string" ? value.replace(/\D/g, "") : value;
|
|
1261
|
+
hookHandleBlur(blurValue);
|
|
1022
1262
|
onBlur?.(e);
|
|
1023
1263
|
};
|
|
1264
|
+
const displayValue = import_react5.default.useMemo(() => {
|
|
1265
|
+
if (format && inputValue) {
|
|
1266
|
+
if (typeof format === "function") {
|
|
1267
|
+
return format(inputValue);
|
|
1268
|
+
}
|
|
1269
|
+
return applyFormat(inputValue, format);
|
|
1270
|
+
}
|
|
1271
|
+
return inputValue;
|
|
1272
|
+
}, [format, inputValue]);
|
|
1273
|
+
import_react5.default.useEffect(() => {
|
|
1274
|
+
if (cursorPosition !== null && internalRef.current) {
|
|
1275
|
+
internalRef.current.setSelectionRange(
|
|
1276
|
+
cursorPosition,
|
|
1277
|
+
cursorPosition
|
|
1278
|
+
);
|
|
1279
|
+
setCursorPosition(null);
|
|
1280
|
+
}
|
|
1281
|
+
}, [cursorPosition, displayValue]);
|
|
1024
1282
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1025
1283
|
"div",
|
|
1026
1284
|
{
|
|
@@ -1053,7 +1311,7 @@ var Input = import_react5.default.forwardRef(
|
|
|
1053
1311
|
},
|
|
1054
1312
|
type,
|
|
1055
1313
|
id: fieldId,
|
|
1056
|
-
value:
|
|
1314
|
+
value: displayValue,
|
|
1057
1315
|
onChange: handleChange,
|
|
1058
1316
|
onBlur: handleBlur,
|
|
1059
1317
|
disabled: isDisabled,
|
|
@@ -5247,6 +5505,9 @@ function useTheme() {
|
|
|
5247
5505
|
}
|
|
5248
5506
|
return context;
|
|
5249
5507
|
}
|
|
5508
|
+
|
|
5509
|
+
// src/index.ts
|
|
5510
|
+
init_validation();
|
|
5250
5511
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5251
5512
|
0 && (module.exports = {
|
|
5252
5513
|
Alert,
|
|
@@ -5265,6 +5526,7 @@ function useTheme() {
|
|
|
5265
5526
|
CheckboxGroup,
|
|
5266
5527
|
CodeSnippet,
|
|
5267
5528
|
Container,
|
|
5529
|
+
DATE_REGEX,
|
|
5268
5530
|
Dialog,
|
|
5269
5531
|
DialogContent,
|
|
5270
5532
|
DialogDescription,
|
|
@@ -5273,6 +5535,7 @@ function useTheme() {
|
|
|
5273
5535
|
DialogTitle,
|
|
5274
5536
|
Divider,
|
|
5275
5537
|
Drawer,
|
|
5538
|
+
EMAIL_REGEX,
|
|
5276
5539
|
EmptyState,
|
|
5277
5540
|
Form,
|
|
5278
5541
|
FormControl,
|
|
@@ -5281,6 +5544,7 @@ function useTheme() {
|
|
|
5281
5544
|
Input,
|
|
5282
5545
|
NativeSelect,
|
|
5283
5546
|
Nav,
|
|
5547
|
+
PHONE_REGEX,
|
|
5284
5548
|
RadioGroup,
|
|
5285
5549
|
Rating,
|
|
5286
5550
|
SectionLayout,
|
|
@@ -5291,7 +5555,19 @@ function useTheme() {
|
|
|
5291
5555
|
Switch,
|
|
5292
5556
|
Textarea,
|
|
5293
5557
|
ThemeProvider,
|
|
5558
|
+
URL_REGEX,
|
|
5559
|
+
applyFormat,
|
|
5294
5560
|
cn,
|
|
5561
|
+
formatCreditCard,
|
|
5562
|
+
formatDate,
|
|
5563
|
+
formatDateTime,
|
|
5564
|
+
formatPhoneIntl,
|
|
5565
|
+
formatPhoneUS,
|
|
5566
|
+
getRawValue,
|
|
5567
|
+
isValidDate,
|
|
5568
|
+
isValidEmail,
|
|
5569
|
+
isValidPhone,
|
|
5570
|
+
isValidUrl,
|
|
5295
5571
|
themes,
|
|
5296
5572
|
useForm,
|
|
5297
5573
|
useFormContext,
|