smart_datetime_input 0.0.1
smart_datetime_input: ^0.0.1 copied to clipboard
A smart, segmented, and editable text field for handling Date, Time, and DateTime input in Flutter. Supports validation, auto-jump, pasting, and custom localization.
DateTime Field #
[Demo]
A highly customizable, segmented, and editable text field for Date, Time, and DateTime input in Flutter.
Instead of forcing users to scroll through picker dialogs only, datetime_field lets them type the value directly with a smooth experience (auto-jump between segments, backspace navigation, validation, and smart paste) while still supporting the standard Material date/time pickers.
✨ Features #
-
Three Modes in One Widget
DateTimeMode.date→ date only (day, month, year).DateTimeMode.time→ time only (hour, minute).DateTimeMode.dateTime→ combined date & time.
-
Segmented Input UX
- Separate fields for day/month/year/hour/minute.
- Auto-focus to next segment once the value is complete or clearly determined.
- Backspace in an empty segment automatically jumps to the previous segment.
-
Smart Typing & Auto-Jump
- Auto zero-padding for single digits when appropriate (e.g. typing
4in day can become04and jump to the next segment). - Configurable
dateOrder(dmy,mdy,ymd). - Logical jump limits per segment (days, months, hours, minutes).
- Auto zero-padding for single digits when appropriate (e.g. typing
-
Smart Paste
- Paste complete date strings (e.g.
2023/10/20,20-10-2023,2023.10.20) directly into any segment. - Paste time strings (e.g.
14:30,2:45) to fill hour and minute automatically. - Accepts
"/","-",".", and":"as separators. - Validates the pasted value before applying it.
- Paste complete date strings (e.g.
-
Built-in Validation
- Prevents obviously invalid values (e.g. month 13, day 32, negative hours).
- Returns
nullfor incomplete or invalid combinations. - Respects optional
firstDateandlastDateconstraints.
-
Integrated Pickers
- Uses
showDatePickerfor dates. - Uses
showTimePickerfor times. - In
dateTimemode, shows date picker then time picker in sequence. - Always keeps text segments in sync with the last picked value.
- Uses
-
Localization & Theming
DateTimeLabelsfor full control over hints and tooltips.- Default English labels.
- Built-in
DateTimeLabels.arabic()factory for Arabic. DateTimeFieldTheme(InheritedWidget) for app-wide configuration.
-
Flexible Layout & Styling
- Custom
dateSeparator(e.g./,-) andtimeSeparator(e.g.:). - Segment width is dynamically calculated based on hint text and text style.
- Supports
styleandsegmentHintStylefor fine-grained control. - Honors
InputDecoration.isDensefor compact layouts.
- Custom
-
Form-Friendly
- Extends
FormField<DateTime>, integrates cleanly with Flutter forms. - Supports
validator,initialValue, andautovalidateMode. - Exposes
onChangedwith the currentDateTime?value.
- Extends
-
Control Over Editing
editable→ allow manual typing or force picker-only behavior.readOnly→ visually enabled but not editable.clearable→ optional clear (X) icon to reset the value.showPickerIcon→ toggle calendar/clock icon visibility.
📦 Installation #
Add this to your pubspec.yaml:
dependencies:
datetime_field: ^0.0.1
Then run:
flutter pub get
🚀 Quick Start #
Basic Date Field #
import 'package:flutter/material.dart';
import 'package:datetime_field/datetime_field.dart';
class Example extends StatelessWidget {
const Example({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Date Field Example')),
body: Padding(
padding: const EdgeInsets.all(16),
child: DateTimeField(
mode: DateTimeMode.date, // date, time, or dateTime
decoration: const InputDecoration(
labelText: 'Enter Date',
border: OutlineInputBorder(),
),
onChanged: (DateTime? value) {
debugPrint('Selected date: $value');
},
),
),
);
}
}
🧭 Modes #
1. Date Only #
DateTimeField(
mode: DateTimeMode.date,
decoration: const InputDecoration(
labelText: 'Date',
border: OutlineInputBorder(),
),
);
- Shows Day / Month / Year segments.
- Uses the configured
dateOrderanddateSeparator.
2. Time Only #
DateTimeField(
mode: DateTimeMode.time,
decoration: const InputDecoration(
labelText: 'Time',
border: OutlineInputBorder(),
),
);
- Shows Hour : Minute segments.
- Under the hood, a
DateTimeis returned with today’s date and the selected time.
3. Date & Time #
DateTimeField(
mode: DateTimeMode.dateTime,
decoration: const InputDecoration(
labelText: 'Date & Time',
border: OutlineInputBorder(),
),
);
- Combines the date segments, a spacer, and the time segments.
- Picker icon will show date picker first, then time picker.
✅ Validation #
DateTimeField is a FormField<DateTime>, so you can use it with Form and FormState like any other field.
Required Field Example #
DateTimeField(
mode: DateTimeMode.dateTime,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value) {
if (value == null) {
return 'Please enter a valid date and time';
}
return null;
},
);
Using firstDate and lastDate #
DateTimeField(
mode: DateTimeMode.date,
firstDate: DateTime(2020, 1, 1),
lastDate: DateTime(2030, 12, 31),
validator: (value) {
if (value == null) {
return 'Date is required';
}
return null;
},
);
If the user types or pastes a date outside this range, the value is treated as invalid (null in the form field).
🌍 Localization & Global Theming #
Using Built-in Arabic Labels Globally #
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return DateTimeFieldTheme(
labels: const DateTimeLabels.arabic(),
child: MaterialApp(
home: Scaffold(
body: Center(
child: DateTimeField(
mode: DateTimeMode.date,
decoration: const InputDecoration(
labelText: 'التاريخ',
border: OutlineInputBorder(),
),
),
),
),
),
);
}
}
All descendant DateTimeField widgets without explicit labels will use these Arabic labels.
Custom Labels for a Single Field #
DateTimeField(
mode: DateTimeMode.time,
labels: const DateTimeLabels(
hintHour: 'HH',
hintMinute: 'MM',
tooltipPick: 'Pick a time',
tooltipClear: 'Clear value',
),
decoration: const InputDecoration(
labelText: 'Time',
border: OutlineInputBorder(),
),
);
DateTimeLabels Structure #
const DateTimeLabels({
this.hintDay = 'DD',
this.hintMonth = 'MM',
this.hintYear = 'YYYY',
this.hintHour = 'HH',
this.hintMinute = 'mm',
this.tooltipPick = 'Select Date/Time',
this.tooltipClear = 'Clear',
});
🎨 Formatting, Layout & Styling #
Date Order & Separators #
DateTimeField(
mode: DateTimeMode.date,
dateOrder: DateFieldOrder.ymd, // ymd, mdy, or dmy
dateSeparator: '-', // e.g. 2023-10-20
timeSeparator: ':', // e.g. 14:30
decoration: const InputDecoration(
labelText: 'Custom Format',
border: OutlineInputBorder(),
),
);
Text Style & Segment Hint Style #
DateTimeField(
mode: DateTimeMode.dateTime,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
segmentHintStyle: const TextStyle(
color: Colors.grey,
fontStyle: FontStyle.italic,
),
decoration: const InputDecoration(
labelText: 'Styled DateTime',
border: OutlineInputBorder(),
),
);
Compact Layout (isDense) #
DateTimeField(
mode: DateTimeMode.date,
decoration: const InputDecoration(
labelText: 'Compact',
isDense: true,
border: OutlineInputBorder(),
),
);
The widget adjusts segment width and padding based on the provided TextStyle and the decoration’s isDense flag.
⌨️ Typing & Clipboard Behavior #
Smart Typing #
-
Segments accept only numeric characters (plus separators for paste).
-
When a segment is logically complete, focus automatically moves to the next:
- Day & Month jump when further digits would be invalid (e.g. starting day with
4→04). - Hours and minutes use similar rules based on valid ranges.
- Day & Month jump when further digits would be invalid (e.g. starting day with
-
Single-digit entries can be auto-padded to two digits and auto-jump to the next segment.
Smart Paste #
The field accepts pasted content such as:
2023/10/2020-10-20232023.10.2014:302:45
If the pasted value is valid:
- Date segments (Y, M, D) are filled automatically.
- Time segments (H, M) are filled automatically.
- The internal
DateTimevalue is updated, and the form is notified.
If the pasted value is invalid, the paste is rejected and the field is not updated.
🧩 Integration with Material Pickers #
By default, a picker icon is shown based on the selected DateTimeMode:
DateTimeMode.date→ calendar icon.DateTimeMode.time→ clock icon.DateTimeMode.dateTime→ calendar+clock icon.
DateTimeField(
mode: DateTimeMode.dateTime,
showPickerIcon: true,
clearable: true,
decoration: const InputDecoration(
labelText: 'With Picker & Clear',
border: OutlineInputBorder(),
),
);
Behavior:
-
Tapping the picker icon opens:
- A date picker (and then a time picker) in
dateTimemode. - Only a date picker in
datemode. - Only a time picker in
timemode.
- A date picker (and then a time picker) in
-
Tapping the clear icon resets all segments and the underlying
DateTimevalue.
To disable manual typing and force users to use the picker:
DateTimeField(
mode: DateTimeMode.dateTime,
editable: false, // segments become readOnly, picker still works
);
⚙️ API Overview #
DateTimeField Constructor (Key Parameters) #
DateTimeField({
Key? key,
bool? enabled,
FormFieldValidator<DateTime>? validator,
DateTime? initialValue,
required DateTimeMode mode,
ValueChanged<DateTime?>? onChanged,
InputDecoration? decoration,
TextStyle? style,
TextStyle? segmentHintStyle,
bool readOnly = false,
bool clearable = false,
bool editable = true,
bool showPickerIcon = true,
DateTime? firstDate,
DateTime? lastDate,
DateFieldOrder dateOrder = DateFieldOrder.dmy,
String dateSeparator = '/',
String timeSeparator = ':',
DateTimeLabels? labels,
AutovalidateMode? autovalidateMode,
})
Parameter Summary #
| Parameter | Type | Default | Description |
|---|---|---|---|
mode |
DateTimeMode |
required | Controls whether the field shows date, time, or both. |
initialValue |
DateTime? |
null |
Initial value for the field. |
onChanged |
ValueChanged<DateTime?>? |
null |
Called whenever the internal DateTime? value changes. |
validator |
FormFieldValidator<DateTime>? |
null |
Validation callback for use in forms. |
enabled |
bool? |
null (inherits from FormField) |
Enables or disables the field. |
decoration |
InputDecoration? |
InputDecoration() |
Standard Flutter InputDecoration. |
style |
TextStyle? |
Theme.of(context).textTheme.bodyLarge |
Text style for segments. |
segmentHintStyle |
TextStyle? |
derived from style |
Text style for segment hints (placeholders). |
readOnly |
bool |
false |
If true, prevents edits and disables picker interaction. |
editable |
bool |
true |
If false, segments are read-only but picker can still be used. |
clearable |
bool |
false |
Shows a clear (X) button when a value is set. |
showPickerIcon |
bool |
true |
Shows or hides the calendar/clock icon. |
firstDate |
DateTime? |
null |
Minimum allowed date when parsing or picking. |
lastDate |
DateTime? |
null |
Maximum allowed date when parsing or picking. |
dateOrder |
DateFieldOrder |
DateFieldOrder.dmy |
Controls the visual order of date segments (DMY, MDY, or YMD). |
dateSeparator |
String |
'/' |
Separator between date segments. |
timeSeparator |
String |
':' |
Separator between time segments. |
labels |
DateTimeLabels? |
null |
Custom labels for hints and tooltips (fallback to theme or English). |
autovalidateMode |
AutovalidateMode? |
AutovalidateMode.disabled |
Standard Flutter form autovalidation mode. |
🤝 Contribution #
Contributions are welcome!
If you’d like to improve this package:
- Open an issue describing bugs, feature requests, or UX improvements.
- Submit a pull request with clear commits and, if possible, tests or examples.
When contributing, please:
- Keep the segmented UX consistent and predictable.
- Consider localization and accessibility.
- Add documentation updates for any new public API.