├── .fvmrc ├── .github ├── dependabot.yaml └── workflows │ ├── base-beta.yaml │ ├── base.yaml │ └── stale.yaml ├── .gitignore ├── .metadata ├── .pubignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── example ├── .gitignore ├── .metadata ├── README.md ├── analysis_options.yaml ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values-night │ │ │ │ └── styles.xml │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── assets │ └── screenshot.png ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ ├── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ ├── Contents.json │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ │ └── LaunchImage.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ └── README.md │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h │ └── RunnerTests │ │ └── RunnerTests.swift ├── l10n.yaml ├── lib │ ├── home_page.dart │ ├── l10n.dart │ ├── l10n │ │ └── app_en.arb │ ├── main.dart │ └── override_form_builder_localizations_en.dart ├── macos │ ├── .gitignore │ ├── Flutter │ │ ├── Flutter-Debug.xcconfig │ │ ├── Flutter-Release.xcconfig │ │ └── GeneratedPluginRegistrant.swift │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ ├── Contents.json │ │ │ │ ├── app_icon_1024.png │ │ │ │ ├── app_icon_128.png │ │ │ │ ├── app_icon_16.png │ │ │ │ ├── app_icon_256.png │ │ │ │ ├── app_icon_32.png │ │ │ │ ├── app_icon_512.png │ │ │ │ └── app_icon_64.png │ │ ├── Base.lproj │ │ │ └── MainMenu.xib │ │ ├── Configs │ │ │ ├── AppInfo.xcconfig │ │ │ ├── Debug.xcconfig │ │ │ ├── Release.xcconfig │ │ │ └── Warnings.xcconfig │ │ ├── DebugProfile.entitlements │ │ ├── Info.plist │ │ ├── MainFlutterWindow.swift │ │ └── Release.entitlements │ └── RunnerTests │ │ └── RunnerTests.swift ├── pubspec.yaml ├── test │ └── widget_test.dart ├── web │ ├── favicon.png │ ├── icons │ │ ├── Icon-192.png │ │ ├── Icon-512.png │ │ ├── Icon-maskable-192.png │ │ └── Icon-maskable-512.png │ ├── index.html │ └── manifest.json └── windows │ ├── .gitignore │ ├── CMakeLists.txt │ ├── flutter │ ├── CMakeLists.txt │ ├── generated_plugin_registrant.cc │ ├── generated_plugin_registrant.h │ └── generated_plugins.cmake │ └── runner │ ├── CMakeLists.txt │ ├── Runner.rc │ ├── flutter_window.cpp │ ├── flutter_window.h │ ├── main.cpp │ ├── resource.h │ ├── resources │ └── app_icon.ico │ ├── runner.exe.manifest │ ├── utils.cpp │ ├── utils.h │ ├── win32_window.cpp │ └── win32_window.h ├── l10n.yaml ├── lib ├── form_builder_validators.dart ├── l10n │ ├── intl_ar.arb │ ├── intl_bg.arb │ ├── intl_bn.arb │ ├── intl_bs.arb │ ├── intl_ca.arb │ ├── intl_cs.arb │ ├── intl_da.arb │ ├── intl_de.arb │ ├── intl_el.arb │ ├── intl_en.arb │ ├── intl_es.arb │ ├── intl_et.arb │ ├── intl_fa.arb │ ├── intl_fi.arb │ ├── intl_fr.arb │ ├── intl_he.arb │ ├── intl_hi.arb │ ├── intl_hr.arb │ ├── intl_hu.arb │ ├── intl_id.arb │ ├── intl_it.arb │ ├── intl_ja.arb │ ├── intl_km.arb │ ├── intl_ko.arb │ ├── intl_ku.arb │ ├── intl_lo.arb │ ├── intl_lv.arb │ ├── intl_mn.arb │ ├── intl_ms.arb │ ├── intl_ne.arb │ ├── intl_nl.arb │ ├── intl_no.arb │ ├── intl_pl.arb │ ├── intl_pt.arb │ ├── intl_ro.arb │ ├── intl_ru.arb │ ├── intl_sk.arb │ ├── intl_sl.arb │ ├── intl_sq.arb │ ├── intl_sv.arb │ ├── intl_sw.arb │ ├── intl_ta.arb │ ├── intl_th.arb │ ├── intl_tr.arb │ ├── intl_uk.arb │ ├── intl_vi.arb │ ├── intl_zh.arb │ └── intl_zh_Hant.arb ├── localization │ └── l10n.dart └── src │ ├── base_validator.dart │ ├── bool │ ├── bool.dart │ ├── has_lowercase_chars_validator.dart │ ├── has_numeric_chars_validator.dart │ ├── has_special_chars_validator.dart │ ├── has_uppercase_chars_validator.dart │ ├── is_false_validator.dart │ └── is_true_validator.dart │ ├── collection │ ├── collection.dart │ ├── contains_element_validator.dart │ ├── equal_length_validator.dart │ ├── max_length_validator.dart │ ├── min_length_validator.dart │ ├── range_validator.dart │ └── unique_validator.dart │ ├── core │ ├── aggregate_validator.dart │ ├── compose_validator.dart │ ├── conditional_validator.dart │ ├── core.dart │ ├── default_value_validator.dart │ ├── equal_validator.dart │ ├── log_validator.dart │ ├── not_equal_validator.dart │ ├── or_validator.dart │ ├── required_validator.dart │ ├── skip_when_validator.dart │ └── transform_validator.dart │ ├── datetime │ ├── date_future_validator.dart │ ├── date_past_validator.dart │ ├── date_range_validator.dart │ ├── date_time_validator.dart │ ├── date_validator.dart │ ├── datetime.dart │ ├── time_validator.dart │ └── timezone_validator.dart │ ├── file │ ├── file.dart │ ├── file_extension_validator.dart │ ├── file_name_validator.dart │ ├── file_size_validator.dart │ ├── mime_type_validator.dart │ └── path_validator.dart │ ├── finance │ ├── bic_validator.dart │ ├── credit_card_cvc_validator.dart │ ├── credit_card_expiration_date_validator.dart │ ├── credit_card_validator.dart │ ├── finance.dart │ └── iban_validator.dart │ ├── form_builder_validators.dart │ ├── form_field_validator_extensions.dart │ ├── identity │ ├── city_validator.dart │ ├── country_validator.dart │ ├── firstname_validator.dart │ ├── identity.dart │ ├── lastname_validator.dart │ ├── passport_number_validator.dart │ ├── password_validator.dart │ ├── ssn_validator.dart │ ├── state_validator.dart │ ├── street_validator.dart │ ├── username_validator.dart │ └── zip_code_validator.dart │ ├── network │ ├── email_validator.dart │ ├── ip_validator.dart │ ├── latitude_validator.dart │ ├── longitude_validator.dart │ ├── mac_address_validator.dart │ ├── network.dart │ ├── phone_number_validator.dart │ ├── port_number_validator.dart │ └── url_validator.dart │ ├── numeric │ ├── between_validator.dart │ ├── even_number_validator.dart │ ├── float_validator.dart │ ├── hexadecimal_validator.dart │ ├── integer_validator.dart │ ├── max_validator.dart │ ├── min_validator.dart │ ├── negative_number_validator.dart │ ├── not_zero_number_validator.dart │ ├── numeric.dart │ ├── numeric_validator.dart │ ├── odd_number_validator.dart │ ├── positive_number_validator.dart │ └── prime_validator.dart │ ├── string │ ├── alphabetical_validator.dart │ ├── contains_validator.dart │ ├── ends_with_validator.dart │ ├── lowercase_validator.dart │ ├── match_not_validator.dart │ ├── match_validator.dart │ ├── max_words_count_validator.dart │ ├── min_words_count_validator.dart │ ├── single_line_validator.dart │ ├── starts_with_validator.dart │ ├── string.dart │ └── uppercase_validator.dart │ ├── translated_validator.dart │ └── usecase │ ├── base64_validator.dart │ ├── color_code_validator.dart │ ├── duns_validator.dart │ ├── isbn_validator.dart │ ├── json_validator.dart │ ├── language_code_validator.dart │ ├── licenseplate_validator.dart │ ├── usecase.dart │ ├── uuid_validator.dart │ └── vin_validator.dart ├── pubspec.yaml └── test ├── src ├── bool │ ├── has_lowercase_chars_validator_test.dart │ ├── has_numeric_chars_validator_test.dart │ ├── has_special_chars_validator_test.dart │ ├── has_uppercase_chars_validator_test.dart │ ├── is_false_validator_test.dart │ └── is_true_validator_test.dart ├── collection │ ├── contains_element_validator_test.dart │ ├── equal_length_validator_test.dart │ ├── max_length_validator_test.dart │ ├── min_length_validator_test.dart │ ├── range_validator_test.dart │ └── unique_validator_test.dart ├── core │ ├── aggregate_validator_test.dart │ ├── compose_validator_test.dart │ ├── conditional_validator_test.dart │ ├── default_value_validator_test.dart │ ├── equal_validator_test.dart │ ├── log_validator_test.dart │ ├── not_equal_validator_test.dart │ ├── or_validator_test.dart │ ├── required_validator_test.dart │ ├── skip_when_validator_test.dart │ └── transform_validator_test.dart ├── datetime │ ├── date_future_validator_test.dart │ ├── date_past_validator_test.dart │ ├── date_range_validator_test.dart │ ├── date_time_validator_test.dart │ ├── date_validator_test.dart │ ├── time_validator_test.dart │ └── timezone_validator_test.dart ├── file │ ├── file_extension_validator_test.dart │ ├── file_name_validator_test.dart │ ├── file_size_validator_test.dart │ ├── mime_type_validator_test.dart │ └── path_validator_test.dart ├── finance │ ├── bic_validator_test.dart │ ├── credit_card_cvc_validator_test.dart │ ├── credit_card_expiration_date_validator_test.dart │ ├── credit_card_validator_test.dart │ └── iban_validator_test.dart ├── form_field_validator_extensions_test.dart ├── identity │ ├── city_validator_test.dart │ ├── country_validator_test.dart │ ├── firstname_validator_test.dart │ ├── lastname_validator_test.dart │ ├── passport_number_validator_test.dart │ ├── password_validator_test.dart │ ├── ssn_validator_test.dart │ ├── state_validator_test.dart │ ├── street_validator_test.dart │ ├── username_validator_test.dart │ └── zip_code_validator_test.dart ├── network │ ├── email_validator_test.dart │ ├── ip_validator_test.dart │ ├── latitude_validator_test.dart │ ├── longitude_validator_test.dart │ ├── mac_address_validator_test.dart │ ├── phone_number_validator_test.dart │ ├── port_number_validator_test.dart │ └── url_validator_test.dart ├── numeric │ ├── between_validator_test.dart │ ├── even_number_validator_test.dart │ ├── float_validator_test.dart │ ├── hexadecimal_validator_test.dart │ ├── integer_validator_test.dart │ ├── max_validator_test.dart │ ├── min_validator_test.dart │ ├── negative_number_validator_test.dart │ ├── not_zero_number_validator_test.dart │ ├── numeric_validator_test.dart │ ├── odd_number_validator_test.dart │ ├── positive_number_validator_test.dart │ └── prime_validator_test.dart ├── string │ ├── alphabetical_validator_test.dart │ ├── contains_validator_test.dart │ ├── ends_with_validator_test.dart │ ├── lowercase_validator_test.dart │ ├── match_not_validator_test.dart │ ├── match_validator_test.dart │ ├── max_words_count_validator_test.dart │ ├── min_words_count_validator_test.dart │ ├── single_line_validator_test.dart │ ├── starts_with_validator_test.dart │ └── uppercase_validator_test.dart └── usecase │ ├── base64_validator_test.dart │ ├── color_code_validator_test.dart │ ├── duns_validator_test.dart │ ├── isbn_validator_test.dart │ ├── json_validator_test.dart │ ├── language_code_validator_test.dart │ ├── licenseplate_validator_test.dart │ ├── uuid_validator_test.dart │ └── vin_validator_test.dart └── tests_helper.dart /.fvmrc: -------------------------------------------------------------------------------- 1 | { 2 | "flutter": "stable", 3 | "flavors": { 4 | "stable": "stable", 5 | "beta": "beta" 6 | } 7 | } -------------------------------------------------------------------------------- /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | enable-beta-ecosystems: true 3 | updates: 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | - package-ecosystem: "pub" 9 | directory: "/" 10 | schedule: 11 | interval: "daily" -------------------------------------------------------------------------------- /.github/workflows/base-beta.yaml: -------------------------------------------------------------------------------- 1 | name: Base (beta) 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 */15 * *' # Runs every 15 days for verifying changes on Flutter beta channel 6 | push: 7 | branches: [beta] 8 | tags: 9 | - '[0-9]+.[0-9]+.[0-9]+-*' 10 | 11 | pull_request: 12 | branches: [beta] 13 | 14 | workflow_dispatch: 15 | 16 | # This ensures that previous jobs for the PR are canceled when PR is updated 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.ref }} 19 | cancel-in-progress: true 20 | 21 | jobs: 22 | build: 23 | uses: flutter-form-builder-ecosystem/.github/.github/workflows/minimal-quality.yaml@main 24 | with: 25 | codecov-name: form_builder_validators 26 | fvm-flavor: beta 27 | enable-generate-l10n: true 28 | example: 29 | uses: flutter-form-builder-ecosystem/.github/.github/workflows/build-examples.yaml@main 30 | with: 31 | fvm-flavor: beta 32 | enable-generate-l10n: true 33 | 34 | 35 | deployment: 36 | permissions: 37 | id-token: write 38 | uses: flutter-form-builder-ecosystem/.github/.github/workflows/deployment.yaml@main 39 | with: 40 | enable-generate-l10n: true 41 | if: ${{ github.ref_type == 'tag' }} 42 | needs: [build, example] 43 | -------------------------------------------------------------------------------- /.github/workflows/base.yaml: -------------------------------------------------------------------------------- 1 | name: Base 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | tags: 7 | - '[0-9]+.[0-9]+.[0-9]+' 8 | 9 | pull_request: 10 | branches: [main] 11 | 12 | workflow_dispatch: 13 | 14 | # This ensures that previous jobs for the PR are canceled when PR is updated 15 | concurrency: 16 | group: ${{ github.workflow }}-${{ github.ref }} 17 | cancel-in-progress: true 18 | 19 | jobs: 20 | build: 21 | uses: flutter-form-builder-ecosystem/.github/.github/workflows/minimal-quality.yaml@main 22 | with: 23 | codecov-name: form_builder_validators 24 | enable-generate-l10n: true 25 | example: 26 | uses: flutter-form-builder-ecosystem/.github/.github/workflows/build-examples.yaml@main 27 | with: 28 | enable-generate-l10n: true 29 | 30 | 31 | deployment: 32 | permissions: 33 | id-token: write 34 | uses: flutter-form-builder-ecosystem/.github/.github/workflows/deployment.yaml@main 35 | with: 36 | enable-generate-l10n: true 37 | if: ${{ github.ref_type == 'tag' }} 38 | needs: [build, example] 39 | -------------------------------------------------------------------------------- /.github/workflows/stale.yaml: -------------------------------------------------------------------------------- 1 | name: "Close stale issues" 2 | on: 3 | schedule: 4 | - cron: "30 1 * * *" 5 | 6 | jobs: 7 | stale: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/stale@v9 11 | with: 12 | repo-token: ${{ secrets.GITHUB_TOKEN }} 13 | stale-issue-message: "This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days." 14 | close-issue-message: "This issue was closed because it has been stalled for 7 days with no activity." 15 | days-before-stale: 30 16 | days-before-pr-close: -1 17 | any-of-issue-labels: 'awaiting author response' 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | .fvm/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | .vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | build/ 33 | pubspec.lock 34 | 35 | # Android related 36 | **/android/**/gradle-wrapper.jar 37 | **/android/.gradle 38 | **/android/captures/ 39 | **/android/gradlew 40 | **/android/gradlew.bat 41 | **/android/local.properties 42 | **/android/**/GeneratedPluginRegistrant.java 43 | 44 | # iOS/XCode related 45 | **/ios/**/*.mode1v3 46 | **/ios/**/*.mode2v3 47 | **/ios/**/*.moved-aside 48 | **/ios/**/*.pbxuser 49 | **/ios/**/*.perspectivev3 50 | **/ios/**/*sync/ 51 | **/ios/**/.sconsign.dblite 52 | **/ios/**/.tags* 53 | **/ios/**/.vagrant/ 54 | **/ios/**/DerivedData/ 55 | **/ios/**/Icon? 56 | **/ios/**/Pods/ 57 | **/ios/**/.symlinks/ 58 | **/ios/**/profile 59 | **/ios/**/xcuserdata 60 | **/ios/.generated/ 61 | **/ios/Flutter/App.framework 62 | **/ios/Flutter/Flutter.framework 63 | **/ios/Flutter/Flutter.podspec 64 | **/ios/Flutter/Generated.xcconfig 65 | **/ios/Flutter/app.flx 66 | **/ios/Flutter/app.zip 67 | **/ios/Flutter/flutter_assets/ 68 | **/ios/Flutter/flutter_export_environment.sh 69 | **/ios/ServiceDefinitions.json 70 | **/ios/Runner/GeneratedPluginRegistrant.* 71 | 72 | # Exceptions to above rules. 73 | !**/ios/**/default.mode1v3 74 | !**/ios/**/default.mode2v3 75 | !**/ios/**/default.pbxuser 76 | !**/ios/**/default.perspectivev3 77 | 78 | # L10n files 79 | **/intl 80 | coverage/lcov.info 81 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: adc687823a831bbebe28bdccfac1a628ca621513 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /.pubignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | .fvm/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | build/ 33 | pubspec.lock 34 | 35 | # Android related 36 | **/android/**/gradle-wrapper.jar 37 | **/android/.gradle 38 | **/android/captures/ 39 | **/android/gradlew 40 | **/android/gradlew.bat 41 | **/android/local.properties 42 | **/android/**/GeneratedPluginRegistrant.java 43 | 44 | # iOS/XCode related 45 | **/ios/**/*.mode1v3 46 | **/ios/**/*.mode2v3 47 | **/ios/**/*.moved-aside 48 | **/ios/**/*.pbxuser 49 | **/ios/**/*.perspectivev3 50 | **/ios/**/*sync/ 51 | **/ios/**/.sconsign.dblite 52 | **/ios/**/.tags* 53 | **/ios/**/.vagrant/ 54 | **/ios/**/DerivedData/ 55 | **/ios/**/Icon? 56 | **/ios/**/Pods/ 57 | **/ios/**/.symlinks/ 58 | **/ios/**/profile 59 | **/ios/**/xcuserdata 60 | **/ios/.generated/ 61 | **/ios/Flutter/App.framework 62 | **/ios/Flutter/Flutter.framework 63 | **/ios/Flutter/Flutter.podspec 64 | **/ios/Flutter/Generated.xcconfig 65 | **/ios/Flutter/app.flx 66 | **/ios/Flutter/app.zip 67 | **/ios/Flutter/flutter_assets/ 68 | **/ios/Flutter/flutter_export_environment.sh 69 | **/ios/ServiceDefinitions.json 70 | **/ios/Runner/GeneratedPluginRegistrant.* 71 | 72 | # Exceptions to above rules. 73 | !**/ios/**/default.mode1v3 74 | !**/ios/**/default.mode2v3 75 | !**/ios/**/default.pbxuser 76 | !**/ios/**/default.perspectivev3 77 | 78 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022 Flutter Form Builder Ecosystem 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | analyzer: 3 | exclude: 4 | - lib/localization/intl/** 5 | 6 | linter: 7 | rules: 8 | one_member_abstracts: false 9 | prefer_relative_imports: true 10 | always_use_package_imports: false 11 | always_specify_types: true 12 | omit_local_variable_types: false 13 | public_member_api_docs: true 14 | directives_ordering: true 15 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | 36 | # Symbolication related 37 | app.*.symbols 38 | 39 | # Obfuscation related 40 | app.*.map.json 41 | 42 | # Android Studio will place build artifacts here 43 | /android/app/debug 44 | /android/app/profile 45 | /android/app/release 46 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "5dcb86f68f239346676ceb1ed1ea385bd215fba1" 8 | channel: "stable" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 17 | base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 18 | - platform: android 19 | create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 20 | base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 21 | - platform: ios 22 | create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 23 | base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 24 | - platform: macos 25 | create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 26 | base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 27 | - platform: web 28 | create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 29 | base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 30 | - platform: windows 31 | create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 32 | base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 33 | 34 | # User provided section 35 | 36 | # List of Local paths (relative to this file) that should be 37 | # ignored by the migrate tool. 38 | # 39 | # Files that are not part of the templates will be ignored by default. 40 | unmanaged_files: 41 | - 'lib/main.dart' 42 | - 'ios/Runner.xcodeproj/project.pbxproj' 43 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | Example app for form_builder_validators 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | analyzer: 3 | exclude: 4 | - lib/localization/intl/** 5 | 6 | linter: 7 | rules: 8 | one_member_abstracts: false 9 | prefer_relative_imports: true 10 | always_use_package_imports: false 11 | always_specify_types: true 12 | omit_local_variable_types: false 13 | public_member_api_docs: true -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/to/reference-keystore 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. 5 | id "dev.flutter.flutter-gradle-plugin" 6 | } 7 | 8 | android { 9 | namespace = "com.example.example" 10 | compileSdk = flutter.compileSdkVersion 11 | ndkVersion = flutter.ndkVersion 12 | 13 | compileOptions { 14 | sourceCompatibility = JavaVersion.VERSION_1_8 15 | targetCompatibility = JavaVersion.VERSION_1_8 16 | } 17 | 18 | kotlinOptions { 19 | jvmTarget = JavaVersion.VERSION_1_8 20 | } 21 | 22 | defaultConfig { 23 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 24 | applicationId = "com.example.example" 25 | // You can update the following values to match your application needs. 26 | // For more information, see: https://flutter.dev/to/review-gradle-config. 27 | minSdk = flutter.minSdkVersion 28 | targetSdk = flutter.targetSdkVersion 29 | versionCode = flutter.versionCode 30 | versionName = flutter.versionName 31 | } 32 | 33 | buildTypes { 34 | release { 35 | // TODO: Add your own signing config for the release build. 36 | // Signing with the debug keys for now, so `flutter run --release` works. 37 | signingConfig = signingConfigs.debug 38 | } 39 | } 40 | } 41 | 42 | flutter { 43 | source = "../.." 44 | } 45 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/example/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() 6 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | rootProject.buildDir = "../build" 9 | subprojects { 10 | project.buildDir = "${rootProject.buildDir}/${project.name}" 11 | } 12 | subprojects { 13 | project.evaluationDependsOn(":app") 14 | } 15 | 16 | tasks.register("clean", Delete) { 17 | delete rootProject.buildDir 18 | } 19 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | }() 9 | 10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 11 | 12 | repositories { 13 | google() 14 | mavenCentral() 15 | gradlePluginPortal() 16 | } 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 21 | id "com.android.application" version "8.1.0" apply false 22 | id "org.jetbrains.kotlin.android" version "1.8.22" apply false 23 | } 24 | 25 | include ":app" 26 | -------------------------------------------------------------------------------- /example/assets/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/assets/screenshot.png -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Example 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | example 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | CADisableMinimumFrameDurationOnPhone 45 | 46 | UIApplicationSupportsIndirectInputEvents 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /example/l10n.yaml: -------------------------------------------------------------------------------- 1 | # https://docs.flutter.dev/development/accessibility-and-localization/internationalization#adding-your-own-localized-messages 2 | # https://docs.google.com/document/d/10e0saTfAv32OZLRmONy866vnaw0I2jwL8zukykpgWBc 3 | arb-dir: lib/l10n 4 | template-arb-file: app_en.arb 5 | synthetic-package: false 6 | output-dir: lib/localization/intl 7 | output-localization-file: app_localizations.dart 8 | output-class: AppLocalizations 9 | nullable-getter: false 10 | #untranslated-messages-file: build/untranslated-messages.txt -------------------------------------------------------------------------------- /example/lib/l10n.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'localization/intl/app_localizations.dart'; 4 | 5 | /// Extension for the app localization. 6 | extension AppLocalizationsExtensions on BuildContext { 7 | /// Get the L10n localization. 8 | AppLocalizations get l10n => AppLocalizations.of(this); 9 | } 10 | -------------------------------------------------------------------------------- /example/lib/l10n/app_en.arb: -------------------------------------------------------------------------------- 1 | { 2 | "@@locale": "en" 3 | } -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_localizations/flutter_localizations.dart'; 3 | import 'package:form_builder_validators/form_builder_validators.dart'; 4 | 5 | import 'home_page.dart'; 6 | import 'localization/intl/app_localizations.dart'; 7 | import 'override_form_builder_localizations_en.dart'; 8 | 9 | void main() { 10 | runApp(const MyApp()); 11 | } 12 | 13 | /// The main application widget. 14 | class MyApp extends StatelessWidget { 15 | /// The main application widget constructor. 16 | const MyApp({super.key}); 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | return MaterialApp( 21 | title: 'Form Builder Validators Demo', 22 | theme: ThemeData(primarySwatch: Colors.blue), 23 | home: const HomePage(), 24 | supportedLocales: AppLocalizations.supportedLocales, 25 | localizationsDelegates: const >[ 26 | ...GlobalMaterialLocalizations.delegates, 27 | // Placed in front of `FormBuilderLocalizations.delegate` 28 | ...AppLocalizations.localizationsDelegates, 29 | OverrideFormBuilderLocalizationsEn.delegate, 30 | FormBuilderLocalizations.delegate, 31 | ], 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /example/lib/override_form_builder_localizations_en.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:form_builder_validators/form_builder_validators.dart'; 4 | 5 | /// Created by ipcjs on 2022/10/31. 6 | /// 7 | /// Overrides the default FormBuilderLocalizationsImplEn class for English localizations. 8 | class OverrideFormBuilderLocalizationsEn 9 | extends FormBuilderLocalizationsImplEn { 10 | /// Constructor for the override class. 11 | OverrideFormBuilderLocalizationsEn(); 12 | 13 | /// The delegate for the override class. 14 | static const LocalizationsDelegate delegate = 15 | _LocalizationsDelegate(); 16 | 17 | /// The list of supported locales for the override class. 18 | static const List supportedLocales = [Locale('en')]; 19 | 20 | // Override a field and return your translation. 21 | @override 22 | String get requiredErrorText => 'override: This field cannot be empty.'; 23 | } 24 | 25 | class _LocalizationsDelegate 26 | extends LocalizationsDelegate { 27 | const _LocalizationsDelegate(); 28 | 29 | @override 30 | Future load(Locale locale) { 31 | final OverrideFormBuilderLocalizationsEn instance = 32 | OverrideFormBuilderLocalizationsEn(); 33 | // IMPORTANT!! must to invoke setCurrentInstance() 34 | FormBuilderLocalizations.setCurrentInstance(instance); 35 | return SynchronousFuture(instance); 36 | } 37 | 38 | @override 39 | bool isSupported(Locale locale) => 40 | OverrideFormBuilderLocalizationsEn.supportedLocales.contains(locale); 41 | 42 | @override 43 | bool shouldReload(_LocalizationsDelegate old) => false; 44 | } 45 | -------------------------------------------------------------------------------- /example/macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | 9 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 10 | } 11 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @NSApplicationMain 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /example/macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = example 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2024 com.example. All rights reserved. 15 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /example/macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /example/macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: Example app for form_builder_validators 3 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 4 | version: 1.0.0+1 5 | 6 | environment: 7 | sdk: ">=3.6.0 <4.0.0" 8 | flutter: ">=3.27.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | flutter_localizations: 14 | sdk: flutter 15 | form_builder_validators: 16 | path: ../ 17 | 18 | dev_dependencies: 19 | flutter_lints: ">=5.0.0 <6.0.0" 20 | flutter_test: 21 | sdk: flutter 22 | 23 | flutter: 24 | uses-material-design: true 25 | generate: true -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | 3 | void main() { 4 | testWidgets('FormBuilderTextField -- Hello Planet', 5 | (WidgetTester tester) async { 6 | expect(true, isTrue); // 😀 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/web/favicon.png -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | example 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "short_name": "example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /example/windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /example/windows/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | 10 | void RegisterPlugins(flutter::PluginRegistry* registry) { 11 | } 12 | -------------------------------------------------------------------------------- /example/windows/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void RegisterPlugins(flutter::PluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /example/windows/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | ) 7 | 8 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 9 | ) 10 | 11 | set(PLUGIN_BUNDLED_LIBRARIES) 12 | 13 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 14 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) 15 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 16 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 18 | endforeach(plugin) 19 | 20 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 21 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) 22 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 23 | endforeach(ffi_plugin) 24 | -------------------------------------------------------------------------------- /example/windows/runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | project(runner LANGUAGES CXX) 3 | 4 | # Define the application target. To change its name, change BINARY_NAME in the 5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer 6 | # work. 7 | # 8 | # Any new source files that you add to the application should be added here. 9 | add_executable(${BINARY_NAME} WIN32 10 | "flutter_window.cpp" 11 | "main.cpp" 12 | "utils.cpp" 13 | "win32_window.cpp" 14 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 15 | "Runner.rc" 16 | "runner.exe.manifest" 17 | ) 18 | 19 | # Apply the standard set of build settings. This can be removed for applications 20 | # that need different build settings. 21 | apply_standard_settings(${BINARY_NAME}) 22 | 23 | # Add preprocessor definitions for the build version. 24 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") 25 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") 26 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") 27 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") 28 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") 29 | 30 | # Disable Windows macros that collide with C++ standard library functions. 31 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") 32 | 33 | # Add dependency libraries and include directories. Add any application-specific 34 | # dependencies here. 35 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) 36 | target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") 37 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") 38 | 39 | # Run the Flutter tool portions of the build. This must not be removed. 40 | add_dependencies(${BINARY_NAME} flutter_assemble) 41 | -------------------------------------------------------------------------------- /example/windows/runner/flutter_window.cpp: -------------------------------------------------------------------------------- 1 | #include "flutter_window.h" 2 | 3 | #include 4 | 5 | #include "flutter/generated_plugin_registrant.h" 6 | 7 | FlutterWindow::FlutterWindow(const flutter::DartProject& project) 8 | : project_(project) {} 9 | 10 | FlutterWindow::~FlutterWindow() {} 11 | 12 | bool FlutterWindow::OnCreate() { 13 | if (!Win32Window::OnCreate()) { 14 | return false; 15 | } 16 | 17 | RECT frame = GetClientArea(); 18 | 19 | // The size here must match the window dimensions to avoid unnecessary surface 20 | // creation / destruction in the startup path. 21 | flutter_controller_ = std::make_unique( 22 | frame.right - frame.left, frame.bottom - frame.top, project_); 23 | // Ensure that basic setup of the controller was successful. 24 | if (!flutter_controller_->engine() || !flutter_controller_->view()) { 25 | return false; 26 | } 27 | RegisterPlugins(flutter_controller_->engine()); 28 | SetChildContent(flutter_controller_->view()->GetNativeWindow()); 29 | 30 | flutter_controller_->engine()->SetNextFrameCallback([&]() { 31 | this->Show(); 32 | }); 33 | 34 | // Flutter can complete the first frame before the "show window" callback is 35 | // registered. The following call ensures a frame is pending to ensure the 36 | // window is shown. It is a no-op if the first frame hasn't completed yet. 37 | flutter_controller_->ForceRedraw(); 38 | 39 | return true; 40 | } 41 | 42 | void FlutterWindow::OnDestroy() { 43 | if (flutter_controller_) { 44 | flutter_controller_ = nullptr; 45 | } 46 | 47 | Win32Window::OnDestroy(); 48 | } 49 | 50 | LRESULT 51 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message, 52 | WPARAM const wparam, 53 | LPARAM const lparam) noexcept { 54 | // Give Flutter, including plugins, an opportunity to handle window messages. 55 | if (flutter_controller_) { 56 | std::optional result = 57 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, 58 | lparam); 59 | if (result) { 60 | return *result; 61 | } 62 | } 63 | 64 | switch (message) { 65 | case WM_FONTCHANGE: 66 | flutter_controller_->engine()->ReloadSystemFonts(); 67 | break; 68 | } 69 | 70 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam); 71 | } 72 | -------------------------------------------------------------------------------- /example/windows/runner/flutter_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_FLUTTER_WINDOW_H_ 2 | #define RUNNER_FLUTTER_WINDOW_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "win32_window.h" 10 | 11 | // A window that does nothing but host a Flutter view. 12 | class FlutterWindow : public Win32Window { 13 | public: 14 | // Creates a new FlutterWindow hosting a Flutter view running |project|. 15 | explicit FlutterWindow(const flutter::DartProject& project); 16 | virtual ~FlutterWindow(); 17 | 18 | protected: 19 | // Win32Window: 20 | bool OnCreate() override; 21 | void OnDestroy() override; 22 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, 23 | LPARAM const lparam) noexcept override; 24 | 25 | private: 26 | // The project to run. 27 | flutter::DartProject project_; 28 | 29 | // The Flutter instance hosted by this window. 30 | std::unique_ptr flutter_controller_; 31 | }; 32 | 33 | #endif // RUNNER_FLUTTER_WINDOW_H_ 34 | -------------------------------------------------------------------------------- /example/windows/runner/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "flutter_window.h" 6 | #include "utils.h" 7 | 8 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, 9 | _In_ wchar_t *command_line, _In_ int show_command) { 10 | // Attach to console when present (e.g., 'flutter run') or create a 11 | // new console when running with a debugger. 12 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { 13 | CreateAndAttachConsole(); 14 | } 15 | 16 | // Initialize COM, so that it is available for use in the library and/or 17 | // plugins. 18 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); 19 | 20 | flutter::DartProject project(L"data"); 21 | 22 | std::vector command_line_arguments = 23 | GetCommandLineArguments(); 24 | 25 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); 26 | 27 | FlutterWindow window(project); 28 | Win32Window::Point origin(10, 10); 29 | Win32Window::Size size(1280, 720); 30 | if (!window.Create(L"example", origin, size)) { 31 | return EXIT_FAILURE; 32 | } 33 | window.SetQuitOnClose(true); 34 | 35 | ::MSG msg; 36 | while (::GetMessage(&msg, nullptr, 0, 0)) { 37 | ::TranslateMessage(&msg); 38 | ::DispatchMessage(&msg); 39 | } 40 | 41 | ::CoUninitialize(); 42 | return EXIT_SUCCESS; 43 | } 44 | -------------------------------------------------------------------------------- /example/windows/runner/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Runner.rc 4 | // 5 | #define IDI_APP_ICON 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /example/windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flutter-form-builder-ecosystem/form_builder_validators/eafb7662827fe938034be6d2081c9d2844a46c10/example/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /example/windows/runner/runner.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PerMonitorV2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /example/windows/runner/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | void CreateAndAttachConsole() { 11 | if (::AllocConsole()) { 12 | FILE *unused; 13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) { 14 | _dup2(_fileno(stdout), 1); 15 | } 16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) { 17 | _dup2(_fileno(stdout), 2); 18 | } 19 | std::ios::sync_with_stdio(); 20 | FlutterDesktopResyncOutputStreams(); 21 | } 22 | } 23 | 24 | std::vector GetCommandLineArguments() { 25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. 26 | int argc; 27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); 28 | if (argv == nullptr) { 29 | return std::vector(); 30 | } 31 | 32 | std::vector command_line_arguments; 33 | 34 | // Skip the first argument as it's the binary name. 35 | for (int i = 1; i < argc; i++) { 36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i])); 37 | } 38 | 39 | ::LocalFree(argv); 40 | 41 | return command_line_arguments; 42 | } 43 | 44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) { 45 | if (utf16_string == nullptr) { 46 | return std::string(); 47 | } 48 | unsigned int target_length = ::WideCharToMultiByte( 49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 50 | -1, nullptr, 0, nullptr, nullptr) 51 | -1; // remove the trailing null character 52 | int input_length = (int)wcslen(utf16_string); 53 | std::string utf8_string; 54 | if (target_length == 0 || target_length > utf8_string.max_size()) { 55 | return utf8_string; 56 | } 57 | utf8_string.resize(target_length); 58 | int converted_length = ::WideCharToMultiByte( 59 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 60 | input_length, utf8_string.data(), target_length, nullptr, nullptr); 61 | if (converted_length == 0) { 62 | return std::string(); 63 | } 64 | return utf8_string; 65 | } 66 | -------------------------------------------------------------------------------- /example/windows/runner/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_UTILS_H_ 2 | #define RUNNER_UTILS_H_ 3 | 4 | #include 5 | #include 6 | 7 | // Creates a console for the process, and redirects stdout and stderr to 8 | // it for both the runner and the Flutter library. 9 | void CreateAndAttachConsole(); 10 | 11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string 12 | // encoded in UTF-8. Returns an empty std::string on failure. 13 | std::string Utf8FromUtf16(const wchar_t* utf16_string); 14 | 15 | // Gets the command line arguments passed in as a std::vector, 16 | // encoded in UTF-8. Returns an empty std::vector on failure. 17 | std::vector GetCommandLineArguments(); 18 | 19 | #endif // RUNNER_UTILS_H_ 20 | -------------------------------------------------------------------------------- /l10n.yaml: -------------------------------------------------------------------------------- 1 | # https://docs.flutter.dev/development/accessibility-and-localization/internationalization#adding-your-own-localized-messages 2 | # https://docs.google.com/document/d/10e0saTfAv32OZLRmONy866vnaw0I2jwL8zukykpgWBc 3 | arb-dir: lib/l10n 4 | template-arb-file: intl_en.arb 5 | synthetic-package: false 6 | output-dir: lib/localization/intl 7 | output-localization-file: messages.dart 8 | output-class: FormBuilderLocalizationsImpl 9 | nullable-getter: false 10 | #untranslated-messages-file: build/untranslated-messages.txt -------------------------------------------------------------------------------- /lib/form_builder_validators.dart: -------------------------------------------------------------------------------- 1 | export 'localization/intl/messages.dart'; 2 | export 'localization/intl/messages_ar.dart'; 3 | export 'localization/intl/messages_bn.dart'; 4 | export 'localization/intl/messages_bs.dart'; 5 | export 'localization/intl/messages_ca.dart'; 6 | export 'localization/intl/messages_cs.dart'; 7 | export 'localization/intl/messages_de.dart'; 8 | export 'localization/intl/messages_en.dart'; 9 | export 'localization/intl/messages_es.dart'; 10 | export 'localization/intl/messages_et.dart'; 11 | export 'localization/intl/messages_fa.dart'; 12 | export 'localization/intl/messages_fr.dart'; 13 | export 'localization/intl/messages_hr.dart'; 14 | export 'localization/intl/messages_hu.dart'; 15 | export 'localization/intl/messages_id.dart'; 16 | export 'localization/intl/messages_it.dart'; 17 | export 'localization/intl/messages_ja.dart'; 18 | export 'localization/intl/messages_ko.dart'; 19 | export 'localization/intl/messages_lo.dart'; 20 | export 'localization/intl/messages_ms.dart'; 21 | export 'localization/intl/messages_nl.dart'; 22 | export 'localization/intl/messages_pl.dart'; 23 | export 'localization/intl/messages_pt.dart'; 24 | export 'localization/intl/messages_ro.dart'; 25 | export 'localization/intl/messages_ru.dart'; 26 | export 'localization/intl/messages_sk.dart'; 27 | export 'localization/intl/messages_sl.dart'; 28 | export 'localization/intl/messages_sw.dart'; 29 | export 'localization/intl/messages_th.dart'; 30 | export 'localization/intl/messages_tr.dart'; 31 | export 'localization/intl/messages_uk.dart'; 32 | export 'localization/intl/messages_zh.dart'; 33 | export 'localization/l10n.dart'; 34 | export 'src/base_validator.dart'; 35 | export 'src/bool/bool.dart'; 36 | export 'src/collection/collection.dart'; 37 | export 'src/core/core.dart'; 38 | export 'src/datetime/datetime.dart'; 39 | export 'src/file/file.dart'; 40 | export 'src/finance/finance.dart'; 41 | export 'src/form_builder_validators.dart'; 42 | export 'src/form_field_validator_extensions.dart'; 43 | export 'src/identity/identity.dart'; 44 | export 'src/network/network.dart'; 45 | export 'src/numeric/numeric.dart'; 46 | export 'src/string/string.dart'; 47 | export 'src/translated_validator.dart'; 48 | export 'src/usecase/usecase.dart'; 49 | -------------------------------------------------------------------------------- /lib/src/base_validator.dart: -------------------------------------------------------------------------------- 1 | /// Base class for all validators. 2 | abstract class BaseValidator { 3 | /// Creates a new instance of the validator. 4 | const BaseValidator({String? errorText, this.checkNullOrEmpty = true}) 5 | : _errorText = errorText; 6 | 7 | /// Backing field for [errorText]. 8 | final String? _errorText; 9 | 10 | /// {@template base_validator_error_text} 11 | /// The error message returned if the value is invalid. 12 | /// {@endtemplate} 13 | String? get errorText => _errorText; 14 | 15 | /// {@template base_validator_null_check} 16 | /// Whether to check if the value is null or empty. 17 | /// {@endtemplate} 18 | final bool checkNullOrEmpty; 19 | 20 | /// Validates the value and checks if it is null or empty. 21 | String? validate(T? valueCandidate) { 22 | final bool isNullOrEmpty = this.isNullOrEmpty(valueCandidate); 23 | 24 | if (checkNullOrEmpty && isNullOrEmpty) { 25 | return errorText; 26 | } else if (!checkNullOrEmpty && isNullOrEmpty) { 27 | return null; 28 | } else { 29 | return validateValue(valueCandidate as T); 30 | } 31 | } 32 | 33 | /// Checks if the value is null or empty. 34 | /// Returns `true` if the value is null or empty, otherwise `false`. 35 | /// The value is considered empty if it is a [String], [Iterable], or [Map] 36 | /// and it is empty or contains only whitespace characters. 37 | /// If the value is not a [String], [Iterable], or [Map], it is considered 38 | /// empty if it is `null`. 39 | bool isNullOrEmpty(T? valueCandidate) { 40 | return valueCandidate == null || 41 | (valueCandidate is String && valueCandidate.trim().isEmpty) || 42 | (valueCandidate is Iterable && valueCandidate.isEmpty) || 43 | (valueCandidate is Map && valueCandidate.isEmpty); 44 | } 45 | 46 | /// Validates the value. 47 | /// Returns `null` if the value is valid, otherwise an error message. 48 | /// Call validate() instead of this method when using the validator. 49 | String? validateValue(T valueCandidate); 50 | } 51 | -------------------------------------------------------------------------------- /lib/src/bool/bool.dart: -------------------------------------------------------------------------------- 1 | export 'has_lowercase_chars_validator.dart'; 2 | export 'has_numeric_chars_validator.dart'; 3 | export 'has_special_chars_validator.dart'; 4 | export 'has_uppercase_chars_validator.dart'; 5 | export 'is_false_validator.dart'; 6 | export 'is_true_validator.dart'; 7 | -------------------------------------------------------------------------------- /lib/src/bool/has_lowercase_chars_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template has_lowercase_chars_template} 4 | /// [HasLowercaseCharsValidator] extends [TranslatedValidator] to validate if a string 5 | /// contains a specified minimum number of lowercase characters. 6 | /// 7 | /// ## Parameters: 8 | /// 9 | /// - [atLeast] The minimum number of lowercase characters required. 10 | /// - [regex] The regular expression used to identify lowercase characters. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// 13 | /// {@macro lower_case_template} 14 | /// {@endtemplate} 15 | class HasLowercaseCharsValidator extends TranslatedValidator { 16 | /// Constructor for the lowercase characters validator. 17 | HasLowercaseCharsValidator({ 18 | this.atLeast = 1, 19 | 20 | /// {@macro lower_case_template} 21 | RegExp? regex, 22 | 23 | /// {@macro base_validator_error_text} 24 | super.errorText, 25 | 26 | /// {@macro base_validator_null_check} 27 | super.checkNullOrEmpty, 28 | }) : regex = regex ?? _lowerCase; 29 | 30 | /// The minimum number of lowercase characters required. 31 | final int atLeast; 32 | 33 | /// The regular expression used to identify lowercase characters. 34 | final RegExp regex; 35 | 36 | @override 37 | String get translatedErrorText => 38 | FormBuilderLocalizations.current.containsLowercaseCharErrorText(atLeast); 39 | 40 | /// {@template lower_case_template} 41 | /// This regex matches any character that is a lowercase letter (a-z). 42 | /// 43 | /// - It includes all lowercase letters. 44 | /// - It can be used to find lowercase characters. 45 | /// 46 | /// Examples: a, b, c 47 | /// {@endtemplate} 48 | static final RegExp _lowerCase = RegExp('[a-z]'); 49 | 50 | @override 51 | String? validateValue(String valueCandidate) { 52 | return lowercaseCharLength(valueCandidate) >= atLeast ? null : errorText; 53 | } 54 | 55 | /// Calculates the number of lowercase characters in the given value. 56 | /// 57 | /// ## Parameters: 58 | /// - [value] The string to be evaluated. 59 | /// 60 | /// ## Returns: 61 | /// The count of lowercase characters in the string. 62 | int lowercaseCharLength(String value) { 63 | return regex.allMatches(value).length; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /lib/src/bool/has_numeric_chars_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template has_numeric_chars_template} 4 | /// [HasNumericCharsValidator] extends [TranslatedValidator] to validate if a string 5 | /// contains a specified minimum number of numeric characters (digits). 6 | /// 7 | /// ## Parameters: 8 | /// 9 | /// - [atLeast] The minimum number of numeric characters required. 10 | /// - [regex] The regular expression used to identify numeric characters. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// 13 | /// {@macro numeric_chars_template} 14 | /// {@endtemplate} 15 | class HasNumericCharsValidator extends TranslatedValidator { 16 | /// Constructor for the numeric characters validator. 17 | HasNumericCharsValidator({ 18 | this.atLeast = 1, 19 | 20 | /// {@macro numeric_chars_template} 21 | RegExp? regex, 22 | 23 | /// {@macro base_validator_error_text} 24 | super.errorText, 25 | 26 | /// {@macro base_validator_null_check} 27 | super.checkNullOrEmpty, 28 | }) : regex = regex ?? _number; 29 | 30 | /// The minimum number of numeric characters required. 31 | final int atLeast; 32 | 33 | /// The regular expression used to identify numeric characters. 34 | final RegExp regex; 35 | 36 | @override 37 | String get translatedErrorText => 38 | FormBuilderLocalizations.current.containsNumberErrorText(atLeast); 39 | 40 | /// {@template numeric_chars_template} 41 | /// This regex matches any character that is a digit (0-9). 42 | /// 43 | /// - It includes all numeric digits. 44 | /// - It can be used to find numeric characters. 45 | /// 46 | /// Examples: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 47 | /// {@endtemplate} 48 | static final RegExp _number = RegExp('[0-9]'); 49 | 50 | @override 51 | String? validateValue(String valueCandidate) { 52 | return numberCharLength(valueCandidate) >= atLeast ? null : errorText; 53 | } 54 | 55 | /// Calculates the number of numeric characters in the given value. 56 | /// 57 | /// ## Parameters: 58 | /// - [value] The string to be evaluated. 59 | /// 60 | /// ## Returns: 61 | /// The count of numeric characters in the string. 62 | int numberCharLength(String value) { 63 | return regex.allMatches(value).length; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /lib/src/bool/has_special_chars_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template has_special_chars_template} 4 | /// [HasSpecialCharsValidator] extends [TranslatedValidator] to validate if a string 5 | /// contains a specified minimum number of special characters. 6 | /// 7 | /// ## Parameters: 8 | /// 9 | /// - [atLeast] The minimum number of special characters required. 10 | /// - [regex] The regular expression used to identify special characters. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// 13 | /// {@macro special_chars_template} 14 | /// {@endtemplate} 15 | class HasSpecialCharsValidator extends TranslatedValidator { 16 | /// Constructor for the special characters validator. 17 | HasSpecialCharsValidator({ 18 | this.atLeast = 1, 19 | 20 | /// {@macro special_chars_template} 21 | RegExp? regex, 22 | 23 | /// {@macro base_validator_error_text} 24 | super.errorText, 25 | 26 | /// {@macro base_validator_null_check} 27 | super.checkNullOrEmpty, 28 | }) : regex = regex ?? _specialChar; 29 | 30 | /// The minimum number of special characters required. 31 | final int atLeast; 32 | 33 | /// The regular expression used to identify special characters. 34 | final RegExp regex; 35 | 36 | @override 37 | String get translatedErrorText => 38 | FormBuilderLocalizations.current.containsSpecialCharErrorText(atLeast); 39 | 40 | /// {@template special_chars_template} 41 | /// This regex matches any character that is not a letter (A-Z, a-z) or a digit (0-9). 42 | /// 43 | /// - It includes special characters and symbols. 44 | /// - It can be used to find non-alphanumeric characters. 45 | /// 46 | /// Examples: @, #, % 47 | /// {@endtemplate} 48 | static final RegExp _specialChar = RegExp('[^A-Za-z0-9]'); 49 | 50 | @override 51 | String? validateValue(String valueCandidate) { 52 | return specialCharLength(valueCandidate) >= atLeast ? null : errorText; 53 | } 54 | 55 | /// Calculates the number of special characters in the given value. 56 | /// 57 | /// ## Parameters: 58 | /// - [value] The string to be evaluated. 59 | /// 60 | /// ## Returns: 61 | /// The count of special characters in the string. 62 | int specialCharLength(String value) { 63 | return regex.allMatches(value).length; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /lib/src/bool/has_uppercase_chars_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template has_uppercase_chars_template} 4 | /// [HasUppercaseCharsValidator] extends [TranslatedValidator] to validate if a string 5 | /// contains a specified minimum number of uppercase characters. 6 | /// 7 | /// ## Parameters: 8 | /// 9 | /// - [atLeast] The minimum number of uppercase characters required. 10 | /// - [regex] The regular expression used to identify uppercase characters. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// 13 | /// {@macro upper_case_template} 14 | /// {@endtemplate} 15 | class HasUppercaseCharsValidator extends TranslatedValidator { 16 | /// Constructor for the uppercase characters validator. 17 | HasUppercaseCharsValidator({ 18 | this.atLeast = 1, 19 | 20 | /// {@macro upper_case_template} 21 | RegExp? regex, 22 | 23 | /// {@macro base_validator_error_text} 24 | super.errorText, 25 | 26 | /// {@macro base_validator_null_check} 27 | super.checkNullOrEmpty, 28 | }) : regex = regex ?? _upperCase; 29 | 30 | /// The minimum number of uppercase characters required. 31 | final int atLeast; 32 | 33 | /// The regular expression used to identify uppercase characters. 34 | final RegExp regex; 35 | 36 | @override 37 | String get translatedErrorText => 38 | FormBuilderLocalizations.current.containsUppercaseCharErrorText(atLeast); 39 | 40 | /// {@template upper_case_template} 41 | /// This regex matches any character that is an uppercase letter (A-Z). 42 | /// 43 | /// - It includes all uppercase letters. 44 | /// - It can be used to find uppercase characters. 45 | /// 46 | /// Examples: A, B, C 47 | /// {@endtemplate} 48 | static final RegExp _upperCase = RegExp('[A-Z]'); 49 | 50 | @override 51 | String? validateValue(String valueCandidate) { 52 | return uppercaseCharLength(valueCandidate) >= atLeast ? null : errorText; 53 | } 54 | 55 | /// Calculates the number of uppercase characters in the given value. 56 | /// 57 | /// ## Parameters: 58 | /// - [value] The string to be evaluated. 59 | /// 60 | /// ## Returns: 61 | /// The count of uppercase characters in the string. 62 | int uppercaseCharLength(String value) { 63 | return regex.allMatches(value).length; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /lib/src/bool/is_false_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template is_false_validator_template} 4 | /// [IsFalseValidator] extends [TranslatedValidator] to validate if a boolean value is false. 5 | /// 6 | /// ## Parameters: 7 | /// 8 | /// - [errorText] The error message returned if the validation fails. 9 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 10 | /// 11 | /// {@endtemplate} 12 | class IsFalseValidator extends TranslatedValidator { 13 | /// Constructor for the false value validator. 14 | const IsFalseValidator({ 15 | /// {@macro base_validator_error_text} 16 | super.errorText, 17 | 18 | /// {@macro base_validator_null_check} 19 | super.checkNullOrEmpty, 20 | }); 21 | 22 | @override 23 | String get translatedErrorText => 24 | FormBuilderLocalizations.current.mustBeFalseErrorText; 25 | 26 | @override 27 | String? validateValue(bool valueCandidate) { 28 | return valueCandidate == false ? null : errorText; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/src/bool/is_true_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template is_true_validator_template} 4 | /// [IsTrueValidator] extends [TranslatedValidator] to validate if a boolean value is true. 5 | /// 6 | /// ## Parameters: 7 | /// 8 | /// - [errorText] The error message returned if the validation fails. 9 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 10 | /// 11 | /// {@endtemplate} 12 | class IsTrueValidator extends TranslatedValidator { 13 | /// Constructor for the true value validator. 14 | const IsTrueValidator({ 15 | /// {@macro base_validator_error_text} 16 | super.errorText, 17 | 18 | /// {@macro base_validator_null_check} 19 | super.checkNullOrEmpty, 20 | }); 21 | 22 | @override 23 | String get translatedErrorText => 24 | FormBuilderLocalizations.current.mustBeTrueErrorText; 25 | 26 | @override 27 | String? validateValue(bool valueCandidate) { 28 | return valueCandidate == true ? null : errorText; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/src/collection/collection.dart: -------------------------------------------------------------------------------- 1 | export 'contains_element_validator.dart'; 2 | export 'equal_length_validator.dart'; 3 | export 'max_length_validator.dart'; 4 | export 'min_length_validator.dart'; 5 | export 'range_validator.dart'; 6 | export 'unique_validator.dart'; 7 | -------------------------------------------------------------------------------- /lib/src/collection/contains_element_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template contains_element_validator_template} 4 | /// [ContainsElementValidator] extends [TranslatedValidator] to validate if a value is 5 | /// contained within a specified list of values. 6 | /// 7 | /// ## Parameters: 8 | /// 9 | /// - [values] The list of values to check against. 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class ContainsElementValidator extends TranslatedValidator { 15 | /// Constructor for the contains element validator. 16 | const ContainsElementValidator( 17 | this.values, { 18 | /// {@macro base_validator_error_text} 19 | super.errorText, 20 | 21 | /// {@macro base_validator_null_check} 22 | super.checkNullOrEmpty, 23 | }); 24 | 25 | /// The list of values to check against. 26 | final List values; 27 | 28 | @override 29 | String get translatedErrorText => 30 | FormBuilderLocalizations.current.containsElementErrorText; 31 | 32 | @override 33 | String? validateValue(T valueCandidate) { 34 | return values.contains(valueCandidate) ? null : errorText; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/src/collection/equal_length_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template equal_length_validator_template} 4 | /// [EqualLengthValidator] extends [TranslatedValidator] to validate if a value has a specified length. 5 | /// 6 | /// This validator works with various types, including String, Iterable, and Map. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [length] The exact length the value should have. 11 | /// - [allowEmpty] Whether to allow empty values. 12 | /// - [errorText] The error message returned if the validation fails. 13 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 14 | /// 15 | /// {@endtemplate} 16 | class EqualLengthValidator extends TranslatedValidator { 17 | /// Constructor for the equal length validator. 18 | const EqualLengthValidator( 19 | this.length, { 20 | this.allowEmpty = false, 21 | 22 | /// {@macro base_validator_error_text} 23 | super.errorText, 24 | 25 | /// {@macro base_validator_null_check} 26 | super.checkNullOrEmpty, 27 | }); 28 | 29 | /// The exact length the value should have. 30 | final int length; 31 | 32 | /// Whether to allow empty values. 33 | final bool allowEmpty; 34 | 35 | @override 36 | String get translatedErrorText => 37 | FormBuilderLocalizations.current.equalLengthErrorText(length); 38 | 39 | @override 40 | String? validateValue(T valueCandidate) { 41 | int valueLength = 0; 42 | 43 | if (valueCandidate is String) valueLength = valueCandidate.length; 44 | if (valueCandidate is Iterable) valueLength = valueCandidate.length; 45 | if (valueCandidate is Map) valueLength = valueCandidate.length; 46 | 47 | return valueLength != length && (!allowEmpty || valueLength > 0) 48 | ? errorText 49 | : null; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/src/collection/max_length_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template max_length_validator_template} 4 | /// [MaxLengthValidator] extends [TranslatedValidator] to validate if a value does not exceed a specified maximum length. 5 | /// 6 | /// This validator works with various types, including String, Iterable, and Map. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [maxLength] The maximum length the value is allowed to have. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class MaxLengthValidator extends TranslatedValidator { 16 | /// Constructor for the maximum length validator. 17 | const MaxLengthValidator( 18 | this.maxLength, { 19 | /// {@macro base_validator_error_text} 20 | super.errorText, 21 | 22 | /// {@macro base_validator_null_check} 23 | super.checkNullOrEmpty, 24 | }); 25 | 26 | /// The maximum length the value is allowed to have. 27 | final int maxLength; 28 | 29 | @override 30 | String get translatedErrorText => 31 | FormBuilderLocalizations.current.maxLengthErrorText(maxLength); 32 | 33 | @override 34 | String? validateValue(T valueCandidate) { 35 | int valueLength = 0; 36 | 37 | if (valueCandidate is String) valueLength = valueCandidate.length; 38 | if (valueCandidate is Iterable) valueLength = valueCandidate.length; 39 | if (valueCandidate is Map) valueLength = valueCandidate.length; 40 | 41 | return valueLength > maxLength ? errorText : null; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/src/collection/min_length_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template min_length_validator_template} 4 | /// [MinLengthValidator] extends [TranslatedValidator] to validate if a value meets a specified minimum length. 5 | /// 6 | /// This validator works with various types, including String, Iterable, and Map. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [minLength] The minimum length the value is required to have. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class MinLengthValidator extends TranslatedValidator { 16 | /// Constructor for the minimum length validator. 17 | const MinLengthValidator( 18 | this.minLength, { 19 | /// {@macro base_validator_error_text} 20 | super.errorText, 21 | 22 | /// {@macro base_validator_null_check} 23 | super.checkNullOrEmpty, 24 | }); 25 | 26 | /// The minimum length the value is required to have. 27 | final int minLength; 28 | 29 | @override 30 | String get translatedErrorText => 31 | FormBuilderLocalizations.current.minLengthErrorText(minLength); 32 | 33 | @override 34 | String? validateValue(T valueCandidate) { 35 | int valueLength = 0; 36 | 37 | if (valueCandidate is String) valueLength = valueCandidate.length; 38 | if (valueCandidate is Iterable) valueLength = valueCandidate.length; 39 | if (valueCandidate is Map) valueLength = valueCandidate.length; 40 | 41 | return valueLength < minLength ? errorText : null; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/src/collection/unique_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template unique_validator_template} 4 | /// [UniqueValidator] extends [TranslatedValidator] to validate if a value is unique within a specified list of values. 5 | /// 6 | /// ## Parameters: 7 | /// 8 | /// - [values] The list of values to check against for uniqueness. 9 | /// - [errorText] The error message returned if the validation fails. 10 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 11 | /// 12 | /// {@endtemplate} 13 | class UniqueValidator extends TranslatedValidator { 14 | /// Constructor for the unique value validator. 15 | const UniqueValidator( 16 | this.values, { 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | /// The list of values to check against for uniqueness. 25 | final List values; 26 | 27 | @override 28 | String get translatedErrorText => 29 | FormBuilderLocalizations.current.uniqueErrorText; 30 | 31 | @override 32 | String? validateValue(T valueCandidate) { 33 | return values.where((T element) => element == valueCandidate).length != 1 34 | ? errorText 35 | : null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/core/aggregate_validator.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | import '../../form_builder_validators.dart'; 4 | 5 | /// {@template aggregate_validator_template} 6 | /// [AggregateValidator] extends [BaseValidator] to validate a value using a list of multiple validators. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [validators] The list of validators to apply to the value. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. This is set to false by default. 12 | /// 13 | /// {@endtemplate} 14 | class AggregateValidator extends BaseValidator { 15 | /// Constructor for the aggregate validator. 16 | const AggregateValidator(this.validators) : super(checkNullOrEmpty: false); 17 | 18 | /// The list of validators to apply to the value. 19 | final List> validators; 20 | 21 | @override 22 | String? validate(T? valueCandidate) { 23 | return validateValue(valueCandidate); 24 | } 25 | 26 | @override 27 | String? validateValue(T? valueCandidate) { 28 | final List errors = []; 29 | for (final FormFieldValidator validator in validators) { 30 | final String? error = validator(valueCandidate); 31 | if (error != null) { 32 | errors.add(error); 33 | } 34 | } 35 | return errors.isNotEmpty ? errors.join('\n') : null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/core/compose_validator.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | import '../../form_builder_validators.dart'; 4 | 5 | /// {@template compose_validator_template} 6 | /// [ComposeValidator] extends [BaseValidator] to validate a value using a list of validators, 7 | /// returning the first validation error encountered. 8 | /// 9 | /// ## Parameters: 10 | /// 11 | /// - [validators] The list of validators to apply to the value. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. This is set to false by default. 13 | /// 14 | /// {@endtemplate} 15 | class ComposeValidator extends BaseValidator { 16 | /// Constructor for the compose validator. 17 | const ComposeValidator(this.validators) : super(checkNullOrEmpty: false); 18 | 19 | /// The list of validators to apply to the value. 20 | final List> validators; 21 | 22 | @override 23 | String? validate(T? valueCandidate) { 24 | return validateValue(valueCandidate); 25 | } 26 | 27 | @override 28 | String? validateValue(T? valueCandidate) { 29 | for (final FormFieldValidator validator in validators) { 30 | final String? validatorResult = validator.call(valueCandidate); 31 | if (validatorResult != null) { 32 | return validatorResult; 33 | } 34 | } 35 | return null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/core/conditional_validator.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | import '../../form_builder_validators.dart'; 4 | 5 | /// {@template conditional_validator_template} 6 | /// [ConditionalValidator] extends [BaseValidator] to conditionally validate a value based on a provided condition. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [condition] A function that returns a boolean indicating whether the validator should be applied. 11 | /// - [validator] The validator to apply if the condition is met. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. This is set to false by default. 13 | /// 14 | /// {@endtemplate} 15 | class ConditionalValidator extends BaseValidator { 16 | /// Constructor for the conditional validator. 17 | const ConditionalValidator( 18 | this.condition, 19 | this.validator, 20 | ) : super(checkNullOrEmpty: false); 21 | 22 | /// A function that returns a boolean indicating whether the validator should be applied. 23 | final bool Function(T? value) condition; 24 | 25 | /// The validator to apply if the condition is met. 26 | final FormFieldValidator validator; 27 | 28 | @override 29 | String? validate(T? valueCandidate) { 30 | return validateValue(valueCandidate); 31 | } 32 | 33 | @override 34 | String? validateValue(T? valueCandidate) { 35 | if (condition(valueCandidate)) { 36 | return validator.call(valueCandidate); 37 | } 38 | return null; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/src/core/core.dart: -------------------------------------------------------------------------------- 1 | export 'aggregate_validator.dart'; 2 | export 'compose_validator.dart'; 3 | export 'conditional_validator.dart'; 4 | export 'default_value_validator.dart'; 5 | export 'equal_validator.dart'; 6 | export 'log_validator.dart'; 7 | export 'not_equal_validator.dart'; 8 | export 'or_validator.dart'; 9 | export 'required_validator.dart'; 10 | export 'skip_when_validator.dart'; 11 | export 'transform_validator.dart'; 12 | -------------------------------------------------------------------------------- /lib/src/core/default_value_validator.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | import '../../form_builder_validators.dart'; 4 | 5 | /// {@template default_value_validator_template} 6 | /// [DefaultValueValidator] extends [BaseValidator] to validate a value using a default value if the value is null. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [defaultValue] The default value to use if the valueCandidate is null. 11 | /// - [validator] The validator to apply to the value or the default value. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. This is set to false by default. 13 | /// 14 | /// {@endtemplate} 15 | class DefaultValueValidator extends BaseValidator { 16 | /// Constructor for the default value validator. 17 | const DefaultValueValidator(this.defaultValue, this.validator) 18 | : super(checkNullOrEmpty: false); 19 | 20 | /// The default value to use if the valueCandidate is null. 21 | final T defaultValue; 22 | 23 | /// The validator to apply to the value or the default value. 24 | final FormFieldValidator validator; 25 | 26 | @override 27 | String? validate(T? valueCandidate) { 28 | return validateValue(valueCandidate); 29 | } 30 | 31 | @override 32 | String? validateValue(T? valueCandidate) { 33 | return validator.call(valueCandidate ?? defaultValue); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/src/core/equal_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template equal_validator_template} 4 | /// [EqualValidator] extends [TranslatedValidator] to validate if a value is equal to a specified value. 5 | /// 6 | /// ## Parameters: 7 | /// 8 | /// - [value] The value to compare against. 9 | /// - [errorText] The error message returned if the validation fails. 10 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 11 | /// 12 | /// {@endtemplate} 13 | class EqualValidator extends TranslatedValidator { 14 | /// Constructor for the equal value validator. 15 | const EqualValidator( 16 | this.value, { 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | /// The value to compare against. 25 | final Object value; 26 | 27 | @override 28 | String get translatedErrorText => 29 | FormBuilderLocalizations.current.equalErrorText(value.toString()); 30 | 31 | @override 32 | String? validateValue(T valueCandidate) { 33 | return valueCandidate != value ? errorText : null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/src/core/log_validator.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | import '../../form_builder_validators.dart'; 4 | 5 | /// {@template log_validator_template} 6 | /// [LogValidator] extends [TranslatedValidator] to log the value being validated. 7 | /// This validator is primarily used for debugging purposes and always returns `null`, indicating no validation errors. 8 | /// 9 | /// ## Parameters: 10 | /// 11 | /// - [log] A custom logging function to log the value. If not provided, the value or error text will be logged using [debugPrint]. 12 | /// - [errorText] The error message that can be used for logging if the value is null. 13 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. This is set to false by default. 14 | /// 15 | /// {@endtemplate} 16 | class LogValidator extends TranslatedValidator { 17 | /// Constructor for the log validator. 18 | const LogValidator({ 19 | this.log, 20 | 21 | /// {@macro base_validator_error_text} 22 | super.errorText, 23 | }) : super(checkNullOrEmpty: false); 24 | 25 | /// A custom logging function to log the value. 26 | final String Function(T? value)? log; 27 | 28 | @override 29 | String get translatedErrorText => 30 | FormBuilderLocalizations.current.requiredErrorText; 31 | 32 | @override 33 | String? validate(T? valueCandidate) { 34 | return validateValue(valueCandidate); 35 | } 36 | 37 | @override 38 | String? validateValue(T? valueCandidate) { 39 | if (log != null) { 40 | debugPrint(log!(valueCandidate)); 41 | } else if (valueCandidate != null) { 42 | debugPrint(valueCandidate.toString()); 43 | } else { 44 | debugPrint(errorText); 45 | } 46 | return null; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/src/core/not_equal_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template not_equal_validator_template} 4 | /// [NotEqualValidator] extends [TranslatedValidator] to validate if a value is not equal to a specified value. 5 | /// 6 | /// ## Parameters: 7 | /// 8 | /// - [value] The value to compare against. 9 | /// - [errorText] The error message returned if the validation fails. 10 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 11 | /// 12 | /// {@endtemplate} 13 | class NotEqualValidator extends TranslatedValidator { 14 | /// Constructor for the not equal value validator. 15 | const NotEqualValidator( 16 | this.value, { 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | /// The value to compare against. 25 | final Object value; 26 | 27 | @override 28 | String get translatedErrorText => 29 | FormBuilderLocalizations.current.notEqualErrorText(value.toString()); 30 | 31 | @override 32 | String? validateValue(T valueCandidate) { 33 | return valueCandidate == value ? errorText : null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/src/core/or_validator.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | import '../../form_builder_validators.dart'; 4 | 5 | /// {@template or_validator_template} 6 | /// [OrValidator] extends [BaseValidator] to validate a value using multiple validators, 7 | /// returning null if at least one of the validators passes. 8 | /// 9 | /// ## Parameters: 10 | /// 11 | /// - [validators] The list of validators to apply to the value. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. This is set to false by default. 13 | /// 14 | /// {@endtemplate} 15 | class OrValidator extends BaseValidator { 16 | /// Constructor for the OR validator. 17 | const OrValidator(this.validators) : super(checkNullOrEmpty: false); 18 | 19 | /// The list of validators to apply to the value. 20 | final List> validators; 21 | 22 | @override 23 | String? validate(T? valueCandidate) { 24 | return validateValue(valueCandidate); 25 | } 26 | 27 | @override 28 | String? validateValue(T? valueCandidate) { 29 | String? errorResult; 30 | for (final FormFieldValidator validator in validators) { 31 | final String? validatorResult = validator.call(valueCandidate); 32 | if (validatorResult == null) { 33 | return null; 34 | } else { 35 | errorResult = validatorResult; 36 | } 37 | } 38 | return errorResult; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/src/core/required_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template required_validator_template} 4 | /// [RequiredValidator] extends [TranslatedValidator] to validate that a value is required (non-null). 5 | /// 6 | /// This validator is primarily used to ensure that a field is not left empty or null. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class RequiredValidator extends TranslatedValidator { 15 | /// Constructor for the required value validator. 16 | const RequiredValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.requiredErrorText; 27 | 28 | @override 29 | String? validateValue(T valueCandidate) { 30 | // BaseValidator will already check for null values 31 | return null; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/src/core/skip_when_validator.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | import '../../form_builder_validators.dart'; 4 | 5 | /// {@template skip_when_validator_template} 6 | /// [SkipWhenValidator] extends [BaseValidator] to conditionally skip validation based on a provided condition. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [condition] A function that returns a boolean indicating whether the validator should be skipped. 11 | /// - [validator] The validator to apply if the condition is not met. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. This is set to false by default. 13 | /// 14 | /// {@endtemplate} 15 | class SkipWhenValidator extends BaseValidator { 16 | /// Constructor for the skip when validator. 17 | const SkipWhenValidator( 18 | this.condition, 19 | this.validator, 20 | ) : super(checkNullOrEmpty: false); 21 | 22 | /// A function that returns a boolean indicating whether the validator should be skipped. 23 | final bool Function(T? value) condition; 24 | 25 | /// The validator to apply if the condition is not met. 26 | final FormFieldValidator validator; 27 | 28 | @override 29 | String? validate(T? valueCandidate) { 30 | return validateValue(valueCandidate); 31 | } 32 | 33 | @override 34 | String? validateValue(T? valueCandidate) { 35 | if (condition(valueCandidate)) { 36 | return null; 37 | } 38 | return validator(valueCandidate); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/src/core/transform_validator.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | import '../../form_builder_validators.dart'; 4 | 5 | /// {@template transform_validator_template} 6 | /// [TransformValidator] extends [BaseValidator] to transform a value before applying a validator. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [transformer] A function that transforms the value before validation. 11 | /// - [validator] The validator to apply to the transformed value. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. This is set to false by default. 13 | /// 14 | /// {@endtemplate} 15 | class TransformValidator extends BaseValidator { 16 | /// Constructor for the transform validator. 17 | const TransformValidator( 18 | this.transformer, 19 | this.validator, 20 | ) : super(checkNullOrEmpty: false); 21 | 22 | /// A function that transforms the value before validation. 23 | final T? Function(T? value) transformer; 24 | 25 | /// The validator to apply to the transformed value. 26 | final FormFieldValidator validator; 27 | 28 | @override 29 | String? validate(T? valueCandidate) { 30 | return validateValue(valueCandidate); 31 | } 32 | 33 | @override 34 | String? validateValue(T? valueCandidate) { 35 | final T? transformedValue = transformer(valueCandidate); 36 | return validator(transformedValue); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/src/datetime/date_future_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template date_future_validator_template} 4 | /// [DateFutureValidator] extends [TranslatedValidator] to validate if a date string represents a future date. 5 | /// 6 | /// This validator checks if the date parsed from the string is after the current date and time. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class DateFutureValidator extends TranslatedValidator { 15 | /// Constructor for the future date validator. 16 | const DateFutureValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.dateMustBeInTheFutureErrorText; 27 | 28 | @override 29 | String? validateValue(String valueCandidate) { 30 | final DateTime? date = DateTime.tryParse(valueCandidate); 31 | return date != null && date.isAfter(DateTime.now()) ? null : errorText; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/src/datetime/date_past_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template date_past_validator_template} 4 | /// [DatePastValidator] extends [TranslatedValidator] to validate if a date string represents a past date. 5 | /// 6 | /// This validator checks if the date parsed from the string is before the current date and time. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class DatePastValidator extends TranslatedValidator { 15 | /// Constructor for the past date validator. 16 | const DatePastValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.dateMustBeInThePastErrorText; 27 | 28 | @override 29 | String? validateValue(String valueCandidate) { 30 | final DateTime? date = DateTime.tryParse(valueCandidate); 31 | return date != null && date.isBefore(DateTime.now()) ? null : errorText; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/src/datetime/date_range_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template date_range_validator_template} 4 | /// [DateRangeValidator] extends [TranslatedValidator] to validate if a date string falls within a specified date range. 5 | /// 6 | /// This validator checks if the date parsed from the string is between the specified minimum and maximum dates. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [minDate] The minimum date of the range. 11 | /// - [maxDate] The maximum date of the range. 12 | /// - [errorText] The error message returned if the validation fails. 13 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 14 | /// 15 | /// {@endtemplate} 16 | class DateRangeValidator extends TranslatedValidator { 17 | /// Constructor for the date range validator. 18 | const DateRangeValidator( 19 | this.minDate, 20 | this.maxDate, { 21 | /// {@macro base_validator_error_text} 22 | super.errorText, 23 | 24 | /// {@macro base_validator_null_check} 25 | super.checkNullOrEmpty, 26 | }); 27 | 28 | /// The minimum date of the range. 29 | final DateTime minDate; 30 | 31 | /// The maximum date of the range. 32 | final DateTime maxDate; 33 | 34 | @override 35 | String get translatedErrorText => 36 | FormBuilderLocalizations.current.dateRangeErrorText(minDate, maxDate); 37 | 38 | @override 39 | String? validateValue(String valueCandidate) { 40 | final DateTime? date = DateTime.tryParse(valueCandidate); 41 | if (date == null || date.isBefore(minDate) || date.isAfter(maxDate)) { 42 | return errorText; 43 | } 44 | return null; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/src/datetime/date_time_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template date_time_validator_template} 4 | /// [DateTimeValidator] extends [TranslatedValidator] to validate if a value is a valid [DateTime] object. 5 | /// 6 | /// This validator ensures that the value is not null and is a valid [DateTime] instance. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class DateTimeValidator extends TranslatedValidator { 15 | /// Constructor for the DateTime validator. 16 | const DateTimeValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.dateStringErrorText; 27 | 28 | @override 29 | String? validateValue(DateTime? valueCandidate) { 30 | if (valueCandidate == null) { 31 | return errorText; 32 | } 33 | return null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/src/datetime/date_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template date_validator_template} 4 | /// [DateValidator] extends [TranslatedValidator] to validate if a string can be parsed into a valid [DateTime] object. 5 | /// 6 | /// This validator ensures that the value is a valid date string. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class DateValidator extends TranslatedValidator { 15 | /// Constructor for the date string validator. 16 | const DateValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.dateStringErrorText; 27 | 28 | @override 29 | String? validateValue(String valueCandidate) { 30 | final DateTime? date = DateTime.tryParse(valueCandidate); 31 | if (date == null) { 32 | return errorText; 33 | } 34 | return null; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/src/datetime/datetime.dart: -------------------------------------------------------------------------------- 1 | export 'date_future_validator.dart'; 2 | export 'date_past_validator.dart'; 3 | export 'date_range_validator.dart'; 4 | export 'date_time_validator.dart'; 5 | export 'date_validator.dart'; 6 | export 'time_validator.dart'; 7 | export 'timezone_validator.dart'; 8 | -------------------------------------------------------------------------------- /lib/src/datetime/time_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template time_validator_template} 4 | /// [TimeValidator] extends [TranslatedValidator] to validate if a string represents a valid time in 24-hour or 12-hour format. 5 | /// 6 | /// This validator checks if the string matches the time format or can be parsed into a valid time. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [regex] The regular expression used to validate the time format. Defaults to a standard time regex. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class TimeValidator extends TranslatedValidator { 16 | /// Constructor for the time string validator. 17 | TimeValidator({ 18 | /// {@macro time_template} 19 | RegExp? regex, 20 | 21 | /// {@macro base_validator_error_text} 22 | super.errorText, 23 | 24 | /// {@macro base_validator_null_check} 25 | super.checkNullOrEmpty, 26 | }) : regex = regex ?? _time; 27 | 28 | /// The regular expression used to validate the time format. 29 | final RegExp regex; 30 | 31 | /// {@template time_template} 32 | /// This regex matches time in 24-hour or 12-hour format. 33 | /// 34 | /// - It allows hours and minutes, with optional AM/PM for 12-hour format. 35 | /// - It supports leading zeros for single-digit hours. 36 | /// 37 | /// Examples: 23:59, 11:59 PM 38 | /// {@endtemplate} 39 | static final RegExp _time = RegExp( 40 | r'^(?:[01]?\d|2[0-3]):[0-5]?\d(?::[0-5]?\d)?$|^(?:0?[1-9]|1[0-2]):[0-5]?\d(?::[0-5]?\d)?\s?(?:[AaPp][Mm])$', 41 | ); 42 | 43 | @override 44 | String get translatedErrorText => 45 | FormBuilderLocalizations.current.timeErrorText; 46 | 47 | @override 48 | String? validateValue(String valueCandidate) { 49 | if (regex.hasMatch(valueCandidate) || 50 | DateTime.tryParse(valueCandidate) != null) { 51 | return null; 52 | } 53 | return errorText; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /lib/src/datetime/timezone_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template time_zone_validator_template} 4 | /// [TimeZoneValidator] extends [TranslatedValidator] to validate if a string represents a valid time zone identifier. 5 | /// 6 | /// This validator checks if the string is in the list of valid time zone identifiers. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [validTimeZones] The list of valid time zone identifiers. Defaults to a standard list of common time zones. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class TimeZoneValidator extends TranslatedValidator { 16 | /// Constructor for the time zone string validator. 17 | TimeZoneValidator({ 18 | List? validTimeZones, 19 | 20 | /// {@macro base_validator_error_text} 21 | super.errorText, 22 | 23 | /// {@macro base_validator_null_check} 24 | super.checkNullOrEmpty, 25 | }) : validTimeZones = validTimeZones ?? timeZones; 26 | 27 | /// The list of valid time zone identifiers. 28 | final List validTimeZones; 29 | 30 | /// A list of valid time zone identifiers. 31 | static final List timeZones = [ 32 | 'UTC', 33 | 'GMT', 34 | 'EST', 35 | 'EDT', 36 | 'CST', 37 | 'CDT', 38 | 'MST', 39 | 'MDT', 40 | 'PST', 41 | 'PDT', 42 | 'ECT', 43 | 'EET', 44 | 'ART', 45 | 'AST', 46 | 'EAT', 47 | 'MET', 48 | 'NET', 49 | 'PLT', 50 | 'IST', 51 | 'BST', 52 | 'VST', 53 | 'CTT', 54 | 'JST', 55 | 'ACT', 56 | 'AET', 57 | 'SST', 58 | 'NST', 59 | 'MIT', 60 | 'HST', 61 | 'AST', 62 | 'PNT', 63 | 'PRT', 64 | 'CNT', 65 | 'AGT', 66 | 'BET', 67 | 'CAT', 68 | ]; 69 | 70 | @override 71 | String get translatedErrorText => 72 | FormBuilderLocalizations.current.timezoneErrorText; 73 | 74 | @override 75 | String? validateValue(String valueCandidate) { 76 | if (validTimeZones.contains(valueCandidate)) { 77 | return null; 78 | } 79 | 80 | return errorText; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /lib/src/file/file.dart: -------------------------------------------------------------------------------- 1 | export 'file_extension_validator.dart'; 2 | export 'file_name_validator.dart'; 3 | export 'file_size_validator.dart'; 4 | export 'mime_type_validator.dart'; 5 | export 'path_validator.dart'; 6 | -------------------------------------------------------------------------------- /lib/src/file/file_extension_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template file_extension_validator_template} 4 | /// [FileExtensionValidator] extends [TranslatedValidator] to validate if a file path has an allowed extension. 5 | /// 6 | /// This validator checks if the file extension is within the list of allowed extensions. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [allowedExtensions] The list of allowed file extensions. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class FileExtensionValidator extends TranslatedValidator { 16 | /// Constructor for the file extension validator. 17 | const FileExtensionValidator( 18 | this.allowedExtensions, { 19 | /// {@macro base_validator_error_text} 20 | super.errorText, 21 | 22 | /// {@macro base_validator_null_check} 23 | super.checkNullOrEmpty, 24 | }); 25 | 26 | /// The list of allowed file extensions. 27 | final List allowedExtensions; 28 | 29 | /// Converts the allowed extensions to lowercase. 30 | List get _allowedExtensionsLowerCase => 31 | allowedExtensions.map((String e) => e.toLowerCase()).toList(); 32 | 33 | @override 34 | String get translatedErrorText => 35 | FormBuilderLocalizations.current.fileExtensionErrorText( 36 | _allowedExtensionsLowerCase.join(', '), 37 | ); 38 | 39 | @override 40 | String? validateValue(String valueCandidate) { 41 | final String extension = 42 | fileExtensionFromPath(valueCandidate).toLowerCase(); 43 | 44 | if (!_allowedExtensionsLowerCase.contains(extension)) { 45 | return errorText; 46 | } 47 | return null; 48 | } 49 | 50 | /// Extracts the file extension from the given file path. 51 | /// 52 | /// ## Parameters: 53 | /// - [path] The file path to extract the extension from. 54 | /// 55 | /// ## Returns: 56 | /// The extracted file extension. 57 | String fileExtensionFromPath(String path) { 58 | final List parts = path.split('.'); 59 | 60 | assert( 61 | parts.length > 1 && parts.last.isNotEmpty, 62 | 'Invalid file path format: $path. Path should contain a valid extension.', 63 | ); 64 | 65 | return parts.last; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /lib/src/file/file_name_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template file_name_validator_template} 4 | /// [FileNameValidator] extends [TranslatedValidator] to validate if a string is a valid file name. 5 | /// 6 | /// This validator checks if the string matches the specified regex pattern for valid file names. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [regex] The regular expression used to validate the file name format. Defaults to a standard file name regex. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class FileNameValidator extends TranslatedValidator { 16 | /// Constructor for the file name validator. 17 | FileNameValidator({ 18 | /// {@macro filename_template} 19 | RegExp? regex, 20 | 21 | /// {@macro base_validator_error_text} 22 | super.errorText, 23 | 24 | /// {@macro base_validator_null_check} 25 | super.checkNullOrEmpty, 26 | }) : regex = regex ?? _fileName; 27 | 28 | /// The regular expression used to validate the file name format. 29 | final RegExp regex; 30 | 31 | /// {@template filename_template} 32 | /// This regex matches valid file name characters. 33 | /// 34 | /// - It allows letters, digits, underscores, hyphens, and periods. 35 | /// - It ensures that the file name does not contain invalid characters. 36 | /// 37 | /// Examples: valid_filename.txt, another-file_name.jpg 38 | /// {@endtemplate} 39 | static final RegExp _fileName = RegExp(r'^[a-zA-Z0-9_\-\.]+$'); 40 | 41 | @override 42 | String get translatedErrorText => 43 | FormBuilderLocalizations.current.fileNameErrorText; 44 | 45 | @override 46 | String? validateValue(String valueCandidate) { 47 | return isFileName(valueCandidate) ? null : errorText; 48 | } 49 | 50 | /// Checks if the provided value is a valid file name. 51 | /// 52 | /// ## Parameters: 53 | /// - [valueCandidate] The string to be evaluated. 54 | /// 55 | /// ## Returns: 56 | /// A boolean indicating whether the value is a valid file name. 57 | bool isFileName(String valueCandidate) { 58 | return regex.hasMatch(valueCandidate); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /lib/src/file/mime_type_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template mime_type_validator_template} 4 | /// [MimeTypeValidator] extends [TranslatedValidator] to validate if a string represents a valid MIME type. 5 | /// 6 | /// This validator checks if the string matches a valid MIME type pattern. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [regex] The regular expression used to validate the MIME type format. Defaults to a standard MIME type regex. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class MimeTypeValidator extends TranslatedValidator { 16 | /// Constructor for the MIME type validator. 17 | MimeTypeValidator({ 18 | RegExp? regex, 19 | 20 | /// {@macro mimetype_validator_template} 21 | super.errorText, 22 | 23 | /// {@macro base_validator_null_check} 24 | super.checkNullOrEmpty, 25 | }) : regex = regex ?? _mimeType; 26 | 27 | /// The regular expression used to validate the MIME type format. 28 | final RegExp regex; 29 | 30 | @override 31 | String get translatedErrorText => 32 | FormBuilderLocalizations.current.invalidMimeTypeErrorText; 33 | 34 | /// {@template mimetype_validator_template} 35 | /// This regex matches valid MIME types. 36 | /// 37 | /// - It ensures the string is in the format 'type/subtype'. 38 | /// - It supports common MIME types such as 'application/json', 'image/png', etc. 39 | /// 40 | /// Examples: application/json, image/png 41 | /// {@endtemplate} 42 | static final RegExp _mimeType = RegExp( 43 | r'^[a-zA-Z0-9!#$&^_-]+\/[a-zA-Z0-9!#$&^_-]+$', 44 | ); 45 | 46 | @override 47 | String? validateValue(String valueCandidate) { 48 | return regex.hasMatch(valueCandidate) ? null : errorText; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/src/file/path_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template path_validator_template} 4 | /// [PathValidator] extends [TranslatedValidator] to validate if a string represents a valid file path. 5 | /// 6 | /// This validator checks if the string matches the specified regex pattern for valid file paths. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [regex] The regular expression used to validate the file path format. Defaults to a standard file path regex. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class PathValidator extends TranslatedValidator { 16 | /// Constructor for the file path validator. 17 | PathValidator({ 18 | /// {@macro file_path_template} 19 | RegExp? regex, 20 | 21 | /// {@macro base_validator_error_text} 22 | super.errorText, 23 | 24 | /// {@macro base_validator_null_check} 25 | super.checkNullOrEmpty, 26 | }) : regex = regex ?? _filePath; 27 | 28 | /// The regular expression used to validate the file path format. 29 | final RegExp regex; 30 | 31 | /// {@template file_path_template} 32 | /// This regex matches file paths. 33 | /// 34 | /// - It allows letters, digits, underscores, hyphens, and forward slashes. 35 | /// 36 | /// Examples: /path/to/file, C:/Users/Name/Documents 37 | /// {@endtemplate} 38 | static final RegExp _filePath = 39 | RegExp(r'^((\/|\\|[a-zA-Z]:\/)?([^<>:"|?*]+(\/|\\)?)+)$'); 40 | 41 | @override 42 | String get translatedErrorText => 43 | FormBuilderLocalizations.current.pathErrorText; 44 | 45 | @override 46 | String? validateValue(String valueCandidate) { 47 | if (!regex.hasMatch(valueCandidate)) { 48 | return errorText; 49 | } 50 | return null; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/src/finance/bic_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template bic_validator_template} 4 | /// [BicValidator] extends [TranslatedValidator] to validate if a string represents a valid BIC (Bank Identifier Code). 5 | /// 6 | /// This validator checks if the string matches the specified regex pattern for valid BICs. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [regex] The regular expression used to validate the BIC format. Defaults to a standard BIC regex. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class BicValidator extends TranslatedValidator { 16 | /// Constructor for the BIC validator. 17 | BicValidator({ 18 | /// {@macro bic_template} 19 | RegExp? regex, 20 | 21 | /// {@macro base_validator_error_text} 22 | super.errorText, 23 | 24 | /// {@macro base_validator_null_check} 25 | super.checkNullOrEmpty, 26 | }) : regex = regex ?? _bic; 27 | 28 | /// The regular expression used to validate the BIC format. 29 | final RegExp regex; 30 | 31 | /// {@template bic_template} 32 | /// This regex matches BIC (Bank Identifier Code). 33 | /// 34 | /// - It consists of 8 or 11 characters. 35 | /// - It starts with four letters (bank code), followed by two letters (country code), two characters (location code), and optionally three characters (branch code). 36 | /// 37 | /// Examples: DEUTDEFF, NEDSZAJJXXX 38 | /// {@endtemplate} 39 | static final RegExp _bic = RegExp(r'^[A-Z]{4}[A-Z]{2}\w{2}(\w{3})?$'); 40 | 41 | @override 42 | String get translatedErrorText => 43 | FormBuilderLocalizations.current.bicErrorText; 44 | 45 | @override 46 | String? validateValue(String valueCandidate) { 47 | return isBIC(valueCandidate) ? null : errorText; 48 | } 49 | 50 | /// Check if the string is a valid BIC string. 51 | /// 52 | /// ## Parameters: 53 | /// - [value] The string to be evaluated. 54 | /// 55 | /// ## Returns: 56 | /// A boolean indicating whether the value is a valid BIC. 57 | bool isBIC(String value) { 58 | final String bic = value.replaceAll(' ', '').toUpperCase(); 59 | 60 | if (bic.length != 8 && bic.length != 11) { 61 | return false; 62 | } 63 | 64 | return regex.hasMatch(bic); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /lib/src/finance/credit_card_cvc_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template credit_card_cvc_validator_template} 4 | /// [CreditCardCvcValidator] extends [TranslatedValidator] to validate if a string represents a valid credit card CVC (Card Verification Code). 5 | /// 6 | /// This validator checks if the CVC is a numeric string of length 3 or 4. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class CreditCardCvcValidator extends TranslatedValidator { 15 | /// Constructor for the credit card CVC validator. 16 | const CreditCardCvcValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.creditCardCVCErrorText; 27 | 28 | @override 29 | String? validateValue(String valueCandidate) { 30 | final int? cvc = int.tryParse(valueCandidate); 31 | if (cvc == null || valueCandidate.length < 3 || valueCandidate.length > 4) { 32 | return errorText; 33 | } 34 | return null; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/src/finance/finance.dart: -------------------------------------------------------------------------------- 1 | export 'bic_validator.dart'; 2 | export 'credit_card_cvc_validator.dart'; 3 | export 'credit_card_expiration_date_validator.dart'; 4 | export 'credit_card_validator.dart'; 5 | export 'iban_validator.dart'; 6 | -------------------------------------------------------------------------------- /lib/src/form_field_validator_extensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../form_builder_validators.dart'; 3 | 4 | /// Extension methods for [FormFieldValidator]. 5 | extension FormFieldValidatorExtensions on FormFieldValidator { 6 | /// Combines the current validator with another validator using logical AND. 7 | FormFieldValidator and(FormFieldValidator other) { 8 | return FormBuilderValidators.compose(>[this, other]); 9 | } 10 | 11 | /// Combines the current validator with another validator using logical OR. 12 | FormFieldValidator or(FormFieldValidator other) { 13 | return FormBuilderValidators.or(>[this, other]); 14 | } 15 | 16 | /// Adds a condition to apply the validator only if the condition is met. 17 | FormFieldValidator when(bool Function(T? value) condition) { 18 | return FormBuilderValidators.conditional(condition, this); 19 | } 20 | 21 | /// Adds a condition to apply the validator only if the condition is not met. 22 | FormFieldValidator unless(bool Function(T? value) condition) { 23 | return FormBuilderValidators.conditional( 24 | (T? value) => !condition(value), 25 | this, 26 | ); 27 | } 28 | 29 | /// Transforms the value before applying the validator. 30 | FormFieldValidator transform(T Function(T? value) transformer) { 31 | return FormBuilderValidators.transform(transformer, this); 32 | } 33 | 34 | /// Skips the validator if the condition is met. 35 | FormFieldValidator skipWhen(bool Function(T? value) condition) { 36 | return FormBuilderValidators.skipWhen(condition, this); 37 | } 38 | 39 | /// Logs the value during the validation process. 40 | FormFieldValidator log({String Function(T? value)? log}) { 41 | return FormBuilderValidators.log(log: log); 42 | } 43 | 44 | /// Overrides the error message of the current validator. 45 | FormFieldValidator withErrorMessage(String errorMessage) { 46 | return (T? valueCandidate) { 47 | final String? result = this(valueCandidate); 48 | return result != null ? errorMessage : null; 49 | }; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/src/identity/country_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template country_validator_template} 4 | /// [CountryValidator] extends [TranslatedValidator] to validate if a string represents a valid country name. 5 | /// 6 | /// This validator checks if the country name is not in a blacklist, 7 | /// and optionally checks if it is in a whitelist. 8 | /// 9 | /// ## Parameters: 10 | /// 11 | /// - [countryWhitelist] A list of valid country names that are explicitly allowed. 12 | /// - [countryBlacklist] A list of invalid country names that are explicitly disallowed. 13 | /// - [errorText] The error message returned if the validation fails. 14 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 15 | /// 16 | /// {@endtemplate} 17 | class CountryValidator extends TranslatedValidator { 18 | /// Constructor for the country name validator. 19 | CountryValidator({ 20 | List? countryWhitelist, 21 | List? countryBlacklist, 22 | 23 | /// {@macro base_validator_error_text} 24 | super.errorText, 25 | 26 | /// {@macro base_validator_null_check} 27 | super.checkNullOrEmpty, 28 | }) : countryWhitelist = countryWhitelist ?? [], 29 | countryBlacklist = countryBlacklist ?? []; 30 | 31 | /// A list of valid country names that are explicitly allowed. 32 | final List countryWhitelist; 33 | 34 | /// A list of invalid country names that are explicitly disallowed. 35 | final List countryBlacklist; 36 | 37 | @override 38 | String get translatedErrorText => 39 | FormBuilderLocalizations.current.countryErrorText; 40 | 41 | @override 42 | String? validateValue(String valueCandidate) { 43 | if (countryBlacklist.contains(valueCandidate)) { 44 | return errorText; 45 | } 46 | 47 | if (countryWhitelist.isEmpty || countryWhitelist.contains(valueCandidate)) { 48 | return null; 49 | } 50 | 51 | return errorText; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/src/identity/identity.dart: -------------------------------------------------------------------------------- 1 | export 'city_validator.dart'; 2 | export 'country_validator.dart'; 3 | export 'firstname_validator.dart'; 4 | export 'lastname_validator.dart'; 5 | export 'passport_number_validator.dart'; 6 | export 'password_validator.dart'; 7 | export 'ssn_validator.dart'; 8 | export 'state_validator.dart'; 9 | export 'street_validator.dart'; 10 | export 'username_validator.dart'; 11 | export 'zip_code_validator.dart'; 12 | -------------------------------------------------------------------------------- /lib/src/identity/ssn_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template ssn_validator_template} 4 | /// [SsnValidator] extends [TranslatedValidator] to validate if a string represents a valid SSN (Social Security Number). 5 | /// 6 | /// This validator checks if the SSN matches the specified regex pattern. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [regex] The regular expression used to validate the SSN format. Defaults to a standard SSN regex. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class SsnValidator extends TranslatedValidator { 16 | /// Constructor for the SSN validator. 17 | SsnValidator({ 18 | /// {@macro ssn_template} 19 | RegExp? regex, 20 | 21 | /// {@macro base_validator_error_text} 22 | super.errorText, 23 | 24 | /// {@macro base_validator_null_check} 25 | super.checkNullOrEmpty, 26 | }) : regex = regex ?? _ssn; 27 | 28 | /// The regular expression used to validate the SSN format. 29 | final RegExp regex; 30 | 31 | /// {@template ssn_template} 32 | /// This regex matches SSN (Social Security Number). 33 | /// - It consists of 9 characters. 34 | /// - It starts with three digits, followed by a hyphen, two digits, 35 | /// another hyphen, and four digits. 36 | /// Examples: 123-45-6789 37 | /// {@endtemplate} 38 | static final RegExp _ssn = RegExp(r'^\d{3}-\d{2}-\d{4}$'); 39 | 40 | static final RegExp _ssnCleaned = RegExp(r'^\d{9}$'); 41 | 42 | @override 43 | String get translatedErrorText => 44 | FormBuilderLocalizations.current.ssnErrorText; 45 | 46 | @override 47 | String? validateValue(String valueCandidate) { 48 | return isSSN(valueCandidate) ? null : errorText; 49 | } 50 | 51 | /// Check if the string is a valid SSN string. 52 | bool isSSN(String value) { 53 | final String ssn = value.replaceAll('-', '').replaceAll(' ', ''); 54 | 55 | if (ssn.length != 9) { 56 | return false; 57 | } 58 | 59 | return regex == _ssn 60 | ? regex.hasMatch(value) || _ssnCleaned.hasMatch(ssn) 61 | : regex.hasMatch(value) || regex.hasMatch(ssn); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /lib/src/identity/zip_code_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template zip_code_validator_template} 4 | /// [ZipCodeValidator] extends [TranslatedValidator] to validate if a string represents a valid USA ZIP code. 5 | /// 6 | /// This validator checks if the ZIP code matches the specified regex pattern. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [regex] The regular expression used to validate the ZIP code format. Defaults to a standard USA ZIP code regex. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class ZipCodeValidator extends TranslatedValidator { 16 | /// Constructor for the ZIP code validator. 17 | ZipCodeValidator({ 18 | /// {@macro zip_code_template} 19 | RegExp? regex, 20 | 21 | /// {@macro zip_code_validator_error_text} 22 | super.errorText, 23 | 24 | /// {@macro base_validator_null_check} 25 | super.checkNullOrEmpty, 26 | }) : regex = regex ?? _zipCode; 27 | 28 | /// The regular expression used to validate the ZIP code format. 29 | final RegExp regex; 30 | 31 | /// {@template zip_code_template} 32 | /// This regex matches a valid USA ZIP code. 33 | /// 34 | /// Examples: 12345, 12345-6789 35 | /// {@endtemplate} 36 | static final RegExp _zipCode = RegExp(r'^\d{5}(?:[-\s]\d{4})?$'); 37 | 38 | @override 39 | String get translatedErrorText => 40 | FormBuilderLocalizations.current.zipCodeErrorText; 41 | 42 | @override 43 | String? validateValue(String valueCandidate) { 44 | return regex.hasMatch(valueCandidate) ? null : errorText; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/src/network/latitude_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template latitude_validator_template} 4 | /// [LatitudeValidator] extends [TranslatedValidator] to validate if a string represents a valid latitude value. 5 | /// 6 | /// This validator checks if the latitude value is a number within the range of -90 to 90 degrees. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class LatitudeValidator extends TranslatedValidator { 15 | /// Constructor for the latitude validator. 16 | const LatitudeValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.latitudeErrorText; 27 | 28 | @override 29 | String? validateValue(String valueCandidate) { 30 | return isLatitude(valueCandidate) ? null : errorText; 31 | } 32 | 33 | /// Check if the string is a valid latitude. 34 | /// 35 | /// ## Parameters: 36 | /// - [value] The string to be evaluated. 37 | /// 38 | /// ## Returns: 39 | /// A boolean indicating whether the value is a valid latitude. 40 | bool isLatitude(String value) { 41 | final String latitudeValue = value.replaceAll(',', '.'); 42 | 43 | final double? latitude = double.tryParse(latitudeValue); 44 | if (latitude == null) { 45 | return false; 46 | } 47 | return latitude >= -90 && latitude <= 90; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/src/network/longitude_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template longitude_validator_template} 4 | /// [LongitudeValidator] extends [TranslatedValidator] to validate if a string represents a valid longitude value. 5 | /// 6 | /// This validator checks if the longitude value is a number within the range of -180 to 180 degrees. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class LongitudeValidator extends TranslatedValidator { 15 | /// Constructor for the longitude validator. 16 | const LongitudeValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.longitudeErrorText; 27 | 28 | @override 29 | String? validateValue(String valueCandidate) { 30 | return isLongitude(valueCandidate) ? null : errorText; 31 | } 32 | 33 | /// Check if the string is a valid longitude. 34 | /// 35 | /// ## Parameters: 36 | /// - [value] The string to be evaluated. 37 | /// 38 | /// ## Returns: 39 | /// A boolean indicating whether the value is a valid longitude. 40 | bool isLongitude(String value) { 41 | final String longitudeValue = value.replaceAll(',', '.'); 42 | 43 | final double? longitude = double.tryParse(longitudeValue); 44 | if (longitude == null) { 45 | return false; 46 | } 47 | return longitude >= -180 && longitude <= 180; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/src/network/mac_address_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template mac_address_validator_template} 4 | /// [MacAddressValidator] extends [TranslatedValidator] to validate if a string represents a valid MAC address. 5 | /// 6 | /// This validator checks if the MAC address matches the specified regex pattern. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [regex] The regular expression used to validate the MAC address format. Defaults to a standard MAC address regex. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class MacAddressValidator extends TranslatedValidator { 16 | /// Constructor for the MAC address validator. 17 | MacAddressValidator({ 18 | /// {@macro mac_address_template} 19 | RegExp? regex, 20 | 21 | /// {@macro base_validator_error_text} 22 | super.errorText, 23 | 24 | /// {@macro base_validator_null_check} 25 | super.checkNullOrEmpty, 26 | }) : regex = regex ?? _macAddress; 27 | 28 | /// The regular expression used to validate the MAC address format. 29 | final RegExp regex; 30 | 31 | /// {@template mac_address_template} 32 | /// This regex matches MAC addresses. 33 | /// 34 | /// - It consists of six groups of two hexadecimal digits. 35 | /// - Each group is separated by a colon or hyphen. 36 | /// 37 | /// Examples: 00:1A:2B:3C:4D:5E, 00-1A-2B-3C-4D-5E 38 | /// {@endtemplate} 39 | static final RegExp _macAddress = RegExp( 40 | r'^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$|^([0-9A-Fa-f]{4}\.){2}([0-9A-Fa-f]{4})$', 41 | ); 42 | 43 | @override 44 | String get translatedErrorText => 45 | FormBuilderLocalizations.current.macAddressErrorText; 46 | 47 | @override 48 | String? validateValue(String valueCandidate) { 49 | return regex.hasMatch(valueCandidate) ? null : errorText; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/src/network/network.dart: -------------------------------------------------------------------------------- 1 | export 'email_validator.dart'; 2 | export 'ip_validator.dart'; 3 | export 'latitude_validator.dart'; 4 | export 'longitude_validator.dart'; 5 | export 'mac_address_validator.dart'; 6 | export 'phone_number_validator.dart'; 7 | export 'port_number_validator.dart'; 8 | export 'url_validator.dart'; 9 | -------------------------------------------------------------------------------- /lib/src/network/phone_number_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template phone_number_validator_template} 4 | /// [PhoneNumberValidator] extends [TranslatedValidator] to validate if a string represents a valid international phone number. 5 | /// 6 | /// This validator checks if the phone number matches the specified regex pattern. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [regex] The regular expression used to validate the phone number format. Defaults to a standard international phone number regex. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class PhoneNumberValidator extends TranslatedValidator { 16 | /// Constructor for the phone number validator. 17 | PhoneNumberValidator({ 18 | /// {@macro phone_number_template} 19 | RegExp? regex, 20 | 21 | /// {@macro base_validator_error_text} 22 | super.errorText, 23 | 24 | /// {@macro base_validator_null_check} 25 | super.checkNullOrEmpty, 26 | }) : regex = regex ?? _phoneNumber; 27 | 28 | /// The regular expression used to validate the phone number format. 29 | final RegExp regex; 30 | 31 | /// {@template phone_number_template} 32 | /// This regex matches international phone numbers. 33 | /// 34 | /// - It supports optional country codes. 35 | /// - It allows spaces, dashes, and dots as separators. 36 | /// - It validates the number of digits in the phone number. 37 | /// 38 | /// Examples: +1-800-555-5555, 1234567890 39 | /// {@endtemplate} 40 | static final RegExp _phoneNumber = RegExp( 41 | r'^\+?(\d{1,4}[\s.-]?)?(\(?\d{1,4}\)?[\s.-]?)?(\d{1,4}[\s.-]?)?(\d{1,4}[\s.-]?)?(\d{1,9})$', 42 | ); 43 | 44 | @override 45 | String get translatedErrorText => 46 | FormBuilderLocalizations.current.phoneErrorText; 47 | 48 | @override 49 | String? validateValue(String valueCandidate) { 50 | final String phoneNumber = 51 | valueCandidate.replaceAll(' ', '').replaceAll('-', ''); 52 | 53 | if (!regex.hasMatch(phoneNumber)) { 54 | return errorText; 55 | } 56 | return null; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /lib/src/network/port_number_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template port_number_validator_template} 4 | /// [PortNumberValidator] extends [TranslatedValidator] to validate if a string represents a valid port number. 5 | /// 6 | /// This validator checks if the port number is an integer within the specified range (0 to 65535 by default). 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [min] The minimum allowable port number. Defaults to 0. 11 | /// - [max] The maximum allowable port number. Defaults to 65535. 12 | /// - [errorText] The error message returned if the validation fails. 13 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 14 | /// 15 | /// {@endtemplate} 16 | class PortNumberValidator extends TranslatedValidator { 17 | /// Constructor for the port number validator. 18 | PortNumberValidator({ 19 | this.min = 0, 20 | this.max = 65535, 21 | 22 | /// {@macro base_validator_error_text} 23 | super.errorText, 24 | 25 | /// {@macro base_validator_null_check} 26 | super.checkNullOrEmpty, 27 | }); 28 | 29 | /// The minimum allowable port number. 30 | final int min; 31 | 32 | /// The maximum allowable port number. 33 | final int max; 34 | 35 | @override 36 | String get translatedErrorText => 37 | FormBuilderLocalizations.current.portNumberErrorText(min, max); 38 | 39 | @override 40 | String? validateValue(String valueCandidate) { 41 | final int? port = int.tryParse(valueCandidate); 42 | if (port == null || port < min || port > max) { 43 | return errorText; 44 | } 45 | return null; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/src/numeric/between_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template between_validator_template} 4 | /// [BetweenValidator] extends [TranslatedValidator] to validate if a number is within a specified range. 5 | /// 6 | /// This validator checks if the value is between the minimum and maximum inclusive. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [min] The minimum allowable value. 11 | /// - [max] The maximum allowable value. 12 | /// - [errorText] The error message returned if the validation fails. 13 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 14 | /// 15 | /// {@endtemplate} 16 | class BetweenValidator extends TranslatedValidator { 17 | /// Constructor for the between validator. 18 | const BetweenValidator( 19 | this.min, 20 | this.max, { 21 | /// {@macro base_validator_error_text} 22 | super.errorText, 23 | 24 | /// {@macro base_validator_null_check} 25 | super.checkNullOrEmpty, 26 | }); 27 | 28 | /// The minimum allowable value. 29 | final num min; 30 | 31 | /// The maximum allowable value. 32 | final num max; 33 | 34 | @override 35 | String get translatedErrorText => 36 | FormBuilderLocalizations.current.betweenErrorText(min, max); 37 | 38 | @override 39 | String? validateValue(T valueCandidate) { 40 | final num? value; 41 | 42 | if (valueCandidate is String) { 43 | value = num.tryParse(valueCandidate); 44 | } else if (valueCandidate is num) { 45 | value = valueCandidate; 46 | } else { 47 | return errorText; 48 | } 49 | 50 | if (value == null || (value < min || value > max)) { 51 | return errorText; 52 | } 53 | 54 | return null; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /lib/src/numeric/even_number_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template even_number_validator_template} 4 | /// [EvenNumberValidator] extends [TranslatedValidator] to validate if a string represents an even number. 5 | /// 6 | /// This validator checks if the provided string can be parsed into an integer and if that integer is even. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class EvenNumberValidator extends TranslatedValidator { 15 | /// Constructor for the even number validator. 16 | const EvenNumberValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.evenNumberErrorText; 27 | 28 | @override 29 | String? validateValue(String valueCandidate) { 30 | final int? number = int.tryParse(valueCandidate); 31 | if (number == null || number.isOdd) { 32 | return errorText; 33 | } 34 | return null; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/src/numeric/float_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template float_validator_template} 4 | /// [FloatValidator] extends [TranslatedValidator] to validate if a value is a float and does not exceed a maximum value. 5 | /// 6 | /// This validator checks if the value is a float number or a string that can be parsed into a float number and ensures it does not exceed the maximum value. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// - [maxValue] The maximum allowed value for the float. Default is 1.0. 13 | /// 14 | /// {@endtemplate} 15 | class FloatValidator extends TranslatedValidator { 16 | /// Constructor for the float validator. 17 | const FloatValidator({ 18 | /// {@macro base_validator_error_text} 19 | super.errorText, 20 | 21 | /// {@macro base_validator_null_check} 22 | super.checkNullOrEmpty, 23 | }); 24 | 25 | @override 26 | String get translatedErrorText => 27 | FormBuilderLocalizations.current.floatErrorText; 28 | 29 | @override 30 | String? validateValue(T valueCandidate) { 31 | final double? value; 32 | if (valueCandidate is String) { 33 | value = double.tryParse(valueCandidate); 34 | } else if (valueCandidate is double) { 35 | value = valueCandidate; 36 | } else if (valueCandidate is num) { 37 | value = valueCandidate.toDouble(); 38 | } else { 39 | return errorText; 40 | } 41 | 42 | if (value == null) { 43 | return errorText; 44 | } 45 | 46 | return null; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/src/numeric/hexadecimal_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template hexadecimal_validator_template} 4 | /// [HexadecimalValidator] extends [TranslatedValidator] to validate if a value is a hexadecimal string. 5 | /// 6 | /// This validator checks if the value is a valid hexadecimal string using a regular expression. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [regex] The regular expression used to validate the hexadecimal string. 12 | /// 13 | /// {@macro hexadecimal_regex_template} 14 | /// {@endtemplate} 15 | class HexadecimalValidator extends TranslatedValidator { 16 | /// Constructor for the hexadecimal validator. 17 | HexadecimalValidator({ 18 | /// {@macro hexadecimal_regex_template} 19 | RegExp? regex, 20 | 21 | /// {@macro base_validator_error_text} 22 | super.errorText, 23 | 24 | /// {@macro base_validator_null_check} 25 | super.checkNullOrEmpty, 26 | }) : regex = regex ?? _hexadecimalRegex; 27 | 28 | @override 29 | String get translatedErrorText => 30 | FormBuilderLocalizations.current.hexadecimalErrorText; 31 | 32 | /// The regular expression used to validate the hexadecimal string. 33 | final RegExp regex; 34 | 35 | /// {@template hexadecimal_regex_template} 36 | /// The default regex matches a hexadecimal string. 37 | /// 38 | /// - It allows digits and letters from A-F (both lowercase and uppercase). 39 | /// - It supports optional prefixes "0x" or "0X". 40 | /// 41 | /// Examples: 1A3F, a1b2c3, 0x4faDA5 42 | /// {@endtemplate} 43 | static final RegExp _hexadecimalRegex = RegExp( 44 | r'^(0[xX])?[0-9a-fA-F]+$', 45 | ); 46 | 47 | @override 48 | String? validateValue(String valueCandidate) { 49 | return regex.hasMatch(valueCandidate) ? null : errorText; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/src/numeric/integer_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template integer_validator_template} 4 | /// [IntegerValidator] extends [TranslatedValidator] to validate if a string represents a valid integer. 5 | /// 6 | /// This validator checks if the provided string can be parsed into an integer with an optional radix. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [radix] The base to use for parsing the integer. Defaults to 10 if not specified. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class IntegerValidator extends TranslatedValidator { 16 | /// Constructor for the integer validator. 17 | const IntegerValidator({ 18 | this.radix, 19 | 20 | /// {@macro base_validator_error_text} 21 | super.errorText, 22 | 23 | /// {@macro base_validator_null_check} 24 | super.checkNullOrEmpty, 25 | }); 26 | 27 | /// The base to use for parsing the integer. 28 | final int? radix; 29 | 30 | @override 31 | String get translatedErrorText => 32 | FormBuilderLocalizations.current.integerErrorText; 33 | 34 | @override 35 | String? validateValue(String valueCandidate) { 36 | final int? number = int.tryParse(valueCandidate, radix: radix); 37 | if (number == null) { 38 | return errorText; 39 | } 40 | return null; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/src/numeric/max_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template max_validator_template} 4 | /// [MaxValidator] extends [TranslatedValidator] to validate if a value is less than or equal to a specified maximum value. 5 | /// 6 | /// This validator checks if the value is a number or a string that can be parsed into a number and ensures it does not exceed the specified maximum value. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [max] The maximum allowable value. 11 | /// - [inclusive] Whether the maximum value is inclusive. Defaults to true. 12 | /// - [errorText] The error message returned if the validation fails. 13 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 14 | /// 15 | /// {@endtemplate} 16 | class MaxValidator extends TranslatedValidator { 17 | /// Constructor for the maximum value validator. 18 | const MaxValidator( 19 | this.max, { 20 | this.inclusive = true, 21 | 22 | /// {@macro base_validator_error_text} 23 | super.errorText, 24 | 25 | /// {@macro base_validator_null_check} 26 | super.checkNullOrEmpty, 27 | }); 28 | 29 | /// The maximum allowable value. 30 | final num max; 31 | 32 | /// Whether the maximum value is inclusive. 33 | final bool inclusive; 34 | 35 | @override 36 | String get translatedErrorText => 37 | FormBuilderLocalizations.current.maxErrorText(max); 38 | 39 | @override 40 | String? validateValue(T valueCandidate) { 41 | final num? value; 42 | 43 | if (valueCandidate is String) { 44 | value = num.tryParse(valueCandidate); 45 | } else if (valueCandidate is num) { 46 | value = valueCandidate; 47 | } else { 48 | return errorText; 49 | } 50 | 51 | if (value == null) { 52 | return errorText; 53 | } 54 | 55 | if (inclusive) { 56 | if (value > max) { 57 | return errorText; 58 | } 59 | } else { 60 | if (value >= max) { 61 | return errorText; 62 | } 63 | } 64 | 65 | return null; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /lib/src/numeric/min_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template min_validator_template} 4 | /// [MinValidator] extends [TranslatedValidator] to validate if a value is greater than or equal to a specified minimum value. 5 | /// 6 | /// This validator checks if the value is a number or a string that can be parsed into a number and ensures it meets the specified minimum value. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [min] The minimum allowable value. 11 | /// - [inclusive] Whether the minimum value is inclusive. Defaults to true. 12 | /// - [errorText] The error message returned if the validation fails. 13 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 14 | /// 15 | /// {@endtemplate} 16 | class MinValidator extends TranslatedValidator { 17 | /// Constructor for the minimum value validator. 18 | const MinValidator( 19 | this.min, { 20 | this.inclusive = true, 21 | 22 | /// {@macro base_validator_error_text} 23 | super.errorText, 24 | 25 | /// {@macro base_validator_null_check} 26 | super.checkNullOrEmpty, 27 | }); 28 | 29 | /// The minimum allowable value. 30 | final num min; 31 | 32 | /// Whether the minimum value is inclusive. 33 | final bool inclusive; 34 | 35 | @override 36 | String get translatedErrorText => 37 | FormBuilderLocalizations.current.minErrorText(min); 38 | 39 | @override 40 | String? validateValue(T valueCandidate) { 41 | final num? value; 42 | if (valueCandidate is String) { 43 | value = num.tryParse(valueCandidate); 44 | } else if (valueCandidate is num) { 45 | value = valueCandidate; 46 | } else { 47 | return errorText; 48 | } 49 | 50 | if (value == null) { 51 | return errorText; 52 | } 53 | 54 | if (inclusive) { 55 | if (value < min) { 56 | return errorText; 57 | } 58 | } else { 59 | if (value <= min) { 60 | return errorText; 61 | } 62 | } 63 | 64 | return null; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /lib/src/numeric/negative_number_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template negative_number_validator_template} 4 | /// [NegativeNumberValidator] extends [TranslatedValidator] to validate if a value is a negative number. 5 | /// 6 | /// This validator checks if the value is a number or a string that can be parsed into a number and ensures it is negative. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class NegativeNumberValidator extends TranslatedValidator { 15 | /// Constructor for the negative number validator. 16 | const NegativeNumberValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.negativeNumberErrorText; 27 | 28 | @override 29 | String? validateValue(T valueCandidate) { 30 | final num? value; 31 | if (valueCandidate is String) { 32 | value = num.tryParse(valueCandidate); 33 | } else if (valueCandidate is num) { 34 | value = valueCandidate; 35 | } else { 36 | return errorText; 37 | } 38 | 39 | if (value == null) { 40 | return errorText; 41 | } 42 | 43 | if (value >= 0) { 44 | return errorText; 45 | } 46 | 47 | return null; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/src/numeric/not_zero_number_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template not_zero_number_validator_template} 4 | /// [NotZeroNumberValidator] extends [TranslatedValidator] to validate if a value is not zero. 5 | /// 6 | /// This validator checks if the value is a number or a string that can be parsed into a number and ensures it is not zero. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class NotZeroNumberValidator extends TranslatedValidator { 15 | /// Constructor for the not zero number validator. 16 | const NotZeroNumberValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.notZeroNumberErrorText; 27 | 28 | @override 29 | String? validateValue(T valueCandidate) { 30 | final num? value; 31 | if (valueCandidate is String) { 32 | value = num.tryParse(valueCandidate); 33 | } else if (valueCandidate is num) { 34 | value = valueCandidate; 35 | } else { 36 | return errorText; 37 | } 38 | 39 | if (value == null) { 40 | return errorText; 41 | } 42 | 43 | if (value == 0) { 44 | return errorText; 45 | } 46 | 47 | return null; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/src/numeric/numeric.dart: -------------------------------------------------------------------------------- 1 | export 'between_validator.dart'; 2 | export 'even_number_validator.dart'; 3 | export 'float_validator.dart'; 4 | export 'hexadecimal_validator.dart'; 5 | export 'integer_validator.dart'; 6 | export 'max_validator.dart'; 7 | export 'min_validator.dart'; 8 | export 'negative_number_validator.dart'; 9 | export 'not_zero_number_validator.dart'; 10 | export 'numeric_validator.dart'; 11 | export 'odd_number_validator.dart'; 12 | export 'positive_number_validator.dart'; 13 | export 'prime_validator.dart'; 14 | -------------------------------------------------------------------------------- /lib/src/numeric/numeric_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template numeric_validator_template} 4 | /// [NumericValidator] extends [TranslatedValidator] to validate if a value is numeric. 5 | /// 6 | /// This validator checks if the value is a number or a string that can be parsed into a number. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class NumericValidator extends TranslatedValidator { 15 | /// Constructor for the numeric validator. 16 | const NumericValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.numericErrorText; 27 | 28 | @override 29 | String? validateValue(T valueCandidate) { 30 | final num? value; 31 | if (valueCandidate is String) { 32 | value = num.tryParse(valueCandidate); 33 | } else if (valueCandidate is num) { 34 | value = valueCandidate; 35 | } else { 36 | return errorText; 37 | } 38 | 39 | return value == null ? errorText : null; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/src/numeric/odd_number_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template odd_number_validator_template} 4 | /// [OddNumberValidator] extends [TranslatedValidator] to validate if a string represents an odd number. 5 | /// 6 | /// This validator checks if the provided string can be parsed into an integer and if that integer is odd. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class OddNumberValidator extends TranslatedValidator { 15 | /// Constructor for the odd number validator. 16 | const OddNumberValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.oddNumberErrorText; 27 | 28 | @override 29 | String? validateValue(String valueCandidate) { 30 | final int? number = int.tryParse(valueCandidate); 31 | if (number == null || number.isEven) { 32 | return errorText; 33 | } 34 | return null; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/src/numeric/positive_number_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template positive_number_validator_template} 4 | /// [PositiveNumberValidator] extends [TranslatedValidator] to validate if a value is a positive number. 5 | /// 6 | /// This validator checks if the value is a number or a string that can be parsed into a number and ensures it is positive. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class PositiveNumberValidator extends TranslatedValidator { 15 | /// Constructor for the positive number validator. 16 | const PositiveNumberValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.positiveNumberErrorText; 27 | 28 | @override 29 | String? validateValue(T valueCandidate) { 30 | final num? value; 31 | if (valueCandidate is String) { 32 | value = num.tryParse(valueCandidate); 33 | } else if (valueCandidate is num) { 34 | value = valueCandidate; 35 | } else { 36 | return errorText; 37 | } 38 | 39 | if (value == null) { 40 | return errorText; 41 | } 42 | 43 | if (value <= 0) { 44 | return errorText; 45 | } 46 | 47 | return null; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/src/numeric/prime_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template prime_number_validator_template} 4 | /// [PrimeNumberValidator] extends [TranslatedValidator] to validate if a value is a prime number. 5 | /// 6 | /// This validator checks if the value is an integer or a string that can be parsed into an integer and ensures it is a prime number. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class PrimeNumberValidator extends TranslatedValidator { 15 | /// Constructor for the prime number validator. 16 | const PrimeNumberValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.primeNumberErrorText; 27 | 28 | @override 29 | String? validateValue(T valueCandidate) { 30 | final int? value; 31 | if (valueCandidate is String) { 32 | value = int.tryParse(valueCandidate); 33 | } else if (valueCandidate is int) { 34 | value = valueCandidate; 35 | } else { 36 | return errorText; 37 | } 38 | 39 | if (value == null) { 40 | return errorText; 41 | } 42 | 43 | if (!isPrime(value)) { 44 | return errorText; 45 | } 46 | 47 | return null; 48 | } 49 | 50 | /// Checks if the number is prime. 51 | /// 52 | /// ## Parameters: 53 | /// - [number] The number to be checked. 54 | /// 55 | /// ## Returns: 56 | /// A boolean indicating whether the number is prime. 57 | bool isPrime(int number) { 58 | if (number <= 1) return false; 59 | for (int i = 2; i * i <= number; i++) { 60 | if (number % i == 0) return false; 61 | } 62 | return true; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /lib/src/string/alphabetical_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template alphabetical_validator_template} 4 | /// [AlphabeticalValidator] extends [TranslatedValidator] to validate if a string contains only alphabetical characters. 5 | /// 6 | /// This validator checks if the value matches the specified regex pattern that allows only letters (both uppercase and lowercase). 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [regex] The regular expression used to validate the alphabetical format. Defaults to a regex that matches only alphabetical characters. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class AlphabeticalValidator extends TranslatedValidator { 16 | /// Constructor for the alphabetical validator. 17 | AlphabeticalValidator({ 18 | /// {@macro alphabetical_template} 19 | RegExp? regex, 20 | 21 | /// {@macro base_validator_error_text} 22 | super.errorText, 23 | 24 | /// {@macro base_validator_null_check} 25 | super.checkNullOrEmpty, 26 | }) : regex = regex ?? _alphabetical; 27 | 28 | /// The regular expression used to validate the alphabetical format. 29 | final RegExp regex; 30 | 31 | /// {@template alphabetical_template} 32 | /// This regex matches only alphabetical characters. 33 | /// 34 | /// - It allows both uppercase and lowercase letters. 35 | /// 36 | /// Examples: abcdef, XYZ 37 | /// {@endtemplate} 38 | static final RegExp _alphabetical = RegExp(r'^[a-zA-Z]+$'); 39 | 40 | @override 41 | String get translatedErrorText => 42 | FormBuilderLocalizations.current.alphabeticalErrorText; 43 | 44 | @override 45 | String? validateValue(String valueCandidate) { 46 | return regex.hasMatch(valueCandidate) ? null : errorText; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/src/string/contains_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template contains_validator_template} 4 | /// [ContainsValidator] extends [TranslatedValidator] to validate if a string contains a specified substring. 5 | /// 6 | /// This validator checks if the value contains the specified substring, with an option for case sensitivity. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [substring] The substring that the value must contain. 11 | /// - [caseSensitive] Whether the search should be case-sensitive. Defaults to true. 12 | /// - [errorText] The error message returned if the validation fails. 13 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 14 | /// 15 | /// {@endtemplate} 16 | class ContainsValidator extends TranslatedValidator { 17 | /// Constructor for the contains validator. 18 | const ContainsValidator( 19 | this.substring, { 20 | this.caseSensitive = true, 21 | 22 | /// {@macro base_validator_error_text} 23 | super.errorText, 24 | 25 | /// {@macro base_validator_null_check} 26 | super.checkNullOrEmpty, 27 | }); 28 | 29 | /// The substring that the value must contain. 30 | final String substring; 31 | 32 | /// Whether the search should be case-sensitive. 33 | final bool caseSensitive; 34 | 35 | @override 36 | String get translatedErrorText => 37 | FormBuilderLocalizations.current.containsErrorText(substring); 38 | 39 | @override 40 | String? validateValue(String valueCandidate) { 41 | if (substring.isEmpty) { 42 | return errorText; 43 | } else if (caseSensitive 44 | ? valueCandidate.contains(substring) 45 | : valueCandidate.toLowerCase().contains(substring.toLowerCase())) { 46 | return null; 47 | } 48 | return errorText; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/src/string/ends_with_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template ends_with_validator_template} 4 | /// [EndsWithValidator] extends [TranslatedValidator] to validate if a string ends with a specified suffix. 5 | /// 6 | /// This validator checks if the value ends with the specified suffix. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [suffix] The suffix that the value must end with. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class EndsWithValidator extends TranslatedValidator { 16 | /// Constructor for the ends with validator. 17 | const EndsWithValidator( 18 | this.suffix, { 19 | /// {@macro base_validator_error_text} 20 | super.errorText, 21 | 22 | /// {@macro base_validator_null_check} 23 | super.checkNullOrEmpty, 24 | }); 25 | 26 | /// The suffix that the value must end with. 27 | final String suffix; 28 | 29 | @override 30 | String get translatedErrorText => 31 | FormBuilderLocalizations.current.endsWithErrorText(suffix); 32 | 33 | @override 34 | String? validateValue(String valueCandidate) { 35 | return valueCandidate.endsWith(suffix) ? null : errorText; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/string/lowercase_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template lowercase_validator_template} 4 | /// [LowercaseValidator] extends [TranslatedValidator] to validate if a string is entirely lowercase. 5 | /// 6 | /// This validator checks if the value is the same as its lowercase version. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class LowercaseValidator extends TranslatedValidator { 15 | /// Constructor for the lowercase validator. 16 | const LowercaseValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.lowercaseErrorText; 27 | 28 | @override 29 | String? validateValue(String valueCandidate) { 30 | return valueCandidate.toLowerCase() == valueCandidate ? null : errorText; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/src/string/match_not_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template match_not_validator_template} 4 | /// [MatchNotValidator] extends [TranslatedValidator] to validate if a string does not match a specified regular expression pattern. 5 | /// 6 | /// This validator checks if the value does not match the provided regex pattern. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [regex] The regular expression pattern that the value must not match. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class MatchNotValidator extends TranslatedValidator { 16 | /// Constructor for the match not validator. 17 | const MatchNotValidator( 18 | this.regex, { 19 | /// {@macro base_validator_error_text} 20 | super.errorText, 21 | 22 | /// {@macro base_validator_null_check} 23 | super.checkNullOrEmpty, 24 | }); 25 | 26 | /// The regular expression pattern that the value must not match. 27 | final RegExp regex; 28 | 29 | @override 30 | String get translatedErrorText => 31 | FormBuilderLocalizations.current.matchErrorText; 32 | 33 | @override 34 | String? validateValue(String valueCandidate) { 35 | return !regex.hasMatch(valueCandidate) ? errorText : null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/string/match_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template match_validator_template} 4 | /// [MatchValidator] extends [TranslatedValidator] to validate if a string matches a specified regular expression pattern. 5 | /// 6 | /// This validator checks if the value matches the provided regex pattern. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [regex] The regular expression pattern that the value must match. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class MatchValidator extends TranslatedValidator { 16 | /// Constructor for the match validator. 17 | const MatchValidator( 18 | this.regex, { 19 | /// {@macro base_validator_error_text} 20 | super.errorText, 21 | 22 | /// {@macro base_validator_null_check} 23 | super.checkNullOrEmpty, 24 | }); 25 | 26 | /// The regular expression pattern that the value must match. 27 | final RegExp regex; 28 | 29 | @override 30 | String get translatedErrorText => 31 | FormBuilderLocalizations.current.matchErrorText; 32 | 33 | @override 34 | String? validateValue(String valueCandidate) { 35 | return regex.hasMatch(valueCandidate) ? null : errorText; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/string/max_words_count_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template max_words_count_validator_template} 4 | /// [MaxWordsCountValidator] extends [TranslatedValidator] to validate if a string contains no more than a specified number of words. 5 | /// 6 | /// This validator checks if the number of words in the value does not exceed the specified maximum word count. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [maxWordsCount] The maximum allowable number of words. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class MaxWordsCountValidator extends TranslatedValidator { 16 | /// Constructor for the maximum words count validator. 17 | const MaxWordsCountValidator( 18 | this.maxWordsCount, { 19 | /// {@macro base_validator_error_text} 20 | super.errorText, 21 | 22 | /// {@macro base_validator_null_check} 23 | super.checkNullOrEmpty, 24 | }); 25 | 26 | /// The maximum allowable number of words. 27 | final int maxWordsCount; 28 | 29 | @override 30 | String get translatedErrorText => 31 | FormBuilderLocalizations.current.maxWordsCountErrorText(maxWordsCount); 32 | 33 | @override 34 | String? validateValue(String valueCandidate) { 35 | final int wordsCount = valueCandidate.trim().split(RegExp(r'\s+')).length; 36 | 37 | return wordsCount > maxWordsCount ? errorText : null; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/string/min_words_count_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template min_words_count_validator_template} 4 | /// [MinWordsCountValidator] extends [TranslatedValidator] to validate if a string contains at least a specified number of words. 5 | /// 6 | /// This validator checks if the number of words in the value is at least the specified minimum word count. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [minWordsCount] The minimum required number of words. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class MinWordsCountValidator extends TranslatedValidator { 16 | /// Constructor for the minimum words count validator. 17 | const MinWordsCountValidator( 18 | this.minWordsCount, { 19 | /// {@macro base_validator_error_text} 20 | super.errorText, 21 | 22 | /// {@macro base_validator_null_check} 23 | super.checkNullOrEmpty, 24 | }); 25 | 26 | /// The minimum required number of words. 27 | final int minWordsCount; 28 | 29 | @override 30 | String get translatedErrorText => 31 | FormBuilderLocalizations.current.minWordsCountErrorText(minWordsCount); 32 | 33 | @override 34 | String? validateValue(String valueCandidate) { 35 | final int wordsCount = valueCandidate.trim().split(RegExp(r'\s+')).length; 36 | 37 | return wordsCount < minWordsCount ? errorText : null; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/string/single_line_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template single_line_validator_template} 4 | /// [SingleLineValidator] extends [TranslatedValidator] to validate if a string contains only a single line. 5 | /// 6 | /// This validator checks if the value does not contain any newline characters. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class SingleLineValidator extends TranslatedValidator { 15 | /// Constructor for the single line validator. 16 | const SingleLineValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.singleLineErrorText; 27 | 28 | @override 29 | String? validateValue(String valueCandidate) { 30 | return valueCandidate.contains('\n') || valueCandidate.contains('\r') 31 | ? errorText 32 | : null; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/src/string/starts_with_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template starts_with_validator_template} 4 | /// [StartsWithValidator] extends [TranslatedValidator] to validate if a string starts with a specified prefix. 5 | /// 6 | /// This validator checks if the value starts with the specified prefix. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [prefix] The prefix that the value must start with. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class StartsWithValidator extends TranslatedValidator { 16 | /// Constructor for the starts with validator. 17 | const StartsWithValidator( 18 | this.prefix, { 19 | /// {@macro base_validator_error_text} 20 | super.errorText, 21 | 22 | /// {@macro base_validator_null_check} 23 | super.checkNullOrEmpty, 24 | }); 25 | 26 | /// The prefix that the value must start with. 27 | final String prefix; 28 | 29 | @override 30 | String get translatedErrorText => 31 | FormBuilderLocalizations.current.startsWithErrorText(prefix); 32 | 33 | @override 34 | String? validateValue(String valueCandidate) { 35 | return valueCandidate.startsWith(prefix) ? null : errorText; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/string/string.dart: -------------------------------------------------------------------------------- 1 | export 'alphabetical_validator.dart'; 2 | export 'contains_validator.dart'; 3 | export 'ends_with_validator.dart'; 4 | export 'lowercase_validator.dart'; 5 | export 'match_not_validator.dart'; 6 | export 'match_validator.dart'; 7 | export 'max_words_count_validator.dart'; 8 | export 'min_words_count_validator.dart'; 9 | export 'single_line_validator.dart'; 10 | export 'starts_with_validator.dart'; 11 | export 'uppercase_validator.dart'; 12 | -------------------------------------------------------------------------------- /lib/src/string/uppercase_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template uppercase_validator_template} 4 | /// [UppercaseValidator] extends [TranslatedValidator] to validate if a string is entirely uppercase. 5 | /// 6 | /// This validator checks if the value is the same as its uppercase version. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class UppercaseValidator extends TranslatedValidator { 15 | /// Constructor for the uppercase validator. 16 | const UppercaseValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.uppercaseErrorText; 27 | 28 | @override 29 | String? validateValue(String valueCandidate) { 30 | return valueCandidate.toUpperCase() == valueCandidate ? null : errorText; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/src/translated_validator.dart: -------------------------------------------------------------------------------- 1 | import '../form_builder_validators.dart'; 2 | 3 | /// Base class for all validators that return a translated error message. 4 | abstract class TranslatedValidator extends BaseValidator { 5 | /// Creates a new instance of the validator. 6 | const TranslatedValidator({super.errorText, super.checkNullOrEmpty}); 7 | 8 | @override 9 | String get errorText => super.errorText ?? translatedErrorText; 10 | 11 | /// The translated error message returned if the value is invalid. 12 | String get translatedErrorText; 13 | } 14 | -------------------------------------------------------------------------------- /lib/src/usecase/base64_validator.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import '../../form_builder_validators.dart'; 4 | 5 | /// {@template base64_validator_template} 6 | /// [Base64Validator] extends [TranslatedValidator] to validate if a string is a valid base64 encoded string. 7 | /// 8 | /// This validator checks if the value can be successfully decoded from base64 format. 9 | /// 10 | /// ## Parameters: 11 | /// 12 | /// - [errorText] The error message returned if the validation fails. 13 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 14 | /// 15 | /// {@endtemplate} 16 | class Base64Validator extends TranslatedValidator { 17 | /// Constructor for the base64 validator. 18 | const Base64Validator({ 19 | /// {@macro base_validator_error_text} 20 | super.errorText, 21 | 22 | /// {@macro base_validator_null_check} 23 | super.checkNullOrEmpty, 24 | }); 25 | 26 | @override 27 | String get translatedErrorText => 28 | FormBuilderLocalizations.current.base64ErrorText; 29 | 30 | @override 31 | String? validateValue(String valueCandidate) { 32 | return isBase64(valueCandidate) ? null : errorText; 33 | } 34 | 35 | /// Checks if the string is a valid base64 string. 36 | /// 37 | /// ## Parameters: 38 | /// - [value] The string to be checked. 39 | /// 40 | /// ## Returns: 41 | /// A boolean indicating whether the string is valid base64. 42 | bool isBase64(String value) { 43 | try { 44 | base64Decode(value); 45 | return true; 46 | } catch (e) { 47 | return false; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/src/usecase/duns_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template duns_validator_template} 4 | /// [DunsValidator] extends [TranslatedValidator] to validate if a string is a valid DUNS number. 5 | /// 6 | /// This validator checks if the value matches the specified regex pattern that requires exactly 9 digits. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [regex] The regular expression used to validate the DUNS number format. Defaults to a regex that matches exactly 9 digits. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class DunsValidator extends TranslatedValidator { 16 | /// Constructor for the DUNS validator. 17 | DunsValidator({ 18 | /// {@macro duns_template} 19 | RegExp? regex, 20 | super.errorText, 21 | super.checkNullOrEmpty, 22 | }) : regex = regex ?? _duns; 23 | 24 | /// The regular expression used to validate the DUNS number format. 25 | final RegExp regex; 26 | 27 | /// {@template duns_template} 28 | /// This regex matches a valid DUNS number format. 29 | /// 30 | /// - It requires exactly 9 digits. 31 | /// 32 | /// Examples: 123456789, 987654321 33 | /// {@endtemplate} 34 | static final RegExp _duns = RegExp(r'^\d{9}$'); 35 | 36 | @override 37 | String get translatedErrorText => 38 | FormBuilderLocalizations.current.dunsErrorText; 39 | 40 | @override 41 | String? validateValue(String valueCandidate) { 42 | if (!regex.hasMatch(valueCandidate)) { 43 | return errorText; 44 | } 45 | 46 | return null; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/src/usecase/isbn_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template isbn_validator_template} 4 | /// [IsbnValidator] extends [TranslatedValidator] to validate if a string is a valid ISBN (International Standard Book Number). 5 | /// 6 | /// This validator checks if the value is a valid ISBN-10 or ISBN-13 format. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [errorText] The error message returned if the validation fails. 11 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 12 | /// 13 | /// {@endtemplate} 14 | class IsbnValidator extends TranslatedValidator { 15 | /// Constructor for the ISBN validator. 16 | const IsbnValidator({ 17 | /// {@macro base_validator_error_text} 18 | super.errorText, 19 | 20 | /// {@macro base_validator_null_check} 21 | super.checkNullOrEmpty, 22 | }); 23 | 24 | @override 25 | String get translatedErrorText => 26 | FormBuilderLocalizations.current.isbnErrorText; 27 | 28 | @override 29 | String? validateValue(String valueCandidate) { 30 | return isISBN(valueCandidate) ? null : errorText; 31 | } 32 | 33 | /// Checks if the string is a valid ISBN (either ISBN-10 or ISBN-13). 34 | /// 35 | /// ## Parameters: 36 | /// - [valueCandidate] The string to be checked. 37 | /// 38 | /// ## Returns: 39 | /// A boolean indicating whether the string is a valid ISBN. 40 | bool isISBN(String valueCandidate) { 41 | final String isbn = valueCandidate.replaceAll('-', '').replaceAll(' ', ''); 42 | 43 | if (isbn.length == 10) { 44 | if (!RegExp(r'^\d{9}[\dX]$').hasMatch(isbn)) return false; 45 | 46 | int sum = 0; 47 | for (int i = 0; i < 9; i++) { 48 | sum += int.parse(isbn[i]) * (10 - i); 49 | } 50 | 51 | final int checkDigit = (isbn[9] == 'X') ? 10 : int.parse(isbn[9]); 52 | sum += checkDigit; 53 | 54 | return sum % 11 == 0; 55 | } else if (isbn.length == 13) { 56 | if (!RegExp(r'^\d{13}$').hasMatch(isbn)) return false; 57 | 58 | int sum = 0; 59 | for (int i = 0; i < 12; i++) { 60 | final int digit = int.parse(isbn[i]); 61 | sum += (i.isEven) ? digit : digit * 3; 62 | } 63 | 64 | final int checkDigit = int.parse(isbn[12]); 65 | final int calculatedCheckDigit = (10 - (sum % 10)) % 10; 66 | 67 | return checkDigit == calculatedCheckDigit; 68 | } else { 69 | return false; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /lib/src/usecase/json_validator.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import '../../form_builder_validators.dart'; 4 | 5 | /// {@template json_validator_template} 6 | /// [JsonValidator] extends [TranslatedValidator] to validate if a string is a valid JSON format. 7 | /// 8 | /// This validator checks if the value can be successfully decoded as JSON. 9 | /// 10 | /// ## Parameters: 11 | /// 12 | /// - [errorText] The error message returned if the validation fails. 13 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 14 | /// 15 | /// {@endtemplate} 16 | class JsonValidator extends TranslatedValidator { 17 | /// Constructor for the JSON validator. 18 | const JsonValidator({ 19 | /// {@macro base_validator_error_text} 20 | super.errorText, 21 | 22 | /// {@macro base_validator_null_check} 23 | super.checkNullOrEmpty, 24 | }); 25 | 26 | @override 27 | String get translatedErrorText => 28 | FormBuilderLocalizations.current.jsonErrorText; 29 | 30 | @override 31 | String? validateValue(String valueCandidate) { 32 | return isJSON(valueCandidate) ? null : errorText; 33 | } 34 | 35 | /// Checks if the string is a valid JSON format. 36 | /// 37 | /// ## Parameters: 38 | /// - [value] The string to be checked. 39 | /// 40 | /// ## Returns: 41 | /// A boolean indicating whether the string is valid JSON. 42 | bool isJSON(String value) { 43 | try { 44 | jsonDecode(value); 45 | return true; 46 | } catch (e) { 47 | return false; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/src/usecase/usecase.dart: -------------------------------------------------------------------------------- 1 | export 'base64_validator.dart'; 2 | export 'color_code_validator.dart'; 3 | export 'duns_validator.dart'; 4 | export 'isbn_validator.dart'; 5 | export 'json_validator.dart'; 6 | export 'language_code_validator.dart'; 7 | export 'licenseplate_validator.dart'; 8 | export 'uuid_validator.dart'; 9 | export 'vin_validator.dart'; 10 | -------------------------------------------------------------------------------- /lib/src/usecase/uuid_validator.dart: -------------------------------------------------------------------------------- 1 | import '../../form_builder_validators.dart'; 2 | 3 | /// {@template uuid_validator_template} 4 | /// [UuidValidator] extends [TranslatedValidator] to validate if a string is a valid UUID (version 4). 5 | /// 6 | /// This validator checks if the value matches the specified regex pattern for UUID format, including hyphens. 7 | /// 8 | /// ## Parameters: 9 | /// 10 | /// - [regex] The regular expression used to validate the UUID format. Defaults to a regex that matches version 4 UUIDs. 11 | /// - [errorText] The error message returned if the validation fails. 12 | /// - [checkNullOrEmpty] Whether to check if the value is null or empty. 13 | /// 14 | /// {@endtemplate} 15 | class UuidValidator extends TranslatedValidator { 16 | /// Constructor for the UUID validator. 17 | UuidValidator({ 18 | /// {@macro uuid_template} 19 | RegExp? regex, 20 | 21 | /// {@macro base_validator_error_text} 22 | super.errorText, 23 | 24 | /// {@macro base_validator_null_check} 25 | super.checkNullOrEmpty, 26 | }) : regex = regex ?? _uuid; 27 | 28 | /// The regular expression used to validate the UUID format. 29 | final RegExp regex; 30 | 31 | /// {@template uuid_template} 32 | /// This regex matches UUIDs (version 4). 33 | /// 34 | /// - It validates the format of a UUID, including hyphens. 35 | /// 36 | /// Examples: 123e4567-e89b-12d3-a456-426614174000 37 | /// {@endtemplate} 38 | static final RegExp _uuid = RegExp( 39 | r'^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$', 40 | ); 41 | 42 | @override 43 | String get translatedErrorText => 44 | FormBuilderLocalizations.current.uuidErrorText; 45 | 46 | @override 47 | String? validateValue(String valueCandidate) { 48 | return regex.hasMatch(valueCandidate) ? null : errorText; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: form_builder_validators 2 | description: Form Builder Validators set of validators for FlutterFormBuilder. Provides common validators and a way to make your own. 3 | version: 11.1.2 4 | repository: https://github.com/flutter-form-builder-ecosystem/form_builder_validators 5 | issue_tracker: https://github.com/flutter-form-builder-ecosystem/form_builder_validators/issues 6 | homepage: https://github.com/flutter-form-builder-ecosystem 7 | topics: 8 | - form 9 | - validator 10 | funding: 11 | - https://opencollective.com/flutter-form-builder-ecosystem 12 | 13 | environment: 14 | sdk: ">=3.6.0 <4.0.0" 15 | flutter: ">=3.27.0" 16 | 17 | dependencies: 18 | flutter: 19 | sdk: flutter 20 | flutter_localizations: 21 | sdk: flutter 22 | intl: ">=0.19.0 <0.21.0" 23 | 24 | dev_dependencies: 25 | faker_dart: ^0.2.2 26 | flutter_lints: ">=5.0.0 <6.0.0" 27 | flutter_test: 28 | sdk: flutter 29 | 30 | flutter: 31 | generate: true 32 | -------------------------------------------------------------------------------- /test/src/bool/is_true_validator_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:faker_dart/faker_dart.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | import 'package:form_builder_validators/form_builder_validators.dart'; 4 | 5 | void main() { 6 | final Faker faker = Faker.instance; 7 | final String customErrorMessage = faker.lorem.sentence(); 8 | 9 | group('Is true -', () { 10 | test('should return null when the value is true', () { 11 | // Arrange 12 | const IsTrueValidator validator = IsTrueValidator(); 13 | const bool value = true; 14 | 15 | // Act 16 | final String? result = validator.validate(value); 17 | 18 | // Assert 19 | expect(result, isNull); 20 | }); 21 | 22 | test('should return the custom error message when the value is false', () { 23 | // Arrange 24 | final IsTrueValidator validator = 25 | IsTrueValidator(errorText: customErrorMessage); 26 | const bool value = false; 27 | 28 | // Act 29 | final String? result = validator.validate(value); 30 | 31 | // Assert 32 | expect(result, equals(customErrorMessage)); 33 | }); 34 | 35 | test('should return the custom error message when the value is null', () { 36 | // Arrange 37 | final IsTrueValidator validator = 38 | IsTrueValidator(errorText: customErrorMessage); 39 | const bool? value = null; 40 | 41 | // Act 42 | final String? result = validator.validate(value); 43 | 44 | // Assert 45 | expect(result, equals(customErrorMessage)); 46 | }); 47 | 48 | test('should return null when not checking for null', () { 49 | // Arrange 50 | const IsTrueValidator validator = 51 | IsTrueValidator(checkNullOrEmpty: false); 52 | const bool? value = null; 53 | 54 | // Act 55 | final String? result = validator.validate(value); 56 | 57 | // Assert 58 | expect(result, isNull); 59 | }); 60 | 61 | test( 62 | 'should return the default error message if the value is true and no custom message is set', 63 | () { 64 | // Arrange 65 | const IsTrueValidator validator = IsTrueValidator(); 66 | const bool value = false; 67 | 68 | // Act 69 | final String? result = validator.validate(value); 70 | 71 | // Assert 72 | expect( 73 | result, 74 | equals(FormBuilderLocalizations.current.mustBeTrueErrorText), 75 | ); 76 | }); 77 | }); 78 | } 79 | -------------------------------------------------------------------------------- /test/tests_helper.dart: -------------------------------------------------------------------------------- 1 | // coverage:ignore-file 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_localizations/flutter_localizations.dart'; 4 | import 'package:flutter_test/flutter_test.dart'; 5 | import 'package:form_builder_validators/localization/l10n.dart'; 6 | 7 | /// Test Harness for running Validations 8 | Future testValidations( 9 | WidgetTester tester, 10 | void Function(BuildContext) validations, 11 | ) async { 12 | await tester.pumpWidget( 13 | MaterialApp( 14 | localizationsDelegates: const >[ 15 | FormBuilderLocalizations.delegate, 16 | GlobalMaterialLocalizations.delegate, 17 | GlobalWidgetsLocalizations.delegate, 18 | ], 19 | home: Builder( 20 | builder: (BuildContext context) { 21 | // Exercise validations using the provided context 22 | validations(context); 23 | // The builder function must return a widget. 24 | return const Placeholder(); 25 | }, 26 | ), 27 | ), 28 | ); 29 | 30 | // Critical to pumpAndSettle to let Builder build to exercise validations 31 | await tester.pumpAndSettle(); 32 | } 33 | --------------------------------------------------------------------------------