@@ -223,7 +223,6 @@ Validator<String> password({
223223}
224224
225225final _numericRegex = RegExp ('[0-9]' );
226- final _specialRegex = RegExp ('[^A-Za-z0-9]' );
227226
228227({int upperCount, int lowerCount}) _upperAndLowerCaseCounter (String value) {
229228 var uppercaseCount = 0 ;
@@ -351,24 +350,43 @@ Validator<String> hasMinNumericChars({
351350/// Returns a [Validator] function that checks if its [String] input has at
352351/// least [min] special chars. If the input satisfies this condition, the
353352/// validator returns `null` . Otherwise, it returns the default error message
354- /// `FormBuilderLocalizations.current.containsSpecialCharErrorText(min)` , if
355- /// [hasMinSpecialCharsMsg] is not provided.
353+ /// `FormBuilderLocalizations.current.containsNumberErrorText(min)` , if
354+ /// [hasMinNumericCharsMsg] is not provided.
355+ ///
356+ ///
357+ /// # Caveats
358+ /// - The default method for calculating special chars is to make the difference
359+ /// between the total number of chars and the sum of digits and alphabetical
360+ /// chars. The alphabetical chars are counted as those which are affected by
361+ /// the String methods toLowercase/toUppercase.
362+ /// - By default, the validator returned counts the special chars using a
363+ /// language independent unicode mapping, which may not work for some languages.
364+ /// For that situations, the user can provide a custom special counter
365+ /// function.
366+ ///
367+ /// ```dart
368+ /// // US-ASCII special chars
369+ /// final validator = hasMinSpecialChars(customSpecialCounter:(v)=>RegExp('[^A-Za-z0-9]'));
370+ /// ```
356371///
357372/// # Errors
358373/// - Throws an [AssertionError] if [min] is not positive (< 1).
374+ ///
375+ ///
359376Validator <String > hasMinSpecialChars ({
360377 int min = 1 ,
361- RegExp ? regex ,
378+ int Function ( String ) ? customSpecialCounter ,
362379 String Function (int )? hasMinSpecialCharsMsg,
363380}) {
364381 assert (min > 0 , 'min must be positive (at least 1)' );
365382 return (value) {
383+ // todo (optimize) avoid calculating _upperAndLowerCaseCounter when user provides customSpecialCounter
366384 final (lowerCount: lowerCount, upperCount: upperCount) =
367385 _upperAndLowerCaseCounter (value);
368386 final specialCount = value.length -
369- (lowerCount + upperCount + RegExp ( '[0-9]' ) .allMatches (value).length);
387+ (lowerCount + upperCount + _numericRegex .allMatches (value).length);
370388
371- return specialCount >= min
389+ return (customSpecialCounter ? . call (value) ?? specialCount) >= min
372390 ? null
373391 : hasMinSpecialCharsMsg? .call (min) ??
374392 FormBuilderLocalizations .current.containsSpecialCharErrorText (min);
0 commit comments