diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml index 7f51ad8..462a459 100644 --- a/.idea/libraries/Dart_Packages.xml +++ b/.idea/libraries/Dart_Packages.xml @@ -5,190 +5,182 @@ - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/.idea/libraries/Dart_SDK.xml b/.idea/libraries/Dart_SDK.xml index c634881..80dfde6 100644 --- a/.idea/libraries/Dart_SDK.xml +++ b/.idea/libraries/Dart_SDK.xml @@ -1,26 +1,25 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 29701a1..c8a135c 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,7 +1,18 @@ + + - + + + + + + + + + \ No newline at end of file diff --git a/example/ios/Flutter/flutter_export_environment.sh b/example/ios/Flutter/flutter_export_environment.sh index 7891fee..75b90a2 100755 --- a/example/ios/Flutter/flutter_export_environment.sh +++ b/example/ios/Flutter/flutter_export_environment.sh @@ -1,14 +1,13 @@ #!/bin/sh # This is a generated file; do not edit or check into version control. -export "FLUTTER_ROOT=/Users/hahung/Development/flutter" -export "FLUTTER_APPLICATION_PATH=/Users/hahung/Development/Workspace/flutter_packages/flutter_pattern_formatter/example" -export "FLUTTER_TARGET=/Users/hahung/Development/Workspace/flutter_packages/flutter_pattern_formatter/example/lib/main.dart" +export "FLUTTER_ROOT=/Users/mehmet/Developer/flutter/fvm/versions/3.3.0" +export "FLUTTER_APPLICATION_PATH=/Users/mehmet/WORKS/flutter_pattern_formatter/example" +export "COCOAPODS_PARALLEL_CODE_SIGN=true" +export "FLUTTER_TARGET=lib/main.dart" export "FLUTTER_BUILD_DIR=build" -export "SYMROOT=${SOURCE_ROOT}/../build/ios" export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NUMBER=1" -export "DART_DEFINES=flutter.inspector.structuredErrors%3Dtrue" export "DART_OBFUSCATION=false" export "TRACK_WIDGET_CREATION=true" export "TREE_SHAKE_ICONS=false" -export "PACKAGE_CONFIG=/Users/hahung/Development/Workspace/flutter_packages/flutter_pattern_formatter/example/.dart_tool/package_config.json" +export "PACKAGE_CONFIG=.dart_tool/package_config.json" diff --git a/example/pubspec.lock b/example/pubspec.lock index cad0547..fb83001 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0" + version: "2.9.0" boolean_selector: dependency: transitive description: @@ -21,28 +21,21 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" + version: "1.2.1" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" + version: "1.16.0" cupertino_icons: dependency: "direct main" description: @@ -56,7 +49,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" flutter: dependency: "direct main" description: flutter @@ -80,21 +73,28 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10" + version: "0.12.12" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.5" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.8.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.2" pattern_formatter: dependency: "direct main" description: @@ -113,7 +113,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.9.0" stack_trace: dependency: transitive description: @@ -134,34 +134,27 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" + version: "0.4.12" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.2" sdks: - dart: ">=2.12.0 <3.0.0" + dart: ">=2.17.0-0 <3.0.0" diff --git a/lib/numeric_formatter.dart b/lib/numeric_formatter.dart index c69a9ed..af89b50 100644 --- a/lib/numeric_formatter.dart +++ b/lib/numeric_formatter.dart @@ -18,6 +18,7 @@ class ThousandsFormatter extends NumberInputFormatter { final NumberFormat? formatter; final bool allowFraction; + final List _skipValues; ThousandsFormatter({this.formatter, this.allowFraction = false}) : _decimalSeparator = (formatter ?? _formatter).symbols.DECIMAL_SEP, @@ -27,7 +28,32 @@ class ThousandsFormatter extends NumberInputFormatter { _decimalFormatter = FilteringTextInputFormatter.allow(RegExp( allowFraction ? '[0-9]+([${(formatter ?? _formatter).symbols.DECIMAL_SEP}])?' - : r'\d+')); + : r'\d+')), + _skipValues = allowFraction + ? List.generate( + _formatter.maximumFractionDigits + 1, + (index) => + '0${(formatter ?? _formatter).symbols.DECIMAL_SEP}${List.generate(index, (index) => '0').join('')}') + : const []; + + @override + TextEditingValue formatEditUpdate( + TextEditingValue oldValue, TextEditingValue newValue) { + if (allowFraction) { + final indexOfDecimalSeperatorNewValue = + newValue.text.indexOf((formatter ?? _formatter).symbols.DECIMAL_SEP); + if (indexOfDecimalSeperatorNewValue != -1) { + if (_skipValues.map((v) { + final indexOfDecimanSeperator = + v.indexOf((formatter ?? _formatter).symbols.DECIMAL_SEP); + return v.substring(indexOfDecimanSeperator); + }).contains(newValue.text.substring(indexOfDecimalSeperatorNewValue))) { + return newValue; + } + } + } + return super.formatEditUpdate(oldValue, newValue); + } @override String _formatPattern(String? digits) { diff --git a/pubspec.lock b/pubspec.lock index a38f32a..cf017fc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0" + version: "2.9.0" boolean_selector: dependency: transitive description: @@ -21,35 +21,28 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" + version: "1.2.1" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" + version: "1.16.0" fake_async: dependency: transitive description: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" flutter: dependency: "direct main" description: flutter @@ -73,21 +66,28 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10" + version: "0.12.12" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.5" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.8.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.2" sky_engine: dependency: transitive description: flutter @@ -99,7 +99,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.9.0" stack_trace: dependency: transitive description: @@ -120,34 +120,27 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" + version: "0.4.12" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.2" sdks: - dart: ">=2.12.0 <3.0.0" + dart: ">=2.17.0-0 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index aaaf601..27b9639 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: pattern_formatter description: A Flutter package provides some implementations of TextInputFormatter that format input with pre-defined patterns -version: 2.0.0 +version: 2.0.1 author: Hung Duy Ha homepage: https://github.com/hnvn/flutter_pattern_formatter @@ -11,7 +11,7 @@ dependencies: flutter: sdk: flutter - intl: ^0.17.0 + intl: dev_dependencies: flutter_test: diff --git a/test/pattern_input_formatter_test.dart b/test/pattern_input_formatter_test.dart index 395caa8..e69d2c3 100644 --- a/test/pattern_input_formatter_test.dart +++ b/test/pattern_input_formatter_test.dart @@ -13,6 +13,11 @@ void main() { _numericFormatterSmokeTest() { final ThousandsFormatter thousandsFormatter = ThousandsFormatter(formatter: NumberFormat.decimalPattern('en_US')); + + final ThousandsFormatter thousandsFormatterAllowedFraction = + ThousandsFormatter( + formatter: NumberFormat.decimalPattern('en_US'), allowFraction: true); + final ThousandsFormatter decimalFormatterUS = ThousandsFormatter( formatter: NumberFormat.decimalPattern('en_US'), allowFraction: true); final ThousandsFormatter decimalFormatterES = ThousandsFormatter( @@ -53,6 +58,62 @@ _numericFormatterSmokeTest() { expect(newValue4.text, equals('12')); }); + test('when input is below than 1 return expected value', () { + final newValue2 = thousandsFormatterAllowedFraction.formatEditUpdate( + TextEditingValue( + text: '20.', selection: TextSelection.collapsed(offset: 2)), + TextEditingValue( + text: '20.0', selection: TextSelection.collapsed(offset: 3))); + + expect(newValue2.text, equals('20.0')); + }); + + test('when input is below than 1 return expected value', () { + final newValue1 = thousandsFormatterAllowedFraction.formatEditUpdate( + TextEditingValue( + text: '0', selection: TextSelection.collapsed(offset: 1)), + TextEditingValue( + text: '0.', selection: TextSelection.collapsed(offset: 2))); + + final newValue2 = thousandsFormatterAllowedFraction.formatEditUpdate( + TextEditingValue( + text: '0.', selection: TextSelection.collapsed(offset: 2)), + TextEditingValue( + text: '0.0', selection: TextSelection.collapsed(offset: 3))); + + final newValue3 = thousandsFormatterAllowedFraction.formatEditUpdate( + TextEditingValue( + text: '0.0', selection: TextSelection.collapsed(offset: 3)), + TextEditingValue( + text: '0.00', selection: TextSelection.collapsed(offset: 4))); + + final newValue4 = thousandsFormatterAllowedFraction.formatEditUpdate( + TextEditingValue( + text: '0.00', selection: TextSelection.collapsed(offset: 4)), + TextEditingValue( + text: '0.005', selection: TextSelection.collapsed(offset: 5))); + + final newValue5 = thousandsFormatterAllowedFraction.formatEditUpdate( + TextEditingValue( + text: '0.', selection: TextSelection.collapsed(offset: 2)), + TextEditingValue( + text: '0.2', selection: TextSelection.collapsed(offset: 3))); + + final newValue6 = thousandsFormatterAllowedFraction.formatEditUpdate( + TextEditingValue( + text: '0.0', selection: TextSelection.collapsed(offset: 3)), + TextEditingValue( + text: '0.02', selection: TextSelection.collapsed(offset: 4))); + + expect(newValue1.text, equals('0.')); + expect(newValue2.text, equals('0.0')); + expect(newValue3.text, equals('0.00')); + expect(newValue4.text, equals('0.005')); + + expect(newValue5.text, equals('0.2')); + expect(newValue6.text, equals('0.02')); + }); + test('thousands grouping smoke test', () { final newValue1 = thousandsFormatter.formatEditUpdate( TextEditingValue(