mirror of
https://github.com/Iconica-Development/flutter_input_library.git
synced 2025-05-18 17:03:45 +02:00
Compare commits
23 commits
Author | SHA1 | Date | |
---|---|---|---|
|
7d64f467bf | ||
|
de5d38ffc7 | ||
|
0da6ba35f2 | ||
|
5bee01e304 | ||
|
f2d1fb5262 | ||
|
815ca7b0b2 | ||
|
b6de3299e0 | ||
|
bc8b1d572b | ||
|
e505662e2f | ||
|
59c3568e0c | ||
|
9838220de7 | ||
|
04752e9a53 | ||
|
cdc06bbb79 | ||
|
d74c702fa7 | ||
|
fbc64dcc23 | ||
|
f30634508e | ||
|
f970719da2 | ||
|
e6ea668b80 | ||
|
6b952ae230 | ||
|
f09037b850 | ||
|
fddf100fb0 | ||
|
8e8fe01467 | ||
|
919f461125 |
39 changed files with 6664 additions and 6334 deletions
14
.github/workflows/release.yml
vendored
Normal file
14
.github/workflows/release.yml
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
name: Iconica Standard Component Release Workflow
|
||||
# Workflow Caller version: 1.0.0
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
call-global-iconica-workflow:
|
||||
uses: Iconica-Development/.github/.github/workflows/component-release.yml@master
|
||||
secrets: inherit
|
||||
permissions: write-all
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -35,3 +35,7 @@ example/windows
|
|||
example/web
|
||||
example/android
|
||||
example/ios
|
||||
|
||||
# FVM Version Cache
|
||||
.fvm/
|
||||
.fvmrc
|
||||
|
|
117
CHANGELOG.md
117
CHANGELOG.md
|
@ -1,74 +1,97 @@
|
|||
## 0.0.1
|
||||
## 3.7.0
|
||||
|
||||
* Initial release, retrieved inputs from flutter_form
|
||||
* Added a 16 pixel padding between the `FlutterFormInputRadioPicker` items that is customizable with the `itemSpacing` parameter.
|
||||
|
||||
## 1.0.0
|
||||
## 3.6.0
|
||||
* Added style parameter to `FlutterFormInputMultiLine`
|
||||
* Upgrade flutter_iconica_analysis to 7.0.0
|
||||
* Changed the name of the `CarouselController` to `FlutterInputCarouselController`
|
||||
|
||||
* enforce 24h clock in the time picker because it can caused a bug on web
|
||||
## 3.5.0
|
||||
* Added `selectableTimePredicate` to the `DateTimeInputField` constructor
|
||||
|
||||
## 1.0.1
|
||||
## 3.4.0
|
||||
* Added `FlutterFormInputDropdown`
|
||||
|
||||
* add decoration option for datetime input fields
|
||||
## 3.3.1
|
||||
* Loosened the dependen on intl to be more compatible with several Flutter versions
|
||||
|
||||
## 1.0.3
|
||||
## 3.3.0
|
||||
* Added `FlutterFormInputRadioPicker`
|
||||
* Changed the `FlutterFormInputNumberPicker` and added axis parameter.
|
||||
* Changed the formating of the result value of the `showDateRangePicker`.
|
||||
|
||||
* add FocusNode option for input fields
|
||||
## 3.2.1
|
||||
* Added `PhoneNumber` model to save the `FlutterFormInputPhone` result.
|
||||
* Added more customization for `FlutterFormInputPhone`.
|
||||
|
||||
## 1.0.4
|
||||
* fix datetimepicker format and validator
|
||||
## 3.2.0
|
||||
* Added `FlutterFormInputPhone`
|
||||
|
||||
## 1.0.5
|
||||
* add style to datetime
|
||||
## 3.1.0
|
||||
* `FlutterFormInputPassword` now has the controller parameter to set the `TextEditingController` of the `TextFormField`
|
||||
|
||||
## 1.0.6
|
||||
* add initial timepicker parameter
|
||||
## 3.0.0
|
||||
* Updated the FlutterFormInputSwitch to FlutterFormInputBool. This now includes a parameter to either show a checkbox or switch
|
||||
|
||||
## 2.0.0
|
||||
* remove 'riverpod' dependency
|
||||
## 2.7.1
|
||||
* Added Iconica CI and Iconica Linter
|
||||
|
||||
## 2.1.0
|
||||
* make compatible with flutter 3.10
|
||||
|
||||
## 2.2.0
|
||||
* Dateformat optional on input from the user, defaulting to 24 hour format
|
||||
## 2.7.0
|
||||
* Addition of 'decoration' parameter to 'FlutterFormInputPassword'
|
||||
|
||||
## 2.2.1
|
||||
* Initial time optional on input from the user, defaulting to current time
|
||||
## 2.6.1
|
||||
* Addition of 'obscureText' parameter to 'FlutterFormInputPlainText'
|
||||
|
||||
## 2.3.0
|
||||
* The ability to set the enabled parameter of TextFormFields
|
||||
## 2.6.0
|
||||
* Addition of the `textCapitalization` parameter to `FlutterFormInputPlainText` and `FlutterFormInputMultiLine`.
|
||||
|
||||
## 2.4.0
|
||||
* The ability to disable the onTap paramater of the DatePicker
|
||||
* FlutterFormInputDateTime now also had the enabled parameter to provide to DateTimeInputField
|
||||
|
||||
## 2.5.0
|
||||
* Addition of the ScrollPicker input field.
|
||||
## 2.5.2
|
||||
* Addition of `style` parameter to `FlutterFormInputPassword` widget.
|
||||
|
||||
## 2.5.1
|
||||
* Addition of `formatInputs` parameter to `FlutterFormInputPlainText` widget.
|
||||
* Addition of `formatInputs` parameter to `FlutterFormInputPassword` widget.
|
||||
|
||||
## 2.5.2
|
||||
* Addition of `style` parameter to `FlutterFormInputPassword` widget.
|
||||
## 2.5.0
|
||||
* Addition of the ScrollPicker input field.
|
||||
|
||||
## 2.6.0
|
||||
* Addition of the `textCapitalization` parameter to `FlutterFormInputPlainText` and `FlutterFormInputMultiLine`.
|
||||
## 2.4.0
|
||||
* The ability to disable the onTap paramater of the DatePicker
|
||||
* FlutterFormInputDateTime now also had the enabled parameter to provide to DateTimeInputField
|
||||
|
||||
## 2.6.1
|
||||
* Addition of 'obscureText' parameter to 'FlutterFormInputPlainText'
|
||||
## 2.3.0
|
||||
* The ability to set the enabled parameter of TextFormFields
|
||||
|
||||
## 2.7.0
|
||||
* Addition of 'decoration' parameter to 'FlutterFormInputPassword'
|
||||
## 2.2.1
|
||||
* Initial time optional on input from the user, defaulting to current time
|
||||
|
||||
## 2.7.1
|
||||
* Added Iconica CI and Iconica Linter
|
||||
## 2.2.0
|
||||
* Dateformat optional on input from the user, defaulting to 24 hour format
|
||||
|
||||
## 3.0.0
|
||||
* Updated the FlutterFormInputSwitch to FlutterFormInputBool. This now includes a parameter to either show a checkbox or switch
|
||||
## 2.1.0
|
||||
* make compatible with flutter 3.10
|
||||
|
||||
## 3.1.0
|
||||
* `FlutterFormInputPassword` now has the controller parameter to set the `TextEditingController` of the `TextFormField`
|
||||
## 2.0.0
|
||||
* remove 'riverpod' dependency
|
||||
|
||||
## 3.2.0
|
||||
* Added `FlutterFormInputPhone`
|
||||
## 1.0.6
|
||||
* add initial timepicker parameter
|
||||
|
||||
## 1.0.5
|
||||
* add style to datetime
|
||||
|
||||
## 1.0.4
|
||||
* fix datetimepicker format and validator
|
||||
|
||||
## 1.0.3
|
||||
* add FocusNode option for input fields
|
||||
|
||||
## 1.0.1
|
||||
* add decoration option for datetime input fields
|
||||
|
||||
## 1.0.0
|
||||
* enforce 24h clock in the time picker because it can caused a bug on web
|
||||
|
||||
## 0.0.1
|
||||
* Initial release, retrieved inputs from flutter_form
|
||||
|
|
|
@ -45,10 +45,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: cupertino_icons
|
||||
sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be
|
||||
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
version: "1.0.8"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -68,15 +68,15 @@ packages:
|
|||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "3.1.0"
|
||||
version: "3.6.0"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c
|
||||
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "2.0.3"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
|
@ -86,50 +86,74 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
|
||||
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.18.1"
|
||||
version: "0.19.0"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.4"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593"
|
||||
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "2.1.1"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
||||
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.16"
|
||||
version: "0.12.16+1"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
||||
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.0"
|
||||
version: "0.8.0"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
version: "1.12.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
|
||||
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.8.3"
|
||||
version: "1.9.0"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
@ -179,10 +203,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.1"
|
||||
version: "0.7.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -191,14 +215,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
web:
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
|
||||
name: vm_service
|
||||
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
version: "14.2.1"
|
||||
sdks:
|
||||
dart: ">=3.2.0-194.0.dev <4.0.0"
|
||||
flutter: ">=1.17.0"
|
||||
dart: ">=3.3.0 <4.0.0"
|
||||
flutter: ">=3.18.0-18.0.pre.54"
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
/// A library for creating input fields in Flutter.
|
||||
library flutter_input_library;
|
||||
|
||||
export 'src/inputs/inputs.dart';
|
||||
export 'src/utils/utils.dart';
|
||||
export "src/inputs/inputs.dart";
|
||||
export "src/utils/utils.dart";
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
// ignore_for_file: avoid_positional_boolean_parameters
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import "package:flutter/material.dart";
|
||||
|
||||
import 'package:flutter_input_library/src/inputs/bool/bool_field.dart';
|
||||
import "package:flutter_input_library/src/inputs/bool/bool_field.dart";
|
||||
|
||||
class FlutterFormInputBool extends StatelessWidget {
|
||||
const FlutterFormInputBool({
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
// ignore_for_file: avoid_positional_boolean_parameters
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_input_library/flutter_input_library.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_input_library/flutter_input_library.dart";
|
||||
|
||||
class BoolFormField extends FormField<bool> {
|
||||
BoolFormField({
|
||||
|
@ -85,7 +85,6 @@ class _BoolWidgetState extends State<BoolWidget> {
|
|||
focusNode: widget.focusNode,
|
||||
onChanged: onChanged,
|
||||
);
|
||||
break;
|
||||
|
||||
case BoolWidgetType.checkbox:
|
||||
child = Checkbox(
|
||||
|
@ -97,7 +96,6 @@ class _BoolWidgetState extends State<BoolWidget> {
|
|||
}
|
||||
},
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return Column(
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import "package:flutter/material.dart";
|
||||
|
||||
import 'package:flutter_input_library/src/inputs/carousel/carousel_form.dart';
|
||||
import "package:flutter_input_library/src/inputs/carousel/carousel_form.dart";
|
||||
|
||||
class FlutterFormInputCarousel extends StatelessWidget {
|
||||
const FlutterFormInputCarousel({
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'dart:async';
|
||||
import "dart:async";
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_input_library/src/inputs/carousel/carousel_options.dart';
|
||||
import 'package:flutter_input_library/src/inputs/carousel/carousel_state.dart';
|
||||
import 'package:flutter_input_library/src/inputs/carousel/carousel_utils.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_input_library/src/inputs/carousel/carousel_options.dart";
|
||||
import "package:flutter_input_library/src/inputs/carousel/carousel_state.dart";
|
||||
import "package:flutter_input_library/src/inputs/carousel/carousel_utils.dart";
|
||||
|
||||
abstract class CarouselController {
|
||||
factory CarouselController() => CarouselControllerImpl();
|
||||
abstract class FlutterInputCarouselController {
|
||||
factory FlutterInputCarouselController() => CarouselControllerImpl();
|
||||
bool get ready;
|
||||
|
||||
Future<void> get onReady;
|
||||
|
@ -28,7 +28,7 @@ abstract class CarouselController {
|
|||
void stopAutoPlay();
|
||||
}
|
||||
|
||||
class CarouselControllerImpl implements CarouselController {
|
||||
class CarouselControllerImpl implements FlutterInputCarouselController {
|
||||
final Completer<void> _readyCompleter = Completer<void>();
|
||||
|
||||
CarouselState? _state;
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_input_library/src/inputs/carousel/carousel_slider.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_input_library/src/inputs/carousel/carousel_slider.dart";
|
||||
|
||||
class CarouselFormField extends FormField<int> {
|
||||
CarouselFormField({
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import "package:flutter/material.dart";
|
||||
|
||||
enum CarouselPageChangedReason { timed, manual, controller }
|
||||
|
||||
|
|
|
@ -4,17 +4,17 @@
|
|||
///
|
||||
library carousel_slider;
|
||||
|
||||
import 'dart:async';
|
||||
import "dart:async";
|
||||
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_input_library/src/inputs/carousel/carousel_controller.dart';
|
||||
import 'package:flutter_input_library/src/inputs/carousel/carousel_options.dart';
|
||||
import 'package:flutter_input_library/src/inputs/carousel/carousel_state.dart';
|
||||
import 'package:flutter_input_library/src/inputs/carousel/carousel_utils.dart';
|
||||
import "package:flutter/gestures.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_input_library/src/inputs/carousel/carousel_controller.dart";
|
||||
import "package:flutter_input_library/src/inputs/carousel/carousel_options.dart";
|
||||
import "package:flutter_input_library/src/inputs/carousel/carousel_state.dart";
|
||||
import "package:flutter_input_library/src/inputs/carousel/carousel_utils.dart";
|
||||
|
||||
export 'carousel_controller.dart';
|
||||
export 'carousel_options.dart';
|
||||
export "carousel_controller.dart";
|
||||
export "carousel_options.dart";
|
||||
|
||||
typedef ExtendedIndexedWidgetBuilder = Widget Function(
|
||||
BuildContext context,
|
||||
|
@ -26,25 +26,25 @@ class CarouselSlider extends StatefulWidget {
|
|||
CarouselSlider({
|
||||
required this.items,
|
||||
required this.options,
|
||||
CarouselController? carouselController,
|
||||
FlutterInputCarouselController? carouselController,
|
||||
super.key,
|
||||
}) : itemBuilder = null,
|
||||
itemCount = items != null ? items.length : 0,
|
||||
_carouselController = carouselController != null
|
||||
? carouselController as CarouselControllerImpl
|
||||
: CarouselController() as CarouselControllerImpl;
|
||||
: FlutterInputCarouselController() as CarouselControllerImpl;
|
||||
|
||||
/// The on demand item builder constructor/
|
||||
CarouselSlider.builder({
|
||||
required this.itemCount,
|
||||
required this.itemBuilder,
|
||||
required this.options,
|
||||
CarouselController? carouselController,
|
||||
FlutterInputCarouselController? carouselController,
|
||||
super.key,
|
||||
}) : items = null,
|
||||
_carouselController = carouselController != null
|
||||
? carouselController as CarouselControllerImpl
|
||||
: CarouselController() as CarouselControllerImpl;
|
||||
: FlutterInputCarouselController() as CarouselControllerImpl;
|
||||
|
||||
/// [CarouselOptions] to create a [CarouselState] with.
|
||||
final CarouselOptions options;
|
||||
|
@ -81,6 +81,7 @@ class CarouselSliderState extends State<CarouselSlider>
|
|||
/// [mode] is related to why the page is being changed.
|
||||
CarouselPageChangedReason mode = CarouselPageChangedReason.controller;
|
||||
|
||||
// ignore: use_setters_to_change_properties
|
||||
void changeMode(CarouselPageChangedReason mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_input_library/src/inputs/carousel/carousel_slider.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_input_library/src/inputs/carousel/carousel_slider.dart";
|
||||
|
||||
class CarouselState {
|
||||
CarouselState(
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_input_library/src/inputs/date_picker/date_picker_field.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_input_library/src/inputs/date_picker/date_picker_field.dart";
|
||||
import "package:intl/intl.dart";
|
||||
|
||||
enum FlutterFormDateTimeType {
|
||||
date,
|
||||
|
@ -36,6 +36,7 @@ class FlutterFormInputDateTime extends StatelessWidget {
|
|||
this.timePickerEntryMode = TimePickerEntryMode.dial,
|
||||
this.enabled = true,
|
||||
this.onTapEnabled = true,
|
||||
this.selectableTimePredicate,
|
||||
});
|
||||
final TextStyle? style;
|
||||
final InputDecoration? decoration;
|
||||
|
@ -57,6 +58,7 @@ class FlutterFormInputDateTime extends StatelessWidget {
|
|||
final TimePickerEntryMode timePickerEntryMode;
|
||||
final bool enabled;
|
||||
final bool onTapEnabled;
|
||||
final bool Function(DateTime)? selectableTimePredicate;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => DateTimeInputField(
|
||||
|
@ -80,5 +82,6 @@ class FlutterFormInputDateTime extends StatelessWidget {
|
|||
timePickerEntryMode: timePickerEntryMode,
|
||||
enabled: enabled,
|
||||
onTapEnabled: onTapEnabled,
|
||||
selectableDayPredicate: selectableTimePredicate,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'dart:async';
|
||||
import "dart:async";
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_input_library/src/inputs/date_picker/date_picker.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_input_library/src/inputs/date_picker/date_picker.dart";
|
||||
import "package:intl/intl.dart";
|
||||
|
||||
class DateTimeInputField extends StatefulWidget {
|
||||
const DateTimeInputField({
|
||||
|
@ -31,6 +31,7 @@ class DateTimeInputField extends StatefulWidget {
|
|||
this.validator,
|
||||
this.enabled = true,
|
||||
this.onTapEnabled = true,
|
||||
this.selectableDayPredicate,
|
||||
});
|
||||
final TextStyle? style;
|
||||
final InputDecoration? decoration;
|
||||
|
@ -52,6 +53,7 @@ class DateTimeInputField extends StatefulWidget {
|
|||
final TimePickerEntryMode timePickerEntryMode;
|
||||
final bool enabled;
|
||||
final bool onTapEnabled;
|
||||
final bool Function(DateTime)? selectableDayPredicate;
|
||||
|
||||
@override
|
||||
State<DateTimeInputField> createState() => _DateInputFieldState();
|
||||
|
@ -63,7 +65,7 @@ class _DateInputFieldState extends State<DateTimeInputField> {
|
|||
late final DateTime initialDate;
|
||||
late final DateTimeRange initialDateRange;
|
||||
late final TimeOfDay? initialTime;
|
||||
String currentValue = '';
|
||||
String currentValue = "";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
@ -95,31 +97,34 @@ class _DateInputFieldState extends State<DateTimeInputField> {
|
|||
FlutterFormDateTimeType inputType, [
|
||||
DateFormat? dateFormat,
|
||||
]) async {
|
||||
var userInput = '';
|
||||
var userInput = "";
|
||||
switch (inputType) {
|
||||
case FlutterFormDateTimeType.date:
|
||||
var unformatted = await showDatePicker(
|
||||
initialDate: initialDate,
|
||||
context: context,
|
||||
firstDate: firstDate,
|
||||
lastDate: lastDate,
|
||||
);
|
||||
userInput = unformatted != null
|
||||
? widget.dateFormat.format(unformatted)
|
||||
: userInput;
|
||||
break;
|
||||
if (context.mounted) {
|
||||
var unformatted = await showDatePicker(
|
||||
initialDate: initialDate,
|
||||
context: context,
|
||||
firstDate: firstDate,
|
||||
lastDate: lastDate,
|
||||
selectableDayPredicate: widget.selectableDayPredicate,
|
||||
);
|
||||
userInput = unformatted != null
|
||||
? widget.dateFormat.format(unformatted)
|
||||
: userInput;
|
||||
}
|
||||
|
||||
case FlutterFormDateTimeType.dateTime:
|
||||
await getInputFromUser(FlutterFormDateTimeType.date)
|
||||
.then((value) async {
|
||||
if (value != '') {
|
||||
if (value != "") {
|
||||
var secondInput =
|
||||
await getInputFromUser(FlutterFormDateTimeType.time);
|
||||
if (secondInput != '') {
|
||||
if (secondInput != "") {
|
||||
var date = widget.dateFormat.parse(value);
|
||||
var time = dateFormat != null
|
||||
? dateFormat.parse('01 01 1970 $secondInput')
|
||||
: DateFormat('dd MM yyyy HH:mm')
|
||||
.parse('01 01 1970 $secondInput');
|
||||
? dateFormat.parse("01 01 1970 $secondInput")
|
||||
: DateFormat("dd MM yyyy HH:mm")
|
||||
.parse("01 01 1970 $secondInput");
|
||||
userInput = widget.dateFormat.format(
|
||||
DateTime(
|
||||
date.year,
|
||||
|
@ -132,7 +137,7 @@ class _DateInputFieldState extends State<DateTimeInputField> {
|
|||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case FlutterFormDateTimeType.range:
|
||||
if (context.mounted) {
|
||||
userInput = await showDateRangePicker(
|
||||
|
@ -142,13 +147,14 @@ class _DateInputFieldState extends State<DateTimeInputField> {
|
|||
initialDateRange: initialDateRange,
|
||||
).then(
|
||||
(value) => value != null
|
||||
? '${widget.dateFormat.format(value.start)} -'
|
||||
'${widget.dateFormat.format(value.end)}'
|
||||
: '',
|
||||
? "${widget.dateFormat.format(value.start)} - "
|
||||
"${widget.dateFormat.format(value.end)}"
|
||||
: "",
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case FlutterFormDateTimeType.time:
|
||||
var locale = MaterialLocalizations.of(context);
|
||||
if (context.mounted) {
|
||||
userInput = await showTimePicker(
|
||||
initialEntryMode: widget.timePickerEntryMode,
|
||||
|
@ -161,9 +167,8 @@ class _DateInputFieldState extends State<DateTimeInputField> {
|
|||
initialTime: initialTimeOfDay,
|
||||
).then(
|
||||
(value) => value == null
|
||||
? ''
|
||||
: MaterialLocalizations.of(context)
|
||||
.formatTimeOfDay(value, alwaysUse24HourFormat: true),
|
||||
? ""
|
||||
: locale.formatTimeOfDay(value, alwaysUse24HourFormat: true),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -182,12 +187,12 @@ class _DateInputFieldState extends State<DateTimeInputField> {
|
|||
? () async {
|
||||
var userInput = await getInputFromUser(
|
||||
widget.inputType,
|
||||
DateFormat('dd MM yyyy HH:mm'),
|
||||
DateFormat("dd MM yyyy HH:mm"),
|
||||
);
|
||||
setState(() {
|
||||
currentValue = userInput != '' ? userInput : currentValue;
|
||||
currentValue = userInput != "" ? userInput : currentValue;
|
||||
widget.onChanged
|
||||
?.call(userInput != '' ? userInput : currentValue);
|
||||
?.call(userInput != "" ? userInput : currentValue);
|
||||
});
|
||||
}
|
||||
: null,
|
||||
|
@ -196,7 +201,7 @@ class _DateInputFieldState extends State<DateTimeInputField> {
|
|||
InputDecoration(
|
||||
suffixIcon: widget.showIcon ? Icon(widget.icon) : null,
|
||||
focusColor: Theme.of(context).primaryColor,
|
||||
label: widget.label ?? const Text('Date'),
|
||||
label: widget.label ?? const Text("Date"),
|
||||
),
|
||||
enabled: widget.enabled,
|
||||
);
|
||||
|
|
99
lib/src/inputs/dropdown/dropdown.dart
Normal file
99
lib/src/inputs/dropdown/dropdown.dart
Normal file
|
@ -0,0 +1,99 @@
|
|||
import "package:flutter/material.dart";
|
||||
|
||||
class FlutterFormInputDropdown extends StatelessWidget {
|
||||
const FlutterFormInputDropdown({
|
||||
this.alignment = AlignmentDirectional.centerStart,
|
||||
this.autofocus = false,
|
||||
this.isExpanded = false,
|
||||
this.isDense = true,
|
||||
this.iconSize = 24,
|
||||
this.elevation = 8,
|
||||
this.items,
|
||||
this.selectedItemBuilder,
|
||||
this.value,
|
||||
this.hint,
|
||||
this.disabledHint,
|
||||
this.onChanged,
|
||||
this.onTap,
|
||||
this.style,
|
||||
this.icon,
|
||||
this.iconDisabledColor,
|
||||
this.iconEnabledColor,
|
||||
this.itemHeight,
|
||||
this.focusColor,
|
||||
this.focusNode,
|
||||
this.dropdownColor,
|
||||
this.decoration,
|
||||
this.onSaved,
|
||||
this.validator,
|
||||
this.autovalidateMode,
|
||||
this.menuMaxHeight,
|
||||
this.enableFeedback,
|
||||
this.borderRadius,
|
||||
this.padding,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final List<DropdownMenuItem<Object?>>? items;
|
||||
final List<Widget> Function(BuildContext)? selectedItemBuilder;
|
||||
final Object? value;
|
||||
final Widget? hint;
|
||||
final Widget? disabledHint;
|
||||
final void Function(Object?)? onChanged;
|
||||
final void Function()? onTap;
|
||||
final int elevation;
|
||||
final TextStyle? style;
|
||||
final Widget? icon;
|
||||
final Color? iconDisabledColor;
|
||||
final Color? iconEnabledColor;
|
||||
final double iconSize;
|
||||
final bool isDense;
|
||||
final bool isExpanded;
|
||||
final double? itemHeight;
|
||||
final Color? focusColor;
|
||||
final FocusNode? focusNode;
|
||||
final bool autofocus;
|
||||
final Color? dropdownColor;
|
||||
final InputDecoration? decoration;
|
||||
final void Function(Object?)? onSaved;
|
||||
final String? Function(Object?)? validator;
|
||||
final AutovalidateMode? autovalidateMode;
|
||||
final double? menuMaxHeight;
|
||||
final bool? enableFeedback;
|
||||
final AlignmentGeometry alignment;
|
||||
final BorderRadius? borderRadius;
|
||||
final EdgeInsetsGeometry? padding;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => DropdownButtonFormField(
|
||||
items: items,
|
||||
selectedItemBuilder: selectedItemBuilder,
|
||||
value: value,
|
||||
hint: hint,
|
||||
disabledHint: disabledHint,
|
||||
onChanged: (value) => onChanged?.call(value),
|
||||
onTap: () => onTap?.call(),
|
||||
elevation: elevation,
|
||||
style: style,
|
||||
icon: icon,
|
||||
iconDisabledColor: iconDisabledColor,
|
||||
iconEnabledColor: iconEnabledColor,
|
||||
iconSize: iconSize,
|
||||
isDense: isDense,
|
||||
isExpanded: isExpanded,
|
||||
itemHeight: itemHeight,
|
||||
focusColor: focusColor,
|
||||
focusNode: focusNode,
|
||||
autofocus: autofocus,
|
||||
dropdownColor: dropdownColor,
|
||||
decoration: decoration,
|
||||
onSaved: (value) => onSaved?.call(value),
|
||||
validator: (value) => validator?.call(value),
|
||||
autovalidateMode: autovalidateMode,
|
||||
menuMaxHeight: menuMaxHeight,
|
||||
enableFeedback: enableFeedback,
|
||||
alignment: alignment,
|
||||
borderRadius: borderRadius,
|
||||
padding: padding,
|
||||
);
|
||||
}
|
|
@ -1,10 +1,13 @@
|
|||
export 'bool/bool.dart';
|
||||
export 'carousel/carousel.dart';
|
||||
export 'date_picker/date_picker.dart';
|
||||
export 'number_picker/number_picker.dart';
|
||||
export 'phone/countries.dart';
|
||||
export 'phone/phone.dart';
|
||||
export 'scroll_picker/scroll_picker.dart';
|
||||
export 'slider/slider.dart';
|
||||
export 'text/password.dart';
|
||||
export 'text/plain_text.dart';
|
||||
export "bool/bool.dart";
|
||||
export "carousel/carousel.dart";
|
||||
export "date_picker/date_picker.dart";
|
||||
export "dropdown/dropdown.dart";
|
||||
export "number_picker/number_picker.dart";
|
||||
export "phone/countries.dart";
|
||||
export "phone/phone.dart";
|
||||
export "phone/phone_number_model.dart";
|
||||
export "radio/radio_picker.dart";
|
||||
export "scroll_picker/scroll_picker.dart";
|
||||
export "slider/slider.dart";
|
||||
export "text/password.dart";
|
||||
export "text/plain_text.dart";
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'dart:math' as math;
|
||||
import "dart:math" as math;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import "package:flutter/material.dart";
|
||||
|
||||
import 'package:flutter_input_library/src/inputs/number_picker/number_picker_field.dart';
|
||||
import "package:flutter_input_library/src/inputs/number_picker/number_picker_field.dart";
|
||||
|
||||
class DecimalNumberPicker extends StatelessWidget {
|
||||
const DecimalNumberPicker({
|
||||
|
@ -28,8 +28,8 @@ class DecimalNumberPicker extends StatelessWidget {
|
|||
this.integerZeroPad = false,
|
||||
this.integerDecoration,
|
||||
this.decimalDecoration,
|
||||
}) : assert(minValue <= value, 'value must be greater than minValue'),
|
||||
assert(value <= maxValue, 'value must be less than maxValue');
|
||||
}) : assert(minValue <= value, "value must be greater than minValue"),
|
||||
assert(value <= maxValue, "value must be less than maxValue");
|
||||
final int minValue;
|
||||
final int maxValue;
|
||||
final double value;
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'dart:math' as math;
|
||||
import "dart:math" as math;
|
||||
|
||||
import 'package:flutter/gestures.dart' show DragStartBehavior;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import "package:flutter/gestures.dart" show DragStartBehavior;
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter/rendering.dart";
|
||||
import "package:flutter/widgets.dart";
|
||||
|
||||
/// Infinite ListView
|
||||
///
|
||||
|
@ -274,18 +274,18 @@ class InfiniteListViewState extends State<InfiniteListView> {
|
|||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties
|
||||
.add(EnumProperty<Axis>('scrollDirection', widget.scrollDirection));
|
||||
.add(EnumProperty<Axis>("scrollDirection", widget.scrollDirection));
|
||||
properties.add(
|
||||
FlagProperty(
|
||||
'reverse',
|
||||
"reverse",
|
||||
value: widget.reverse,
|
||||
ifTrue: 'reversed',
|
||||
ifTrue: "reversed",
|
||||
showName: true,
|
||||
),
|
||||
);
|
||||
properties.add(
|
||||
DiagnosticsProperty<ScrollController>(
|
||||
'controller',
|
||||
"controller",
|
||||
widget.controller,
|
||||
showName: false,
|
||||
defaultValue: null,
|
||||
|
@ -293,7 +293,7 @@ class InfiniteListViewState extends State<InfiniteListView> {
|
|||
);
|
||||
properties.add(
|
||||
DiagnosticsProperty<ScrollPhysics>(
|
||||
'physics',
|
||||
"physics",
|
||||
widget.physics,
|
||||
showName: false,
|
||||
defaultValue: null,
|
||||
|
@ -301,16 +301,16 @@ class InfiniteListViewState extends State<InfiniteListView> {
|
|||
);
|
||||
properties.add(
|
||||
DiagnosticsProperty<EdgeInsetsGeometry>(
|
||||
'padding',
|
||||
"padding",
|
||||
widget.padding,
|
||||
defaultValue: null,
|
||||
),
|
||||
);
|
||||
properties.add(
|
||||
DoubleProperty('itemExtent', widget.itemExtent, defaultValue: null),
|
||||
DoubleProperty("itemExtent", widget.itemExtent, defaultValue: null),
|
||||
);
|
||||
properties.add(
|
||||
DoubleProperty('cacheExtent', widget.cacheExtent, defaultValue: null),
|
||||
DoubleProperty("cacheExtent", widget.cacheExtent, defaultValue: null),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import "package:flutter/material.dart";
|
||||
|
||||
import 'package:flutter_input_library/src/inputs/number_picker/number_picker_field.dart';
|
||||
import "package:flutter_input_library/src/inputs/number_picker/number_picker_field.dart";
|
||||
|
||||
class FlutterFormInputNumberPicker extends StatelessWidget {
|
||||
const FlutterFormInputNumberPicker({
|
||||
|
@ -15,7 +15,8 @@ class FlutterFormInputNumberPicker extends StatelessWidget {
|
|||
this.onChanged,
|
||||
this.initialValue,
|
||||
this.validator,
|
||||
}) : assert(minValue < maxValue, 'minValue must be less than maxValue');
|
||||
this.axis = Axis.vertical,
|
||||
}) : assert(minValue < maxValue, "minValue must be less than maxValue");
|
||||
|
||||
final int minValue;
|
||||
final int maxValue;
|
||||
|
@ -23,6 +24,7 @@ class FlutterFormInputNumberPicker extends StatelessWidget {
|
|||
final String? Function(int?)? validator;
|
||||
final int? initialValue;
|
||||
final Function(int?)? onChanged;
|
||||
final Axis axis;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => NumberPickerFormField(
|
||||
|
@ -32,6 +34,7 @@ class FlutterFormInputNumberPicker extends StatelessWidget {
|
|||
validator: (value) => validator?.call(value),
|
||||
onChanged: (value) => onChanged?.call(value),
|
||||
initialValue: initialValue ?? 0,
|
||||
axis: axis,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -44,6 +47,7 @@ class NumberPickerFormField extends FormField<int> {
|
|||
int super.initialValue = 0,
|
||||
int minValue = 0,
|
||||
int maxValue = 100,
|
||||
Axis axis = Axis.vertical,
|
||||
}) : super(
|
||||
builder: (FormFieldState<int> state) => NumberPicker(
|
||||
minValue: minValue,
|
||||
|
@ -55,7 +59,9 @@ class NumberPickerFormField extends FormField<int> {
|
|||
state.didChange(value);
|
||||
},
|
||||
itemHeight: 35,
|
||||
itemWidth: 35,
|
||||
itemCount: 5,
|
||||
axis: axis,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'dart:async';
|
||||
import "dart:async";
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_input_library/src/inputs/number_picker/infinite_listview.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter/services.dart";
|
||||
import "package:flutter_input_library/src/inputs/number_picker/infinite_listview.dart";
|
||||
|
||||
typedef TextMapper = String Function(String numberText);
|
||||
|
||||
|
@ -29,8 +29,8 @@ class NumberPicker extends StatefulWidget {
|
|||
this.zeroPad = false,
|
||||
this.textMapper,
|
||||
this.infiniteLoop = false,
|
||||
}) : assert(minValue <= value, 'value must be greater than minValue'),
|
||||
assert(value <= maxValue, 'value must be less than maxValue');
|
||||
}) : assert(minValue <= value, "value must be greater than minValue"),
|
||||
assert(value <= maxValue, "value must be less than maxValue");
|
||||
|
||||
/// Min value user can pick
|
||||
final int minValue;
|
||||
|
@ -182,8 +182,8 @@ class NumberPickerState extends State<NumberPicker> {
|
|||
children: [
|
||||
Center(
|
||||
child: Container(
|
||||
width: 300,
|
||||
height: 45,
|
||||
width: widget.itemWidth,
|
||||
height: widget.itemHeight,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
color: const Color(0xFFD8D8D8).withOpacity(0.50),
|
||||
|
@ -248,7 +248,7 @@ class NumberPickerState extends State<NumberPicker> {
|
|||
|
||||
String _getDisplayedValue(int value) {
|
||||
var text = widget.zeroPad
|
||||
? value.toString().padLeft(widget.maxValue.toString().length, '0')
|
||||
? value.toString().padLeft(widget.maxValue.toString().length, "0")
|
||||
: value.toString();
|
||||
if (widget.textMapper != null) {
|
||||
return widget.textMapper!(text);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3,9 +3,9 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// ignore: depend_on_referenced_packages
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_input_library/flutter_input_library.dart';
|
||||
import "package:collection/collection.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_input_library/flutter_input_library.dart";
|
||||
|
||||
class FlutterFormInputPhone extends StatefulWidget {
|
||||
const FlutterFormInputPhone({
|
||||
|
@ -17,25 +17,27 @@ class FlutterFormInputPhone extends StatefulWidget {
|
|||
this.onSaved,
|
||||
this.validator,
|
||||
this.onFieldSubmitted,
|
||||
this.style,
|
||||
this.numberFieldStyle,
|
||||
this.dialCodeSelectorStyle,
|
||||
this.enabled = true,
|
||||
this.priorityCountries = const ['NL', 'BE', 'LU'],
|
||||
this.countrySelectorUnderline,
|
||||
this.countrySelectorWidth = 100,
|
||||
this.priorityCountries = const ["NL", "BE", "LU"],
|
||||
this.textAlignVertical = TextAlignVertical.top,
|
||||
this.dialCodeSelectorPadding = const EdgeInsets.only(top: 6),
|
||||
});
|
||||
|
||||
final InputDecoration? decoration;
|
||||
final Widget? label;
|
||||
final String? initialValue;
|
||||
final Function(String?)? onSaved;
|
||||
final String? Function(String?)? validator;
|
||||
final Function(String?)? onChanged;
|
||||
final Function(String?)? onFieldSubmitted;
|
||||
final TextStyle? style;
|
||||
final PhoneNumber? initialValue;
|
||||
final Function(PhoneNumber?)? onSaved;
|
||||
final String? Function(PhoneNumber?)? validator;
|
||||
final Function(PhoneNumber?)? onChanged;
|
||||
final Function(PhoneNumber?)? onFieldSubmitted;
|
||||
final TextStyle? numberFieldStyle;
|
||||
final TextStyle? dialCodeSelectorStyle;
|
||||
final bool enabled;
|
||||
final List<String>? priorityCountries;
|
||||
final Widget? countrySelectorUnderline;
|
||||
final double countrySelectorWidth;
|
||||
final EdgeInsets dialCodeSelectorPadding;
|
||||
final TextAlignVertical textAlignVertical;
|
||||
|
||||
@override
|
||||
State<FlutterFormInputPhone> createState() => _FlutterFormInputPhoneState();
|
||||
|
@ -70,25 +72,45 @@ class _FlutterFormInputPhoneState extends State<FlutterFormInputPhone> {
|
|||
}
|
||||
}
|
||||
|
||||
_selectedCountry = _countryList.first;
|
||||
_selectedCountry = _countryList.firstWhereOrNull(
|
||||
(country) => widget.initialValue?.dialCode == country.dialCode,
|
||||
) ??
|
||||
_countryList.first;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var inputDecoration = widget.decoration ??
|
||||
InputDecoration(
|
||||
label: widget.label ?? const Text('Phone number'),
|
||||
label: widget.label ?? const Text("Phone number"),
|
||||
);
|
||||
|
||||
return Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.only(top: 16),
|
||||
width: widget.countrySelectorWidth,
|
||||
return FlutterFormInputPlainText(
|
||||
label: widget.label,
|
||||
style: widget.numberFieldStyle,
|
||||
initialValue: widget.initialValue?.number,
|
||||
onSaved: (value) => widget.onSaved?.call(
|
||||
PhoneNumber(dialCode: _selectedCountry.dialCode, number: value),
|
||||
),
|
||||
validator: (value) => widget.validator?.call(
|
||||
PhoneNumber(dialCode: _selectedCountry.dialCode, number: value),
|
||||
),
|
||||
onChanged: (value) => widget.onChanged?.call(
|
||||
PhoneNumber(dialCode: _selectedCountry.dialCode, number: value),
|
||||
),
|
||||
onFieldSubmitted: (value) => widget.onFieldSubmitted?.call(
|
||||
PhoneNumber(dialCode: _selectedCountry.dialCode, number: value),
|
||||
),
|
||||
decoration: inputDecoration.copyWith(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
prefixIcon: Padding(
|
||||
padding: widget.dialCodeSelectorPadding,
|
||||
child: DropdownButton(
|
||||
padding: EdgeInsets.zero,
|
||||
elevation: 0,
|
||||
value: _selectedCountry,
|
||||
style: widget.style,
|
||||
underline: widget.countrySelectorUnderline,
|
||||
style: widget.dialCodeSelectorStyle,
|
||||
underline: const SizedBox.shrink(),
|
||||
items: [
|
||||
for (var country in _countryList) ...[
|
||||
DropdownMenuItem(
|
||||
|
@ -100,7 +122,7 @@ class _FlutterFormInputPhoneState extends State<FlutterFormInputPhone> {
|
|||
const SizedBox(
|
||||
width: 4,
|
||||
),
|
||||
Text('+${country.dialCode}'),
|
||||
Text("+${country.dialCode}"),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -115,27 +137,10 @@ class _FlutterFormInputPhoneState extends State<FlutterFormInputPhone> {
|
|||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 16,
|
||||
),
|
||||
Expanded(
|
||||
child: FlutterFormInputPlainText(
|
||||
style: widget.style,
|
||||
initialValue: widget.initialValue,
|
||||
onSaved: (value) =>
|
||||
widget.onSaved?.call('${_selectedCountry.dialCode}$value'),
|
||||
validator: (value) =>
|
||||
widget.validator?.call('${_selectedCountry.dialCode}$value'),
|
||||
onChanged: (value) =>
|
||||
widget.onChanged?.call('${_selectedCountry.dialCode}$value'),
|
||||
onFieldSubmitted: (value) => widget.onFieldSubmitted
|
||||
?.call('${_selectedCountry.dialCode}$value'),
|
||||
decoration: inputDecoration.copyWith(),
|
||||
keyboardType: TextInputType.phone,
|
||||
enabled: widget.enabled,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
keyboardType: TextInputType.phone,
|
||||
enabled: widget.enabled,
|
||||
textAlignVertical: widget.textAlignVertical,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
9
lib/src/inputs/phone/phone_number_model.dart
Normal file
9
lib/src/inputs/phone/phone_number_model.dart
Normal file
|
@ -0,0 +1,9 @@
|
|||
class PhoneNumber {
|
||||
const PhoneNumber({
|
||||
this.dialCode,
|
||||
this.number,
|
||||
});
|
||||
|
||||
final String? dialCode;
|
||||
final String? number;
|
||||
}
|
77
lib/src/inputs/radio/radio_picker.dart
Normal file
77
lib/src/inputs/radio/radio_picker.dart
Normal file
|
@ -0,0 +1,77 @@
|
|||
// SPDX-FileCopyrightText: 2024 Iconica
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// ignore: depend_on_referenced_packages
|
||||
import "package:collection/collection.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_input_library/src/inputs/radio/radio_picker_field.dart";
|
||||
|
||||
class FlutterFormInputRadioPicker extends StatelessWidget {
|
||||
const FlutterFormInputRadioPicker({
|
||||
required this.items,
|
||||
super.key,
|
||||
this.onSaved,
|
||||
this.onChanged,
|
||||
this.initialValue,
|
||||
this.itemSpacing = 16.0,
|
||||
});
|
||||
|
||||
final Function(RadioItem?)? onSaved;
|
||||
final String? initialValue;
|
||||
final Function(RadioItem?)? onChanged;
|
||||
final List<RadioItem> items;
|
||||
final double itemSpacing;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => RadioPickerFormField(
|
||||
onSaved: (value) => onSaved?.call(value),
|
||||
onChanged: (value) => onChanged?.call(value),
|
||||
initialValue: items.firstWhereOrNull((i) => i.value == initialValue),
|
||||
itemSpacing: itemSpacing,
|
||||
items: items,
|
||||
);
|
||||
}
|
||||
|
||||
class RadioPickerFormField extends FormField<RadioItem?> {
|
||||
RadioPickerFormField({
|
||||
required FormFieldSetter<RadioItem> super.onSaved,
|
||||
required List<RadioItem> items,
|
||||
required double itemSpacing,
|
||||
void Function(RadioItem value)? onChanged,
|
||||
super.initialValue,
|
||||
super.key,
|
||||
}) : super(
|
||||
builder: (FormFieldState<RadioItem?> state) => RadioPicker(
|
||||
onChanged: (value) {
|
||||
onChanged?.call(value);
|
||||
|
||||
state.didChange(value);
|
||||
},
|
||||
items: items,
|
||||
initialValue: initialValue,
|
||||
itemSpacing: itemSpacing,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class RadioItem<T> {
|
||||
/// Creates an item for a radio menu.
|
||||
///
|
||||
/// The [child] argument is required.
|
||||
const RadioItem({
|
||||
required this.child,
|
||||
required this.value,
|
||||
this.onTap,
|
||||
});
|
||||
|
||||
/// Called when the dropdown menu item is tapped.
|
||||
final VoidCallback? onTap;
|
||||
|
||||
/// The value to return if the user selects this menu item.
|
||||
///
|
||||
/// Eventually returned in a call to [DropdownButton.onChanged].
|
||||
final T value;
|
||||
|
||||
final Widget child;
|
||||
}
|
55
lib/src/inputs/radio/radio_picker_field.dart
Normal file
55
lib/src/inputs/radio/radio_picker_field.dart
Normal file
|
@ -0,0 +1,55 @@
|
|||
import "package:flutter/material.dart";
|
||||
import "package:flutter_input_library/src/inputs/radio/radio_picker.dart";
|
||||
|
||||
class RadioPicker extends StatefulWidget {
|
||||
const RadioPicker({
|
||||
required this.onChanged,
|
||||
required this.items,
|
||||
this.itemSpacing = 16.0,
|
||||
this.initialValue,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final RadioItem? initialValue;
|
||||
final Function(RadioItem) onChanged;
|
||||
final List<RadioItem> items;
|
||||
|
||||
/// The spacing between each item.
|
||||
final double itemSpacing;
|
||||
|
||||
@override
|
||||
State<RadioPicker> createState() => _RadioPickerState();
|
||||
}
|
||||
|
||||
class _RadioPickerState extends State<RadioPicker> {
|
||||
late RadioItem? value = widget.initialValue;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Wrap(
|
||||
children: [
|
||||
for (var item in widget.items) ...[
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
item.child,
|
||||
Radio<RadioItem>(
|
||||
value: item,
|
||||
groupValue: value,
|
||||
onChanged: (v) {
|
||||
if (v != null) {
|
||||
setState(() {
|
||||
value = v;
|
||||
});
|
||||
widget.onChanged(v);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
if (widget.items.last != item) ...[
|
||||
SizedBox(width: widget.itemSpacing),
|
||||
],
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
|
@ -1,3 +1,3 @@
|
|||
export 'scroll_picker_decoration.dart';
|
||||
export 'scroll_picker_type_extensions.dart';
|
||||
export 'scroll_picker_widget.dart';
|
||||
export "scroll_picker_decoration.dart";
|
||||
export "scroll_picker_type_extensions.dart";
|
||||
export "scroll_picker_widget.dart";
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import "package:flutter/material.dart";
|
||||
|
||||
class ScrollPickerDecoration {
|
||||
const ScrollPickerDecoration({
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_input_library/src/inputs/scroll_picker/scroll_picker_decoration.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_input_library/src/inputs/scroll_picker/scroll_picker_decoration.dart";
|
||||
|
||||
class ScrollPicker extends StatefulWidget {
|
||||
const ScrollPicker({
|
||||
|
|
|
@ -35,7 +35,7 @@ class TypeUtils {
|
|||
WeekDay end,
|
||||
) {
|
||||
if (start.index > end.index) {
|
||||
throw ArgumentError('Start month must be before or equal to end month.');
|
||||
throw ArgumentError("Start month must be before or equal to end month.");
|
||||
}
|
||||
|
||||
var result = <DateTime>[];
|
||||
|
@ -49,7 +49,7 @@ class TypeUtils {
|
|||
/// Creates list of Datetime with the months from start to end.
|
||||
List<DateTime> createMonthList(Month start, Month end, {int? year}) {
|
||||
if (start.index > end.index) {
|
||||
throw ArgumentError('Start month must be before or equal to end month.');
|
||||
throw ArgumentError("Start month must be before or equal to end month.");
|
||||
}
|
||||
|
||||
var result = <DateTime>[];
|
||||
|
@ -65,7 +65,7 @@ class TypeUtils {
|
|||
/// Creates a list of Datetime with the years from start to end.
|
||||
List<DateTime> createYearList(int start, int end) {
|
||||
if (start > end) {
|
||||
throw ArgumentError('Start year must be before or equal to year month.');
|
||||
throw ArgumentError("Start year must be before or equal to year month.");
|
||||
}
|
||||
|
||||
var result = <DateTime>[];
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_input_library/src/inputs/scroll_picker/scroll_picker_decoration.dart';
|
||||
import 'package:flutter_input_library/src/inputs/scroll_picker/scroll_picker_field.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_input_library/src/inputs/scroll_picker/scroll_picker_decoration.dart";
|
||||
import "package:flutter_input_library/src/inputs/scroll_picker/scroll_picker_field.dart";
|
||||
|
||||
class FlutterFormInputScrollPicker<T> extends StatelessWidget {
|
||||
const FlutterFormInputScrollPicker({
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_input_library/src/inputs/slider/slider_field.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_input_library/src/inputs/slider/slider_field.dart";
|
||||
|
||||
class FlutterFormInputSlider extends StatelessWidget {
|
||||
const FlutterFormInputSlider({
|
||||
|
@ -15,7 +15,7 @@ class FlutterFormInputSlider extends StatelessWidget {
|
|||
this.initialValue,
|
||||
this.validator,
|
||||
this.focusNode,
|
||||
}) : assert(minValue < maxValue, 'minValue must be less than maxValue');
|
||||
}) : assert(minValue < maxValue, "minValue must be less than maxValue");
|
||||
|
||||
final int minValue;
|
||||
final int maxValue;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import "package:flutter/material.dart";
|
||||
|
||||
/// Creates a slider with the given input parameters
|
||||
class SliderFormField extends FormField<double> {
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter/services.dart";
|
||||
|
||||
/// Generates a [TextFormField] for passwords. It requires a
|
||||
/// [FlutterFormInputController] as the [controller] parameter and an
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter/services.dart";
|
||||
|
||||
class FlutterFormInputPlainText extends StatelessWidget {
|
||||
const FlutterFormInputPlainText({
|
||||
|
@ -53,7 +53,7 @@ class FlutterFormInputPlainText extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
var inputDecoration = decoration ??
|
||||
InputDecoration(
|
||||
label: label ?? const Text('Plain text'),
|
||||
label: label ?? const Text("Plain text"),
|
||||
);
|
||||
|
||||
return TextFormField(
|
||||
|
@ -96,6 +96,7 @@ class FlutterFormInputMultiLine extends StatelessWidget {
|
|||
this.validator,
|
||||
this.onFieldSubmitted,
|
||||
this.textCapitalization = TextCapitalization.sentences,
|
||||
this.style,
|
||||
});
|
||||
|
||||
final Widget? label;
|
||||
|
@ -113,12 +114,14 @@ class FlutterFormInputMultiLine extends StatelessWidget {
|
|||
final Function(String?)? onChanged;
|
||||
final Function(String?)? onFieldSubmitted;
|
||||
final TextCapitalization textCapitalization;
|
||||
final TextStyle? style;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: FlutterFormInputPlainText(
|
||||
style: style,
|
||||
label: label,
|
||||
textAlignVertical: TextAlignVertical.top,
|
||||
expands: true,
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
export 'validators/validators.dart';
|
||||
export "validators/validators.dart";
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
export 'email/email.dart';
|
||||
export "email/email.dart";
|
||||
|
|
13
pubspec.yaml
13
pubspec.yaml
|
@ -1,16 +1,19 @@
|
|||
name: flutter_input_library
|
||||
description: A new Flutter package project.
|
||||
version: 3.2.0
|
||||
version: 3.7.0
|
||||
repository: https://github.com/Iconica-Development/flutter_input_library
|
||||
|
||||
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||
|
||||
environment:
|
||||
sdk: ">=2.18.2 <3.0.0"
|
||||
sdk: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
collection: ^1.18.0
|
||||
flutter:
|
||||
sdk: flutter
|
||||
intl: ^0.18.0
|
||||
intl: ">=0.18.0 <1.0.0"
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
@ -18,6 +21,4 @@ dev_dependencies:
|
|||
flutter_iconica_analysis:
|
||||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
||||
ref: 6.0.0
|
||||
|
||||
flutter:
|
||||
ref: 7.0.0
|
||||
|
|
Loading…
Reference in a new issue