From 0ccedb57d40b2714d9d41403498af9d273af9732 Mon Sep 17 00:00:00 2001 From: Matthias Ngeo Date: Wed, 4 Dec 2024 11:02:39 +0800 Subject: [PATCH 01/12] Backport hooks to 0.7.0 --- forui_hooks/lib/src/popover_controller_hook.dart | 2 +- forui_hooks/lib/src/tooltip_controller_hook.dart | 2 +- forui_hooks/pubspec.yaml | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/forui_hooks/lib/src/popover_controller_hook.dart b/forui_hooks/lib/src/popover_controller_hook.dart index 9b8118460..81f62b1cf 100644 --- a/forui_hooks/lib/src/popover_controller_hook.dart +++ b/forui_hooks/lib/src/popover_controller_hook.dart @@ -41,7 +41,7 @@ class _PopoverControllerHook extends Hook { class _PopoverControllerHookState extends HookState { late final FPopoverController _controller = FPopoverController( vsync: hook.vsync, - animationDuration: hook.animationDuration, + duration: hook.animationDuration, ); @override diff --git a/forui_hooks/lib/src/tooltip_controller_hook.dart b/forui_hooks/lib/src/tooltip_controller_hook.dart index 2a4153228..8b8365cd6 100644 --- a/forui_hooks/lib/src/tooltip_controller_hook.dart +++ b/forui_hooks/lib/src/tooltip_controller_hook.dart @@ -41,7 +41,7 @@ class _TooltipControllerHook extends Hook { class _TooltipControllerHookState extends HookState { late final FTooltipController _controller = FTooltipController( vsync: hook.vsync, - animationDuration: hook.animationDuration, + duration: hook.animationDuration, ); @override diff --git a/forui_hooks/pubspec.yaml b/forui_hooks/pubspec.yaml index d13475cba..c06661661 100644 --- a/forui_hooks/pubspec.yaml +++ b/forui_hooks/pubspec.yaml @@ -21,9 +21,7 @@ dev_dependencies: flutter_test: sdk: flutter -dependency_overrides: - forui: - path: ../forui + flutter: From 5590c720ee2f8155201e6e3fb07af702789a271d Mon Sep 17 00:00:00 2001 From: Matthias Ngeo Date: Wed, 4 Dec 2024 11:05:49 +0800 Subject: [PATCH 02/12] Revert backport changes --- forui_hooks/lib/src/popover_controller_hook.dart | 2 +- forui_hooks/lib/src/tooltip_controller_hook.dart | 2 +- forui_hooks/pubspec.yaml | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/forui_hooks/lib/src/popover_controller_hook.dart b/forui_hooks/lib/src/popover_controller_hook.dart index 81f62b1cf..9b8118460 100644 --- a/forui_hooks/lib/src/popover_controller_hook.dart +++ b/forui_hooks/lib/src/popover_controller_hook.dart @@ -41,7 +41,7 @@ class _PopoverControllerHook extends Hook { class _PopoverControllerHookState extends HookState { late final FPopoverController _controller = FPopoverController( vsync: hook.vsync, - duration: hook.animationDuration, + animationDuration: hook.animationDuration, ); @override diff --git a/forui_hooks/lib/src/tooltip_controller_hook.dart b/forui_hooks/lib/src/tooltip_controller_hook.dart index 8b8365cd6..2a4153228 100644 --- a/forui_hooks/lib/src/tooltip_controller_hook.dart +++ b/forui_hooks/lib/src/tooltip_controller_hook.dart @@ -41,7 +41,7 @@ class _TooltipControllerHook extends Hook { class _TooltipControllerHookState extends HookState { late final FTooltipController _controller = FTooltipController( vsync: hook.vsync, - duration: hook.animationDuration, + animationDuration: hook.animationDuration, ); @override diff --git a/forui_hooks/pubspec.yaml b/forui_hooks/pubspec.yaml index c06661661..d13475cba 100644 --- a/forui_hooks/pubspec.yaml +++ b/forui_hooks/pubspec.yaml @@ -21,7 +21,9 @@ dev_dependencies: flutter_test: sdk: flutter - +dependency_overrides: + forui: + path: ../forui flutter: From 82abfcb5c7b39b4a58fe0672ca42b67759eef07f Mon Sep 17 00:00:00 2001 From: Matthias Ngeo Date: Wed, 4 Dec 2024 12:34:01 +0800 Subject: [PATCH 03/12] Update forui_hooks README --- forui_hooks/README.md | 59 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/forui_hooks/README.md b/forui_hooks/README.md index 45b8c6db7..9b958bfc1 100644 --- a/forui_hooks/README.md +++ b/forui_hooks/README.md @@ -1,11 +1,62 @@ # Forui Hooks -Companion hooks for [Forui](../forui), a UI library for Flutter that provides a set of a set of beautifully designed, -minimalistic widgets. +Forui provides first class integration with [Flutter Hooks](https://pub.dev/packages/flutter_hooks). All controllers +are exposed as hooks in the companion `forui_hooks` package. + +## Installation + +From your Flutter project directory, run the following command to install `flutter_hooks` and `forui_hooks`. + +```bash filename="bash" +flutter pub add flutter_hooks +flutter pub add forui_hooks +``` + +## Usage + +To use Forui hooks in your Flutter app, import the `forui_hooks` package and initialize a hook inside a `HookWidget`. + +```dart {5, 7, 10} +import 'package:flutter/widgets.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; + +import 'package:forui/forui.dart'; +import 'package:forui_hooks/forui_hooks.dart'; + +class Example extends HookWidget { + @override + Widget build(BuildContext context) { + final controller = useFAccordionController(); + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + FAccordion( + controller: controller, + items: [ + FAccordionItem( + title: const Text('Is it accessible?'), + child: const Text('Yes. It adheres to the WAI-ARIA design pattern.'), + ), + FAccordionItem( + initiallyExpanded: true, + title: const Text('Is it Styled?'), + child: const Text("Yes. It comes with default styles that matches the other components' aesthetics"), + ), + FAccordionItem( + title: const Text('Is it Animated?'), + child: const Text('Yes. It is animated by default, but you can disable it if you prefer'), + ), + ], + ), + ], + ); + } +} +``` ## Documentation -Visit [forui.dev/docs](https://forui.dev/docs) to view the documentation. +Visit [forui.dev/docs/hooks](https://forui.dev/docs/hooks) to view the documentation. ## Contributing @@ -13,4 +64,4 @@ Please read the [contributing guide](../CONTRIBUTING.md). ## License -Licensed under the [MIT License](/LICENSE) & [ISC license](/LICENSE). \ No newline at end of file +Licensed under the [MIT License](/LICENSE). \ No newline at end of file From 3d60dd48f7178de6a5f9433b7c28659d9f01f8cf Mon Sep 17 00:00:00 2001 From: Matthias Ngeo Date: Wed, 4 Dec 2024 18:41:36 +0800 Subject: [PATCH 04/12] Update README.md (#301) --- forui_hooks/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forui_hooks/README.md b/forui_hooks/README.md index 9b958bfc1..3251e334c 100644 --- a/forui_hooks/README.md +++ b/forui_hooks/README.md @@ -56,7 +56,7 @@ class Example extends HookWidget { ## Documentation -Visit [forui.dev/docs/hooks](https://forui.dev/docs/hooks) to view the documentation. +Visit [forui.dev/docs](https://forui.dev/docs) to view the documentation. ## Contributing @@ -64,4 +64,4 @@ Please read the [contributing guide](../CONTRIBUTING.md). ## License -Licensed under the [MIT License](/LICENSE). \ No newline at end of file +Licensed under the [MIT License](/LICENSE). From b3dbf1a03949b18c4489d672bad65389f2c7e49c Mon Sep 17 00:00:00 2001 From: Matthias Ngeo Date: Wed, 4 Dec 2024 19:21:38 +0800 Subject: [PATCH 05/12] Publish forui_hooks 0.7.0+1 --- forui_hooks/CHANGELOG.md | 4 ++++ forui_hooks/lib/src/popover_controller_hook.dart | 2 +- forui_hooks/lib/src/tooltip_controller_hook.dart | 2 +- forui_hooks/pubspec.yaml | 4 ---- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/forui_hooks/CHANGELOG.md b/forui_hooks/CHANGELOG.md index ef4ca8830..815505be4 100644 --- a/forui_hooks/CHANGELOG.md +++ b/forui_hooks/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.7.0+1 + +Updated the README file. + ## 0.7.0 Initial release! diff --git a/forui_hooks/lib/src/popover_controller_hook.dart b/forui_hooks/lib/src/popover_controller_hook.dart index 9b8118460..81f62b1cf 100644 --- a/forui_hooks/lib/src/popover_controller_hook.dart +++ b/forui_hooks/lib/src/popover_controller_hook.dart @@ -41,7 +41,7 @@ class _PopoverControllerHook extends Hook { class _PopoverControllerHookState extends HookState { late final FPopoverController _controller = FPopoverController( vsync: hook.vsync, - animationDuration: hook.animationDuration, + duration: hook.animationDuration, ); @override diff --git a/forui_hooks/lib/src/tooltip_controller_hook.dart b/forui_hooks/lib/src/tooltip_controller_hook.dart index 2a4153228..8b8365cd6 100644 --- a/forui_hooks/lib/src/tooltip_controller_hook.dart +++ b/forui_hooks/lib/src/tooltip_controller_hook.dart @@ -41,7 +41,7 @@ class _TooltipControllerHook extends Hook { class _TooltipControllerHookState extends HookState { late final FTooltipController _controller = FTooltipController( vsync: hook.vsync, - animationDuration: hook.animationDuration, + duration: hook.animationDuration, ); @override diff --git a/forui_hooks/pubspec.yaml b/forui_hooks/pubspec.yaml index d13475cba..f7a7d4afd 100644 --- a/forui_hooks/pubspec.yaml +++ b/forui_hooks/pubspec.yaml @@ -21,10 +21,6 @@ dev_dependencies: flutter_test: sdk: flutter -dependency_overrides: - forui: - path: ../forui - flutter: import_sorter: From 05ff2225e1b850c9f9f79f2967603bdaffb56ea2 Mon Sep 17 00:00:00 2001 From: Matthias Ngeo Date: Wed, 4 Dec 2024 19:24:28 +0800 Subject: [PATCH 06/12] Bump version --- forui_hooks/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forui_hooks/pubspec.yaml b/forui_hooks/pubspec.yaml index f7a7d4afd..31ecd8f5a 100644 --- a/forui_hooks/pubspec.yaml +++ b/forui_hooks/pubspec.yaml @@ -1,6 +1,6 @@ name: forui_hooks description: "Companion hooks for Forui, a set of beautifully designed, minimalistic widgets for desktop & touch devices." -version: 0.7.0 +version: 0.7.0+1 homepage: https://forui.dev/ documentation: https://forui.dev/docs repository: https://github.com/forus-labs/forui/tree/main/forui_hooks From 5a38eb2851dddfda8c2ba7001255cb61a4eeb1c6 Mon Sep 17 00:00:00 2001 From: Matthias Ngeo Date: Wed, 4 Dec 2024 19:26:20 +0800 Subject: [PATCH 07/12] Revert --- forui_hooks/lib/src/popover_controller_hook.dart | 2 +- forui_hooks/lib/src/tooltip_controller_hook.dart | 2 +- forui_hooks/pubspec.yaml | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/forui_hooks/lib/src/popover_controller_hook.dart b/forui_hooks/lib/src/popover_controller_hook.dart index 81f62b1cf..9b8118460 100644 --- a/forui_hooks/lib/src/popover_controller_hook.dart +++ b/forui_hooks/lib/src/popover_controller_hook.dart @@ -41,7 +41,7 @@ class _PopoverControllerHook extends Hook { class _PopoverControllerHookState extends HookState { late final FPopoverController _controller = FPopoverController( vsync: hook.vsync, - duration: hook.animationDuration, + animationDuration: hook.animationDuration, ); @override diff --git a/forui_hooks/lib/src/tooltip_controller_hook.dart b/forui_hooks/lib/src/tooltip_controller_hook.dart index 8b8365cd6..2a4153228 100644 --- a/forui_hooks/lib/src/tooltip_controller_hook.dart +++ b/forui_hooks/lib/src/tooltip_controller_hook.dart @@ -41,7 +41,7 @@ class _TooltipControllerHook extends Hook { class _TooltipControllerHookState extends HookState { late final FTooltipController _controller = FTooltipController( vsync: hook.vsync, - duration: hook.animationDuration, + animationDuration: hook.animationDuration, ); @override diff --git a/forui_hooks/pubspec.yaml b/forui_hooks/pubspec.yaml index 31ecd8f5a..ba445cedd 100644 --- a/forui_hooks/pubspec.yaml +++ b/forui_hooks/pubspec.yaml @@ -21,6 +21,10 @@ dev_dependencies: flutter_test: sdk: flutter +dependency_overrides: + forui: + path: ../forui + flutter: import_sorter: From a299d21279625003102f61c455901efdd6149e11 Mon Sep 17 00:00:00 2001 From: Matthias Ngeo Date: Wed, 4 Dec 2024 20:44:23 +0800 Subject: [PATCH 08/12] Improve `FCalendar` ergonomics (#297) * Update calendar controller * Commit from GitHub Actions (Forui Presubmit) * Update hook * Fix failing build * Rename convert parameter to truncateAndStripTimezone * Commit from GitHub Actions (Forui Presubmit) * Add callout --------- Co-authored-by: Pante --- docs/pages/docs/form/calendar.mdx | 54 ++--- forui/CHANGELOG.md | 18 ++ forui/example/lib/sandbox.dart | 37 +--- forui/lib/src/widgets/calendar/calendar.dart | 26 ++- .../widgets/calendar/calendar_controller.dart | 201 +++++++++++++++--- .../src/widgets/calendar/day/day_picker.dart | 4 + .../calendar/day/paged_day_picker.dart | 6 +- .../src/widgets/calendar/shared/entry.dart | 24 ++- forui/lib/widgets/calendar.dart | 2 +- .../calendar/calendar_controller_test.dart | 199 ++++++++++++++++- .../lib/src/calendar_controller_hook.dart | 54 ++++- samples/lib/widgets/calendar.dart | 32 ++- 12 files changed, 532 insertions(+), 125 deletions(-) diff --git a/docs/pages/docs/form/calendar.mdx b/docs/pages/docs/form/calendar.mdx index bef652a18..ba5b9f315 100644 --- a/docs/pages/docs/form/calendar.mdx +++ b/docs/pages/docs/form/calendar.mdx @@ -1,4 +1,4 @@ -import { Tabs } from 'nextra/components'; +import { Callout, Tabs } from 'nextra/components'; import { Widget } from "../../../components/widget.tsx"; import LinkBadge from "../../../components/link-badge/link-badge.tsx"; import LinkBadgeGroup from "../../../components/link-badge/link-badge-group.tsx"; @@ -9,13 +9,16 @@ A date field component that allows users to enter and edit date. The calendar pages are designed to be navigable through swipe gestures on mobile platforms, allowing left and right swipes to transition between pages. -An [`FCalendarController`](https://pub.dev/documentation/forui/latest/forui.widgets.calendar/FCalendarController-class.html) is used -to customize the date selection behavior. +A [`FCalendarController`](https://pub.dev/documentation/forui/latest/forui.widgets.calendar/FCalendarController-class.html) +is used to customize the date selection behavior. + + `FCalendar` and all `FCalendarController`s return `DateTime`s in UTC timezone, truncated to the nearest day. + @@ -25,8 +28,8 @@ to customize the date selection behavior. ```dart FCalendar( controller: FCalendarController.date(initialSelection: selected), - start: DateTime.utc(2000), - end: DateTime.utc(2030), + start: DateTime(2000), + end: DateTime(2030), ); ``` @@ -39,14 +42,15 @@ to customize the date selection behavior. ```dart FCalendar( controller: FCalendarController.date( - initialSelection: DateTime.utc(2024, 9, 13), + initialSelection: DateTime(2024, 9, 13), selectable: (date) => allowedDates.contains(date), ), - start: DateTime.utc(2024), - end: DateTime.utc(2030), - today: DateTime.utc(2024, 7, 14), + dayBuilder: (context, data, child) => !child, + start: DateTime(2024), + end: DateTime(2030), + today: DateTime(2024, 7, 14), initialType = FCalendarPickerType.yearMonth, - initialMonth = DateTime.utc(2024, 9), + initialMonth = DateTime(2024, 9), onMonthChange: (date) => print(date), onPress: (date) => print(date), onLongPress: (date) => print(date), @@ -63,8 +67,8 @@ FCalendar( ```dart {2} FCalendar( controller: FCalendarController.date(), - start: DateTime.utc(2000), - end: DateTime.utc(2030), + start: DateTime(2000), + end: DateTime(2030), ); ``` @@ -79,11 +83,11 @@ FCalendar( ```dart {2-4} FCalendar( controller: FCalendarController.dates( - initialSelections: {DateTime.utc(2024, 7, 17), DateTime.utc(2024, 7, 20)}, + initialSelections: {DateTime(2024, 7, 17), DateTime(2024, 7, 20)}, ), - start: DateTime.utc(2000), - today: DateTime.utc(2024, 7, 15), - end: DateTime.utc(2030), + start: DateTime(2000), + today: DateTime(2024, 7, 15), + end: DateTime(2030), ); ``` @@ -98,12 +102,12 @@ FCalendar( ```dart {4} FCalendar( controller: FCalendarController.dates( - initialSelections: {DateTime.utc(2024, 7, 17), DateTime.utc(2024, 7, 20)}, - selectable: (date) => !{DateTime.utc(2024, 7, 18), DateTime.utc(2024, 7, 19)}.contains(date), + initialSelections: {DateTime(2024, 7, 17), DateTime(2024, 7, 20)}, + selectable: (date) => !{DateTime(2024, 7, 18), DateTime(2024, 7, 19)}.contains(date), ), - start: DateTime.utc(2000), - today: DateTime.utc(2024, 7, 15), - end: DateTime.utc(2030), + start: DateTime(2000), + today: DateTime(2024, 7, 15), + end: DateTime(2030), ); ``` @@ -118,11 +122,11 @@ FCalendar( ```dart {2-4} FCalendar( controller: FCalendarController.range( - initialSelection: (DateTime.utc(2024, 7, 17), DateTime.utc(2024, 7, 20)), + initialSelection: (DateTime(2024, 7, 17), DateTime(2024, 7, 20)), ), - start: DateTime.utc(2000), - today: DateTime.utc(2024, 7, 15), - end: DateTime.utc(2030), + start: DateTime(2000), + today: DateTime(2024, 7, 15), + end: DateTime(2030), ); ``` diff --git a/forui/CHANGELOG.md b/forui/CHANGELOG.md index 9bb523a62..6505e7c0c 100644 --- a/forui/CHANGELOG.md +++ b/forui/CHANGELOG.md @@ -2,6 +2,14 @@ ### Additions +* Add `truncateAndStripTimezone` to `FCalendarController.date(...)`. + +* Add `truncateAndStripTimezone` to `FCalendarController.dates(...)`. + +* Add `truncateAndStripTimezone` to `FCalendarController.range(...)`. + +* Add `FCalendar.dayBuilder`. + * Add `FTileGroup.builder`. * Add `FSelectTileGroup.builder`. @@ -10,6 +18,16 @@ ### Changes +* Change `FCalendarController.date(...)` to automatically strip and truncate all DateTimes to dates in UTC timezone. + +* Change `FCalendarController.dates(...)` to automatically strip and truncate all DateTimes to dates in UTC timezone. + +* Change `FCalendarController.ranges(...)` to automatically strip and truncate all DateTimes to dates in UTC timezone. + +* Change `FCalendar.start` to be optional and default to 1st January 1900. + +* Change `FCalendar.end` to be optional and default to 1st January 2100. + * Change `FTheme` to internally extend `InheritedTheme`. * Change `FTileGroup` to be scrollable. diff --git a/forui/example/lib/sandbox.dart b/forui/example/lib/sandbox.dart index 3d7cc06cd..5a7ed9f80 100644 --- a/forui/example/lib/sandbox.dart +++ b/forui/example/lib/sandbox.dart @@ -15,6 +15,7 @@ class _SandboxState extends State with SingleTickerProviderStateMixin { final GlobalKey _formKey = GlobalKey(); final FRadioSelectGroupController controller = FRadioSelectGroupController(); late FPopoverController popoverController; + late FCalendarController a = FCalendarController.date(); @override void initState() { @@ -28,41 +29,7 @@ class _SandboxState extends State with SingleTickerProviderStateMixin { child: Column( mainAxisSize: MainAxisSize.min, children: [ - FSelectMenuTile( - groupController: controller, - popoverController: popoverController, - autoHide: true, - validator: (value) => value == null ? 'Select an item' : null, - prefixIcon: FIcon(FAssets.icons.bell), - title: const Text('Notifications'), - details: ListenableBuilder( - listenable: controller, - builder: (context, _) => Text(switch (controller.values.firstOrNull) { - Notification.all => 'All', - Notification.direct => 'Direct Messages', - null || Notification.nothing => 'None', - }), - ), - menu: [ - FSelectTile(title: const Text('All'), value: Notification.all), - FSelectTile(title: const Text('Direct Messages'), value: Notification.direct), - FSelectTile(title: const Text('None'), value: Notification.nothing), - ], - ), - const SizedBox(height: 20), - FButton( - autofocus: true, - label: const Text('Save'), - onPress: () { - if (!_formKey.currentState!.validate()) { - // Handle errors here. - return; - } - - _formKey.currentState!.save(); - // Do something. - }, - ) + FCalendar(controller: a), ], ), ); diff --git a/forui/lib/src/widgets/calendar/calendar.dart b/forui/lib/src/widgets/calendar/calendar.dart index 830569ffd..704304f3c 100644 --- a/forui/lib/src/widgets/calendar/calendar.dart +++ b/forui/lib/src/widgets/calendar/calendar.dart @@ -23,19 +23,27 @@ import 'package:forui/src/widgets/calendar/year_month_picker.dart'; /// * [FCalendarController] for customizing a calendar's date selection behavior. /// * [FCalendarStyle] for customizing a calendar's appearance. class FCalendar extends StatelessWidget { + static Widget _dayBuilder(BuildContext context, FCalendarDayData data, Widget? child) => child!; + /// The style. Defaults to [FThemeData.calendarStyle]. final FCalendarStyle? style; /// A controller that determines if a date is selected. final FCalendarController controller; - /// The start date, inclusive. It is truncated to the nearest date. + /// The builder used to build a day in the day picker. Defaults to returning the given child. + /// + /// The `child` is the default content with no alterations. Consider wrapping the `child` and other custom decoration + /// in a [Stack] to avoid re-creating the custom day content from scratch. + final ValueWidgetBuilder dayBuilder; + + /// The start date, inclusive. It is truncated to the nearest date. Defaults to 1st January, 1900. /// /// ## Contract /// Throws [AssertionError] if [end] <= [start]. final DateTime start; - /// The end date, exclusive. It is truncated to the nearest date. + /// The end date, exclusive. It is truncated to the nearest date. Defaults to 1st January, 2100. /// /// ## Contract /// Throws [AssertionError] if [end] <= [start]. @@ -61,20 +69,24 @@ class FCalendar extends StatelessWidget { /// [initialMonth] defaults to [today]. It is truncated to the nearest date. FCalendar({ required this.controller, - required this.start, - required this.end, this.style, + this.dayBuilder = _dayBuilder, this.onMonthChange, this.onPress, this.onLongPress, FCalendarPickerType initialType = FCalendarPickerType.day, + DateTime? start, + DateTime? end, DateTime? today, DateTime? initialMonth, super.key, - }) : assert(start.toLocalDate() < end.toLocalDate(), 'end date must be greater than start date'), + }) : start = start ?? DateTime(1990), + end = end ?? DateTime(2100), today = today ?? DateTime.now(), _type = ValueNotifier(initialType), - _month = ValueNotifier((initialMonth ?? today ?? DateTime.now()).toLocalDate().truncate(to: DateUnit.months)); + _month = ValueNotifier((initialMonth ?? today ?? DateTime.now()).toLocalDate().truncate(to: DateUnit.months)) { + assert(this.start.toLocalDate() < this.end.toLocalDate(), 'end date must be greater than start date'); + } @override Widget build(BuildContext context) { @@ -102,6 +114,7 @@ class FCalendar extends StatelessWidget { builder: (context, value, child) => switch (value) { FCalendarPickerType.day => PagedDayPicker( style: style, + dayBuilder: dayBuilder, start: start.toLocalDate(), end: end.toLocalDate(), today: today.toLocalDate(), @@ -142,6 +155,7 @@ class FCalendar extends StatelessWidget { properties ..add(DiagnosticsProperty('style', style)) ..add(DiagnosticsProperty('controller', controller)) + ..add(ObjectFlagProperty.has('dayBuilder', dayBuilder)) ..add(DiagnosticsProperty('start', start)) ..add(DiagnosticsProperty('end', end)) ..add(DiagnosticsProperty('today', today)) diff --git a/forui/lib/src/widgets/calendar/calendar_controller.dart b/forui/lib/src/widgets/calendar/calendar_controller.dart index c96131e12..8a9b8c09a 100644 --- a/forui/lib/src/widgets/calendar/calendar_controller.dart +++ b/forui/lib/src/widgets/calendar/calendar_controller.dart @@ -4,9 +4,11 @@ import 'package:forui/forui.dart'; bool _true(DateTime _) => true; +DateTime _stripTimezone(DateTime date) => DateTime.utc(date.year, date.month, date.day); + /// A controller that controls date selection in a calendar. /// -/// The [DateTime]s are always in UTC timezone and truncated to the nearest day. +/// All returned [DateTime]s are in UTC timezone with no time component. /// /// This class should be extended to customize date selection. By default, the following controllers are provided: /// * [FCalendarController.date] for selecting a single date. @@ -18,66 +20,129 @@ abstract class FCalendarController extends FValueNotifier { /// /// [selectable] will always return true if not given. /// + /// [truncateAndStripTimezone] determines whether the controller should truncate and convert all given [DateTime]s to + /// dates in UTC timezone. Defaults to true. + /// + /// ```dart + /// DateTime truncateAndStripTimezone(DateTime date) => DateTime.utc(date.year, date.month, date.day); + /// ``` + /// + /// [truncateAndStripTimezone] should be set to false if you can guarantee that all dates are in UTC timezone (with + /// the help of a 3rd party library), which will improve performance. **Warning:** Giving a [DateTime] in local + /// timezone or with a time component when [truncateAndStripTimezone] is false is undefined behavior. + /// /// ## Contract - /// Throws [AssertionError] if [initialSelection] is not in UTC timezone. + /// Throws [AssertionError] if [initialSelection] is not in UTC timezone and [truncateAndStripTimezone] is false. static FCalendarController date({ DateTime? initialSelection, Predicate? selectable, + bool truncateAndStripTimezone = true, }) => - _DateController(initialSelection: initialSelection, selectable: selectable); + truncateAndStripTimezone + ? _AutoDateController(initialSelection: initialSelection, selectable: selectable) + : _DateController(initialSelection: initialSelection, selectable: selectable); /// Creates a [FCalendarController] that allows multiple dates to be selected, with the given initial selected dates. /// /// [selectable] will always return true if not given. /// + /// [truncateAndStripTimezone] determines whether the controller should truncate and convert all given [DateTime]s to + /// dates in UTC timezone. Defaults to true. + /// + /// ```dart + /// DateTime truncateAndStripTimezone(DateTime date) => DateTime.utc(date.year, date.month, date.day); + /// ``` + /// + /// [truncateAndStripTimezone] should be set to false if you can guarantee that all dates are in UTC timezone (with + /// the help of an 3rd party library), which will improve performance. **Warning:** Giving a [DateTime] in local + /// timezone or with a time component when [truncateAndStripTimezone] is false is undefined behavior. + /// /// ## Contract - /// Throws [AssertionError] if the dates in [initialSelections] are not in UTC timezone. + /// Throws [AssertionError] if the dates in [initialSelections] are not in UTC timezone and [truncateAndStripTimezone] + /// is false. static FCalendarController> dates({ Set initialSelections = const {}, Predicate? selectable, + bool truncateAndStripTimezone = true, }) => - _DatesController(initialSelections: initialSelections, selectable: selectable); + truncateAndStripTimezone + ? _AutoDatesController(initialSelections: initialSelections, selectable: selectable) + : _DatesController(initialSelections: initialSelections, selectable: selectable); /// Creates a [FCalendarController] that allows a single range to be selected, with the given initial range. /// /// [selectable] will always return true if not given. /// - /// Both the start and end dates of the range is inclusive. The selected dates are always in UTC timezone and - /// truncated to the nearest day. Unselectable dates within the selected range are selected regardless. + /// [truncateAndStripTimezone] determines whether the controller should truncate and convert all given [DateTime]s to + /// dates in UTC timezone. Defaults to true. + /// + /// ```dart + /// DateTime truncateAndStripTimezone(DateTime date) => DateTime.utc(date.year, date.month, date.day); + /// ``` + /// + /// [truncateAndStripTimezone] should be set to false if you can guarantee that all dates are in UTC timezone (with + /// the help of an 3rd party library), which will improve performance. **Warning:** Giving a [DateTime] in local + /// timezone or with a time component when [truncateAndStripTimezone] is false is undefined behavior. + /// + /// Both the start and end dates of the range is inclusive. Unselectable dates within the selected range are selected + /// regardless. /// /// ## Contract /// Throws [AssertionError] if: - /// * the given dates in [value] is not in UTC timezone. + /// * the given dates in [initialSelection] is not in UTC timezone and [truncateAndStripTimezone] is false. /// * the end date is less than start date. static FCalendarController<(DateTime, DateTime)?> range({ (DateTime, DateTime)? initialSelection, Predicate? selectable, + bool truncateAndStripTimezone = true, }) => - _RangeController(initialSelection: initialSelection, selectable: selectable); + truncateAndStripTimezone + ? _AutoRangeController(initialSelection: initialSelection, selectable: selectable) + : _RangeController(initialSelection: initialSelection, selectable: selectable); /// Creates a [FCalendarController] with the given initial [value]. FCalendarController(super._value); /// Returns true if the given [date] can be selected/unselected. /// - /// [date] should always in UTC timezone and truncated to the nearest day. - /// /// ## Note /// It is unsafe for this function to have side effects since it may be called more than once for a single date. As it - /// is called frequently, it should not be computationally expensive. + /// is called frequently, it should also not be computationally expensive. bool selectable(DateTime date); /// Returns true if the given [date] is selected. - /// - /// [date] should always in UTC timezone and truncated to the nearest day. bool selected(DateTime date); /// Selects the given [date]. - /// - /// [date] should always in UTC timezone and truncated to the nearest day. void select(DateTime date); } +// The single date controllers. +class _AutoDateController extends FCalendarController { + final Predicate _selectable; + + _AutoDateController({ + DateTime? initialSelection, + Predicate? selectable, + }) : _selectable = selectable ?? _true, + super(initialSelection = initialSelection == null ? null : _stripTimezone(initialSelection)); + + @override + bool selectable(DateTime date) => _selectable(_stripTimezone(date)); + + @override + bool selected(DateTime date) => value == _stripTimezone(date); + + @override + void select(DateTime date) { + date = _stripTimezone(date); + super.value = value == date ? null : date; + } + + @override + set value(DateTime? value) => super.value = value == null ? null : _stripTimezone(value); +} + class _DateController extends FCalendarController { final Predicate _selectable; @@ -92,12 +157,36 @@ class _DateController extends FCalendarController { bool selectable(DateTime date) => _selectable(date); @override - bool selected(DateTime date) => value?.toLocalDate() == date.toLocalDate(); + bool selected(DateTime date) => value == date; + + @override + void select(DateTime date) => value = value == date ? null : date; +} + +// The multiple dates controllers. +final class _AutoDatesController extends FCalendarController> { + final Predicate _selectable; + + _AutoDatesController({ + Set initialSelections = const {}, + Predicate? selectable, + }) : _selectable = selectable ?? _true, + super(initialSelections.map(_stripTimezone).toSet()); + + @override + bool selectable(DateTime date) => _selectable(_stripTimezone(date)); + + @override + bool selected(DateTime date) => value.contains(_stripTimezone(date)); @override void select(DateTime date) { - value = value?.toLocalDate() == date.toLocalDate() ? null : date; + final copy = {...value}; + super.value = copy..toggle(_stripTimezone(date)); } + + @override + set value(Set value) => super.value = value.map(_stripTimezone).toSet(); } final class _DatesController extends FCalendarController> { @@ -116,11 +205,68 @@ final class _DatesController extends FCalendarController> { @override bool selected(DateTime date) => value.contains(date); + @override + void select(DateTime date) => value = value..toggle(date); +} + +// The range controllers. +final class _AutoRangeController extends FCalendarController<(DateTime, DateTime)?> { + final Predicate _selectable; + + _AutoRangeController({ + (DateTime, DateTime)? initialSelection, + Predicate? selectable, + }) : _selectable = selectable ?? _true, + super( + initialSelection = initialSelection == null + ? null + : (_stripTimezone(initialSelection.$1), _stripTimezone(initialSelection.$2)), + ) { + final range = value; + assert( + range == null || (range.$1.isBefore(range.$2) || range.$1.isAtSameMomentAs(range.$2)), + 'end date must be greater than or equal to start date', + ); + } + + @override + bool selectable(DateTime date) => _selectable(_stripTimezone(date)); + + @override + bool selected(DateTime date) { + if (value case (final first, final last)) { + final current = date.toLocalDate(); + return first.toLocalDate() <= current && current <= last.toLocalDate(); + } + + return false; + } + @override void select(DateTime date) { - final copy = {...value}; - value = copy..toggle(date); + date = _stripTimezone(date); + if (value == null) { + super.value = (date, date); + return; + } + + final (first, last) = value!; + + switch ((first, last)) { + case (final first, final last) when date == first || date == last: + super.value = null; + + case (final first, final last) when date.isBefore(first): + super.value = (date, last); + + case (final first, _): + super.value = (first, date); + } } + + @override + set value((DateTime, DateTime)? value) => + super.value = value == null ? null : (_stripTimezone(value.$1), _stripTimezone(value.$2)); } final class _RangeController extends FCalendarController<(DateTime, DateTime)?> { @@ -158,22 +304,21 @@ final class _RangeController extends FCalendarController<(DateTime, DateTime)?> @override void select(DateTime date) { if (value == null) { - value = (date, date); + super.value = (date, date); return; } final (first, last) = value!; - final pressed = date.toLocalDate(); - switch ((first.toLocalDate(), last.toLocalDate())) { - case (final first, final last) when pressed == first || pressed == last: - value = null; + switch ((first, last)) { + case (final first, final last) when date == first || date == last: + super.value = null; - case (final first, final last) when pressed < first: - value = (pressed.toNative(), last.toNative()); + case (final first, final last) when date.isBefore(first): + super.value = (date, last); case (final first, _): - value = (first.toNative(), pressed.toNative()); + super.value = (first, date); } } } diff --git a/forui/lib/src/widgets/calendar/day/day_picker.dart b/forui/lib/src/widgets/calendar/day/day_picker.dart index 4287e196d..de9316fcd 100644 --- a/forui/lib/src/widgets/calendar/day/day_picker.dart +++ b/forui/lib/src/widgets/calendar/day/day_picker.dart @@ -16,6 +16,7 @@ class DayPicker extends StatefulWidget { final FCalendarDayPickerStyle style; final FLocalizations localization; + final ValueWidgetBuilder dayBuilder; final LocalDate month; final LocalDate today; final LocalDate? focused; @@ -27,6 +28,7 @@ class DayPicker extends StatefulWidget { const DayPicker({ required this.style, required this.localization, + required this.dayBuilder, required this.month, required this.today, required this.focused, @@ -46,6 +48,7 @@ class DayPicker extends StatefulWidget { properties ..add(DiagnosticsProperty('style', style)) ..add(DiagnosticsProperty('localization', localization)) + ..add(ObjectFlagProperty.has('dayBuilder', dayBuilder)) ..add(DiagnosticsProperty('month', month)) ..add(DiagnosticsProperty('today', today)) ..add(DiagnosticsProperty('focused', focused)) @@ -111,6 +114,7 @@ class _DayPickerState extends State { Entry.day( style: widget.style, localizations: widget.localization, + dayBuilder: widget.dayBuilder, date: date, focusNode: focusNode, current: date.month == widget.month.month, diff --git a/forui/lib/src/widgets/calendar/day/paged_day_picker.dart b/forui/lib/src/widgets/calendar/day/paged_day_picker.dart index e5ce27025..617f2ed26 100644 --- a/forui/lib/src/widgets/calendar/day/paged_day_picker.dart +++ b/forui/lib/src/widgets/calendar/day/paged_day_picker.dart @@ -15,12 +15,14 @@ class PagedDayPicker extends PagedPicker { final ValueChanged? onMonthChange; final ValueChanged onPress; final ValueChanged onLongPress; + final ValueWidgetBuilder dayBuilder; PagedDayPicker({ required this.selected, required this.onMonthChange, required this.onPress, required this.onLongPress, + required this.dayBuilder, required super.style, required super.start, required super.end, @@ -40,7 +42,8 @@ class PagedDayPicker extends PagedPicker { ..add(DiagnosticsProperty('selected', selected)) ..add(DiagnosticsProperty('onMonthChange', onMonthChange)) ..add(DiagnosticsProperty('onPress', onPress)) - ..add(DiagnosticsProperty('onLongPress', onLongPress)); + ..add(DiagnosticsProperty('onLongPress', onLongPress)) + ..add(DiagnosticsProperty('dayBuilder', dayBuilder)); } } @@ -51,6 +54,7 @@ class _PagedDayPickerState extends PagedPickerState { Widget buildItem(BuildContext context, int page) => DayPicker( style: widget.style.dayPickerStyle, localization: FLocalizations.of(context), + dayBuilder: widget.dayBuilder, month: widget.start.truncate(to: DateUnit.months).plus(months: page), today: widget.today, focused: focusedDate, diff --git a/forui/lib/src/widgets/calendar/shared/entry.dart b/forui/lib/src/widgets/calendar/shared/entry.dart index 514c588a3..0d95da286 100644 --- a/forui/lib/src/widgets/calendar/shared/entry.dart +++ b/forui/lib/src/widgets/calendar/shared/entry.dart @@ -6,6 +6,16 @@ import 'package:sugar/sugar.dart'; import 'package:forui/forui.dart'; +/// A calendar day's data. +typedef FCalendarDayData = ({ + FCalendarDayPickerStyle style, + DateTime date, + bool current, + bool today, + bool selectable, + bool selected, +}); + @internal abstract class Entry extends StatelessWidget { final FCalendarEntryStyle style; @@ -14,6 +24,7 @@ abstract class Entry extends StatelessWidget { factory Entry.day({ required FCalendarDayPickerStyle style, required FLocalizations localizations, + required ValueWidgetBuilder dayBuilder, required LocalDate date, required FocusNode focusNode, required bool current, @@ -34,7 +45,16 @@ abstract class Entry extends StatelessWidget { final yesterday = isSelected && selected(date.yesterday) ? Radius.zero : entryStyle.radius; final tomorrow = isSelected && selected(date.tomorrow) ? Radius.zero : entryStyle.radius; - return _Content( + final dayData = ( + style: style, + date: date.toNative(), + current: current, + today: today, + selectable: canSelect, + selected: isSelected, + ); + + final child = _Content( style: entryStyle, borderRadius: switch (Directionality.maybeOf(context)) { TextDirection.ltr || null => BorderRadius.horizontal(left: yesterday, right: tomorrow), @@ -44,6 +64,8 @@ abstract class Entry extends StatelessWidget { data: data, current: today, ); + + return dayBuilder(context, dayData, child); } if (canSelect) { diff --git a/forui/lib/widgets/calendar.dart b/forui/lib/widgets/calendar.dart index 76d0c8c58..4f5319511 100644 --- a/forui/lib/widgets/calendar.dart +++ b/forui/lib/widgets/calendar.dart @@ -7,7 +7,7 @@ library forui.widgets.calendar; export '../src/widgets/calendar/calendar.dart'; export '../src/widgets/calendar/day/day_picker.dart' show FCalendarDayPickerStyle, FCalendarDayStyle; -export '../src/widgets/calendar/shared/entry.dart' show FCalendarEntryStyle; +export '../src/widgets/calendar/shared/entry.dart' show FCalendarDayData, FCalendarEntryStyle; export '../src/widgets/calendar/shared/header.dart' show FCalendarHeaderStyle, FCalendarPickerType; export '../src/widgets/calendar/calendar_controller.dart'; export '../src/widgets/calendar/year_month_picker.dart' show FCalendarYearMonthPickerStyle; diff --git a/forui/test/src/widgets/calendar/calendar_controller_test.dart b/forui/test/src/widgets/calendar/calendar_controller_test.dart index 239196bd1..ba74ddfbd 100644 --- a/forui/test/src/widgets/calendar/calendar_controller_test.dart +++ b/forui/test/src/widgets/calendar/calendar_controller_test.dart @@ -4,17 +4,77 @@ import 'package:forui/forui.dart'; void main() { group('FCalendarController.date(...)', () { + test( + 'constructor converts date time', + () => expect( + FCalendarController.date(initialSelection: DateTime(2024, 11, 30, 12)).value, + DateTime.utc(2024, 11, 30), + ), + ); + + test('selectable(...)', () { + FCalendarController.date( + selectable: (date) { + expect(date, DateTime.utc(2024)); + return true; + }, + ).selectable(DateTime(2024, 1, 1, 1)); + }); + + for (final (date, expected) in [ + (DateTime(2024, 5, 4, 3), true), + (DateTime(2024, 5, 5, 3), false), + ]) { + test('selected(...) contains date', () { + final controller = FCalendarController.date(initialSelection: DateTime(2024, 5, 4)); + expect(controller.selected(date), expected); + }); + } + + for (final (initial, date, expected) in [ + (null, DateTime(2024), DateTime.utc(2024)), + (null, DateTime(2025), DateTime.utc(2025)), + (DateTime(2024), DateTime(2025), DateTime.utc(2025)), + (DateTime(2024), DateTime(2024), null), + ]) { + test('select(...)', () { + final controller = FCalendarController.date(initialSelection: initial)..select(date); + expect(controller.value, expected); + }); + } + + test('value', () { + final controller = FCalendarController.date()..value = DateTime(2024, 11, 30, 12); + expect(controller.value, DateTime.utc(2024, 11, 30)); + }); + }); + + group('FCalendarController.date(...) no auto-convert', () { test( 'constructor throws error', - () => expect(() => FCalendarController.date(initialSelection: DateTime.now()), throwsAssertionError), + () => expect( + () => FCalendarController.date(initialSelection: DateTime.now(), truncateAndStripTimezone: false), + throwsAssertionError, + ), ); + test('selectable(...)', () { + FCalendarController.date( + truncateAndStripTimezone: false, + selectable: (date) { + expect(date, DateTime(2024, 1, 1, 1)); + return true; + }, + ).selectable(DateTime(2024, 1, 1, 1)); + }); + for (final (date, expected) in [ (DateTime.utc(2024, 5, 4), true), (DateTime.utc(2024, 5, 5), false), ]) { test('selected(...) contains date', () { - final controller = FCalendarController.date(initialSelection: DateTime.utc(2024, 5, 4)); + final controller = + FCalendarController.date(initialSelection: DateTime.utc(2024, 5, 4), truncateAndStripTimezone: false); expect(controller.selected(date), expected); }); } @@ -26,19 +86,84 @@ void main() { (DateTime.utc(2024), DateTime.utc(2024), null), ]) { test('select(...)', () { - final controller = FCalendarController.date(initialSelection: initial)..select(date); + final controller = FCalendarController.date(initialSelection: initial, truncateAndStripTimezone: false) + ..select(date); + expect(controller.value, expected); + }); + } + }); + + group('FCalendarController.dates(...)', () { + test( + 'constructor converts date time', + () => expect( + FCalendarController.dates(initialSelections: {DateTime(2024, 11, 30, 12)}).value, + {DateTime.utc(2024, 11, 30)}, + ), + ); + + test('selectable(...)', () { + FCalendarController.dates( + selectable: (date) { + expect(date, DateTime.utc(2024)); + return true; + }, + ).selectable(DateTime(2024, 1, 1, 1)); + }); + + for (final (date, expected) in [ + (DateTime(2024), true), + (DateTime(2025), false), + ]) { + test('selected(...)', () { + final controller = FCalendarController.dates(initialSelections: {DateTime.utc(2024)}); + expect(controller.selected(date), expected); + }); + } + + for (final (initial, date, expected) in [ + ({DateTime(2024)}, DateTime(2024), {}), + ({}, DateTime.utc(2024), {DateTime.utc(2024)}), + ({DateTime(2024)}, DateTime(2025), {DateTime.utc(2024), DateTime.utc(2025)}), + ]) { + test('select(...)', () { + final controller = FCalendarController.dates(initialSelections: initial)..select(date); expect(controller.value, expected); }); } + + test('value', () { + final controller = FCalendarController.dates()..value = {DateTime(2024, 11, 30, 12)}; + expect(controller.value, {DateTime.utc(2024, 11, 30)}); + }); }); - group('FCalendarController.dates', () { + group('FCalendarController.dates(...) no auto-convert', () { + test( + 'constructor throws error', + () => expect( + () => FCalendarController.dates(initialSelections: {DateTime.now()}, truncateAndStripTimezone: false), + throwsAssertionError, + ), + ); + + test('selectable(...)', () { + FCalendarController.dates( + truncateAndStripTimezone: false, + selectable: (date) { + expect(date, DateTime(2024, 1, 1, 1)); + return true; + }, + ).selectable(DateTime(2024, 1, 1, 1)); + }); + for (final (date, expected) in [ (DateTime.utc(2024), true), (DateTime.utc(2025), false), ]) { test('selected(...)', () { - final controller = FCalendarController.dates(initialSelections: {DateTime.utc(2024)}); + final controller = + FCalendarController.dates(initialSelections: {DateTime.utc(2024)}, truncateAndStripTimezone: false); expect(controller.selected(date), expected); }); } @@ -49,17 +174,72 @@ void main() { ({DateTime.utc(2024)}, DateTime.utc(2025), {DateTime.utc(2024), DateTime.utc(2025)}), ]) { test('select(...)', () { - final controller = FCalendarController.dates(initialSelections: initial)..select(date); + final controller = FCalendarController.dates(initialSelections: initial, truncateAndStripTimezone: false) + ..select(date); expect(controller.value, expected); }); } }); group('FCalendarController.range(...)', () { + test( + 'constructor converts date time', + () => expect( + FCalendarController.range(initialSelection: (DateTime(2024, 11, 30, 12), DateTime(2024, 12, 12, 12))).value, + (DateTime.utc(2024, 11, 30), DateTime.utc(2024, 12, 12)), + ), + ); + + test('selectable(...)', () { + FCalendarController.range( + selectable: (date) { + expect(date, DateTime.utc(2024)); + return true; + }, + ).selectable(DateTime(2024, 1, 1, 1)); + }); + + for (final (initial, date, expected) in [ + ((DateTime(2024), DateTime(2025)), DateTime.utc(2024), true), + ((DateTime(2024), DateTime(2025)), DateTime.utc(2025), true), + ((DateTime(2024), DateTime(2025)), DateTime.utc(2023), false), + ((DateTime(2024), DateTime(2025)), DateTime.utc(2026), false), + (null, DateTime.utc(2023), false), + ]) { + test('selected(...)', () { + final controller = FCalendarController.range(initialSelection: initial); + expect(controller.selected(date), expected); + }); + } + + for (final (initial, date, expected) in [ + ((DateTime(2024), DateTime(2025)), DateTime(2024), null), + ((DateTime(2024), DateTime(2025)), DateTime(2025), null), + ((DateTime(2024), DateTime(2025)), DateTime(2023), (DateTime.utc(2023), DateTime.utc(2025))), + ((DateTime(2024), DateTime(2025)), DateTime(2026), (DateTime.utc(2024), DateTime.utc(2026))), + ((DateTime(2024), DateTime(2027)), DateTime(2025), (DateTime.utc(2024), DateTime.utc(2025))), + (null, DateTime(2023), (DateTime.utc(2023), DateTime.utc(2023))), + ]) { + test('select(...)', () { + final controller = FCalendarController.range(initialSelection: initial)..select(date); + expect(controller.value, expected); + }); + } + + test('value', () { + final controller = FCalendarController.range()..value = (DateTime(2024, 11, 30, 12), DateTime(2024, 12, 12, 12)); + expect(controller.value, (DateTime.utc(2024, 11, 30), DateTime.utc(2024, 12, 12))); + }); + }); + + group('FCalendarController.range(...) no auto-convert', () { test( 'constructor throws error', () => expect( - () => FCalendarController.range(initialSelection: (DateTime(2025), DateTime(2024))), + () => FCalendarController.range( + initialSelection: (DateTime(2025), DateTime(2024)), + truncateAndStripTimezone: false, + ), throwsAssertionError, ), ); @@ -72,7 +252,7 @@ void main() { (null, DateTime.utc(2023), false), ]) { test('selected(...)', () { - final controller = FCalendarController.range(initialSelection: initial); + final controller = FCalendarController.range(initialSelection: initial, truncateAndStripTimezone: false); expect(controller.selected(date), expected); }); } @@ -86,7 +266,8 @@ void main() { (null, DateTime.utc(2023), (DateTime.utc(2023), DateTime.utc(2023))), ]) { test('select(...)', () { - final controller = FCalendarController.range(initialSelection: initial)..select(date); + final controller = FCalendarController.range(initialSelection: initial, truncateAndStripTimezone: false) + ..select(date); expect(controller.value, expected); }); } diff --git a/forui_hooks/lib/src/calendar_controller_hook.dart b/forui_hooks/lib/src/calendar_controller_hook.dart index ee0494bcd..e94ed0483 100644 --- a/forui_hooks/lib/src/calendar_controller_hook.dart +++ b/forui_hooks/lib/src/calendar_controller_hook.dart @@ -9,9 +9,24 @@ typedef _Create = FCalendarController Function(_CalendarControllerHook) /// Creates a [FCalendarController] that allows only a single date to be selected and is automatically disposed. /// /// [selectable] will always return true if not given. +/// +/// [autoConvert] determines whether the controller should truncate and convert all given [DateTime]s to dates in +/// UTC timezone. Defaults to true. +/// +/// ```dart +/// DateTime convert(DateTime date) => DateTime.utc(date.year, date.month, date.day); +/// ``` +/// +/// [autoConvert] should be set to false if you can guarantee that all dates are in UTC timezone (with the help of an +/// 3rd party library), which will improve performance. **Warning:** Giving a [DateTime] in local timezone or with a +/// time component when [autoConvert] is false is undefined behavior. +/// +/// ## Contract +/// Throws [AssertionError] if [initialSelection] is not in UTC timezone and [autoConvert] is false. FCalendarController useFDateCalendarController({ DateTime? initialSelection, bool Function(DateTime)? selectable, + bool autoConvert = true, List? keys, }) => use(_CalendarControllerHook( @@ -21,15 +36,31 @@ FCalendarController useFDateCalendarController({ create: (hook) => FCalendarController.date( initialSelection: hook.value, selectable: hook.selectable, + truncateAndStripTimezone: autoConvert, ), )); /// Creates a [FCalendarController] that allows only multiple dates to be selected and is automatically disposed. /// /// [selectable] will always return true if not given. +/// +/// [autoConvert] determines whether the controller should truncate and convert all given [DateTime]s to dates in +/// UTC timezone. Defaults to true. +/// +/// ```dart +/// DateTime convert(DateTime date) => DateTime.utc(date.year, date.month, date.day); +/// ``` +/// +/// [autoConvert] should be set to false if you can guarantee that all dates are in UTC timezone (with the help of an +/// 3rd party library), which will improve performance. **Warning:** Giving a [DateTime] in local timezone or with a +/// time component when [autoConvert] is false is undefined behavior. +/// +/// ## Contract +/// Throws [AssertionError] if the dates in [initialSelections] are not in UTC timezone and [autoConvert] is false. FCalendarController> useFDatesCalendarController({ Set initialSelections = const {}, bool Function(DateTime)? selectable, + bool autoConvert = true, List? keys, }) => use(_CalendarControllerHook>( @@ -39,6 +70,7 @@ FCalendarController> useFDatesCalendarController({ create: (hook) => FCalendarController.dates( initialSelections: hook.value, selectable: hook.selectable, + truncateAndStripTimezone: autoConvert, ), )); @@ -47,11 +79,28 @@ FCalendarController> useFDatesCalendarController({ /// /// [selectable] will always return true if not given. /// -/// Both the start and end dates of the range is inclusive. The selected dates are always in UTC timezone and truncated -/// to the nearest day. Unselectable dates within the selected range are selected regardless. +/// [autoConvert] determines whether the controller should truncate and convert all given [DateTime]s to dates in +/// UTC timezone. Defaults to true. +/// +/// ```dart +/// DateTime convert(DateTime date) => DateTime.utc(date.year, date.month, date.day); +/// ``` +/// +/// [autoConvert] should be set to false if you can guarantee that all dates are in UTC timezone (with the help of an +/// 3rd party library), which will improve performance. **Warning:** Giving a [DateTime] in local timezone or with a +/// time component when [autoConvert] is false is undefined behavior. +/// +/// Both the start and end dates of the range is inclusive. Unselectable dates within the selected range are +/// selected regardless. +/// +/// ## Contract +/// Throws [AssertionError] if: +/// * the given dates in [initialSelection] is not in UTC timezone and [autoConvert] is false. +/// * the end date is less than start date. FCalendarController<(DateTime, DateTime)?> useFRangeCalendarController({ (DateTime, DateTime)? initialSelection, bool Function(DateTime)? selectable, + bool autoConvert = true, List? keys, }) => use(_CalendarControllerHook<(DateTime, DateTime)?>( @@ -61,6 +110,7 @@ FCalendarController<(DateTime, DateTime)?> useFRangeCalendarController({ create: (hook) => FCalendarController.range( initialSelection: hook.value, selectable: hook.selectable, + truncateAndStripTimezone: autoConvert, ), )); diff --git a/samples/lib/widgets/calendar.dart b/samples/lib/widgets/calendar.dart index 2693b3238..228f70017 100644 --- a/samples/lib/widgets/calendar.dart +++ b/samples/lib/widgets/calendar.dart @@ -25,8 +25,8 @@ class CalendarPage extends Sample { @override Widget sample(BuildContext context) => FCalendar( controller: FCalendarController.date(initialSelection: selected), - start: DateTime.utc(2000), - end: DateTime.utc(2030), + start: DateTime(2000), + end: DateTime(2030), ); } @@ -39,11 +39,11 @@ class DatesCalendarPage extends Sample { @override Widget sample(BuildContext context) => FCalendar( controller: FCalendarController.dates( - initialSelections: {DateTime.utc(2024, 7, 17), DateTime.utc(2024, 7, 20)}, + initialSelections: {DateTime(2024, 7, 17), DateTime(2024, 7, 20)}, ), - start: DateTime.utc(2000), - today: DateTime.utc(2024, 7, 15), - end: DateTime.utc(2030), + start: DateTime(2000), + today: DateTime(2024, 7, 15), + end: DateTime(2030), ); } @@ -56,12 +56,12 @@ class UnselectableCalendarPage extends Sample { @override Widget sample(BuildContext context) => FCalendar( controller: FCalendarController.dates( - initialSelections: {DateTime.utc(2024, 7, 17), DateTime.utc(2024, 7, 20)}, - selectable: (date) => !{DateTime.utc(2024, 7, 18), DateTime.utc(2024, 7, 19)}.contains(date), + initialSelections: {DateTime(2024, 7, 17), DateTime(2024, 7, 20)}, + selectable: (date) => !{DateTime(2024, 7, 18), DateTime(2024, 7, 19)}.contains(date), ), - start: DateTime.utc(2000), - today: DateTime.utc(2024, 7, 15), - end: DateTime.utc(2030), + start: DateTime(2000), + today: DateTime(2024, 7, 15), + end: DateTime(2030), ); } @@ -73,11 +73,9 @@ class RangeCalendarPage extends Sample { @override Widget sample(BuildContext context) => FCalendar( - controller: FCalendarController.range( - initialSelection: (DateTime.utc(2024, 7, 17), DateTime.utc(2024, 7, 20)), - ), - start: DateTime.utc(2000), - today: DateTime.utc(2024, 7, 15), - end: DateTime.utc(2030), + controller: FCalendarController.range(initialSelection: (DateTime(2024, 7, 17), DateTime(2024, 7, 20))), + start: DateTime(2000), + today: DateTime(2024, 7, 15), + end: DateTime(2030), ); } From 5de7fe355ab6d7d25ccc4c7e2af5354f4829b01e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Dec 2024 20:45:59 +0800 Subject: [PATCH 09/12] chore(deps): update subosito/flutter-action action to v2.18.0 (#300) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/docs_deploy.yaml | 2 +- .github/workflows/docs_preview_deploy.yaml | 2 +- .github/workflows/forui_build.yaml | 6 +++--- .github/workflows/forui_hooks_build.yaml | 2 +- .github/workflows/forui_hooks_presubmit.yaml | 2 +- .github/workflows/forui_presubmit.yaml | 2 +- .github/workflows/samples_build.yaml | 2 +- .github/workflows/samples_presubmit.yaml | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/docs_deploy.yaml b/.github/workflows/docs_deploy.yaml index 173445b89..f0a670270 100644 --- a/.github/workflows/docs_deploy.yaml +++ b/.github/workflows/docs_deploy.yaml @@ -65,7 +65,7 @@ jobs: working-directory: ./samples steps: - uses: actions/checkout@v4 - - uses: subosito/flutter-action@v2.17.0 + - uses: subosito/flutter-action@v2.18.0 with: flutter-version: 3.24.x cache: true diff --git a/.github/workflows/docs_preview_deploy.yaml b/.github/workflows/docs_preview_deploy.yaml index 4ca2f8d37..0bab5d76e 100644 --- a/.github/workflows/docs_preview_deploy.yaml +++ b/.github/workflows/docs_preview_deploy.yaml @@ -25,7 +25,7 @@ jobs: ref: ${{ github.event.pull_request.head.ref }} # Publish samples - - uses: subosito/flutter-action@v2.17.0 + - uses: subosito/flutter-action@v2.18.0 with: flutter-version: 3.24.x cache: true diff --git a/.github/workflows/forui_build.yaml b/.github/workflows/forui_build.yaml index 6b5b54e31..04fbe217d 100644 --- a/.github/workflows/forui_build.yaml +++ b/.github/workflows/forui_build.yaml @@ -22,7 +22,7 @@ jobs: flutter-version: [ 3.x ] steps: - uses: actions/checkout@v4 - - uses: subosito/flutter-action@v2.17.0 + - uses: subosito/flutter-action@v2.18.0 with: flutter-version: ${{ matrix.flutter-version }} cache: true @@ -51,7 +51,7 @@ jobs: with: distribution: 'temurin' java-version: 17 - - uses: subosito/flutter-action@v2.17.0 + - uses: subosito/flutter-action@v2.18.0 with: flutter-version: ${{ matrix.flutter-version }} cache: true @@ -71,7 +71,7 @@ jobs: flutter-version: [ 3.x ] steps: - uses: actions/checkout@v4 - - uses: subosito/flutter-action@v2.17.0 + - uses: subosito/flutter-action@v2.18.0 with: flutter-version: ${{ matrix.flutter-version }} cache: true diff --git a/.github/workflows/forui_hooks_build.yaml b/.github/workflows/forui_hooks_build.yaml index 1143daea1..bfb23aca2 100644 --- a/.github/workflows/forui_hooks_build.yaml +++ b/.github/workflows/forui_hooks_build.yaml @@ -22,7 +22,7 @@ jobs: flutter-version: [ 3.x ] steps: - uses: actions/checkout@v4 - - uses: subosito/flutter-action@v2.16.0 + - uses: subosito/flutter-action@v2.18.0 with: flutter-version: ${{ matrix.flutter-version }} cache: true diff --git a/.github/workflows/forui_hooks_presubmit.yaml b/.github/workflows/forui_hooks_presubmit.yaml index 24a3fd32d..2bc0cdc50 100644 --- a/.github/workflows/forui_hooks_presubmit.yaml +++ b/.github/workflows/forui_hooks_presubmit.yaml @@ -37,7 +37,7 @@ jobs: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.ref }} - - uses: subosito/flutter-action@v2.16.0 + - uses: subosito/flutter-action@v2.18.0 with: cache: true diff --git a/.github/workflows/forui_presubmit.yaml b/.github/workflows/forui_presubmit.yaml index 029f792fa..1bf72231f 100644 --- a/.github/workflows/forui_presubmit.yaml +++ b/.github/workflows/forui_presubmit.yaml @@ -37,7 +37,7 @@ jobs: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.ref }} - - uses: subosito/flutter-action@v2.17.0 + - uses: subosito/flutter-action@v2.18.0 with: cache: true diff --git a/.github/workflows/samples_build.yaml b/.github/workflows/samples_build.yaml index 46c00ca80..1a9439f09 100644 --- a/.github/workflows/samples_build.yaml +++ b/.github/workflows/samples_build.yaml @@ -24,7 +24,7 @@ jobs: flutter-version: [ 3.x ] steps: - uses: actions/checkout@v4 - - uses: subosito/flutter-action@v2.17.0 + - uses: subosito/flutter-action@v2.18.0 with: flutter-version: ${{ matrix.flutter-version }} cache: true diff --git a/.github/workflows/samples_presubmit.yaml b/.github/workflows/samples_presubmit.yaml index a5cce048f..5c45b26b8 100644 --- a/.github/workflows/samples_presubmit.yaml +++ b/.github/workflows/samples_presubmit.yaml @@ -37,7 +37,7 @@ jobs: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.ref }} - - uses: subosito/flutter-action@v2.17.0 + - uses: subosito/flutter-action@v2.18.0 with: cache: true From c6d608cdee200fe9100d210cb1691da637a9b3d5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Dec 2024 20:47:15 +0800 Subject: [PATCH 10/12] chore(deps): update plugin com.android.application to v8.7.3 (#299) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- forui/example/android/settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forui/example/android/settings.gradle b/forui/example/android/settings.gradle index 9db74ac3c..ffbfcf941 100644 --- a/forui/example/android/settings.gradle +++ b/forui/example/android/settings.gradle @@ -19,7 +19,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version '8.7.2' apply false + id "com.android.application" version '8.7.3' apply false id "org.jetbrains.kotlin.android" version "2.1.0" apply false } From 49587510134165ba0fab3b5de6999f13732a9eae Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 00:47:40 +0800 Subject: [PATCH 11/12] chore(deps): update docs - minor revisions (#298) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- docs/pnpm-lock.yaml | 143 ++++++++++++++++++++++---------------------- 1 file changed, 72 insertions(+), 71 deletions(-) diff --git a/docs/pnpm-lock.yaml b/docs/pnpm-lock.yaml index 6efbef739..bc3471e04 100644 --- a/docs/pnpm-lock.yaml +++ b/docs/pnpm-lock.yaml @@ -16,13 +16,13 @@ importers: version: 0.462.0(react@18.3.1) next: specifier: ^14.2.14 - version: 14.2.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) nextra: specifier: ^3.0.8 - version: 3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2) + version: 3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2) nextra-theme-docs: specifier: ^3.0.8 - version: 3.2.4(next@14.2.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 3.2.4(next@14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: 18.3.1 version: 18.3.1 @@ -44,7 +44,7 @@ importers: version: 8.4.49 tailwindcss: specifier: ^3.4.13 - version: 3.4.15 + version: 3.4.16 typescript: specifier: ^5.6.2 version: 5.7.2 @@ -238,59 +238,59 @@ packages: resolution: {integrity: sha512-jMxvwzkKzd3cXo2EB9GM2ic0eYo2rP/BS6gJt6HnWbsDO1O8GSD4k7o2Cpr2YERtMpGF/MGcDfsfj2EbQPtrXw==} engines: {node: '>= 10'} - '@next/env@14.2.18': - resolution: {integrity: sha512-2vWLOUwIPgoqMJKG6dt35fVXVhgM09tw4tK3/Q34GFXDrfiHlG7iS33VA4ggnjWxjiz9KV5xzfsQzJX6vGAekA==} + '@next/env@14.2.19': + resolution: {integrity: sha512-8yWSNi1p+AOsd1QsxZMMkXtdrz8wvYoRxoUa9olmHBspHVLnxpptyKoI574ZF90yq1gXv/CqpchVLBoK8RcN7w==} - '@next/swc-darwin-arm64@14.2.18': - resolution: {integrity: sha512-tOBlDHCjGdyLf0ube/rDUs6VtwNOajaWV+5FV/ajPgrvHeisllEdymY/oDgv2cx561+gJksfMUtqf8crug7sbA==} + '@next/swc-darwin-arm64@14.2.19': + resolution: {integrity: sha512-mL0Nn2PNKV0L++F1l69wY3ySCg9ryw9NtvPhAXm952wpxLVWCCDkVb6XTtOeicF8EdstbjZyLRBflEHtv/Wk2w==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@14.2.18': - resolution: {integrity: sha512-uJCEjutt5VeJ30jjrHV1VIHCsbMYnEqytQgvREx+DjURd/fmKy15NaVK4aR/u98S1LGTnjq35lRTnRyygglxoA==} + '@next/swc-darwin-x64@14.2.19': + resolution: {integrity: sha512-2HWOTmk+qNa5R+NW8+752jye5JXlQVkGTf6IV+cT2+q3YeRYQPoqYcIr9KSlB8pvgqRqtIGHcioZFvWSeXjxVA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@14.2.18': - resolution: {integrity: sha512-IL6rU8vnBB+BAm6YSWZewc+qvdL1EaA+VhLQ6tlUc0xp+kkdxQrVqAnh8Zek1ccKHlTDFRyAft0e60gteYmQ4A==} + '@next/swc-linux-arm64-gnu@14.2.19': + resolution: {integrity: sha512-tlbHT+Chnjqh9gSrNNrDAnqFHkoA++wI829bTawoLwAPemji57/qhDp88YteTuUN3rd4U3FcV0f9qiZbyMStFQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@14.2.18': - resolution: {integrity: sha512-RCaENbIZqKKqTlL8KNd+AZV/yAdCsovblOpYFp0OJ7ZxgLNbV5w23CUU1G5On+0fgafrsGcW+GdMKdFjaRwyYA==} + '@next/swc-linux-arm64-musl@14.2.19': + resolution: {integrity: sha512-v0FD7DDS1yapnJw8JuvvePlqxyNY+OKrfoVDvibc+9ADVVzbINkHTCXIDshMXy/rBKheUpkycgS1lOaovgZQ5Q==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@14.2.18': - resolution: {integrity: sha512-3kmv8DlyhPRCEBM1Vavn8NjyXtMeQ49ID0Olr/Sut7pgzaQTo4h01S7Z8YNE0VtbowyuAL26ibcz0ka6xCTH5g==} + '@next/swc-linux-x64-gnu@14.2.19': + resolution: {integrity: sha512-S+DneEj0Knv8+cilSn8ZP+xU/926eeeueZ4DjQcFy3hZT+2R29wTYBnDeUk+FCVchjzD9s0dvWff6eHDYrJoSA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@14.2.18': - resolution: {integrity: sha512-mliTfa8seVSpTbVEcKEXGjC18+TDII8ykW4a36au97spm9XMPqQTpdGPNBJ9RySSFw9/hLuaCMByluQIAnkzlw==} + '@next/swc-linux-x64-musl@14.2.19': + resolution: {integrity: sha512-RwczHg2q4n4Ls9PJtBDlBNkfl6G7Fd4uvSRIXPM6Inw52q8R+oWduvuqdzlvcygnv78wt1yrQI14ZRiU0BjgVw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@14.2.18': - resolution: {integrity: sha512-J5g0UFPbAjKYmqS3Cy7l2fetFmWMY9Oao32eUsBPYohts26BdrMUyfCJnZFQkX9npYaHNDOWqZ6uV9hSDPw9NA==} + '@next/swc-win32-arm64-msvc@14.2.19': + resolution: {integrity: sha512-42YlHVSq3q1nTxLkikG2dRUsKM6vq8v0jrxbR1M6vlgprWlIoXme31g3SpJvVp52v1SfE9WbyAegQxfSIENDSQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-ia32-msvc@14.2.18': - resolution: {integrity: sha512-Ynxuk4ZgIpdcN7d16ivJdjsDG1+3hTvK24Pp8DiDmIa2+A4CfhJSEHHVndCHok6rnLUzAZD+/UOKESQgTsAZGg==} + '@next/swc-win32-ia32-msvc@14.2.19': + resolution: {integrity: sha512-xMEXItVFcT7fV6ndcfnT4ZHm3R0C8398tiC3KInsK+511Or9Jq5G7zagz8aonNRKZkw15zdM1txRslSMRHe4mA==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] - '@next/swc-win32-x64-msvc@14.2.18': - resolution: {integrity: sha512-dtRGMhiU9TN5nyhwzce+7c/4CCeykYS+ipY/4mIrGzJ71+7zNo55ZxCB7cAVuNqdwtYniFNR2c9OFQ6UdFIMcg==} + '@next/swc-win32-x64-msvc@14.2.19': + resolution: {integrity: sha512-bOkmujDRcqbHO2Mxun7SogL1fwzGT/PYqFZ0+aTBjmkhGhx7V/Dun4MNjnxJEGByGNg2EcwdWzsYcRUnHs8Ivg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -630,8 +630,8 @@ packages: caniuse-lite@1.0.30001666: resolution: {integrity: sha512-gD14ICmoV5ZZM1OdzPWmpx+q4GyefaK06zi8hmfHV5xe4/2nOQX3+Dw5o+fSqOws2xVwL9j+anOPFwHzdEdV4g==} - caniuse-lite@1.0.30001680: - resolution: {integrity: sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==} + caniuse-lite@1.0.30001686: + resolution: {integrity: sha512-Y7deg0Aergpa24M3qLC5xjNklnKnhsmSyR/V89dLZ1n0ucJIFNs7PgR2Yfa/Zf6W79SbBicgtGxZr2juHkEUIA==} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -1251,12 +1251,8 @@ packages: layout-base@2.0.1: resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} - lilconfig@2.1.0: - resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} - engines: {node: '>=10'} - - lilconfig@3.1.2: - resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} lines-and-columns@1.2.4: @@ -1510,6 +1506,11 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nanoid@3.3.8: + resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + negotiator@1.0.0: resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} engines: {node: '>= 0.6'} @@ -1520,8 +1521,8 @@ packages: react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - next@14.2.18: - resolution: {integrity: sha512-H9qbjDuGivUDEnK6wa+p2XKO+iMzgVgyr9Zp/4Iv29lKa+DYaxJGjOeEA+5VOvJh/M7HLiskehInSa0cWxVXUw==} + next@14.2.19: + resolution: {integrity: sha512-YTOWj8MDofNLfSeHhDgFJK6koeMOrbzEZIL2SQ7yeSA8WWGgfoajI4V21Wn2bqVtM7D3QYWSIK/Sdvqi0ptfQQ==} engines: {node: '>=18.17.0'} hasBin: true peerDependencies: @@ -1952,8 +1953,8 @@ packages: tailwind-merge@2.5.5: resolution: {integrity: sha512-0LXunzzAZzo0tEPxV3I297ffKZPlKDrjj7NXphC8V5ak9yHC5zRmxnOe2m/Rd/7ivsOMJe3JZ2JVocoDdQTRBA==} - tailwindcss@3.4.15: - resolution: {integrity: sha512-r4MeXnfBmSOuKUWmXe6h2CcyfzJCEk4F0pptO5jlnYSIViUkVmsawj80N5h2lO3gwcmSb4n3PuN+e+GC1Guylw==} + tailwindcss@3.4.16: + resolution: {integrity: sha512-TI4Cyx7gDiZ6r44ewaJmt0o6BrMCT5aK5e0rmJ/G9Xq3w7CX/5VXl/zIPEJZFUK5VEqwByyhqNPycPlvcK4ZNw==} engines: {node: '>=14.0.0'} hasBin: true @@ -2348,33 +2349,33 @@ snapshots: '@napi-rs/simple-git-win32-arm64-msvc': 0.1.19 '@napi-rs/simple-git-win32-x64-msvc': 0.1.19 - '@next/env@14.2.18': {} + '@next/env@14.2.19': {} - '@next/swc-darwin-arm64@14.2.18': + '@next/swc-darwin-arm64@14.2.19': optional: true - '@next/swc-darwin-x64@14.2.18': + '@next/swc-darwin-x64@14.2.19': optional: true - '@next/swc-linux-arm64-gnu@14.2.18': + '@next/swc-linux-arm64-gnu@14.2.19': optional: true - '@next/swc-linux-arm64-musl@14.2.18': + '@next/swc-linux-arm64-musl@14.2.19': optional: true - '@next/swc-linux-x64-gnu@14.2.18': + '@next/swc-linux-x64-gnu@14.2.19': optional: true - '@next/swc-linux-x64-musl@14.2.18': + '@next/swc-linux-x64-musl@14.2.19': optional: true - '@next/swc-win32-arm64-msvc@14.2.18': + '@next/swc-win32-arm64-msvc@14.2.19': optional: true - '@next/swc-win32-ia32-msvc@14.2.18': + '@next/swc-win32-ia32-msvc@14.2.19': optional: true - '@next/swc-win32-x64-msvc@14.2.18': + '@next/swc-win32-x64-msvc@14.2.19': optional: true '@nodelib/fs.scandir@2.1.5': @@ -2756,7 +2757,7 @@ snapshots: caniuse-lite@1.0.30001666: {} - caniuse-lite@1.0.30001680: {} + caniuse-lite@1.0.30001686: {} ccount@2.0.1: {} @@ -3474,9 +3475,7 @@ snapshots: layout-base@2.0.1: {} - lilconfig@2.1.0: {} - - lilconfig@3.1.2: {} + lilconfig@3.1.3: {} lines-and-columns@1.2.4: {} @@ -4045,6 +4044,8 @@ snapshots: nanoid@3.3.7: {} + nanoid@3.3.8: {} + negotiator@1.0.0: {} next-themes@0.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1): @@ -4052,46 +4053,46 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - next@14.2.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next@14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@next/env': 14.2.18 + '@next/env': 14.2.19 '@swc/helpers': 0.5.5 busboy: 1.6.0 - caniuse-lite: 1.0.30001680 + caniuse-lite: 1.0.30001686 graceful-fs: 4.2.11 postcss: 8.4.31 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) styled-jsx: 5.1.1(react@18.3.1) optionalDependencies: - '@next/swc-darwin-arm64': 14.2.18 - '@next/swc-darwin-x64': 14.2.18 - '@next/swc-linux-arm64-gnu': 14.2.18 - '@next/swc-linux-arm64-musl': 14.2.18 - '@next/swc-linux-x64-gnu': 14.2.18 - '@next/swc-linux-x64-musl': 14.2.18 - '@next/swc-win32-arm64-msvc': 14.2.18 - '@next/swc-win32-ia32-msvc': 14.2.18 - '@next/swc-win32-x64-msvc': 14.2.18 + '@next/swc-darwin-arm64': 14.2.19 + '@next/swc-darwin-x64': 14.2.19 + '@next/swc-linux-arm64-gnu': 14.2.19 + '@next/swc-linux-arm64-musl': 14.2.19 + '@next/swc-linux-x64-gnu': 14.2.19 + '@next/swc-linux-x64-musl': 14.2.19 + '@next/swc-win32-arm64-msvc': 14.2.19 + '@next/swc-win32-ia32-msvc': 14.2.19 + '@next/swc-win32-x64-msvc': 14.2.19 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros - nextra-theme-docs@3.2.4(next@14.2.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + nextra-theme-docs@3.2.4(next@14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@headlessui/react': 2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) clsx: 2.1.1 escape-string-regexp: 5.0.0 flexsearch: 0.7.43 - next: 14.2.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-themes: 0.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - nextra: 3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2) + nextra: 3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) scroll-into-view-if-needed: 3.1.0 zod: 3.23.8 - nextra@3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2): + nextra@3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2): dependencies: '@formatjs/intl-localematcher': 0.5.8 '@headlessui/react': 2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -4114,7 +4115,7 @@ snapshots: mdast-util-gfm: 3.0.0 mdast-util-to-hast: 13.2.0 negotiator: 1.0.0 - next: 14.2.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) p-limit: 6.1.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -4256,7 +4257,7 @@ snapshots: postcss-load-config@4.0.2(postcss@8.4.49): dependencies: - lilconfig: 3.1.2 + lilconfig: 3.1.3 yaml: 2.6.1 optionalDependencies: postcss: 8.4.49 @@ -4275,7 +4276,7 @@ snapshots: postcss@8.4.31: dependencies: - nanoid: 3.3.7 + nanoid: 3.3.8 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -4622,7 +4623,7 @@ snapshots: tailwind-merge@2.5.5: {} - tailwindcss@3.4.15: + tailwindcss@3.4.16: dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -4633,7 +4634,7 @@ snapshots: glob-parent: 6.0.2 is-glob: 4.0.3 jiti: 1.21.6 - lilconfig: 2.1.0 + lilconfig: 3.1.3 micromatch: 4.0.8 normalize-path: 3.0.0 object-hash: 3.0.0 From 242be5e22a762c2fb4159a56b44c4afe78882e9d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 08:39:47 +0800 Subject: [PATCH 12/12] chore(deps): update docs - minor revisions (#302) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- docs/pnpm-lock.yaml | 102 ++++++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/docs/pnpm-lock.yaml b/docs/pnpm-lock.yaml index bc3471e04..b34fa25e2 100644 --- a/docs/pnpm-lock.yaml +++ b/docs/pnpm-lock.yaml @@ -16,13 +16,13 @@ importers: version: 0.462.0(react@18.3.1) next: specifier: ^14.2.14 - version: 14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1) nextra: specifier: ^3.0.8 - version: 3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2) + version: 3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2) nextra-theme-docs: specifier: ^3.0.8 - version: 3.2.4(next@14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 3.2.4(next@14.2.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: 18.3.1 version: 18.3.1 @@ -238,59 +238,59 @@ packages: resolution: {integrity: sha512-jMxvwzkKzd3cXo2EB9GM2ic0eYo2rP/BS6gJt6HnWbsDO1O8GSD4k7o2Cpr2YERtMpGF/MGcDfsfj2EbQPtrXw==} engines: {node: '>= 10'} - '@next/env@14.2.19': - resolution: {integrity: sha512-8yWSNi1p+AOsd1QsxZMMkXtdrz8wvYoRxoUa9olmHBspHVLnxpptyKoI574ZF90yq1gXv/CqpchVLBoK8RcN7w==} + '@next/env@14.2.20': + resolution: {integrity: sha512-JfDpuOCB0UBKlEgEy/H6qcBSzHimn/YWjUHzKl1jMeUO+QVRdzmTTl8gFJaNO87c8DXmVKhFCtwxQ9acqB3+Pw==} - '@next/swc-darwin-arm64@14.2.19': - resolution: {integrity: sha512-mL0Nn2PNKV0L++F1l69wY3ySCg9ryw9NtvPhAXm952wpxLVWCCDkVb6XTtOeicF8EdstbjZyLRBflEHtv/Wk2w==} + '@next/swc-darwin-arm64@14.2.20': + resolution: {integrity: sha512-WDfq7bmROa5cIlk6ZNonNdVhKmbCv38XteVFYsxea1vDJt3SnYGgxLGMTXQNfs5OkFvAhmfKKrwe7Y0Hs+rWOg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@14.2.19': - resolution: {integrity: sha512-2HWOTmk+qNa5R+NW8+752jye5JXlQVkGTf6IV+cT2+q3YeRYQPoqYcIr9KSlB8pvgqRqtIGHcioZFvWSeXjxVA==} + '@next/swc-darwin-x64@14.2.20': + resolution: {integrity: sha512-XIQlC+NAmJPfa2hruLvr1H1QJJeqOTDV+v7tl/jIdoFvqhoihvSNykLU/G6NMgoeo+e/H7p/VeWSOvMUHKtTIg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@14.2.19': - resolution: {integrity: sha512-tlbHT+Chnjqh9gSrNNrDAnqFHkoA++wI829bTawoLwAPemji57/qhDp88YteTuUN3rd4U3FcV0f9qiZbyMStFQ==} + '@next/swc-linux-arm64-gnu@14.2.20': + resolution: {integrity: sha512-pnzBrHTPXIMm5QX3QC8XeMkpVuoAYOmyfsO4VlPn+0NrHraNuWjdhe+3xLq01xR++iCvX+uoeZmJDKcOxI201Q==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@14.2.19': - resolution: {integrity: sha512-v0FD7DDS1yapnJw8JuvvePlqxyNY+OKrfoVDvibc+9ADVVzbINkHTCXIDshMXy/rBKheUpkycgS1lOaovgZQ5Q==} + '@next/swc-linux-arm64-musl@14.2.20': + resolution: {integrity: sha512-WhJJAFpi6yqmUx1momewSdcm/iRXFQS0HU2qlUGlGE/+98eu7JWLD5AAaP/tkK1mudS/rH2f9E3WCEF2iYDydQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@14.2.19': - resolution: {integrity: sha512-S+DneEj0Knv8+cilSn8ZP+xU/926eeeueZ4DjQcFy3hZT+2R29wTYBnDeUk+FCVchjzD9s0dvWff6eHDYrJoSA==} + '@next/swc-linux-x64-gnu@14.2.20': + resolution: {integrity: sha512-ao5HCbw9+iG1Kxm8XsGa3X174Ahn17mSYBQlY6VGsdsYDAbz/ZP13wSLfvlYoIDn1Ger6uYA+yt/3Y9KTIupRg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@14.2.19': - resolution: {integrity: sha512-RwczHg2q4n4Ls9PJtBDlBNkfl6G7Fd4uvSRIXPM6Inw52q8R+oWduvuqdzlvcygnv78wt1yrQI14ZRiU0BjgVw==} + '@next/swc-linux-x64-musl@14.2.20': + resolution: {integrity: sha512-CXm/kpnltKTT7945np6Td3w7shj/92TMRPyI/VvveFe8+YE+/YOJ5hyAWK5rpx711XO1jBCgXl211TWaxOtkaA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@14.2.19': - resolution: {integrity: sha512-42YlHVSq3q1nTxLkikG2dRUsKM6vq8v0jrxbR1M6vlgprWlIoXme31g3SpJvVp52v1SfE9WbyAegQxfSIENDSQ==} + '@next/swc-win32-arm64-msvc@14.2.20': + resolution: {integrity: sha512-upJn2HGQgKNDbXVfIgmqT2BN8f3z/mX8ddoyi1I565FHbfowVK5pnMEwauvLvaJf4iijvuKq3kw/b6E9oIVRWA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-ia32-msvc@14.2.19': - resolution: {integrity: sha512-xMEXItVFcT7fV6ndcfnT4ZHm3R0C8398tiC3KInsK+511Or9Jq5G7zagz8aonNRKZkw15zdM1txRslSMRHe4mA==} + '@next/swc-win32-ia32-msvc@14.2.20': + resolution: {integrity: sha512-igQW/JWciTGJwj3G1ipalD2V20Xfx3ywQy17IV0ciOUBbFhNfyU1DILWsTi32c8KmqgIDviUEulW/yPb2FF90w==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] - '@next/swc-win32-x64-msvc@14.2.19': - resolution: {integrity: sha512-bOkmujDRcqbHO2Mxun7SogL1fwzGT/PYqFZ0+aTBjmkhGhx7V/Dun4MNjnxJEGByGNg2EcwdWzsYcRUnHs8Ivg==} + '@next/swc-win32-x64-msvc@14.2.20': + resolution: {integrity: sha512-AFmqeLW6LtxeFTuoB+MXFeM5fm5052i3MU6xD0WzJDOwku6SkZaxb1bxjBaRC8uNqTRTSPl0yMFtjNowIVI67w==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -1521,8 +1521,8 @@ packages: react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - next@14.2.19: - resolution: {integrity: sha512-YTOWj8MDofNLfSeHhDgFJK6koeMOrbzEZIL2SQ7yeSA8WWGgfoajI4V21Wn2bqVtM7D3QYWSIK/Sdvqi0ptfQQ==} + next@14.2.20: + resolution: {integrity: sha512-yPvIiWsiyVYqJlSQxwmzMIReXn5HxFNq4+tlVQ812N1FbvhmE+fDpIAD7bcS2mGYQwPJ5vAsQouyme2eKsxaug==} engines: {node: '>=18.17.0'} hasBin: true peerDependencies: @@ -2349,33 +2349,33 @@ snapshots: '@napi-rs/simple-git-win32-arm64-msvc': 0.1.19 '@napi-rs/simple-git-win32-x64-msvc': 0.1.19 - '@next/env@14.2.19': {} + '@next/env@14.2.20': {} - '@next/swc-darwin-arm64@14.2.19': + '@next/swc-darwin-arm64@14.2.20': optional: true - '@next/swc-darwin-x64@14.2.19': + '@next/swc-darwin-x64@14.2.20': optional: true - '@next/swc-linux-arm64-gnu@14.2.19': + '@next/swc-linux-arm64-gnu@14.2.20': optional: true - '@next/swc-linux-arm64-musl@14.2.19': + '@next/swc-linux-arm64-musl@14.2.20': optional: true - '@next/swc-linux-x64-gnu@14.2.19': + '@next/swc-linux-x64-gnu@14.2.20': optional: true - '@next/swc-linux-x64-musl@14.2.19': + '@next/swc-linux-x64-musl@14.2.20': optional: true - '@next/swc-win32-arm64-msvc@14.2.19': + '@next/swc-win32-arm64-msvc@14.2.20': optional: true - '@next/swc-win32-ia32-msvc@14.2.19': + '@next/swc-win32-ia32-msvc@14.2.20': optional: true - '@next/swc-win32-x64-msvc@14.2.19': + '@next/swc-win32-x64-msvc@14.2.20': optional: true '@nodelib/fs.scandir@2.1.5': @@ -4053,9 +4053,9 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - next@14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next@14.2.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@next/env': 14.2.19 + '@next/env': 14.2.20 '@swc/helpers': 0.5.5 busboy: 1.6.0 caniuse-lite: 1.0.30001686 @@ -4065,34 +4065,34 @@ snapshots: react-dom: 18.3.1(react@18.3.1) styled-jsx: 5.1.1(react@18.3.1) optionalDependencies: - '@next/swc-darwin-arm64': 14.2.19 - '@next/swc-darwin-x64': 14.2.19 - '@next/swc-linux-arm64-gnu': 14.2.19 - '@next/swc-linux-arm64-musl': 14.2.19 - '@next/swc-linux-x64-gnu': 14.2.19 - '@next/swc-linux-x64-musl': 14.2.19 - '@next/swc-win32-arm64-msvc': 14.2.19 - '@next/swc-win32-ia32-msvc': 14.2.19 - '@next/swc-win32-x64-msvc': 14.2.19 + '@next/swc-darwin-arm64': 14.2.20 + '@next/swc-darwin-x64': 14.2.20 + '@next/swc-linux-arm64-gnu': 14.2.20 + '@next/swc-linux-arm64-musl': 14.2.20 + '@next/swc-linux-x64-gnu': 14.2.20 + '@next/swc-linux-x64-musl': 14.2.20 + '@next/swc-win32-arm64-msvc': 14.2.20 + '@next/swc-win32-ia32-msvc': 14.2.20 + '@next/swc-win32-x64-msvc': 14.2.20 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros - nextra-theme-docs@3.2.4(next@14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + nextra-theme-docs@3.2.4(next@14.2.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@headlessui/react': 2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) clsx: 2.1.1 escape-string-regexp: 5.0.0 flexsearch: 0.7.43 - next: 14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-themes: 0.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - nextra: 3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2) + nextra: 3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) scroll-into-view-if-needed: 3.1.0 zod: 3.23.8 - nextra@3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2): + nextra@3.2.4(@types/react@18.3.3)(acorn@8.14.0)(next@14.2.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2): dependencies: '@formatjs/intl-localematcher': 0.5.8 '@headlessui/react': 2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -4115,7 +4115,7 @@ snapshots: mdast-util-gfm: 3.0.0 mdast-util-to-hast: 13.2.0 negotiator: 1.0.0 - next: 14.2.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1) p-limit: 6.1.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1)