Skip to content

Commit a72c313

Browse files
committed
Add color code check
1 parent b23b9ed commit a72c313

File tree

3 files changed

+58
-2
lines changed

3 files changed

+58
-2
lines changed

lib/l10n/intl_en.arb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@
2121
"phoneErrorText": "This field requires a valid phone number.",
2222
"creditCardExpirationDateErrorText": "This field requires a valid expiration date.",
2323
"creditCardExpiredErrorText": "This credit card has expired.",
24-
"creditCardCVCErrorText": "This field requires a valid CVC code."
24+
"creditCardCVCErrorText": "This field requires a valid CVC code.",
25+
"colorCodeErrorText": "Value should be a valid {colorCode} color code."
2526
}

lib/src/form_builder_validators.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,4 +359,15 @@ class FormBuilderValidators {
359359
true == valueCandidate?.isNotEmpty && !isPhoneNumber(valueCandidate!)
360360
? errorText ?? FormBuilderLocalizations.current.phoneErrorText
361361
: null;
362+
363+
/// [FormFieldValidator] that requires the field's value to be a valid color code.
364+
/// * [formats] is a list of allowed color code formats (e.g., ['hex', 'rgb', 'hsl'])
365+
static FormFieldValidator<String> colorCode({
366+
List<String> formats = const ['hex', 'rgb', 'hsl'],
367+
String? errorText,
368+
}) =>
369+
(valueCandidate) => true == valueCandidate?.isNotEmpty &&
370+
!isColorCode(valueCandidate!, formats: formats)
371+
? errorText ?? FormBuilderLocalizations.current.colorCodeErrorText(formats.join(', '))
372+
: null;
362373
}

lib/src/utils/validators.dart

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,17 @@ RegExp _creditCard = RegExp(
1212
r'^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$',
1313
);
1414

15-
RegExp _phoneNumber = RegExp(r'^(\+?\d{0,1})?\(?\d{3}\)?[-.\s]\d{3}[-.\s]\d{4}$');
15+
RegExp _phoneNumber =
16+
RegExp(r'^(\+?\d{0,1})?\(?\d{3}\)?[-.\s]\d{3}[-.\s]\d{4}$');
1617

1718
RegExp _creditCardExpirationDate = RegExp(r'^[0-1][0-9]/\d{2}$');
1819

20+
RegExp _hexRegExp = RegExp(r'^#[0-9a-fA-F]{6}$');
21+
22+
RegExp _rgbRegExp = RegExp(r'^rgb\(\d{1,3},\s*\d{1,3},\s*\d{1,3}\)$');
23+
24+
RegExp _hslRegExp = RegExp(r'^hsl\(\d+,\s*\d+%,\s*\d+%\)$');
25+
1926
int _maxUrlLength = 2083;
2027

2128
/// check if the string [str] is an email
@@ -284,3 +291,40 @@ bool isNotExpiredCreditCardDate(String str) {
284291

285292
return true;
286293
}
294+
295+
bool isColorCode(String value,
296+
{List<String> formats = const ['hex', 'rgb', 'hsl']}) {
297+
if (formats.contains('hex')) {
298+
if (_hexRegExp.hasMatch(value)) return true;
299+
}
300+
if (formats.contains('rgb')) {
301+
if (_rgbRegExp.hasMatch(value)) {
302+
final parts = value.substring(4, value.length - 1).split(',');
303+
for (final part in parts) {
304+
final int colorValue = int.tryParse(part.trim()) ?? -1;
305+
if (colorValue < 0 || colorValue > 255) {
306+
return false;
307+
}
308+
}
309+
return true;
310+
}
311+
}
312+
if (formats.contains('hsl')) {
313+
if (_hslRegExp.hasMatch(value)) {
314+
final parts = value.substring(4, value.length - 1).split(',');
315+
for (var i = 0; i < parts.length; i++) {
316+
final int colorValue = int.tryParse(parts[i].trim()) ?? -1;
317+
if (i == 0) {
318+
// Hue
319+
if (colorValue < 0 || colorValue > 360) {
320+
return false;
321+
}
322+
} else if (colorValue < 0 || colorValue > 100) {
323+
return false;
324+
}
325+
}
326+
return true;
327+
}
328+
}
329+
return false;
330+
}

0 commit comments

Comments
 (0)