Compare commits

..

No commits in common. "c8214efdb9356620cabf24e25715ff28891511dd" and "546db9006ab2f47a5ce7497a84171af461d63906" have entirely different histories.

7 changed files with 134 additions and 203 deletions

View file

@ -1,137 +1,130 @@
# 3.0.6 ##3.0.1
- Fixing issue #42 dense empty form field * Fixing [issue #29](https://github.com/GaspardMerten/date_field/issues/29) -> adding 24h format support for material time picker dialog
# 3.0.5 ##3.0.0
- Bumping intl to 0.18.0 * Breaking Upgraded minimum Dart version to 2.15 for Constructor Tearoff support
* Added optional `DateTimeFieldCreator` argument to `DateTimeFormField` to allow specifying custom implementations of `DateTimeField`
* Refactored `DateTimeField` to expose `showMaterialTimePicker`, `showMaterialDatePicker`, and `showMaterialTimePicker` as separate overrideable methods
* Made `kCupertinoDatePickerHeight` and `cupertinoModeFromPickerMode` public for convenience
* Removed `DateTimeFormFieldState`, replaced by an instance of `FormFieldState<DateTime>`
* Fixed the behaviour of the `initialDate' parameter.
# 3.0.4 ##2.1.3
- Updating Changelog.md * [TheGlorySaint](https://github.com/TheGlorySaint) added the possibility to use the 24Hour Format at the Timepicker. Default it is set to false
# 3.0.3 ##2.1.2
- Updating the README.md file. Adding more information about the package, rewriting the text to make it more appealing. * Adding the possibility to specify the initial date selected in the date picker dialog.
- Adding support for providing a different initial time mode for the material time picker dialog (thanks to @schalky).
# 3.0.2 ##2.1.1
Added support for clickable pointer on desktop and web. * Formatting with Dart FM
# 3.0.1 ##2.1.0
Fixed issue #29 by adding 24-hour format support for the material time picker dialog. * Fixing label & hint style issues
* Moving to a more generic architecture
* Updating the analysis_options.yaml file
# 3.0.0 ##2.0.1
Upgraded the minimum Dart version to 2.15 for constructor tear-off support, which is a breaking change. * Adding the ability to specify the entry mode for the material date picker.
Added an optional DateTimeFieldCreator argument to DateTimeFormField for specifying custom implementations of DateTimeField.
Refactored DateTimeField to expose showMaterialTimePicker, showMaterialDatePicker, and showMaterialTimePicker as separate overrideable methods.
Made kCupertinoDatePickerHeight and cupertinoModeFromPickerMode public for convenience.
Removed DateTimeFormFieldState and replaced it with an instance of FormFieldState<DateTime>.
Fixed the behavior of the initialDate parameter.
# 2.1.3 ##2.0.0
Added the possibility to use the 24-hour format for the time picker. Default is set to false. * Migrating to null-safety
# 2.1.2
Added the ability to specify the initial date selected in the date picker dialog. ##1.0.5
# 2.1.1 * Removing unused variables
* Improving description
Formatted code with Dart FM.
# 2.1.0 ##1.0.4
Fixed label and hint style issues. * Fixing critical issue
Moved to a more generic architecture.
Updated the analysis_options.yaml file.
# 2.0.1 ##1.0.3
Added the ability to specify the entry mode for the material date picker. * Improving package description
# 2.0.0 ##1.0.2
Migrated to null-safety. * Improving package description
# 1.0.5 ##1.0.1
Removed unused variables and improved the description. * Removing the ripple effect
# 1.0.4 ##1.0.0
Fixed a critical issue. * Full support for input decoration
* New standardized usage, many deprecations
# 1.0.3 ##0.3.3
Improved the package description. * Intl => any support
# 1.0.2 Breaking change:
* Removing the label property, please consider using the InputDecoration to customize the label.
Improved the package description. ##0.3.2
# 1.0.1 * Formating with dartfm
Removed the ripple effect. ##0.3.1
# 1.0.0 * Adding the possibility to style the text with TextStyle
Added full support for input decoration. ## 0.3.0
Adopted a new standardized usage, with many deprecations.
# 0.3.3 Breaking changes:
* No more const constructor.
Changed support from Intl to any, which is a breaking change. Deprecated:
Removed the label property, and suggested using the InputDecoration to customize the label. * DateField and DateFormField are now deprecated and will be removed in the next version, please consider switching to
DateTimeField and DateTimeFormField.
# 0.3.2 Improvements:
* Adding support for time. Now you can ask the user for a time, a date or both.
* Improving performances by setting default value in the constructor.
* Adding .time constructor for the DateField widget only.
Formatted the code with Dart FM. ## 0.2.2
# 0.3.1 * Auto-formatting with dart-fm to meet pub.dev requirements
Added the possibility to style the text with TextStyle. ## 0.2.1
# 0.3.0 * Adding support for Flutter web
Removed the const constructor, which is a breaking change. ## 0.2.0
Deprecated DateField and DateFormField, and added support for time.
Improved performance by setting the default value in the constructor.
Added a .time constructor for the DateField widget only.
# 0.2.2 * DateFormField now extends FormField. All issues related to this are now fiex
* The style of the DateField (and by extension the one of DateFormField) is now rigorously applying the theme or any customization.
Formatted the code with dart-fm to meet pub.dev requirements. ## 0.1.2
# 0.2.1 * Fixing an incorrect boolean (iOS picker was inverted with the Android one)
Added support for Flutter web. ## 0.1.1
# 0.2.0 * Formatting with DartFM!
Changed DateFormField to extend FormField, and rigorously applied the style to match the theme or any customization. ## 0.1.0
# 0.1.2 * Updating documentation!
Fixed an incorrect boolean value (the iOS picker was inverted with the Android one). ## 0.0.2
# 0.1.1 * Fixing README.md
* Updating package description
* Formatting with DartFM
Formatted the code with DartFM. ## 0.0.1
# 0.1.0
Updated the documentation.
# 0.0.2
Fixed the README.md and updated the package description.
Formatted the code with DartFM.
# 0.0.1
* Initial version * Initial version

View file

@ -1,54 +1,51 @@
# Welcome to the Date Field package! 📅 # date_field
[![pub package](https://img.shields.io/pub/v/date_field.svg)](https://pub.dev/packages/date_field) [![pub package](https://img.shields.io/pub/v/date_field.svg)](https://pub.dartlang.org/packages/date_field)
This package provides two widgets, DateTimeField and DateTimeFormField, which allow users to pick a date and/or time from an input field. You can customize the appearance of the widgets using the decoration argument, and specify whether to ask for a date, a time, or both using the mode parameter.
## Here's how to get started 🚀 Contains DateTimeField and DateTimeFormField which allows the user to pick a DateTime from an input field! Depending on
the mode, it can ask the user the time, the date or both at the same time ;) !
Add the date_field package to your project's dependencies in pubspec.yaml. <img src='https://raw.githubusercontent.com/GaspardMerten/date_field/master/example/demo.gif' height='250px'></img>
## Usage
In the `pubspec.yaml` of your flutter project, add the following dependency:
```yaml ```yaml
dependencies: dependencies:
... ...
date_field: ^3.0.5 date_field: ^3.0.0
``` ```
In your library add the following import:
Import the package in your Dart code.
```dart ```dart
import 'package:date_field/date_field.dart'; import 'package:date_field/date_field.dart';
``` ```
Use the DateTimeField or DateTimeFormField widget in your code, and customize it using the available parameters.
## Available Parameters 📝 ## Getting Started
- <b>onSaved</b>: a callback that is called when the form is saved. There are two widgets in this package:
- <b>validator</b>: a callback that is called to validate the value.
- <b>initialValue</b>: the initial value of the field.
- <b>autovalidateMode</b>: when to validate the field.
- <b>enabled</b>: whether the field is enabled or disabled.
- <b>use24hFormat</b>: whether to use a 24-hour format for the time picker.
- <b>dateTextStyle</b>: the text style for the date.
- <b>dateFormat</b>: the format of the date.
- <b>firstDate</b>: the earliest date that can be selected.
- <b>lastDate</b>: the latest date that can be selected.
- <b>initialDate</b>: the initial date that is selected.
- <b>onDateSelected</b>: a callback that is called when a date is selected.
- <b>decoration</b>: the decoration for the field.
- <b>initialEntryMode</b>: the initial entry mode of the date picker.
- <b>initialDatePickerMode</b>: the initial date picker mode.
- <b>mode</b>: the mode of the date and time picker.
- <b>initialTimePickerEntryMode</b>: the initial entry mode of the time picker.
- <b>fieldCreator</b>: the creator of the DateTimeField.
## Example Usage 📖 - DateTimeField
- DateTimeFormField
Here's an example usage of <b>DateTimeFormField</b>: It follows the usual Flutter patterns convention, meaning the DateTimeFormField extends the FormField widget and wraps a DateTimeField widget.
```dart You can customize both of these widgets with the decoration argument which is fully supported.
You can also specify whether you would like to ask the user for a date, a time or both using the mode parameter.
## Example
The following picture illustrates some things you can do with this package.
<img src='https://raw.githubusercontent.com/GaspardMerten/date_field/master/example/demo.gif' height='250px'></img>
``` dart
DateTimeFormField( DateTimeFormField(
decoration: const InputDecoration( decoration: const InputDecoration(
hintStyle: TextStyle(color: Colors.black45), hintStyle: TextStyle(color: Colors.black45),
@ -63,19 +60,7 @@ DateTimeFormField(
onDateSelected: (DateTime value) { onDateSelected: (DateTime value) {
print(value); print(value);
}, },
) ),
``` ```
You can find more examples and a complete example on the GitHub repository. We hope this package is helpful to you! You can check the GitHub repo for a complete example.
## License 📜
This package is released under the MIT license.
## Contributing 🤝
Contributions to this package are welcome! If you find a bug or have a feature request, please create an issue on the GitHub repository. If you'd like to contribute code, please create a pull request with your changes.
Before submitting a pull request, please make sure to run the tests and ensure they all pass. Additionally, please follow the existing coding style and make sure your code is well-documented.
Thank you for your contributions!

1
example/.gitignore vendored
View file

@ -32,6 +32,7 @@
/build/ /build/
# Web related # Web related
lib/generated_plugin_registrant.dart
# Symbolication related # Symbolication related
app.*.symbols app.*.symbols

View file

@ -65,7 +65,6 @@ class _MyHomePageState extends State<MyHomePage> {
Form( Form(
child: Column( child: Column(
children: <Widget>[ children: <Widget>[
DateTimeFormField(),
DateTimeFormField( DateTimeFormField(
decoration: const InputDecoration( decoration: const InputDecoration(
hintStyle: TextStyle(color: Colors.black45), hintStyle: TextStyle(color: Colors.black45),

View file

@ -1,6 +1,5 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
final DateTime _kDefaultFirstSelectableDate = DateTime(1900); final DateTime _kDefaultFirstSelectableDate = DateTime(1900);
@ -25,7 +24,6 @@ typedef DateTimeFieldCreator = DateTimeField Function({
DateTime? lastDate, DateTime? lastDate,
DateTimeFieldPickerMode mode, DateTimeFieldPickerMode mode,
bool use24hFormat, bool use24hFormat,
TimePickerEntryMode initialTimePickerEntryMode,
}); });
/// [DateTimeField] /// [DateTimeField]
@ -49,7 +47,6 @@ class DateTimeField extends StatelessWidget {
DateTime? firstDate, DateTime? firstDate,
DateTime? lastDate, DateTime? lastDate,
DateFormat? dateFormat, DateFormat? dateFormat,
this.initialTimePickerEntryMode = TimePickerEntryMode.dial,
}) : dateFormat = dateFormat ?? getDateFormatFromDateFieldPickerMode(mode), }) : dateFormat = dateFormat ?? getDateFormatFromDateFieldPickerMode(mode),
firstDate = firstDate ?? _kDefaultFirstSelectableDate, firstDate = firstDate ?? _kDefaultFirstSelectableDate,
lastDate = lastDate ?? _kDefaultLastSelectableDate, lastDate = lastDate ?? _kDefaultLastSelectableDate,
@ -65,7 +62,6 @@ class DateTimeField extends StatelessWidget {
this.dateTextStyle, this.dateTextStyle,
this.use24hFormat = false, this.use24hFormat = false,
this.initialEntryMode = DatePickerEntryMode.calendar, this.initialEntryMode = DatePickerEntryMode.calendar,
this.initialTimePickerEntryMode = TimePickerEntryMode.dial,
DateTime? firstDate, DateTime? firstDate,
DateTime? lastDate, DateTime? lastDate,
}) : initialDatePickerMode = null, }) : initialDatePickerMode = null,
@ -114,9 +110,6 @@ class DateTimeField extends StatelessWidget {
/// The initial entry mode for the material date picker dialog /// The initial entry mode for the material date picker dialog
final DatePickerEntryMode initialEntryMode; final DatePickerEntryMode initialEntryMode;
// the initial entry mode for the material time picker dialog
final TimePickerEntryMode initialTimePickerEntryMode;
/// Shows a dialog asking the user to pick a date ! /// Shows a dialog asking the user to pick a date !
Future<void> _selectDate(BuildContext context) async { Future<void> _selectDate(BuildContext context) async {
final DateTime initialDateTime; final DateTime initialDateTime;
@ -133,20 +126,23 @@ class DateTimeField extends StatelessWidget {
} }
if (Theme.of(context).platform == TargetPlatform.iOS) { if (Theme.of(context).platform == TargetPlatform.iOS) {
final DateTime? _selectedDateTime = await showCupertinoPicker(context, initialDateTime); final DateTime? _selectedDateTime =
await showCupertinoPicker(context, initialDateTime);
if (_selectedDateTime != null) { if (_selectedDateTime != null) {
onDateSelected!(_selectedDateTime); onDateSelected!(_selectedDateTime);
} }
} else { } else {
DateTime _selectedDateTime = initialDateTime; DateTime _selectedDateTime = initialDateTime;
const List<DateTimeFieldPickerMode> modesWithDate = <DateTimeFieldPickerMode>[ const List<DateTimeFieldPickerMode> modesWithDate =
<DateTimeFieldPickerMode>[
DateTimeFieldPickerMode.dateAndTime, DateTimeFieldPickerMode.dateAndTime,
DateTimeFieldPickerMode.date DateTimeFieldPickerMode.date
]; ];
if (modesWithDate.contains(mode)) { if (modesWithDate.contains(mode)) {
final DateTime? _selectedDate = await showMaterialDatePicker(context, initialDateTime); final DateTime? _selectedDate =
await showMaterialDatePicker(context, initialDateTime);
if (_selectedDate != null) { if (_selectedDate != null) {
_selectedDateTime = _selectedDate; _selectedDateTime = _selectedDate;
@ -155,14 +151,15 @@ class DateTimeField extends StatelessWidget {
} }
} }
final List<DateTimeFieldPickerMode> modesWithTime = <DateTimeFieldPickerMode>[ final List<DateTimeFieldPickerMode> modesWithTime =
<DateTimeFieldPickerMode>[
DateTimeFieldPickerMode.dateAndTime, DateTimeFieldPickerMode.dateAndTime,
DateTimeFieldPickerMode.time DateTimeFieldPickerMode.time
]; ];
if (modesWithTime.contains(mode)) { if (modesWithTime.contains(mode)) {
final TimeOfDay? _selectedTime = await showMaterialTimePicker(context, initialDateTime, final TimeOfDay? _selectedTime =
initialEntryMode: initialTimePickerEntryMode); await showMaterialTimePicker(context, initialDateTime);
if (_selectedTime != null) { if (_selectedTime != null) {
_selectedDateTime = DateTime( _selectedDateTime = DateTime(
@ -181,12 +178,13 @@ class DateTimeField extends StatelessWidget {
/// Launches the Material time picker by invoking [showTimePicker]. /// Launches the Material time picker by invoking [showTimePicker].
/// Can be @[override]n to allow further customization of the picker options /// Can be @[override]n to allow further customization of the picker options
Future<TimeOfDay?> showMaterialTimePicker(BuildContext context, DateTime initialDateTime, Future<TimeOfDay?> showMaterialTimePicker(
{TimePickerEntryMode initialEntryMode = TimePickerEntryMode.dial}) async { BuildContext context,
DateTime initialDateTime,
) async {
return showTimePicker( return showTimePicker(
initialTime: TimeOfDay.fromDateTime(initialDateTime), initialTime: TimeOfDay.fromDateTime(initialDateTime),
context: context, context: context,
initialEntryMode: initialEntryMode,
builder: (BuildContext context, Widget? child) { builder: (BuildContext context, Widget? child) {
return MediaQuery( return MediaQuery(
data: MediaQuery.of(context).copyWith( data: MediaQuery.of(context).copyWith(
@ -268,7 +266,8 @@ enum DateTimeFieldPickerMode { time, date, dateAndTime }
/// Returns the [CupertinoDatePickerMode] corresponding to the selected /// Returns the [CupertinoDatePickerMode] corresponding to the selected
/// [DateTimeFieldPickerMode]. This exists to prevent redundancy in the [DateTimeField] /// [DateTimeFieldPickerMode]. This exists to prevent redundancy in the [DateTimeField]
/// widget parameters. /// widget parameters.
CupertinoDatePickerMode cupertinoModeFromPickerMode(DateTimeFieldPickerMode mode) { CupertinoDatePickerMode cupertinoModeFromPickerMode(
DateTimeFieldPickerMode mode) {
switch (mode) { switch (mode) {
case DateTimeFieldPickerMode.time: case DateTimeFieldPickerMode.time:
return CupertinoDatePickerMode.time; return CupertinoDatePickerMode.time;
@ -297,7 +296,7 @@ DateFormat getDateFormatFromDateFieldPickerMode(DateTimeFieldPickerMode mode) {
/// Shows a field with a dropdown arrow ! /// Shows a field with a dropdown arrow !
/// It does not show any popup menu, it'll just trigger onPressed whenever the /// It does not show any popup menu, it'll just trigger onPressed whenever the
/// user does click on it ! /// user does click on it !
class _InputDropdown extends StatefulWidget { class _InputDropdown extends StatelessWidget {
const _InputDropdown({ const _InputDropdown({
Key? key, Key? key,
required this.text, required this.text,
@ -327,46 +326,21 @@ class _InputDropdown extends StatefulWidget {
/// Defaults to false. /// Defaults to false.
final bool isEmpty; final bool isEmpty;
@override
State<_InputDropdown> createState() => _InputDropdownState();
}
class _InputDropdownState extends State<_InputDropdown> {
bool focused = false;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final InputDecoration effectiveDecoration = widget.decoration ?? final InputDecoration effectiveDecoration = decoration ??
const InputDecoration( const InputDecoration(
suffixIcon: Icon(Icons.arrow_drop_down), suffixIcon: Icon(Icons.arrow_drop_down),
); );
return MouseRegion( return GestureDetector(
cursor: SystemMouseCursors.click, onTap: onPressed,
child: GestureDetector( child: InputDecorator(
onTap: widget.onPressed, decoration: effectiveDecoration.applyDefaults(
child: Focus( Theme.of(context).inputDecorationTheme,
onFocusChange: (bool newFocus) => setState(() {
focused = newFocus;
}),
onKey: (_, RawKeyEvent key) {
if (key.isKeyPressed(LogicalKeyboardKey.space)) {
widget.onPressed?.call();
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
},
child: InputDecorator(
isHovering: focused,
decoration: effectiveDecoration.applyDefaults(
Theme.of(context).inputDecorationTheme,
),
isEmpty: widget.isEmpty,
child: widget.text == null
? Text('', style: widget.textStyle)
: Text(widget.text!, style: widget.textStyle),
),
), ),
isEmpty: isEmpty,
child: text == null ? null : Text(text!, style: textStyle),
), ),
); );
} }

View file

@ -30,38 +30,27 @@ class DateTimeFormField extends FormField<DateTime> {
DatePickerEntryMode initialEntryMode = DatePickerEntryMode.calendar, DatePickerEntryMode initialEntryMode = DatePickerEntryMode.calendar,
DatePickerMode initialDatePickerMode = DatePickerMode.day, DatePickerMode initialDatePickerMode = DatePickerMode.day,
DateTimeFieldPickerMode mode = DateTimeFieldPickerMode.dateAndTime, DateTimeFieldPickerMode mode = DateTimeFieldPickerMode.dateAndTime,
TimePickerEntryMode initialTimePickerEntryMode = TimePickerEntryMode.dial,
DateTimeFormFieldController? controller,
DateTimeFieldCreator fieldCreator = DateTimeField.new, DateTimeFieldCreator fieldCreator = DateTimeField.new,
}) : super( }) : super(
key: key, key: key,
initialValue: initialValue: initialValue,
initialValue == null && controller != null ? controller.selectedDate : initialValue,
onSaved: onSaved, onSaved: onSaved,
validator: validator, validator: validator,
autovalidateMode: autovalidateMode, autovalidateMode: autovalidateMode,
enabled: enabled, enabled: enabled,
builder: (FormFieldState<DateTime> field) { builder: (FormFieldState<DateTime> field) {
if (controller != null) {
controller.addListener(() {
field.didChange(controller.selectedDate);
});
}
// Theme defaults are applied inside the _InputDropdown widget // Theme defaults are applied inside the _InputDropdown widget
final InputDecoration _decorationWithThemeDefaults = final InputDecoration _decorationWithThemeDefaults =
decoration ?? const InputDecoration(); decoration ?? const InputDecoration();
final InputDecoration effectiveDecoration = final InputDecoration effectiveDecoration =
_decorationWithThemeDefaults.copyWith(errorText: field.errorText); _decorationWithThemeDefaults.copyWith(
errorText: field.errorText);
void onChangedHandler(DateTime value) { void onChangedHandler(DateTime value) {
if (onDateSelected != null) { if (onDateSelected != null) {
onDateSelected(value); onDateSelected(value);
} }
if (controller != null) {
controller.selectedDate = value;
}
field.didChange(value); field.didChange(value);
} }
@ -79,7 +68,6 @@ class DateTimeFormField extends FormField<DateTime> {
mode: mode, mode: mode,
initialEntryMode: initialEntryMode, initialEntryMode: initialEntryMode,
dateTextStyle: dateTextStyle, dateTextStyle: dateTextStyle,
initialTimePickerEntryMode: initialTimePickerEntryMode,
); );
}, },
); );
@ -87,12 +75,3 @@ class DateTimeFormField extends FormField<DateTime> {
@override @override
FormFieldState<DateTime> createState() => FormFieldState<DateTime>(); FormFieldState<DateTime> createState() => FormFieldState<DateTime>();
} }
class DateTimeFormFieldController extends ChangeNotifier {
DateTime? _selectedDate;
DateTime? get selectedDate => _selectedDate;
set selectedDate(DateTime? value) {
_selectedDate = value;
notifyListeners();
}
}

View file

@ -1,6 +1,6 @@
name: date_field name: date_field
description: A widget in the form of a field that lets people choose a date, a time or both. description: A widget in the form of a field that lets people choose a date, a time or both.
version: 3.0.6 version: 3.0.1
homepage: 'https://github.com/GaspardMerten/date_field' homepage: 'https://github.com/GaspardMerten/date_field'
environment: environment:
@ -10,5 +10,5 @@ dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
intl: ^0.18.0 intl: ^0.17.0