Compare commits

...

10 commits

Author SHA1 Message Date
Dominic Grimm c8214efdb9 Add controller support 2023-12-16 18:52:38 +01:00
Gaspard Merten 190a5d734b
Merge pull request #43 from torbenkeller/master 2023-09-03 20:17:41 +02:00
torbenkeller 9ee7a69f5d fixes #42 dense empty form field 2023-08-17 17:01:44 +02:00
Gaspard Merten f0f2dc025d Bumping intl to 0.18.0 2023-04-12 17:00:42 +02:00
Gaspard Merten 600608cde8 Updating readme 2023-04-12 10:16:47 +02:00
Gaspard Merten 6fa939b8b5
Merge pull request #36 from totem-technologies/master
Allow caller to pick default entry mode
2023-04-12 09:51:16 +02:00
Gaspard Merten 6e62a13d8f Oups 2023-01-25 13:48:51 +01:00
Steve Schalkhauser d3474da603
Merge pull request #1 from totem-technologies/update/time_initial_option
support for providing a different initial time mode
2022-11-29 20:10:39 -08:00
schalky f843d7034a support for providing a different initial time mode 2022-11-29 20:09:40 -08:00
Gaspard Merten 4c4a08a5b3 Adding click pointer for desktop and web 2022-11-09 12:46:06 +01:00
7 changed files with 203 additions and 134 deletions

View file

