You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Added
WDatePickerMode.dateTime: the picker can now capture a time of day, not just a date. Every previous mode ran its selection through _normalizeToDay, so the emitted value was always midnight and no input anywhere in the ecosystem could express "10 Aug 2026, 14:30"; a consumer needing a scheduled window had to invent its own control. The new mode composes the tapped day with a time row and emits a plain local DateTime carrying the hour and minute (no timezone conversion: DateTime cannot hold an arbitrary offset, so a value crossing the wire is the caller's toUtc() to make). The time row is authored in Wind markup, two 24-hour spinners plus a confirm control built from WDiv / WText / WIcon and className tokens with their dark: pairs, NOT a Material showTimePicker dialog; it exposes a labelled Semantics container and per-button Semantics, honors minDate/maxDate on the full instant (a step that would leave the window renders disabled, and a day tap that would land outside it is pulled to the bound), and never wraps 23:00 up to 00:00, which would move the instant a day backwards. New props: minuteStep (default 5, asserted between 1 and 59 on BOTH widgets so a bad value names the one the caller wrote), timeLabel, doneLabel, forwarded by WFormDatePicker. single and range behavior, the default mode, and the emitted midnight values are unchanged. (lib/src/widgets/w_date_picker.dart, lib/src/widgets/w_form_date_picker.dart)
Fixed
The dateTime time row's step controls and confirm control now carry a SemanticsAction.tap of their own. Semantics(button: true) declared the role, but the GestureDetector underneath was not that node's semantics owner, so a screen reader (or an automation driver like dusk) could name each control and had nothing to invoke; a pointer tap was the only way in. A disabled step control still exposes no action. (lib/src/widgets/w_date_picker.dart)
Clearing a controlled dateTime value (a form reset setting value back to null) now re-seeds the time row from the wall clock instead of leaving the last picked time on display, which advertised a time the picker no longer held. (lib/src/widgets/w_date_picker.dart)
minuteStep is clamped to 1-59 at the point of use. The constructor assert on both widgets is stripped from a release build, where a step computed at runtime (a remote config value, a user preference) could still arrive as 0 and leave the minute spinners silently inert. (lib/src/widgets/w_date_picker.dart)
Quality
WDatePickerMode.dateTime gained its example page, example/lib/pages/widgets/date_picker_datetime.dart (basic usage, minuteStep, row labels + displayFormat, an instant-bounded maintenance window pair, and a WFormDatePicker with a time-of-day validator), wired into example/lib/routes.dart and referenced from both date-picker doc pages by <x-preview>. The mode shipped without one. (example/, doc/widgets/w-date-picker.md, doc/widgets/w-form-date-picker.md)
Documented the one-sided maxDate trap in dateTime mode: a bare-day bound is that day at 00:00, so the last day admits only midnight. Pinned by tests on both shapes of bound. The bounds stay instant-level; special-casing a midnight maxDate into an end-of-day would make 00:00 unexpressible. (lib/src/widgets/w_date_picker.dart, doc/widgets/w-date-picker.md, skills/wind-ui/references/widgets.md)
The dateTime semantics tests run through a testWidgetsWithSemantics wrapper that disposes the SemanticsHandle in a finally. Disposal cannot move to tearDown / addTearDown: flutter_test verifies it in _endOfTestVerifications, which runs first and reports a leaked handle on every test. (test/widgets/w_date_picker_test.dart)