@ -1,130 +1,137 @@
##3.0.1
# 3.0.6
* Fixing [issue #29](https://github.com/GaspardMerten/date_field/issues/29) -> adding 24h format support for material time picker dialog
- Fixing issue #42 dense empty form field
##3.0.0
# 3.0.5
* 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.
- Bumping intl to 0.18.0
##2.1.3
# 3.0.4
* [TheGlorySaint](https://github.com/TheGlorySaint) added the possibility to use the 24Hour Format at the Timepicker. Default it is set to false
- Updating Changelog.md
##2.1.2
# 3.0.3
* Adding the possibility to specify the initial date selected in the date picker dialog.
- Updating the README.md file. Adding more information about the package, rewriting the text to make it more appealing.
- Adding support for providing a different initial time mode for the material time picker dialog (thanks to @schalky).
##2.1.1
# 3.0.2
* Formatting with Dart FM
Added support for clickable pointer on desktop and web.
##2.1.0
# 3.0.1
* Fixing label & hint style issues
* Moving to a more generic architecture
* Updating the analysis_options.yaml file
Fixed issue #29 by adding 24-hour format support for the material time picker dialog.
##2.0.1
# 3.0.0
* Adding the ability to specify the entry mode for the material date picker.
Upgraded the minimum Dart version to 2.15 for constructor tear-off support, which is a breaking change.
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.0.0
# 2.1.3
* Migrating to null-safety
Added the possibility to use the 24-hour format for the time picker. Default is set to false.
# 2.1.2
##1.0.5
Added the ability to specify the initial date selected in the date picker dialog.
* Removing unused variables
* Improving description
# 2.1.1
Formatted code with Dart FM.
##1.0.4
# 2.1.0
* Fixing critical issue
Fixed label and hint style issues.
Moved to a more generic architecture.
Updated the analysis_options.yaml file.
##1.0.3
# 2.0.1
* Improving package description
Added the ability to specify the entry mode for the material date picker.
##1.0.2
# 2.0.0
* Improving package description
Migrated to null-safety.
##1.0.1
# 1.0.5
* Removing the ripple effect
Removed unused variables and improved the description.
##1.0.0
# 1.0.4
* Full support for input decoration
* New standardized usage, many deprecations
Fixed a critical issue.
##0.3.3
# 1.0.3
* Intl => any support
Improved the package description.
Breaking change:
* Removing the label property, please consider using the InputDecoration to customize the label.
# 1.0.2
##0.3.2
Improved the package description.
* Formating with dartfm
# 1.0.1
##0.3.1
Removed the ripple effect.
* Adding the possibility to style the text with TextStyle
# 1.0.0
## 0.3.0
Added full support for input decoration.
Adopted a new standardized usage, with many deprecations.
Breaking changes:
* No more const constructor.
# 0.3.3
Deprecated:
* DateField and DateFormField are now deprecated and will be removed in the next version, please consider switching to
DateTimeField and DateTimeFormField.
Changed support from Intl to any, which is a breaking change.
Removed the label property, and suggested using the InputDecoration to customize the label.
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.
# 0.3.2
## 0.2.2
Formatted the code with Dart FM.
* Auto-formatting with dart-fm to meet pub.dev requirements
# 0.3.1
## 0.2.1
Added the possibility to style the text with TextStyle.
* Adding support for Flutter web
# 0.3.0
## 0.2.0
Removed the const constructor, which is a breaking change.
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.
* 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.
# 0.2.2
## 0.1.2
Formatted the code with dart-fm to meet pub.dev requirements.
* Fixing an incorrect boolean (iOS picker was inverted with the Android one)
# 0.2.1
## 0.1.1
Added support for Flutter web.
* Formatting with DartFM!
# 0.2.0
## 0.1.0
Changed DateFormField to extend FormField, and rigorously applied the style to match the theme or any customization.
* Updating documentation!
# 0.1.2
## 0.0.2
Fixed an incorrect boolean value (the iOS picker was inverted with the Android one).
* Fixing README.md
* Updating package description
* Formatting with DartFM
# 0.1.1
## 0.0.1
Formatted the code with DartFM.
# 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

View file

@ -1,51 +1,54 @@
# date_field
# Welcome to the Date Field package! 📅
[![pub package](https://img.shields.io/pub/v/date_field.svg)](https://pub.dartlang.org/packages/date_field)
[![pub package](https://img.shields.io/pub/v/date_field.svg)](https://pub.dev/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.
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 ;) !
## Here's how to get started 🚀
<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:
Add the date_field package to your project's dependencies in pubspec.yaml.
```yaml
dependencies:
...
date_field: ^3.0.0
date_field: ^3.0.5
```
In your library add the following import:
Import the package in your Dart code.
```dart
import 'package:date_field/date_field.dart';
```
Use the DateTimeField or DateTimeFormField widget in your code, and customize it using the available parameters.
## Getting Started
## Available Parameters 📝
There are two widgets in this package:
- <b>onSaved</b>: a callback that is called when the form is saved.
- <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.
- DateTimeField
- DateTimeFormField
## Example Usage 📖
It follows the usual Flutter patterns convention, meaning the DateTimeFormField extends the FormField widget and wraps a DateTimeField widget.
Here's an example usage of <b>DateTimeFormField</b>:
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
```dart
DateTimeFormField(
decoration: const InputDecoration(
hintStyle: TextStyle(color: Colors.black45),
@ -60,7 +63,19 @@ DateTimeFormField(
onDateSelected: (DateTime value) {
print(value);
},
),
)
```
You can check the GitHub repo for a complete example.
You can find more examples and a complete example on the GitHub repository. We hope this package is helpful to you!
## 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,7 +32,6 @@
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols

View file

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

View file

@ -1,5 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:intl/intl.dart';
final DateTime _kDefaultFirstSelectableDate = DateTime(1900);
@ -24,6 +25,7 @@ typedef DateTimeFieldCreator = DateTimeField Function({
DateTime? lastDate,
DateTimeFieldPickerMode mode,
bool use24hFormat,
TimePickerEntryMode initialTimePickerEntryMode,
});
/// [DateTimeField]
@ -47,6 +49,7 @@ class DateTimeField extends StatelessWidget {
DateTime? firstDate,
DateTime? lastDate,
DateFormat? dateFormat,
this.initialTimePickerEntryMode = TimePickerEntryMode.dial,
}) : dateFormat = dateFormat ?? getDateFormatFromDateFieldPickerMode(mode),
firstDate = firstDate ?? _kDefaultFirstSelectableDate,
lastDate = lastDate ?? _kDefaultLastSelectableDate,
@ -62,6 +65,7 @@ class DateTimeField extends StatelessWidget {
this.dateTextStyle,
this.use24hFormat = false,
this.initialEntryMode = DatePickerEntryMode.calendar,
this.initialTimePickerEntryMode = TimePickerEntryMode.dial,
DateTime? firstDate,
DateTime? lastDate,
}) : initialDatePickerMode = null,
@ -110,6 +114,9 @@ class DateTimeField extends StatelessWidget {
/// The initial entry mode for the material date picker dialog
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 !
Future<void> _selectDate(BuildContext context) async {
final DateTime initialDateTime;
@ -126,23 +133,20 @@ class DateTimeField extends StatelessWidget {
}
if (Theme.of(context).platform == TargetPlatform.iOS) {
final DateTime? _selectedDateTime =
await showCupertinoPicker(context, initialDateTime);
final DateTime? _selectedDateTime = await showCupertinoPicker(context, initialDateTime);
if (_selectedDateTime != null) {
onDateSelected!(_selectedDateTime);
}
} else {
DateTime _selectedDateTime = initialDateTime;
const List<DateTimeFieldPickerMode> modesWithDate =
<DateTimeFieldPickerMode>[
const List<DateTimeFieldPickerMode> modesWithDate = <DateTimeFieldPickerMode>[
DateTimeFieldPickerMode.dateAndTime,
DateTimeFieldPickerMode.date
];
if (modesWithDate.contains(mode)) {
final DateTime? _selectedDate =
await showMaterialDatePicker(context, initialDateTime);
final DateTime? _selectedDate = await showMaterialDatePicker(context, initialDateTime);
if (_selectedDate != null) {
_selectedDateTime = _selectedDate;
@ -151,15 +155,14 @@ class DateTimeField extends StatelessWidget {
}
}
final List<DateTimeFieldPickerMode> modesWithTime =
<DateTimeFieldPickerMode>[
final List<DateTimeFieldPickerMode> modesWithTime = <DateTimeFieldPickerMode>[
DateTimeFieldPickerMode.dateAndTime,
DateTimeFieldPickerMode.time
];
if (modesWithTime.contains(mode)) {
final TimeOfDay? _selectedTime =
await showMaterialTimePicker(context, initialDateTime);
final TimeOfDay? _selectedTime = await showMaterialTimePicker(context, initialDateTime,
initialEntryMode: initialTimePickerEntryMode);
if (_selectedTime != null) {
_selectedDateTime = DateTime(
@ -178,13 +181,12 @@ class DateTimeField extends StatelessWidget {
/// Launches the Material time picker by invoking [showTimePicker].
/// Can be @[override]n to allow further customization of the picker options
Future<TimeOfDay?> showMaterialTimePicker(
BuildContext context,
DateTime initialDateTime,
) async {
Future<TimeOfDay?> showMaterialTimePicker(BuildContext context, DateTime initialDateTime,
{TimePickerEntryMode initialEntryMode = TimePickerEntryMode.dial}) async {
return showTimePicker(
initialTime: TimeOfDay.fromDateTime(initialDateTime),
context: context,
initialEntryMode: initialEntryMode,
builder: (BuildContext context, Widget? child) {
return MediaQuery(
data: MediaQuery.of(context).copyWith(
@ -266,8 +268,7 @@ enum DateTimeFieldPickerMode { time, date, dateAndTime }
/// Returns the [CupertinoDatePickerMode] corresponding to the selected
/// [DateTimeFieldPickerMode]. This exists to prevent redundancy in the [DateTimeField]
/// widget parameters.
CupertinoDatePickerMode cupertinoModeFromPickerMode(
DateTimeFieldPickerMode mode) {
CupertinoDatePickerMode cupertinoModeFromPickerMode(DateTimeFieldPickerMode mode) {
switch (mode) {
case DateTimeFieldPickerMode.time:
return CupertinoDatePickerMode.time;
@ -296,7 +297,7 @@ DateFormat getDateFormatFromDateFieldPickerMode(DateTimeFieldPickerMode mode) {
/// Shows a field with a dropdown arrow !
/// It does not show any popup menu, it'll just trigger onPressed whenever the
/// user does click on it !
class _InputDropdown extends StatelessWidget {
class _InputDropdown extends StatefulWidget {
const _InputDropdown({
Key? key,
required this.text,
@ -326,21 +327,46 @@ class _InputDropdown extends StatelessWidget {
/// Defaults to false.
final bool isEmpty;
@override
State<_InputDropdown> createState() => _InputDropdownState();
}
class _InputDropdownState extends State<_InputDropdown> {
bool focused = false;
@override
Widget build(BuildContext context) {
final InputDecoration effectiveDecoration = decoration ??
final InputDecoration effectiveDecoration = widget.decoration ??
const InputDecoration(
suffixIcon: Icon(Icons.arrow_drop_down),
);
return GestureDetector(
onTap: onPressed,
child: InputDecorator(
decoration: effectiveDecoration.applyDefaults(
Theme.of(context).inputDecorationTheme,
return MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: widget.onPressed,
child: Focus(
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,27 +30,38 @@ class DateTimeFormField extends FormField<DateTime> {
DatePickerEntryMode initialEntryMode = DatePickerEntryMode.calendar,
DatePickerMode initialDatePickerMode = DatePickerMode.day,
DateTimeFieldPickerMode mode = DateTimeFieldPickerMode.dateAndTime,
TimePickerEntryMode initialTimePickerEntryMode = TimePickerEntryMode.dial,
DateTimeFormFieldController? controller,
DateTimeFieldCreator fieldCreator = DateTimeField.new,
}) : super(
key: key,
initialValue: initialValue,
initialValue:
initialValue == null && controller != null ? controller.selectedDate : initialValue,
onSaved: onSaved,
validator: validator,
autovalidateMode: autovalidateMode,
enabled: enabled,
builder: (FormFieldState<DateTime> field) {
if (controller != null) {
controller.addListener(() {
field.didChange(controller.selectedDate);
});
}
// Theme defaults are applied inside the _InputDropdown widget
final InputDecoration _decorationWithThemeDefaults =
decoration ?? const InputDecoration();
final InputDecoration effectiveDecoration =
_decorationWithThemeDefaults.copyWith(
errorText: field.errorText);
_decorationWithThemeDefaults.copyWith(errorText: field.errorText);
void onChangedHandler(DateTime value) {
if (onDateSelected != null) {
onDateSelected(value);
}
if (controller != null) {
controller.selectedDate = value;
}
field.didChange(value);
}
@ -68,6 +79,7 @@ class DateTimeFormField extends FormField<DateTime> {
mode: mode,
initialEntryMode: initialEntryMode,
dateTextStyle: dateTextStyle,
initialTimePickerEntryMode: initialTimePickerEntryMode,
);
},
);
@ -75,3 +87,12 @@ class DateTimeFormField extends FormField<DateTime> {
@override
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
description: A widget in the form of a field that lets people choose a date, a time or both.
version: 3.0.1
version: 3.0.6
homepage: 'https://github.com/GaspardMerten/date_field'
environment:
@ -10,5 +10,5 @@ dependencies:
flutter:
sdk: flutter
intl: ^0.17.0
intl: ^0.18.0