diff --git a/docs/pages/docs/overlay/_meta.ts b/docs/pages/docs/overlay/_meta.ts new file mode 100644 index 000000000..1ec888077 --- /dev/null +++ b/docs/pages/docs/overlay/_meta.ts @@ -0,0 +1,8 @@ +export default { + dialog: 'Dialog', + sheet: 'Sheet', + 'persistent-sheet': 'Persistent Sheet', + popover: 'Popover', + 'popover-menu': 'Popover Menu', + tooltip: 'Tooltip', +}; diff --git a/docs/pages/docs/overlay/persistent-sheet.mdx b/docs/pages/docs/overlay/persistent-sheet.mdx new file mode 100644 index 000000000..fe7ff98cf --- /dev/null +++ b/docs/pages/docs/overlay/persistent-sheet.mdx @@ -0,0 +1,395 @@ +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"; + +# Persistent Sheet + +A persistent sheet is displayed above another widget while still allowing users to interact with the widget below. +It is part of [FScaffold](/docs/layout/scaffold), which should be preferred in most cases. + + + + + + + A closely related widget is a [modal sheet](/docs/overlay/sheet) which prevents the user from interacting with the + rest of the app. + + + + All calls to `showFPersistentSheet(...)` should be made inside widgets that have either `FScaffold` or `FSheets` as + their ancestor. + + + + + + + + ```dart + class Sheets extends StatefulWidget { + @override + State createState() => _State(); + } + + class _State extends State { + final Map _controllers = {}; + + @override + Widget build(BuildContext context) { + VoidCallback onPress(Layout side) => () { + for (final MapEntry(:key, :value) in _controllers.entries) { + if (key != side && value.shown) { + return; + } + } + + var controller = _controllers[side]; + if (controller == null) { + controller = _controllers[side] ??= showFPersistentSheet( + context: context, + side: Layout.ltr, + builder: (context, controller) => Form(side: side, controller: controller), + ); + } else { + controller.toggle(); + } + }; + + return FScaffold( // This can be replaced with FSheets + content: Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + FButton( + label: const Text('Left'), + onPress: onPress(Layout.ltr), + ), + const SizedBox(height: 5), + FButton( + label: const Text('Top'), + onPress: onPress(Layout.ttb), + ), + const SizedBox(height: 5), + FButton( + label: const Text('Right'), + onPress: onPress(Layout.rtl), + ), + const SizedBox(height: 5), + FButton( + label: const Text('Bottom'), + onPress: onPress(Layout.btt), + ), + ], + ), + ); + } + } + + class Form extends StatelessWidget { + final Layout side; + final FSheetController controller; + + const Form({required this.side, required this.controller, super.key}); + + @override + Widget build(BuildContext context) => Container( + height: double.infinity, + width: double.infinity, + decoration: BoxDecoration( + color: context.theme.colorScheme.background, + border: side.vertical + ? Border.symmetric(horizontal: BorderSide(color: context.theme.colorScheme.border)) + : Border.symmetric(vertical: BorderSide(color: context.theme.colorScheme.border)), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8.0), + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Account', + style: context.theme.typography.xl2.copyWith( + fontWeight: FontWeight.w600, + color: context.theme.colorScheme.foreground, + height: 1.5, + ), + ), + Text( + 'Make changes to your account here. Click save when you are done.', + style: context.theme.typography.sm.copyWith( + color: context.theme.colorScheme.mutedForeground, + ), + ), + const SizedBox(height: 8), + SizedBox( + width: 450, + child: Column( + children: [ + const FTextField( + label: Text('Name'), + hint: 'John Renalo', + ), + const SizedBox(height: 10), + const FTextField( + label: Text('Email'), + hint: 'john@doe.com', + ), + const SizedBox(height: 16), + FButton( + label: const Text('Save'), + onPress: () => Navigator.of(context).pop(), + ), + ], + ), + ), + ], + ), + ), + ), + ); + + @override + void dispose() { + for (final controller in _controllers.values) { + controller.dispose(); + } + super.dispose(); + } + } + ``` + + + +## Usage + +### `showFPersistentSheet(...)` + +```dart +showFPersistentSheet( + context: context, + side: Layout.ltr, + useRootNavigator: true, + useSafeArea: false, + keepAliveOffstage: true, + mainAxisMaxRatio: null, + constraints: const BoxConstraints(maxWidth: 450, maxHeight: 450), + draggable: true, + builder: (context) => const Placeholder(), +); +``` + +## Examples + +### With `KeepAliveOffstage` + + + + + + + ```dart {23} + class Sheets extends StatefulWidget { + @override + State createState() => _State(); + } + + class _State extends State { + final Map _controllers = {}; + + @override + Widget build(BuildContext context) { + VoidCallback onPress(Layout side) => () { + for (final MapEntry(:key, :value) in _controllers.entries) { + if (key != side && value.shown) { + return; + } + } + + var controller = _controllers[side]; + if (controller == null) { + controller = _controllers[side] ??= showFPersistentSheet( + context: context, + side: Layout.ltr, + keepAliveOffstage: true, + builder: (context, controller) => Form(side: side, controller: controller), + ); + } else { + controller.toggle(); + } + }; + + return FScaffold( // This can be replaced with FSheets + content: Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + FButton( + label: const Text('Left'), + onPress: onPress(Layout.ltr), + ), + const SizedBox(height: 5), + FButton( + label: const Text('Top'), + onPress: onPress(Layout.ttb), + ), + const SizedBox(height: 5), + FButton( + label: const Text('Right'), + onPress: onPress(Layout.rtl), + ), + const SizedBox(height: 5), + FButton( + label: const Text('Bottom'), + onPress: onPress(Layout.btt), + ), + ], + ), + ); + } + } + + class Form extends StatelessWidget { + final Layout side; + final FSheetController controller; + + const Form({required this.side, required this.controller, super.key}); + + @override + Widget build(BuildContext context) => Container( + height: double.infinity, + width: double.infinity, + decoration: BoxDecoration( + color: context.theme.colorScheme.background, + border: side.vertical + ? Border.symmetric(horizontal: BorderSide(color: context.theme.colorScheme.border)) + : Border.symmetric(vertical: BorderSide(color: context.theme.colorScheme.border)), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8.0), + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Account', + style: context.theme.typography.xl2.copyWith( + fontWeight: FontWeight.w600, + color: context.theme.colorScheme.foreground, + height: 1.5, + ), + ), + Text( + 'Make changes to your account here. Click save when you are done.', + style: context.theme.typography.sm.copyWith( + color: context.theme.colorScheme.mutedForeground, + ), + ), + const SizedBox(height: 8), + SizedBox( + width: 450, + child: Column( + children: [ + const FTextField( + label: Text('Name'), + hint: 'John Renalo', + ), + const SizedBox(height: 10), + const FTextField( + label: Text('Email'), + hint: 'john@doe.com', + ), + const SizedBox(height: 16), + FButton( + label: const Text('Save'), + onPress: () => Navigator.of(context).pop(), + ), + ], + ), + ), + ], + ), + ), + ), + ); + + @override + void dispose() { + for (final controller in _controllers.values) { + controller.dispose(); + } + super.dispose(); + } + } + ``` + + + +### With `DraggableScrollableSheet` + + + + + + + ```dart {23-41} + class DraggableSheets extends StatefulWidget { + @override + State createState() => _State(); + } + + class _State extends State { + FSheetController? controller; + + @override + Widget build(BuildContext context) => FScaffold( + content: FButton( + label: const Text('Click me'), + onPress: () { + if (controller != null) { + controller!.toggle(); + return; + } + + controller = showFPersistentSheet( + context: context, + side: Layout.btt, + mainAxisMaxRatio: null, + builder: (context, _) => DraggableScrollableSheet( + expand: false, + builder: (context, controller) => ScrollConfiguration( + // This is required to enable dragging on desktop. + // See https://github.com/flutter/flutter/issues/101903 for more information. + behavior: ScrollConfiguration.of(context).copyWith( + dragDevices: { + PointerDeviceKind.touch, + PointerDeviceKind.mouse, + PointerDeviceKind.trackpad, + }, + ), + child: FTileGroup.builder( + count: 25, + controller: controller, + tileBuilder: (context, index) => FTile(title: Text('Tile $index')), + ), + ), + ), + ); + }, + ), + ); + + @override + void dispose() { + controller?.dispose(); + super.dispose(); + } + } + ``` + + + diff --git a/docs/pages/docs/overlay/popover.mdx b/docs/pages/docs/overlay/popover.mdx index 78a43ecd3..4b77dc6bd 100644 --- a/docs/pages/docs/overlay/popover.mdx +++ b/docs/pages/docs/overlay/popover.mdx @@ -105,7 +105,7 @@ const FPopover( ); ``` -### `FPopover.tappable()`. +### `FPopover.tappable()` ```dart const FPopover.tappable( diff --git a/docs/pages/docs/overlay/sheet.mdx b/docs/pages/docs/overlay/sheet.mdx new file mode 100644 index 000000000..1b480ffd4 --- /dev/null +++ b/docs/pages/docs/overlay/sheet.mdx @@ -0,0 +1,195 @@ +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"; + +# Sheet + +A modal sheet is an alternative to a menu or a dialog and prevents the user from interacting with the rest of the app. +It navigates to a new page each time. + + + + + + + A closely related widget is a [persistent sheet](/docs/overlay/persistent-sheet), which shows information that + supplements the primary content of the app without preventing the user from interacting with the app. + + + + + + + + ```dart + class ModalSheet extends StatelessWidget { + @override + Widget build(BuildContext context) => Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + FButton( + label: const Text('Left'), + onPress: () => showFSheet( + context: context, + side: Layout.ltr, + builder: (context) => const Form(side: Layout.ltr), + ), + ), + const SizedBox(height: 5), + FButton( + label: const Text('Top'), + onPress: () => showFSheet( + context: context, + side: Layout.ttb, + builder: (context) => const Form(side: Layout.ttb), + ), + ), + const SizedBox(height: 5), + FButton( + label: const Text('Right'), + onPress: () => showFSheet( + context: context, + side: Layout.rtl, + builder: (context) => const Form(side: Layout.btt), + ), + ), + const SizedBox(height: 5), + FButton( + label: const Text('Bottom'), + onPress: () => showFSheet( + context: context, + side: Layout.btt, + builder: (context) => const Form(side: Layout.btt), + ), + ), + ], + ); + } + + class Form extends StatelessWidget { + final Layout side; + + const Form({required this.side, super.key}); + + @override + Widget build(BuildContext context) => Container( + height: double.infinity, + width: double.infinity, + decoration: BoxDecoration( + color: context.theme.colorScheme.background, + border: side.vertical + ? Border.symmetric(horizontal: BorderSide(color: context.theme.colorScheme.border)) + : Border.symmetric(vertical: BorderSide(color: context.theme.colorScheme.border)), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8.0), + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Account', + style: context.theme.typography.xl2.copyWith( + fontWeight: FontWeight.w600, + color: context.theme.colorScheme.foreground, + height: 1.5, + ), + ), + Text( + 'Make changes to your account here. Click save when you are done.', + style: context.theme.typography.sm.copyWith( + color: context.theme.colorScheme.mutedForeground, + ), + ), + const SizedBox(height: 8), + SizedBox( + width: 450, + child: Column( + children: [ + const FTextField( + label: Text('Name'), + hint: 'John Renalo', + ), + const SizedBox(height: 10), + const FTextField( + label: Text('Email'), + hint: 'john@doe.com', + ), + const SizedBox(height: 16), + FButton( + label: const Text('Save'), + onPress: () => Navigator.of(context).pop(), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } + ``` + + + +## Usage + +### `showFSheet(...)` + +```dart +showFSheet( + context: context, + side: Layout.ltr, + useRootNavigator: true, + useSafeArea: false, + mainAxisMaxRatio: null, + constraints: const BoxConstraints(maxWidth: 450, maxHeight: 450), + barrierDismissible: true, + draggable: true, + builder: (context) => const Placeholder(), +); +``` + +## Examples + +### With `DraggableScrollableSheet` + + + + + + + ```dart {9-22} + FButton( + label: const Text('Click me'), + onPress: () => showFModalSheet( + context: context, + side: Layout.btt, + mainAxisMaxRatio: null, + builder: (context) => DraggableScrollableSheet( + expand: false, + builder: (context, controller) => ScrollConfiguration( + // This is required to enable dragging on desktop. + // See https://github.com/flutter/flutter/issues/101903 for more information. + behavior: ScrollConfiguration.of(context).copyWith(dragDevices: { + PointerDeviceKind.touch, + PointerDeviceKind.mouse, + PointerDeviceKind.trackpad, + }), + child: FTileGroup.builder( + count: 25, + controller: controller, + tileBuilder: (context, index) => FTile(title: Text('Tile $index')), + ), + ), + ), + ), + ); + ``` + + + diff --git a/forui/CHANGELOG.md b/forui/CHANGELOG.md index 6505e7c0c..fe9a3f42a 100644 --- a/forui/CHANGELOG.md +++ b/forui/CHANGELOG.md @@ -2,6 +2,16 @@ ### Additions +* Add `showFSheet(...)`. + +* Add `showFModalSheet(...)`. + +* Add `FModalSheetRoute`. + +* Add `FSheets`. + +* Add `FSheets` internally to `FScaffold`. + * Add `truncateAndStripTimezone` to `FCalendarController.date(...)`. * Add `truncateAndStripTimezone` to `FCalendarController.dates(...)`. diff --git a/forui/example/lib/sandbox.dart b/forui/example/lib/sandbox.dart index 5a7ed9f80..74e9f45f5 100644 --- a/forui/example/lib/sandbox.dart +++ b/forui/example/lib/sandbox.dart @@ -13,14 +13,12 @@ class Sandbox extends StatefulWidget { class _SandboxState extends State with SingleTickerProviderStateMixin { final GlobalKey _formKey = GlobalKey(); - final FRadioSelectGroupController controller = FRadioSelectGroupController(); - late FPopoverController popoverController; - late FCalendarController a = FCalendarController.date(); + late AnimationController controller; @override void initState() { super.initState(); - popoverController = FPopoverController(vsync: this); + controller = AnimationController(vsync: this, duration: const Duration(milliseconds: 300)); } @override @@ -29,7 +27,16 @@ class _SandboxState extends State with SingleTickerProviderStateMixin { child: Column( mainAxisSize: MainAxisSize.min, children: [ - FCalendar(controller: a), + FButton( + label: const Text('Click me'), + onPress: () => showFSheet( + context: context, + side: Layout.ltr, + builder: (context) => ListView.builder( + itemBuilder: (context, index) => FTile(title: Text('Tile $index')), + ), + ), + ), ], ), ); @@ -40,3 +47,68 @@ class _SandboxState extends State with SingleTickerProviderStateMixin { super.dispose(); } } + +class AForm extends StatelessWidget { + final Layout side; + + const AForm({required this.side, super.key}); + + @override + Widget build(BuildContext context) => Container( + height: double.infinity, + width: double.infinity, + decoration: BoxDecoration( + color: context.theme.colorScheme.background, + border: side.vertical + ? Border.symmetric(horizontal: BorderSide(color: context.theme.colorScheme.border)) + : Border.symmetric(vertical: BorderSide(color: context.theme.colorScheme.border)), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8.0), + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Account', + style: context.theme.typography.xl2.copyWith( + fontWeight: FontWeight.w600, + color: context.theme.colorScheme.foreground, + height: 1.5, + ), + ), + Text( + 'Make changes to your account here. Click save when you are done.', + style: context.theme.typography.sm.copyWith( + color: context.theme.colorScheme.mutedForeground, + ), + ), + const SizedBox(height: 8), + SizedBox( + width: 450, + child: Column( + children: [ + const FTextField( + label: Text('Name'), + hint: 'John Renalo', + ), + const SizedBox(height: 10), + const FTextField( + label: Text('Email'), + hint: 'john@doe.com', + ), + const SizedBox(height: 16), + FButton( + label: const Text('Save'), + onPress: () => Navigator.of(context).pop(), + ), + ], + ), + ), + ], + ), + ), + ), + ); +} diff --git a/forui/example/pubspec.lock b/forui/example/pubspec.lock index 498cffe37..b35981699 100644 --- a/forui/example/pubspec.lock +++ b/forui/example/pubspec.lock @@ -236,10 +236,10 @@ packages: dependency: transitive description: name: flutter_svg - sha256: "936d9c1c010d3e234d1672574636f3352b4941ca3decaddd3cafaeb9ad49c471" + sha256: "54900a1a1243f3c4a5506d853a2b5c2dbc38d5f27e52a52618a8054401431123" url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.0.16" flutter_test: dependency: "direct dev" description: flutter @@ -501,18 +501,18 @@ packages: dependency: transitive description: name: path_provider_android - sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a + sha256: "8c4967f8b7cb46dc914e178daa29813d83ae502e0529d7b0478330616a691ef7" url: "https://pub.dev" source: hosted - version: "2.2.12" + version: "2.2.14" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 + sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" path_provider_linux: dependency: transitive description: @@ -714,10 +714,10 @@ packages: dependency: transitive description: name: vector_graphics_compiler - sha256: ab9ff38fc771e9ee1139320adbe3d18a60327370c218c60752068ebee4b49ab1 + sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad" url: "https://pub.dev" source: hosted - version: "1.1.15" + version: "1.1.16" vector_math: dependency: transitive description: @@ -786,10 +786,10 @@ packages: dependency: transitive description: name: win32 - sha256: "84ba388638ed7a8cb3445a320c8273136ab2631cd5f2c57888335504ddab1bc2" + sha256: "8b338d4486ab3fbc0ba0db9f9b4f5239b6697fcee427939a40e720cbb9ee0a69" url: "https://pub.dev" source: hosted - version: "5.8.0" + version: "5.9.0" xdg_directories: dependency: transitive description: diff --git a/forui/lib/forui.dart b/forui/lib/forui.dart index 321df3e39..ebfc5ef7e 100644 --- a/forui/lib/forui.dart +++ b/forui/lib/forui.dart @@ -29,6 +29,7 @@ export 'widgets/scaffold.dart'; export 'widgets/select_group.dart'; export 'widgets/select_menu_tile.dart'; export 'widgets/select_tile_group.dart'; +export 'widgets/sheet.dart'; export 'widgets/slider.dart'; export 'widgets/switch.dart'; export 'widgets/tabs.dart'; diff --git a/forui/lib/l10n/f_af.arb b/forui/lib/l10n/f_af.arb index 9e26dfeeb..f4f7030e8 100644 --- a/forui/lib/l10n/f_af.arb +++ b/forui/lib/l10n/f_af.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialoog", + "sheetLabel": "blad", + "barrierOnTapHint": "Maak $modalRouteContentName toe", + "barrierLabel": "Skerm" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_am.arb b/forui/lib/l10n/f_am.arb index 9e26dfeeb..447edd405 100644 --- a/forui/lib/l10n/f_am.arb +++ b/forui/lib/l10n/f_am.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "መገናኛ", + "sheetLabel": "ሉህ", + "barrierOnTapHint": "$modalRouteContentNameን ዝጋ", + "barrierLabel": "ገዳቢ" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_ar.arb b/forui/lib/l10n/f_ar.arb index 9e26dfeeb..f76ebe7b4 100644 --- a/forui/lib/l10n/f_ar.arb +++ b/forui/lib/l10n/f_ar.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "مربع حوار", + "sheetLabel": "بطاق ", + "barrierOnTapHint": "إغلاق \"$modalRouteContentName\"", + "barrierLabel": "تمويه" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_as.arb b/forui/lib/l10n/f_as.arb index 9e26dfeeb..fe9b69537 100644 --- a/forui/lib/l10n/f_as.arb +++ b/forui/lib/l10n/f_as.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "ডায়ল'গ", + "sheetLabel": "শ্বীট", + "barrierOnTapHint": "$modalRouteContentName বন্ধ কৰক", + "barrierLabel": "স্ক্ৰিম" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_az.arb b/forui/lib/l10n/f_az.arb index 9e26dfeeb..2b5aa8052 100644 --- a/forui/lib/l10n/f_az.arb +++ b/forui/lib/l10n/f_az.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialoq", + "sheetLabel": "Vərəq", + "barrierOnTapHint": "Bağlayın: $modalRouteContentName", + "barrierLabel": "Kətan" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_be.arb b/forui/lib/l10n/f_be.arb index 9e26dfeeb..12477e0af 100644 --- a/forui/lib/l10n/f_be.arb +++ b/forui/lib/l10n/f_be.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Дыялогавае акно", + "sheetLabel": "аркуш", + "barrierOnTapHint": "Закрыць: $modalRouteContentName", + "barrierLabel": "Палатно" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_bg.arb b/forui/lib/l10n/f_bg.arb index 9e26dfeeb..cacd38976 100644 --- a/forui/lib/l10n/f_bg.arb +++ b/forui/lib/l10n/f_bg.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Диалогов прозорец", + "sheetLabel": "лист", + "barrierOnTapHint": "Затваряне на $modalRouteContentName", + "barrierLabel": "Скрим" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_bn.arb b/forui/lib/l10n/f_bn.arb index 9e26dfeeb..89f4a4767 100644 --- a/forui/lib/l10n/f_bn.arb +++ b/forui/lib/l10n/f_bn.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "ডায়ালগ", + "sheetLabel": "শীট", + "barrierOnTapHint": "$modalRouteContentName বন্ধ করুন", + "barrierLabel": "স্ক্রিম" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_bs.arb b/forui/lib/l10n/f_bs.arb index 9e26dfeeb..180c95998 100644 --- a/forui/lib/l10n/f_bs.arb +++ b/forui/lib/l10n/f_bs.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dijaloški okvir", + "sheetLabel": "tabela", + "barrierOnTapHint": "Zatvori: $modalRouteContentName", + "barrierLabel": "Rubno" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_ca.arb b/forui/lib/l10n/f_ca.arb index 9e26dfeeb..546f23d07 100644 --- a/forui/lib/l10n/f_ca.arb +++ b/forui/lib/l10n/f_ca.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diàleg", + "sheetLabel": "Full", + "barrierOnTapHint": "Tanca $modalRouteContentName", + "barrierLabel": "Fons atenuat" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_cs.arb b/forui/lib/l10n/f_cs.arb index 9e26dfeeb..bac81491f 100644 --- a/forui/lib/l10n/f_cs.arb +++ b/forui/lib/l10n/f_cs.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialogové okno", + "sheetLabel": "tabulka", + "barrierOnTapHint": "Zavřít $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_cy.arb b/forui/lib/l10n/f_cy.arb index 9e26dfeeb..edc096f91 100644 --- a/forui/lib/l10n/f_cy.arb +++ b/forui/lib/l10n/f_cy.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Deialog", + "sheetLabel": "Taflen", + "barrierOnTapHint": "Cau $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_da.arb b/forui/lib/l10n/f_da.arb index 9e26dfeeb..40481e134 100644 --- a/forui/lib/l10n/f_da.arb +++ b/forui/lib/l10n/f_da.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialogboks", + "sheetLabel": "Felt", + "barrierOnTapHint": "Luk $modalRouteContentName", + "barrierLabel": "Dæmpeskærm" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_de.arb b/forui/lib/l10n/f_de.arb index 9e26dfeeb..f78b171c3 100644 --- a/forui/lib/l10n/f_de.arb +++ b/forui/lib/l10n/f_de.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialogfeld", + "sheetLabel": "Ansicht", + "barrierOnTapHint": "$modalRouteContentName schließen", + "barrierLabel": "Gitter" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_de_CH.arb b/forui/lib/l10n/f_de_CH.arb index 9e26dfeeb..6ee866ee2 100644 --- a/forui/lib/l10n/f_de_CH.arb +++ b/forui/lib/l10n/f_de_CH.arb @@ -1 +1,3 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialogfeld" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_el.arb b/forui/lib/l10n/f_el.arb index 9e26dfeeb..fca6c59be 100644 --- a/forui/lib/l10n/f_el.arb +++ b/forui/lib/l10n/f_el.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Παράθυρο διαλόγου", + "sheetLabel": "Φύλλο", + "barrierOnTapHint": "Κλείσιμο $modalRouteContentName", + "barrierLabel": "Επικάλυψη" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_en.arb b/forui/lib/l10n/f_en.arb index 8edaba35a..3e3c7adb5 100644 --- a/forui/lib/l10n/f_en.arb +++ b/forui/lib/l10n/f_en.arb @@ -9,7 +9,6 @@ } } }, - "year": "{date}", "@year": { "description": "The year.", @@ -20,7 +19,6 @@ } } }, - "yearMonth": "{date}", "@yearMonth": { "description": "The year and month.", @@ -31,7 +29,6 @@ } } }, - "abbreviatedMonth": "{date}", "@abbreviatedMonth": { "description": "The abbreviated month.", @@ -42,7 +39,6 @@ } } }, - "day": "{date}", "@day": { "description": "The day of the month.", @@ -52,5 +48,30 @@ "format": "d" } } + }, + + "dialogLabel": "Dialog", + "@dialogLabel": { + "description": "The audio announcement made when a dialog is opened." + }, + + "sheetLabel": "Sheet", + "@dialogLabel": { + "description": "The sheet's label." + }, + + "barrierLabel": "Barrier", + "@barrierLabel": { + "description": "The label for the barrier rendered underneath the content of a bottom sheet (used as the 'modalRouteContentName' of the 'barrierOnTapHint' message)." + }, + + "barrierOnTapHint": "Close {modalRouteContentName}", + "@barrierOnTapHint": { + "description": "The onTapHint for the barrier rendered underneath the content of a modal route (especially a sheet) which users can tap to dismiss the content.", + "placeholders": { + "modalRouteContentName": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/forui/lib/l10n/f_en_AU.arb b/forui/lib/l10n/f_en_AU.arb index 9e26dfeeb..391db18ab 100644 --- a/forui/lib/l10n/f_en_AU.arb +++ b/forui/lib/l10n/f_en_AU.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialogue", + "sheetLabel": "Sheet", + "barrierOnTapHint": "Close $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_en_CA.arb b/forui/lib/l10n/f_en_CA.arb index 9e26dfeeb..f7b78b655 100644 --- a/forui/lib/l10n/f_en_CA.arb +++ b/forui/lib/l10n/f_en_CA.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialog", + "sheetLabel": "Sheet", + "barrierOnTapHint": "Close $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_en_GB.arb b/forui/lib/l10n/f_en_GB.arb index 9e26dfeeb..86e2346a5 100644 --- a/forui/lib/l10n/f_en_GB.arb +++ b/forui/lib/l10n/f_en_GB.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialogue", + "sheetLabel": "sheet", + "barrierOnTapHint": "Close $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_en_IE.arb b/forui/lib/l10n/f_en_IE.arb index 9e26dfeeb..86e2346a5 100644 --- a/forui/lib/l10n/f_en_IE.arb +++ b/forui/lib/l10n/f_en_IE.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialogue", + "sheetLabel": "sheet", + "barrierOnTapHint": "Close $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_en_IN.arb b/forui/lib/l10n/f_en_IN.arb index 9e26dfeeb..86e2346a5 100644 --- a/forui/lib/l10n/f_en_IN.arb +++ b/forui/lib/l10n/f_en_IN.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialogue", + "sheetLabel": "sheet", + "barrierOnTapHint": "Close $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_en_NZ.arb b/forui/lib/l10n/f_en_NZ.arb index 9e26dfeeb..391db18ab 100644 --- a/forui/lib/l10n/f_en_NZ.arb +++ b/forui/lib/l10n/f_en_NZ.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialogue", + "sheetLabel": "Sheet", + "barrierOnTapHint": "Close $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_en_SG.arb b/forui/lib/l10n/f_en_SG.arb index 9e26dfeeb..86e2346a5 100644 --- a/forui/lib/l10n/f_en_SG.arb +++ b/forui/lib/l10n/f_en_SG.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialogue", + "sheetLabel": "sheet", + "barrierOnTapHint": "Close $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_en_ZA.arb b/forui/lib/l10n/f_en_ZA.arb index 9e26dfeeb..86e2346a5 100644 --- a/forui/lib/l10n/f_en_ZA.arb +++ b/forui/lib/l10n/f_en_ZA.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialogue", + "sheetLabel": "sheet", + "barrierOnTapHint": "Close $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es.arb b/forui/lib/l10n/f_es.arb index 9e26dfeeb..ceed48ba3 100644 --- a/forui/lib/l10n/f_es.arb +++ b/forui/lib/l10n/f_es.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Cuadro de diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Sombreado" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_419.arb b/forui/lib/l10n/f_es_419.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_419.arb +++ b/forui/lib/l10n/f_es_419.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_AR.arb b/forui/lib/l10n/f_es_AR.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_AR.arb +++ b/forui/lib/l10n/f_es_AR.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_BO.arb b/forui/lib/l10n/f_es_BO.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_BO.arb +++ b/forui/lib/l10n/f_es_BO.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_CL.arb b/forui/lib/l10n/f_es_CL.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_CL.arb +++ b/forui/lib/l10n/f_es_CL.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_CO.arb b/forui/lib/l10n/f_es_CO.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_CO.arb +++ b/forui/lib/l10n/f_es_CO.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_CR.arb b/forui/lib/l10n/f_es_CR.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_CR.arb +++ b/forui/lib/l10n/f_es_CR.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_DO.arb b/forui/lib/l10n/f_es_DO.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_DO.arb +++ b/forui/lib/l10n/f_es_DO.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_EC.arb b/forui/lib/l10n/f_es_EC.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_EC.arb +++ b/forui/lib/l10n/f_es_EC.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_GT.arb b/forui/lib/l10n/f_es_GT.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_GT.arb +++ b/forui/lib/l10n/f_es_GT.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_HN.arb b/forui/lib/l10n/f_es_HN.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_HN.arb +++ b/forui/lib/l10n/f_es_HN.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_MX.arb b/forui/lib/l10n/f_es_MX.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_MX.arb +++ b/forui/lib/l10n/f_es_MX.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_NI.arb b/forui/lib/l10n/f_es_NI.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_NI.arb +++ b/forui/lib/l10n/f_es_NI.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_PA.arb b/forui/lib/l10n/f_es_PA.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_PA.arb +++ b/forui/lib/l10n/f_es_PA.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_PE.arb b/forui/lib/l10n/f_es_PE.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_PE.arb +++ b/forui/lib/l10n/f_es_PE.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_PR.arb b/forui/lib/l10n/f_es_PR.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_PR.arb +++ b/forui/lib/l10n/f_es_PR.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_PY.arb b/forui/lib/l10n/f_es_PY.arb index 9e26dfeeb..62ae3b26a 100644 --- a/forui/lib/l10n/f_es_PY.arb +++ b/forui/lib/l10n/f_es_PY.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "inferior", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_SV.arb b/forui/lib/l10n/f_es_SV.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_SV.arb +++ b/forui/lib/l10n/f_es_SV.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_US.arb b/forui/lib/l10n/f_es_US.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_US.arb +++ b/forui/lib/l10n/f_es_US.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_UY.arb b/forui/lib/l10n/f_es_UY.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_UY.arb +++ b/forui/lib/l10n/f_es_UY.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_es_VE.arb b/forui/lib/l10n/f_es_VE.arb index 9e26dfeeb..e1a646c6b 100644 --- a/forui/lib/l10n/f_es_VE.arb +++ b/forui/lib/l10n/f_es_VE.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Diálogo", + "sheetLabel": "Hoja", + "barrierOnTapHint": "Cerrar $modalRouteContentName", + "barrierLabel": "Lámina" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_et.arb b/forui/lib/l10n/f_et.arb index 9e26dfeeb..e3230789a 100644 --- a/forui/lib/l10n/f_et.arb +++ b/forui/lib/l10n/f_et.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialoog", + "sheetLabel": "leht", + "barrierOnTapHint": "Sule $modalRouteContentName", + "barrierLabel": "Sirm" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_eu.arb b/forui/lib/l10n/f_eu.arb index 9e26dfeeb..289e77f0a 100644 --- a/forui/lib/l10n/f_eu.arb +++ b/forui/lib/l10n/f_eu.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Leihoa", + "sheetLabel": "orria", + "barrierOnTapHint": "Itxi $modalRouteContentName", + "barrierLabel": "Barrera" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_fa.arb b/forui/lib/l10n/f_fa.arb index 9e26dfeeb..1bba83e29 100644 --- a/forui/lib/l10n/f_fa.arb +++ b/forui/lib/l10n/f_fa.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "کادر گفتگو", + "sheetLabel": "برگ", + "barrierOnTapHint": "بستن $modalRouteContentName", + "barrierLabel": "رویه" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_fi.arb b/forui/lib/l10n/f_fi.arb index 9e26dfeeb..3b8597aa3 100644 --- a/forui/lib/l10n/f_fi.arb +++ b/forui/lib/l10n/f_fi.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Valintaikkuna", + "sheetLabel": "arkki", + "barrierOnTapHint": "Sulje $modalRouteContentName", + "barrierLabel": "Sermi" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_fil.arb b/forui/lib/l10n/f_fil.arb index 9e26dfeeb..18d5664e0 100644 --- a/forui/lib/l10n/f_fil.arb +++ b/forui/lib/l10n/f_fil.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialog", + "sheetLabel": "sheet", + "barrierOnTapHint": "Isara ang $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_fr.arb b/forui/lib/l10n/f_fr.arb index 9e26dfeeb..70827c266 100644 --- a/forui/lib/l10n/f_fr.arb +++ b/forui/lib/l10n/f_fr.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Boîte de dialogue", + "sheetLabel": "sheet", + "barrierOnTapHint": "Fermer $modalRouteContentName", + "barrierLabel": "Fond" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_fr_CA.arb b/forui/lib/l10n/f_fr_CA.arb index 9e26dfeeb..42d5aebe2 100644 --- a/forui/lib/l10n/f_fr_CA.arb +++ b/forui/lib/l10n/f_fr_CA.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Boîte de dialogue", + "sheetLabel": "Zone de contenu", + "barrierOnTapHint": "Fermer $modalRouteContentName", + "barrierLabel": "Grille" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_gl.arb b/forui/lib/l10n/f_gl.arb index 9e26dfeeb..614934b89 100644 --- a/forui/lib/l10n/f_gl.arb +++ b/forui/lib/l10n/f_gl.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Cadro de diálogo", + "sheetLabel": "Panel", + "barrierOnTapHint": "Pechar $modalRouteContentName", + "barrierLabel": "Sombreado" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_gsw.arb b/forui/lib/l10n/f_gsw.arb index 9e26dfeeb..f78b171c3 100644 --- a/forui/lib/l10n/f_gsw.arb +++ b/forui/lib/l10n/f_gsw.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialogfeld", + "sheetLabel": "Ansicht", + "barrierOnTapHint": "$modalRouteContentName schließen", + "barrierLabel": "Gitter" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_gu.arb b/forui/lib/l10n/f_gu.arb index 9e26dfeeb..48341219a 100644 --- a/forui/lib/l10n/f_gu.arb +++ b/forui/lib/l10n/f_gu.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "સંવાદ", + "sheetLabel": "શીટ", + "barrierOnTapHint": "$modalRouteContentNameને બંધ કરો", + "barrierLabel": "સ્ક્રિમ" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_he.arb b/forui/lib/l10n/f_he.arb index 9e26dfeeb..43500e149 100644 --- a/forui/lib/l10n/f_he.arb +++ b/forui/lib/l10n/f_he.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "תיבת דו-שיח", + "sheetLabel": "גיליו ", + "barrierOnTapHint": "סגירת $modalRouteContentName", + "barrierLabel": "מיסוך" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_hi.arb b/forui/lib/l10n/f_hi.arb index 9e26dfeeb..ea74f8926 100644 --- a/forui/lib/l10n/f_hi.arb +++ b/forui/lib/l10n/f_hi.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "डायलॉग", + "sheetLabel": "शीट", + "barrierOnTapHint": "$modalRouteContentName को बंद करें", + "barrierLabel": "स्क्रिम" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_hr.arb b/forui/lib/l10n/f_hr.arb index 9e26dfeeb..9c053acf8 100644 --- a/forui/lib/l10n/f_hr.arb +++ b/forui/lib/l10n/f_hr.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dijalog", + "sheetLabel": "tablica", + "barrierOnTapHint": "Zatvori $modalRouteContentName", + "barrierLabel": "Rubno" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_hu.arb b/forui/lib/l10n/f_hu.arb index 9e26dfeeb..6eebb19b8 100644 --- a/forui/lib/l10n/f_hu.arb +++ b/forui/lib/l10n/f_hu.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Párbeszédablak", + "sheetLabel": "lap", + "barrierOnTapHint": "$modalRouteContentName bezárása", + "barrierLabel": "Borítás" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_hy.arb b/forui/lib/l10n/f_hy.arb index 9e26dfeeb..3863ac709 100644 --- a/forui/lib/l10n/f_hy.arb +++ b/forui/lib/l10n/f_hy.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Երկխոսության պատուհան", + "sheetLabel": "էկրան", + "barrierOnTapHint": "Փակել՝ $modalRouteContentName", + "barrierLabel": "Դիմակ" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_id.arb b/forui/lib/l10n/f_id.arb index 9e26dfeeb..2003ad0bb 100644 --- a/forui/lib/l10n/f_id.arb +++ b/forui/lib/l10n/f_id.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialog", + "sheetLabel": "Sheet", + "barrierOnTapHint": "Tutup $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_is.arb b/forui/lib/l10n/f_is.arb index 9e26dfeeb..41bcc1d5d 100644 --- a/forui/lib/l10n/f_is.arb +++ b/forui/lib/l10n/f_is.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Gluggi", + "sheetLabel": "Blað", + "barrierOnTapHint": "Loka $modalRouteContentName", + "barrierLabel": "Möskvi" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_it.arb b/forui/lib/l10n/f_it.arb index 9e26dfeeb..ecdea25c3 100644 --- a/forui/lib/l10n/f_it.arb +++ b/forui/lib/l10n/f_it.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Finestra di dialogo", + "sheetLabel": "Riquadro", + "barrierOnTapHint": "Chiudi $modalRouteContentName", + "barrierLabel": "Rete" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_ja.arb b/forui/lib/l10n/f_ja.arb index 9e26dfeeb..387394461 100644 --- a/forui/lib/l10n/f_ja.arb +++ b/forui/lib/l10n/f_ja.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "ダイアログ", + "sheetLabel": "シート", + "barrierOnTapHint": "$modalRouteContentName を閉じる", + "barrierLabel": "スクリム" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_ka.arb b/forui/lib/l10n/f_ka.arb index 9e26dfeeb..6c43bf503 100644 --- a/forui/lib/l10n/f_ka.arb +++ b/forui/lib/l10n/f_ka.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "დიალოგი", + "sheetLabel": "ფურცელი", + "barrierOnTapHint": "$modalRouteContentName-ის დახურვა", + "barrierLabel": "სკრიმი" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_kk.arb b/forui/lib/l10n/f_kk.arb index 9e26dfeeb..39f2705c3 100644 --- a/forui/lib/l10n/f_kk.arb +++ b/forui/lib/l10n/f_kk.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Диалогтық терезе", + "sheetLabel": "парақша", + "barrierOnTapHint": "$modalRouteContentName жабу", + "barrierLabel": "Кенеп" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_km.arb b/forui/lib/l10n/f_km.arb index 9e26dfeeb..a05eaaa5c 100644 --- a/forui/lib/l10n/f_km.arb +++ b/forui/lib/l10n/f_km.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "ប្រអប់", + "sheetLabel": "សន្លឹក", + "barrierOnTapHint": "បិទ $modalRouteContentName", + "barrierLabel": "ផ្ទាំងស្រអាប់" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_kn.arb b/forui/lib/l10n/f_kn.arb index 9e26dfeeb..aa6bb7374 100644 --- a/forui/lib/l10n/f_kn.arb +++ b/forui/lib/l10n/f_kn.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "ಡೈಲಾಗ್", + "sheetLabel": "ಶೀಟ್", + "barrierOnTapHint": "$modalRouteContentName ಅನ್ನು ಮುಚ್ಚಿರಿ", + "barrierLabel": "ಸ್ಕ್ರಿಮ್" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_ko.arb b/forui/lib/l10n/f_ko.arb index 9e26dfeeb..02f00e4b5 100644 --- a/forui/lib/l10n/f_ko.arb +++ b/forui/lib/l10n/f_ko.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "대화상자", + "sheetLabel": "시트", + "barrierOnTapHint": "$modalRouteContentName 닫기", + "barrierLabel": "스크림" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_ky.arb b/forui/lib/l10n/f_ky.arb index 9e26dfeeb..199d0e5a6 100644 --- a/forui/lib/l10n/f_ky.arb +++ b/forui/lib/l10n/f_ky.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Диалог", + "sheetLabel": "экран", + "barrierOnTapHint": "$modalRouteContentName жабуу", + "barrierLabel": "Кенеп" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_lo.arb b/forui/lib/l10n/f_lo.arb index 9e26dfeeb..6354ddd82 100644 --- a/forui/lib/l10n/f_lo.arb +++ b/forui/lib/l10n/f_lo.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "ຂໍ້ຄວາມ", + "sheetLabel": "ແຜ່ນ", + "barrierOnTapHint": "ປິດ $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_lt.arb b/forui/lib/l10n/f_lt.arb index 9e26dfeeb..f1ed32860 100644 --- a/forui/lib/l10n/f_lt.arb +++ b/forui/lib/l10n/f_lt.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialogo langas", + "sheetLabel": "lapas", + "barrierOnTapHint": "Uždaryti „$modalRouteContentName“", + "barrierLabel": "Užsklanda" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_lv.arb b/forui/lib/l10n/f_lv.arb index 9e26dfeeb..315b722cc 100644 --- a/forui/lib/l10n/f_lv.arb +++ b/forui/lib/l10n/f_lv.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialoglodziņš", + "sheetLabel": "lapa", + "barrierOnTapHint": "Aizvērt $modalRouteContentName", + "barrierLabel": "Pārklājums" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_mk.arb b/forui/lib/l10n/f_mk.arb index 9e26dfeeb..1801cb075 100644 --- a/forui/lib/l10n/f_mk.arb +++ b/forui/lib/l10n/f_mk.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Дијалог", + "sheetLabel": "лист", + "barrierOnTapHint": "Затворете ја $modalRouteContentName", + "barrierLabel": "Скрим" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_ml.arb b/forui/lib/l10n/f_ml.arb index 9e26dfeeb..a22548c84 100644 --- a/forui/lib/l10n/f_ml.arb +++ b/forui/lib/l10n/f_ml.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "ഡയലോഗ്", + "sheetLabel": "ഷീറ്റ്", + "barrierOnTapHint": "$modalRouteContentName അടയ്ക്കുക", + "barrierLabel": "സ്ക്രിം" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_mn.arb b/forui/lib/l10n/f_mn.arb index 9e26dfeeb..822e5e603 100644 --- a/forui/lib/l10n/f_mn.arb +++ b/forui/lib/l10n/f_mn.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Харилцах цонх", + "sheetLabel": "хүснэгт", + "barrierOnTapHint": "$modalRouteContentName-г хаах", + "barrierLabel": "Скрим" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_mr.arb b/forui/lib/l10n/f_mr.arb index 9e26dfeeb..b27d0c1a7 100644 --- a/forui/lib/l10n/f_mr.arb +++ b/forui/lib/l10n/f_mr.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "डायलॉग", + "sheetLabel": "शीट", + "barrierOnTapHint": "$modalRouteContentName बंद करा", + "barrierLabel": "स्क्रिम" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_ms.arb b/forui/lib/l10n/f_ms.arb index 9e26dfeeb..f0d27ddf2 100644 --- a/forui/lib/l10n/f_ms.arb +++ b/forui/lib/l10n/f_ms.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialog", + "sheetLabel": "Helaian", + "barrierOnTapHint": "Tutup $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_my.arb b/forui/lib/l10n/f_my.arb index 9e26dfeeb..1e7217d20 100644 --- a/forui/lib/l10n/f_my.arb +++ b/forui/lib/l10n/f_my.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "ဒိုင်ယာလော့", + "sheetLabel": "ပိုဆောင်း စာမျက်နှာ", + "barrierOnTapHint": "$modalRouteContentName ပိတ်ရန်", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_nb.arb b/forui/lib/l10n/f_nb.arb index 9e26dfeeb..35e841252 100644 --- a/forui/lib/l10n/f_nb.arb +++ b/forui/lib/l10n/f_nb.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialogboks", + "sheetLabel": "Felt", + "barrierOnTapHint": "Lukk $modalRouteContentName", + "barrierLabel": "Vev" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_ne.arb b/forui/lib/l10n/f_ne.arb index 9e26dfeeb..b1d54e267 100644 --- a/forui/lib/l10n/f_ne.arb +++ b/forui/lib/l10n/f_ne.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "संवाद", + "sheetLabel": "पाना", + "barrierOnTapHint": "$modalRouteContentName बन्द गर्नुहोस्", + "barrierLabel": "स्क्रिम" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_nl.arb b/forui/lib/l10n/f_nl.arb index 9e26dfeeb..89786aef0 100644 --- a/forui/lib/l10n/f_nl.arb +++ b/forui/lib/l10n/f_nl.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialoogvenster", + "sheetLabel": "Blad", + "barrierOnTapHint": "$modalRouteContentName sluiten", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_no.arb b/forui/lib/l10n/f_no.arb index 9e26dfeeb..35e841252 100644 --- a/forui/lib/l10n/f_no.arb +++ b/forui/lib/l10n/f_no.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialogboks", + "sheetLabel": "Felt", + "barrierOnTapHint": "Lukk $modalRouteContentName", + "barrierLabel": "Vev" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_or.arb b/forui/lib/l10n/f_or.arb index 9e26dfeeb..7fb28c6e6 100644 --- a/forui/lib/l10n/f_or.arb +++ b/forui/lib/l10n/f_or.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "ଡାୟଲଗ୍", + "sheetLabel": "ସିଟ", + "barrierOnTapHint": "$modalRouteContentNameକୁ ବନ୍ଦ କରନ୍ତୁ", + "barrierLabel": "ସ୍କ୍ରିମ" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_pa.arb b/forui/lib/l10n/f_pa.arb index 9e26dfeeb..44b499384 100644 --- a/forui/lib/l10n/f_pa.arb +++ b/forui/lib/l10n/f_pa.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "ਵਿੰਡੋ", + "sheetLabel": "ਸ਼ੀਟ", + "barrierOnTapHint": "$modalRouteContentName ਨੂੰ ਬੰਦ ਕਰੋ", + "barrierLabel": "ਸਕ੍ਰਿਮ" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_pl.arb b/forui/lib/l10n/f_pl.arb index 9e26dfeeb..b52db54d1 100644 --- a/forui/lib/l10n/f_pl.arb +++ b/forui/lib/l10n/f_pl.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Okno dialogowe", + "sheetLabel": "Plansza", + "barrierOnTapHint": "Zamknij: $modalRouteContentName", + "barrierLabel": "Siatka" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_ps.arb b/forui/lib/l10n/f_ps.arb index 9e26dfeeb..a7a9d5b72 100644 --- a/forui/lib/l10n/f_ps.arb +++ b/forui/lib/l10n/f_ps.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "خبرې اترې", + "sheetLabel": "Sheet", + "barrierOnTapHint": "Close $modalRouteName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_pt.arb b/forui/lib/l10n/f_pt.arb index 9e26dfeeb..42cde9097 100644 --- a/forui/lib/l10n/f_pt.arb +++ b/forui/lib/l10n/f_pt.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Caixa de diálogo", + "sheetLabel": "inferior", + "barrierOnTapHint": "Fechar $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_pt_PT.arb b/forui/lib/l10n/f_pt_PT.arb index 9e26dfeeb..b60f09c7a 100644 --- a/forui/lib/l10n/f_pt_PT.arb +++ b/forui/lib/l10n/f_pt_PT.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Caixa de diálogo", + "sheetLabel": "Secção", + "barrierOnTapHint": "Fechar $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_ro.arb b/forui/lib/l10n/f_ro.arb index 9e26dfeeb..bc8e163ad 100644 --- a/forui/lib/l10n/f_ro.arb +++ b/forui/lib/l10n/f_ro.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Casetă de dialog", + "sheetLabel": "Foaie", + "barrierOnTapHint": "Închideți $modalRouteContentName", + "barrierLabel": "Material" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_ru.arb b/forui/lib/l10n/f_ru.arb index 9e26dfeeb..cd6f012a6 100644 --- a/forui/lib/l10n/f_ru.arb +++ b/forui/lib/l10n/f_ru.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Диалоговое окно", + "sheetLabel": "экран", + "barrierOnTapHint": "Закрыть $modalRouteContentName", + "barrierLabel": "Маска" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_si.arb b/forui/lib/l10n/f_si.arb index 9e26dfeeb..92545ba46 100644 --- a/forui/lib/l10n/f_si.arb +++ b/forui/lib/l10n/f_si.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "සංවාදය", + "sheetLabel": "පත්‍රය", + "barrierOnTapHint": "$modalRouteContentName වසන්න", + "barrierLabel": "ස්ක්‍රිම්" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_sk.arb b/forui/lib/l10n/f_sk.arb index 9e26dfeeb..ef4937d14 100644 --- a/forui/lib/l10n/f_sk.arb +++ b/forui/lib/l10n/f_sk.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialógové okno", + "sheetLabel": "hárok", + "barrierOnTapHint": "Zavrieť $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_sl.arb b/forui/lib/l10n/f_sl.arb index 9e26dfeeb..337be873b 100644 --- a/forui/lib/l10n/f_sl.arb +++ b/forui/lib/l10n/f_sl.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Pogovorno okno", + "sheetLabel": "Razdelek", + "barrierOnTapHint": "Zapiranje »$modalRouteContentName«", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_sq.arb b/forui/lib/l10n/f_sq.arb index 9e26dfeeb..ffbd1a92e 100644 --- a/forui/lib/l10n/f_sq.arb +++ b/forui/lib/l10n/f_sq.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialogu", + "sheetLabel": "Fleta", + "barrierOnTapHint": "Mbyll $modalRouteContentName", + "barrierLabel": "Kanavacë" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_sr.arb b/forui/lib/l10n/f_sr.arb index 9e26dfeeb..6e4089262 100644 --- a/forui/lib/l10n/f_sr.arb +++ b/forui/lib/l10n/f_sr.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Дијалог", + "sheetLabel": "табела", + "barrierOnTapHint": "Затвори: $modalRouteContentName", + "barrierLabel": "Скрим" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_sr_Latn.arb b/forui/lib/l10n/f_sr_Latn.arb index 9e26dfeeb..909cc39e2 100644 --- a/forui/lib/l10n/f_sr_Latn.arb +++ b/forui/lib/l10n/f_sr_Latn.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dijalog", + "sheetLabel": "tabela", + "barrierOnTapHint": "Zatvori: $modalRouteContentName", + "barrierLabel": "Skrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_sv.arb b/forui/lib/l10n/f_sv.arb index 9e26dfeeb..9e0176c87 100644 --- a/forui/lib/l10n/f_sv.arb +++ b/forui/lib/l10n/f_sv.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialogruta", + "sheetLabel": "Ark", + "barrierOnTapHint": "Stäng $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_sw.arb b/forui/lib/l10n/f_sw.arb index 9e26dfeeb..6b21d2579 100644 --- a/forui/lib/l10n/f_sw.arb +++ b/forui/lib/l10n/f_sw.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Kidirisha", + "sheetLabel": "Safu", + "barrierOnTapHint": "Funga $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_ta.arb b/forui/lib/l10n/f_ta.arb index 9e26dfeeb..16ef7db5b 100644 --- a/forui/lib/l10n/f_ta.arb +++ b/forui/lib/l10n/f_ta.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "உரையாடல்", + "sheetLabel": "திரை", + "barrierOnTapHint": "$modalRouteContentName ஐ மூடுக", + "barrierLabel": "ஸ்க்ரிம்" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_te.arb b/forui/lib/l10n/f_te.arb index 9e26dfeeb..6e615ca09 100644 --- a/forui/lib/l10n/f_te.arb +++ b/forui/lib/l10n/f_te.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "డైలాగ్", + "sheetLabel": "షీట్", + "barrierOnTapHint": "$modalRouteContentName‌ను మూసివేయండి", + "barrierLabel": "స్క్రిమ్" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_th.arb b/forui/lib/l10n/f_th.arb index 9e26dfeeb..f60302c4d 100644 --- a/forui/lib/l10n/f_th.arb +++ b/forui/lib/l10n/f_th.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "กล่องโต้ตอบ", + "sheetLabel": "Sheet", + "barrierOnTapHint": "ปิด $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_tl.arb b/forui/lib/l10n/f_tl.arb index 9e26dfeeb..18d5664e0 100644 --- a/forui/lib/l10n/f_tl.arb +++ b/forui/lib/l10n/f_tl.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Dialog", + "sheetLabel": "sheet", + "barrierOnTapHint": "Isara ang $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_tr.arb b/forui/lib/l10n/f_tr.arb index 9e26dfeeb..6c764a5d1 100644 --- a/forui/lib/l10n/f_tr.arb +++ b/forui/lib/l10n/f_tr.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "İletişim kutusu", + "sheetLabel": "sayfa", + "barrierOnTapHint": "$modalRouteContentName içeriğini kapat", + "barrierLabel": "opaklık katmanı" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_uk.arb b/forui/lib/l10n/f_uk.arb index 9e26dfeeb..a24a0a352 100644 --- a/forui/lib/l10n/f_uk.arb +++ b/forui/lib/l10n/f_uk.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Вікно", + "sheetLabel": "екран", + "barrierOnTapHint": "Закрити: $modalRouteContentName", + "barrierLabel": "Маскувальний фон" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_ur.arb b/forui/lib/l10n/f_ur.arb index 9e26dfeeb..a3b312b08 100644 --- a/forui/lib/l10n/f_ur.arb +++ b/forui/lib/l10n/f_ur.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "ڈائلاگ", + "sheetLabel": "شیٹ", + "barrierOnTapHint": "$modalRouteContentName بند کریں", + "barrierLabel": "اسکریم" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_uz.arb b/forui/lib/l10n/f_uz.arb index 9e26dfeeb..682f1f04f 100644 --- a/forui/lib/l10n/f_uz.arb +++ b/forui/lib/l10n/f_uz.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Muloqot oynasi", + "sheetLabel": "ekran", + "barrierOnTapHint": "Yopish: $modalRouteContentName", + "barrierLabel": "Kanop" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_vi.arb b/forui/lib/l10n/f_vi.arb index 9e26dfeeb..4400aa794 100644 --- a/forui/lib/l10n/f_vi.arb +++ b/forui/lib/l10n/f_vi.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Hộp thoại", + "sheetLabel": "Bảng", + "barrierOnTapHint": "Đóng $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_zh.arb b/forui/lib/l10n/f_zh.arb index 9e26dfeeb..03215ae06 100644 --- a/forui/lib/l10n/f_zh.arb +++ b/forui/lib/l10n/f_zh.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "对话框", + "sheetLabel": "动作条", + "barrierOnTapHint": "关闭 $modalRouteContentName", + "barrierLabel": "纱罩" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_zh_HK.arb b/forui/lib/l10n/f_zh_HK.arb index 9e26dfeeb..214a53ddf 100644 --- a/forui/lib/l10n/f_zh_HK.arb +++ b/forui/lib/l10n/f_zh_HK.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "對話方塊", + "sheetLabel": "面板", + "barrierOnTapHint": "關閉 $modalRouteContentName", + "barrierLabel": "Scrim" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_zh_TW.arb b/forui/lib/l10n/f_zh_TW.arb index 9e26dfeeb..6ed0d4fcd 100644 --- a/forui/lib/l10n/f_zh_TW.arb +++ b/forui/lib/l10n/f_zh_TW.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "對話方塊", + "sheetLabel": "功能表", + "barrierOnTapHint": "關閉「$modalRouteContentName」", + "barrierLabel": "紗罩" +} \ No newline at end of file diff --git a/forui/lib/l10n/f_zu.arb b/forui/lib/l10n/f_zu.arb index 9e26dfeeb..ca858bf0b 100644 --- a/forui/lib/l10n/f_zu.arb +++ b/forui/lib/l10n/f_zu.arb @@ -1 +1,6 @@ -{} \ No newline at end of file +{ + "dialogLabel": "Ingxoxo", + "sheetLabel": "Ishidi", + "barrierOnTapHint": "Vala i-$modalRouteContentName", + "barrierLabel": "I-Scrim" +} \ No newline at end of file diff --git a/forui/lib/src/localizations/localization.dart b/forui/lib/src/localizations/localization.dart index 649c3245d..8df67c08a 100644 --- a/forui/lib/src/localizations/localization.dart +++ b/forui/lib/src/localizations/localization.dart @@ -32,4 +32,16 @@ class DefaultLocalizations extends FLocalizations { @override String day(DateTime date) => DateFormat.d().format(date); + + @override + String get dialogLabel => 'Dialog'; + + @override + String get sheetLabel => 'Sheet'; + + @override + String get barrierLabel => 'Barrier'; + + @override + String barrierOnTapHint(String modalRouteContentName) => 'Close $modalRouteContentName'; } diff --git a/forui/lib/src/localizations/localizations.dart b/forui/lib/src/localizations/localizations.dart index 94b86ccb2..8ee8fcdc2 100644 --- a/forui/lib/src/localizations/localizations.dart +++ b/forui/lib/src/localizations/localizations.dart @@ -314,6 +314,30 @@ abstract class FLocalizations { /// In en, this message translates to: /// **'{date}'** String day(DateTime date); + + /// The sheet's label. + /// + /// In en, this message translates to: + /// **'Dialog'** + String get dialogLabel; + + /// No description provided for @sheetLabel. + /// + /// In en, this message translates to: + /// **'Sheet'** + String get sheetLabel; + + /// The label for the barrier rendered underneath the content of a bottom sheet (used as the 'modalRouteContentName' of the 'barrierOnTapHint' message). + /// + /// In en, this message translates to: + /// **'Barrier'** + String get barrierLabel; + + /// The onTapHint for the barrier rendered underneath the content of a modal route (especially a sheet) which users can tap to dismiss the content. + /// + /// In en, this message translates to: + /// **'Close {modalRouteContentName}'** + String barrierOnTapHint(String modalRouteContentName); } class _FLocalizationsDelegate extends LocalizationsDelegate { diff --git a/forui/lib/src/localizations/localizations_af.dart b/forui/lib/src/localizations/localizations_af.dart index 792153a62..d4ead4422 100644 --- a/forui/lib/src/localizations/localizations_af.dart +++ b/forui/lib/src/localizations/localizations_af.dart @@ -47,4 +47,18 @@ class FLocalizationsAf extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialoog'; + + @override + String get sheetLabel => 'blad'; + + @override + String get barrierLabel => 'Skerm'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Maak \$modalRouteContentName toe'; + } } diff --git a/forui/lib/src/localizations/localizations_am.dart b/forui/lib/src/localizations/localizations_am.dart index 02c279749..f2758aa7a 100644 --- a/forui/lib/src/localizations/localizations_am.dart +++ b/forui/lib/src/localizations/localizations_am.dart @@ -47,4 +47,18 @@ class FLocalizationsAm extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'መገናኛ'; + + @override + String get sheetLabel => 'ሉህ'; + + @override + String get barrierLabel => 'ገዳቢ'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentNameን ዝጋ'; + } } diff --git a/forui/lib/src/localizations/localizations_ar.dart b/forui/lib/src/localizations/localizations_ar.dart index a182772b7..507b8adfc 100644 --- a/forui/lib/src/localizations/localizations_ar.dart +++ b/forui/lib/src/localizations/localizations_ar.dart @@ -47,4 +47,18 @@ class FLocalizationsAr extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'مربع حوار'; + + @override + String get sheetLabel => 'بطاق '; + + @override + String get barrierLabel => 'تمويه'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'إغلاق \"\$modalRouteContentName\"'; + } } diff --git a/forui/lib/src/localizations/localizations_as.dart b/forui/lib/src/localizations/localizations_as.dart index 661d02c36..ba735940c 100644 --- a/forui/lib/src/localizations/localizations_as.dart +++ b/forui/lib/src/localizations/localizations_as.dart @@ -47,4 +47,18 @@ class FLocalizationsAs extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'ডায়ল\'গ'; + + @override + String get sheetLabel => 'শ্বীট'; + + @override + String get barrierLabel => 'স্ক্ৰিম'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName বন্ধ কৰক'; + } } diff --git a/forui/lib/src/localizations/localizations_az.dart b/forui/lib/src/localizations/localizations_az.dart index 1d80c6d11..adc404ecf 100644 --- a/forui/lib/src/localizations/localizations_az.dart +++ b/forui/lib/src/localizations/localizations_az.dart @@ -47,4 +47,18 @@ class FLocalizationsAz extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialoq'; + + @override + String get sheetLabel => 'Vərəq'; + + @override + String get barrierLabel => 'Kətan'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Bağlayın: \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_be.dart b/forui/lib/src/localizations/localizations_be.dart index e93e18d49..d837ecb28 100644 --- a/forui/lib/src/localizations/localizations_be.dart +++ b/forui/lib/src/localizations/localizations_be.dart @@ -47,4 +47,18 @@ class FLocalizationsBe extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Дыялогавае акно'; + + @override + String get sheetLabel => 'аркуш'; + + @override + String get barrierLabel => 'Палатно'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Закрыць: \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_bg.dart b/forui/lib/src/localizations/localizations_bg.dart index ba949c8d2..e0ac1dd62 100644 --- a/forui/lib/src/localizations/localizations_bg.dart +++ b/forui/lib/src/localizations/localizations_bg.dart @@ -47,4 +47,18 @@ class FLocalizationsBg extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Диалогов прозорец'; + + @override + String get sheetLabel => 'лист'; + + @override + String get barrierLabel => 'Скрим'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Затваряне на \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_bn.dart b/forui/lib/src/localizations/localizations_bn.dart index d11399a6d..bc6112cc7 100644 --- a/forui/lib/src/localizations/localizations_bn.dart +++ b/forui/lib/src/localizations/localizations_bn.dart @@ -47,4 +47,18 @@ class FLocalizationsBn extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'ডায়ালগ'; + + @override + String get sheetLabel => 'শীট'; + + @override + String get barrierLabel => 'স্ক্রিম'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName বন্ধ করুন'; + } } diff --git a/forui/lib/src/localizations/localizations_bs.dart b/forui/lib/src/localizations/localizations_bs.dart index 4bcb20546..5466ad763 100644 --- a/forui/lib/src/localizations/localizations_bs.dart +++ b/forui/lib/src/localizations/localizations_bs.dart @@ -47,4 +47,18 @@ class FLocalizationsBs extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dijaloški okvir'; + + @override + String get sheetLabel => 'tabela'; + + @override + String get barrierLabel => 'Rubno'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Zatvori: \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_ca.dart b/forui/lib/src/localizations/localizations_ca.dart index 56d887b76..9ff52da99 100644 --- a/forui/lib/src/localizations/localizations_ca.dart +++ b/forui/lib/src/localizations/localizations_ca.dart @@ -47,4 +47,18 @@ class FLocalizationsCa extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Diàleg'; + + @override + String get sheetLabel => 'Full'; + + @override + String get barrierLabel => 'Fons atenuat'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Tanca \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_cs.dart b/forui/lib/src/localizations/localizations_cs.dart index 1623849af..8163de2f7 100644 --- a/forui/lib/src/localizations/localizations_cs.dart +++ b/forui/lib/src/localizations/localizations_cs.dart @@ -47,4 +47,18 @@ class FLocalizationsCs extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialogové okno'; + + @override + String get sheetLabel => 'tabulka'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Zavřít \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_cy.dart b/forui/lib/src/localizations/localizations_cy.dart index 04ecbce74..6bb3e769f 100644 --- a/forui/lib/src/localizations/localizations_cy.dart +++ b/forui/lib/src/localizations/localizations_cy.dart @@ -47,4 +47,18 @@ class FLocalizationsCy extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Deialog'; + + @override + String get sheetLabel => 'Taflen'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cau \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_da.dart b/forui/lib/src/localizations/localizations_da.dart index 37e143504..297452529 100644 --- a/forui/lib/src/localizations/localizations_da.dart +++ b/forui/lib/src/localizations/localizations_da.dart @@ -47,4 +47,18 @@ class FLocalizationsDa extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialogboks'; + + @override + String get sheetLabel => 'Felt'; + + @override + String get barrierLabel => 'Dæmpeskærm'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Luk \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_de.dart b/forui/lib/src/localizations/localizations_de.dart index c79a02895..bbb792063 100644 --- a/forui/lib/src/localizations/localizations_de.dart +++ b/forui/lib/src/localizations/localizations_de.dart @@ -47,9 +47,26 @@ class FLocalizationsDe extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialogfeld'; + + @override + String get sheetLabel => 'Ansicht'; + + @override + String get barrierLabel => 'Gitter'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName schließen'; + } } /// The translations for German, as used in Switzerland (`de_CH`). class FLocalizationsDeCh extends FLocalizationsDe { FLocalizationsDeCh() : super('de_CH'); + + @override + String get dialogLabel => 'Dialogfeld'; } diff --git a/forui/lib/src/localizations/localizations_el.dart b/forui/lib/src/localizations/localizations_el.dart index fb54e1b11..9674a3297 100644 --- a/forui/lib/src/localizations/localizations_el.dart +++ b/forui/lib/src/localizations/localizations_el.dart @@ -47,4 +47,18 @@ class FLocalizationsEl extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Παράθυρο διαλόγου'; + + @override + String get sheetLabel => 'Φύλλο'; + + @override + String get barrierLabel => 'Επικάλυψη'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Κλείσιμο \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_en.dart b/forui/lib/src/localizations/localizations_en.dart index 9c8ca4eb4..3651b7c09 100644 --- a/forui/lib/src/localizations/localizations_en.dart +++ b/forui/lib/src/localizations/localizations_en.dart @@ -47,44 +47,170 @@ class FLocalizationsEn extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialog'; + + @override + String get sheetLabel => 'Sheet'; + + @override + String get barrierLabel => 'Barrier'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Close $modalRouteContentName'; + } } /// The translations for English, as used in Australia (`en_AU`). class FLocalizationsEnAu extends FLocalizationsEn { FLocalizationsEnAu() : super('en_AU'); + + @override + String get dialogLabel => 'Dialogue'; + + @override + String get sheetLabel => 'Sheet'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Close \$modalRouteContentName'; + } } /// The translations for English, as used in Canada (`en_CA`). class FLocalizationsEnCa extends FLocalizationsEn { FLocalizationsEnCa() : super('en_CA'); + + @override + String get dialogLabel => 'Dialog'; + + @override + String get sheetLabel => 'Sheet'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Close \$modalRouteContentName'; + } } /// The translations for English, as used in the United Kingdom (`en_GB`). class FLocalizationsEnGb extends FLocalizationsEn { FLocalizationsEnGb() : super('en_GB'); + + @override + String get dialogLabel => 'Dialogue'; + + @override + String get sheetLabel => 'sheet'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Close \$modalRouteContentName'; + } } /// The translations for English, as used in Ireland (`en_IE`). class FLocalizationsEnIe extends FLocalizationsEn { FLocalizationsEnIe() : super('en_IE'); + + @override + String get dialogLabel => 'Dialogue'; + + @override + String get sheetLabel => 'sheet'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Close \$modalRouteContentName'; + } } /// The translations for English, as used in India (`en_IN`). class FLocalizationsEnIn extends FLocalizationsEn { FLocalizationsEnIn() : super('en_IN'); + + @override + String get dialogLabel => 'Dialogue'; + + @override + String get sheetLabel => 'sheet'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Close \$modalRouteContentName'; + } } /// The translations for English, as used in New Zealand (`en_NZ`). class FLocalizationsEnNz extends FLocalizationsEn { FLocalizationsEnNz() : super('en_NZ'); + + @override + String get dialogLabel => 'Dialogue'; + + @override + String get sheetLabel => 'Sheet'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Close \$modalRouteContentName'; + } } /// The translations for English, as used in Singapore (`en_SG`). class FLocalizationsEnSg extends FLocalizationsEn { FLocalizationsEnSg() : super('en_SG'); + + @override + String get dialogLabel => 'Dialogue'; + + @override + String get sheetLabel => 'sheet'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Close \$modalRouteContentName'; + } } /// The translations for English, as used in South Africa (`en_ZA`). class FLocalizationsEnZa extends FLocalizationsEn { FLocalizationsEnZa() : super('en_ZA'); + + @override + String get dialogLabel => 'Dialogue'; + + @override + String get sheetLabel => 'sheet'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Close \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_es.dart b/forui/lib/src/localizations/localizations_es.dart index a46eefe40..40a8fa347 100644 --- a/forui/lib/src/localizations/localizations_es.dart +++ b/forui/lib/src/localizations/localizations_es.dart @@ -47,104 +47,398 @@ class FLocalizationsEs extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Cuadro de diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Sombreado'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in Latin America and the Caribbean (`es_419`). class FLocalizationsEs419 extends FLocalizationsEs { FLocalizationsEs419() : super('es_419'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in Argentina (`es_AR`). class FLocalizationsEsAr extends FLocalizationsEs { FLocalizationsEsAr() : super('es_AR'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in Bolivia (`es_BO`). class FLocalizationsEsBo extends FLocalizationsEs { FLocalizationsEsBo() : super('es_BO'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in Chile (`es_CL`). class FLocalizationsEsCl extends FLocalizationsEs { FLocalizationsEsCl() : super('es_CL'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in Colombia (`es_CO`). class FLocalizationsEsCo extends FLocalizationsEs { FLocalizationsEsCo() : super('es_CO'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in Costa Rica (`es_CR`). class FLocalizationsEsCr extends FLocalizationsEs { FLocalizationsEsCr() : super('es_CR'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in the Dominican Republic (`es_DO`). class FLocalizationsEsDo extends FLocalizationsEs { FLocalizationsEsDo() : super('es_DO'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in Ecuador (`es_EC`). class FLocalizationsEsEc extends FLocalizationsEs { FLocalizationsEsEc() : super('es_EC'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in Guatemala (`es_GT`). class FLocalizationsEsGt extends FLocalizationsEs { FLocalizationsEsGt() : super('es_GT'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in Honduras (`es_HN`). class FLocalizationsEsHn extends FLocalizationsEs { FLocalizationsEsHn() : super('es_HN'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in Mexico (`es_MX`). class FLocalizationsEsMx extends FLocalizationsEs { FLocalizationsEsMx() : super('es_MX'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in Nicaragua (`es_NI`). class FLocalizationsEsNi extends FLocalizationsEs { FLocalizationsEsNi() : super('es_NI'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in Panama (`es_PA`). class FLocalizationsEsPa extends FLocalizationsEs { FLocalizationsEsPa() : super('es_PA'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in Peru (`es_PE`). class FLocalizationsEsPe extends FLocalizationsEs { FLocalizationsEsPe() : super('es_PE'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in Puerto Rico (`es_PR`). class FLocalizationsEsPr extends FLocalizationsEs { FLocalizationsEsPr() : super('es_PR'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in Paraguay (`es_PY`). class FLocalizationsEsPy extends FLocalizationsEs { FLocalizationsEsPy() : super('es_PY'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'inferior'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in El Salvador (`es_SV`). class FLocalizationsEsSv extends FLocalizationsEs { FLocalizationsEsSv() : super('es_SV'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in the United States (`es_US`). class FLocalizationsEsUs extends FLocalizationsEs { FLocalizationsEsUs() : super('es_US'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in Uruguay (`es_UY`). class FLocalizationsEsUy extends FLocalizationsEs { FLocalizationsEsUy() : super('es_UY'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } /// The translations for Spanish Castilian, as used in Venezuela (`es_VE`). class FLocalizationsEsVe extends FLocalizationsEs { FLocalizationsEsVe() : super('es_VE'); + + @override + String get dialogLabel => 'Diálogo'; + + @override + String get sheetLabel => 'Hoja'; + + @override + String get barrierLabel => 'Lámina'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Cerrar \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_et.dart b/forui/lib/src/localizations/localizations_et.dart index 18ddb790e..6d2ff2be0 100644 --- a/forui/lib/src/localizations/localizations_et.dart +++ b/forui/lib/src/localizations/localizations_et.dart @@ -47,4 +47,18 @@ class FLocalizationsEt extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialoog'; + + @override + String get sheetLabel => 'leht'; + + @override + String get barrierLabel => 'Sirm'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Sule \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_eu.dart b/forui/lib/src/localizations/localizations_eu.dart index 3fac395db..eb4c2daf8 100644 --- a/forui/lib/src/localizations/localizations_eu.dart +++ b/forui/lib/src/localizations/localizations_eu.dart @@ -47,4 +47,18 @@ class FLocalizationsEu extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Leihoa'; + + @override + String get sheetLabel => 'orria'; + + @override + String get barrierLabel => 'Barrera'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Itxi \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_fa.dart b/forui/lib/src/localizations/localizations_fa.dart index 5c6a42bfd..ae9653df0 100644 --- a/forui/lib/src/localizations/localizations_fa.dart +++ b/forui/lib/src/localizations/localizations_fa.dart @@ -47,4 +47,18 @@ class FLocalizationsFa extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'کادر گفتگو'; + + @override + String get sheetLabel => 'برگ'; + + @override + String get barrierLabel => 'رویه'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'بستن \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_fi.dart b/forui/lib/src/localizations/localizations_fi.dart index 57fd14919..bef0bdb7f 100644 --- a/forui/lib/src/localizations/localizations_fi.dart +++ b/forui/lib/src/localizations/localizations_fi.dart @@ -47,4 +47,18 @@ class FLocalizationsFi extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Valintaikkuna'; + + @override + String get sheetLabel => 'arkki'; + + @override + String get barrierLabel => 'Sermi'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Sulje \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_fil.dart b/forui/lib/src/localizations/localizations_fil.dart index c835ce3fc..35b01a9f7 100644 --- a/forui/lib/src/localizations/localizations_fil.dart +++ b/forui/lib/src/localizations/localizations_fil.dart @@ -47,4 +47,18 @@ class FLocalizationsFil extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialog'; + + @override + String get sheetLabel => 'sheet'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Isara ang \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_fr.dart b/forui/lib/src/localizations/localizations_fr.dart index 7f9dea2b7..e602f0f20 100644 --- a/forui/lib/src/localizations/localizations_fr.dart +++ b/forui/lib/src/localizations/localizations_fr.dart @@ -47,9 +47,37 @@ class FLocalizationsFr extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Boîte de dialogue'; + + @override + String get sheetLabel => 'sheet'; + + @override + String get barrierLabel => 'Fond'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Fermer \$modalRouteContentName'; + } } /// The translations for French, as used in Canada (`fr_CA`). class FLocalizationsFrCa extends FLocalizationsFr { FLocalizationsFrCa() : super('fr_CA'); + + @override + String get dialogLabel => 'Boîte de dialogue'; + + @override + String get sheetLabel => 'Zone de contenu'; + + @override + String get barrierLabel => 'Grille'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Fermer \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_gl.dart b/forui/lib/src/localizations/localizations_gl.dart index 02f88a4fe..95287d153 100644 --- a/forui/lib/src/localizations/localizations_gl.dart +++ b/forui/lib/src/localizations/localizations_gl.dart @@ -47,4 +47,18 @@ class FLocalizationsGl extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Cadro de diálogo'; + + @override + String get sheetLabel => 'Panel'; + + @override + String get barrierLabel => 'Sombreado'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Pechar \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_gsw.dart b/forui/lib/src/localizations/localizations_gsw.dart index c0239a469..f79e466cf 100644 --- a/forui/lib/src/localizations/localizations_gsw.dart +++ b/forui/lib/src/localizations/localizations_gsw.dart @@ -47,4 +47,18 @@ class FLocalizationsGsw extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialogfeld'; + + @override + String get sheetLabel => 'Ansicht'; + + @override + String get barrierLabel => 'Gitter'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName schließen'; + } } diff --git a/forui/lib/src/localizations/localizations_gu.dart b/forui/lib/src/localizations/localizations_gu.dart index f6a87decb..c2dd39aa0 100644 --- a/forui/lib/src/localizations/localizations_gu.dart +++ b/forui/lib/src/localizations/localizations_gu.dart @@ -47,4 +47,18 @@ class FLocalizationsGu extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'સંવાદ'; + + @override + String get sheetLabel => 'શીટ'; + + @override + String get barrierLabel => 'સ્ક્રિમ'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentNameને બંધ કરો'; + } } diff --git a/forui/lib/src/localizations/localizations_he.dart b/forui/lib/src/localizations/localizations_he.dart index 23d69689f..68f56a624 100644 --- a/forui/lib/src/localizations/localizations_he.dart +++ b/forui/lib/src/localizations/localizations_he.dart @@ -47,4 +47,18 @@ class FLocalizationsHe extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'תיבת דו-שיח'; + + @override + String get sheetLabel => 'גיליו '; + + @override + String get barrierLabel => 'מיסוך'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'סגירת \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_hi.dart b/forui/lib/src/localizations/localizations_hi.dart index f31f1bdca..dde3069a0 100644 --- a/forui/lib/src/localizations/localizations_hi.dart +++ b/forui/lib/src/localizations/localizations_hi.dart @@ -47,4 +47,18 @@ class FLocalizationsHi extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'डायलॉग'; + + @override + String get sheetLabel => 'शीट'; + + @override + String get barrierLabel => 'स्क्रिम'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName को बंद करें'; + } } diff --git a/forui/lib/src/localizations/localizations_hr.dart b/forui/lib/src/localizations/localizations_hr.dart index fed86b8ad..c904fdebe 100644 --- a/forui/lib/src/localizations/localizations_hr.dart +++ b/forui/lib/src/localizations/localizations_hr.dart @@ -47,4 +47,18 @@ class FLocalizationsHr extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dijalog'; + + @override + String get sheetLabel => 'tablica'; + + @override + String get barrierLabel => 'Rubno'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Zatvori \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_hu.dart b/forui/lib/src/localizations/localizations_hu.dart index 806833eb2..97e471dfb 100644 --- a/forui/lib/src/localizations/localizations_hu.dart +++ b/forui/lib/src/localizations/localizations_hu.dart @@ -47,4 +47,18 @@ class FLocalizationsHu extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Párbeszédablak'; + + @override + String get sheetLabel => 'lap'; + + @override + String get barrierLabel => 'Borítás'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName bezárása'; + } } diff --git a/forui/lib/src/localizations/localizations_hy.dart b/forui/lib/src/localizations/localizations_hy.dart index 263340036..6c6b8bc15 100644 --- a/forui/lib/src/localizations/localizations_hy.dart +++ b/forui/lib/src/localizations/localizations_hy.dart @@ -47,4 +47,18 @@ class FLocalizationsHy extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Երկխոսության պատուհան'; + + @override + String get sheetLabel => 'էկրան'; + + @override + String get barrierLabel => 'Դիմակ'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Փակել՝ \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_id.dart b/forui/lib/src/localizations/localizations_id.dart index 97e84d1e2..7a0d121dd 100644 --- a/forui/lib/src/localizations/localizations_id.dart +++ b/forui/lib/src/localizations/localizations_id.dart @@ -47,4 +47,18 @@ class FLocalizationsId extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialog'; + + @override + String get sheetLabel => 'Sheet'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Tutup \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_is.dart b/forui/lib/src/localizations/localizations_is.dart index 9c9ac735b..166bdf2f3 100644 --- a/forui/lib/src/localizations/localizations_is.dart +++ b/forui/lib/src/localizations/localizations_is.dart @@ -47,4 +47,18 @@ class FLocalizationsIs extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Gluggi'; + + @override + String get sheetLabel => 'Blað'; + + @override + String get barrierLabel => 'Möskvi'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Loka \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_it.dart b/forui/lib/src/localizations/localizations_it.dart index fc93e1047..f239f7b88 100644 --- a/forui/lib/src/localizations/localizations_it.dart +++ b/forui/lib/src/localizations/localizations_it.dart @@ -47,4 +47,18 @@ class FLocalizationsIt extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Finestra di dialogo'; + + @override + String get sheetLabel => 'Riquadro'; + + @override + String get barrierLabel => 'Rete'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Chiudi \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_ja.dart b/forui/lib/src/localizations/localizations_ja.dart index 617b1bdaa..10e0c7cc6 100644 --- a/forui/lib/src/localizations/localizations_ja.dart +++ b/forui/lib/src/localizations/localizations_ja.dart @@ -47,4 +47,18 @@ class FLocalizationsJa extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'ダイアログ'; + + @override + String get sheetLabel => 'シート'; + + @override + String get barrierLabel => 'スクリム'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName を閉じる'; + } } diff --git a/forui/lib/src/localizations/localizations_ka.dart b/forui/lib/src/localizations/localizations_ka.dart index 3eea4f4a0..280ee28c4 100644 --- a/forui/lib/src/localizations/localizations_ka.dart +++ b/forui/lib/src/localizations/localizations_ka.dart @@ -47,4 +47,18 @@ class FLocalizationsKa extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'დიალოგი'; + + @override + String get sheetLabel => 'ფურცელი'; + + @override + String get barrierLabel => 'სკრიმი'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName-ის დახურვა'; + } } diff --git a/forui/lib/src/localizations/localizations_kk.dart b/forui/lib/src/localizations/localizations_kk.dart index a9632d68d..3592220b1 100644 --- a/forui/lib/src/localizations/localizations_kk.dart +++ b/forui/lib/src/localizations/localizations_kk.dart @@ -47,4 +47,18 @@ class FLocalizationsKk extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Диалогтық терезе'; + + @override + String get sheetLabel => 'парақша'; + + @override + String get barrierLabel => 'Кенеп'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName жабу'; + } } diff --git a/forui/lib/src/localizations/localizations_km.dart b/forui/lib/src/localizations/localizations_km.dart index 5f5e504f2..eaf0482bf 100644 --- a/forui/lib/src/localizations/localizations_km.dart +++ b/forui/lib/src/localizations/localizations_km.dart @@ -47,4 +47,18 @@ class FLocalizationsKm extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'ប្រអប់'; + + @override + String get sheetLabel => 'សន្លឹក'; + + @override + String get barrierLabel => 'ផ្ទាំងស្រអាប់'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'បិទ \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_kn.dart b/forui/lib/src/localizations/localizations_kn.dart index d7f9ff50b..9c5e542b2 100644 --- a/forui/lib/src/localizations/localizations_kn.dart +++ b/forui/lib/src/localizations/localizations_kn.dart @@ -47,4 +47,18 @@ class FLocalizationsKn extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'ಡೈಲಾಗ್'; + + @override + String get sheetLabel => 'ಶೀಟ್'; + + @override + String get barrierLabel => 'ಸ್ಕ್ರಿಮ್'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName ಅನ್ನು ಮುಚ್ಚಿರಿ'; + } } diff --git a/forui/lib/src/localizations/localizations_ko.dart b/forui/lib/src/localizations/localizations_ko.dart index 1c2bf8b8e..ffa94e4f5 100644 --- a/forui/lib/src/localizations/localizations_ko.dart +++ b/forui/lib/src/localizations/localizations_ko.dart @@ -47,4 +47,18 @@ class FLocalizationsKo extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => '대화상자'; + + @override + String get sheetLabel => '시트'; + + @override + String get barrierLabel => '스크림'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName 닫기'; + } } diff --git a/forui/lib/src/localizations/localizations_ky.dart b/forui/lib/src/localizations/localizations_ky.dart index a53a8d6d1..2218f204c 100644 --- a/forui/lib/src/localizations/localizations_ky.dart +++ b/forui/lib/src/localizations/localizations_ky.dart @@ -47,4 +47,18 @@ class FLocalizationsKy extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Диалог'; + + @override + String get sheetLabel => 'экран'; + + @override + String get barrierLabel => 'Кенеп'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName жабуу'; + } } diff --git a/forui/lib/src/localizations/localizations_lo.dart b/forui/lib/src/localizations/localizations_lo.dart index 348cdb957..d51a2048e 100644 --- a/forui/lib/src/localizations/localizations_lo.dart +++ b/forui/lib/src/localizations/localizations_lo.dart @@ -47,4 +47,18 @@ class FLocalizationsLo extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'ຂໍ້ຄວາມ'; + + @override + String get sheetLabel => 'ແຜ່ນ'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'ປິດ \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_lt.dart b/forui/lib/src/localizations/localizations_lt.dart index 7a201741c..647304bdd 100644 --- a/forui/lib/src/localizations/localizations_lt.dart +++ b/forui/lib/src/localizations/localizations_lt.dart @@ -47,4 +47,18 @@ class FLocalizationsLt extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialogo langas'; + + @override + String get sheetLabel => 'lapas'; + + @override + String get barrierLabel => 'Užsklanda'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Uždaryti „\$modalRouteContentName“'; + } } diff --git a/forui/lib/src/localizations/localizations_lv.dart b/forui/lib/src/localizations/localizations_lv.dart index 32a60f261..b1e35cdee 100644 --- a/forui/lib/src/localizations/localizations_lv.dart +++ b/forui/lib/src/localizations/localizations_lv.dart @@ -47,4 +47,18 @@ class FLocalizationsLv extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialoglodziņš'; + + @override + String get sheetLabel => 'lapa'; + + @override + String get barrierLabel => 'Pārklājums'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Aizvērt \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_mk.dart b/forui/lib/src/localizations/localizations_mk.dart index 362d9153c..b46e0a497 100644 --- a/forui/lib/src/localizations/localizations_mk.dart +++ b/forui/lib/src/localizations/localizations_mk.dart @@ -47,4 +47,18 @@ class FLocalizationsMk extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Дијалог'; + + @override + String get sheetLabel => 'лист'; + + @override + String get barrierLabel => 'Скрим'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Затворете ја \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_ml.dart b/forui/lib/src/localizations/localizations_ml.dart index a4820dd87..67847c804 100644 --- a/forui/lib/src/localizations/localizations_ml.dart +++ b/forui/lib/src/localizations/localizations_ml.dart @@ -47,4 +47,18 @@ class FLocalizationsMl extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'ഡയലോഗ്'; + + @override + String get sheetLabel => 'ഷീറ്റ്'; + + @override + String get barrierLabel => 'സ്ക്രിം'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName അടയ്ക്കുക'; + } } diff --git a/forui/lib/src/localizations/localizations_mn.dart b/forui/lib/src/localizations/localizations_mn.dart index 1a4076adc..58c9a96ed 100644 --- a/forui/lib/src/localizations/localizations_mn.dart +++ b/forui/lib/src/localizations/localizations_mn.dart @@ -47,4 +47,18 @@ class FLocalizationsMn extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Харилцах цонх'; + + @override + String get sheetLabel => 'хүснэгт'; + + @override + String get barrierLabel => 'Скрим'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName-г хаах'; + } } diff --git a/forui/lib/src/localizations/localizations_mr.dart b/forui/lib/src/localizations/localizations_mr.dart index 5ff8ad851..87daea5c3 100644 --- a/forui/lib/src/localizations/localizations_mr.dart +++ b/forui/lib/src/localizations/localizations_mr.dart @@ -47,4 +47,18 @@ class FLocalizationsMr extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'डायलॉग'; + + @override + String get sheetLabel => 'शीट'; + + @override + String get barrierLabel => 'स्क्रिम'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName बंद करा'; + } } diff --git a/forui/lib/src/localizations/localizations_ms.dart b/forui/lib/src/localizations/localizations_ms.dart index 1a7b92728..1bdcb45c2 100644 --- a/forui/lib/src/localizations/localizations_ms.dart +++ b/forui/lib/src/localizations/localizations_ms.dart @@ -47,4 +47,18 @@ class FLocalizationsMs extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialog'; + + @override + String get sheetLabel => 'Helaian'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Tutup \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_my.dart b/forui/lib/src/localizations/localizations_my.dart index 14788ecae..575c1a8a5 100644 --- a/forui/lib/src/localizations/localizations_my.dart +++ b/forui/lib/src/localizations/localizations_my.dart @@ -47,4 +47,18 @@ class FLocalizationsMy extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'ဒိုင်ယာလော့'; + + @override + String get sheetLabel => 'ပိုဆောင်း စာမျက်နှာ'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName ပိတ်ရန်'; + } } diff --git a/forui/lib/src/localizations/localizations_nb.dart b/forui/lib/src/localizations/localizations_nb.dart index 0f362c869..5bf29f917 100644 --- a/forui/lib/src/localizations/localizations_nb.dart +++ b/forui/lib/src/localizations/localizations_nb.dart @@ -47,4 +47,18 @@ class FLocalizationsNb extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialogboks'; + + @override + String get sheetLabel => 'Felt'; + + @override + String get barrierLabel => 'Vev'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Lukk \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_ne.dart b/forui/lib/src/localizations/localizations_ne.dart index 45496ac7c..d975d8041 100644 --- a/forui/lib/src/localizations/localizations_ne.dart +++ b/forui/lib/src/localizations/localizations_ne.dart @@ -47,4 +47,18 @@ class FLocalizationsNe extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'संवाद'; + + @override + String get sheetLabel => 'पाना'; + + @override + String get barrierLabel => 'स्क्रिम'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName बन्द गर्नुहोस्'; + } } diff --git a/forui/lib/src/localizations/localizations_nl.dart b/forui/lib/src/localizations/localizations_nl.dart index 7d370088a..f829a652b 100644 --- a/forui/lib/src/localizations/localizations_nl.dart +++ b/forui/lib/src/localizations/localizations_nl.dart @@ -47,4 +47,18 @@ class FLocalizationsNl extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialoogvenster'; + + @override + String get sheetLabel => 'Blad'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName sluiten'; + } } diff --git a/forui/lib/src/localizations/localizations_no.dart b/forui/lib/src/localizations/localizations_no.dart index 7fe2a4920..a16015a97 100644 --- a/forui/lib/src/localizations/localizations_no.dart +++ b/forui/lib/src/localizations/localizations_no.dart @@ -47,4 +47,18 @@ class FLocalizationsNo extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialogboks'; + + @override + String get sheetLabel => 'Felt'; + + @override + String get barrierLabel => 'Vev'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Lukk \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_or.dart b/forui/lib/src/localizations/localizations_or.dart index 8af75fe39..d895b8d5e 100644 --- a/forui/lib/src/localizations/localizations_or.dart +++ b/forui/lib/src/localizations/localizations_or.dart @@ -47,4 +47,18 @@ class FLocalizationsOr extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'ଡାୟଲଗ୍'; + + @override + String get sheetLabel => 'ସିଟ'; + + @override + String get barrierLabel => 'ସ୍କ୍ରିମ'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentNameକୁ ବନ୍ଦ କରନ୍ତୁ'; + } } diff --git a/forui/lib/src/localizations/localizations_pa.dart b/forui/lib/src/localizations/localizations_pa.dart index 09ff361ce..944a6d451 100644 --- a/forui/lib/src/localizations/localizations_pa.dart +++ b/forui/lib/src/localizations/localizations_pa.dart @@ -47,4 +47,18 @@ class FLocalizationsPa extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'ਵਿੰਡੋ'; + + @override + String get sheetLabel => 'ਸ਼ੀਟ'; + + @override + String get barrierLabel => 'ਸਕ੍ਰਿਮ'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName ਨੂੰ ਬੰਦ ਕਰੋ'; + } } diff --git a/forui/lib/src/localizations/localizations_pl.dart b/forui/lib/src/localizations/localizations_pl.dart index 4ada2665a..b11dab5aa 100644 --- a/forui/lib/src/localizations/localizations_pl.dart +++ b/forui/lib/src/localizations/localizations_pl.dart @@ -47,4 +47,18 @@ class FLocalizationsPl extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Okno dialogowe'; + + @override + String get sheetLabel => 'Plansza'; + + @override + String get barrierLabel => 'Siatka'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Zamknij: \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_ps.dart b/forui/lib/src/localizations/localizations_ps.dart index b96a01939..070ae95c3 100644 --- a/forui/lib/src/localizations/localizations_ps.dart +++ b/forui/lib/src/localizations/localizations_ps.dart @@ -47,4 +47,18 @@ class FLocalizationsPs extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'خبرې اترې'; + + @override + String get sheetLabel => 'Sheet'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Close \$modalRouteName'; + } } diff --git a/forui/lib/src/localizations/localizations_pt.dart b/forui/lib/src/localizations/localizations_pt.dart index 0c5100358..9ac42bd55 100644 --- a/forui/lib/src/localizations/localizations_pt.dart +++ b/forui/lib/src/localizations/localizations_pt.dart @@ -47,9 +47,37 @@ class FLocalizationsPt extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Caixa de diálogo'; + + @override + String get sheetLabel => 'inferior'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Fechar \$modalRouteContentName'; + } } /// The translations for Portuguese, as used in Portugal (`pt_PT`). class FLocalizationsPtPt extends FLocalizationsPt { FLocalizationsPtPt() : super('pt_PT'); + + @override + String get dialogLabel => 'Caixa de diálogo'; + + @override + String get sheetLabel => 'Secção'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Fechar \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_ro.dart b/forui/lib/src/localizations/localizations_ro.dart index ed9bac50b..24bf13299 100644 --- a/forui/lib/src/localizations/localizations_ro.dart +++ b/forui/lib/src/localizations/localizations_ro.dart @@ -47,4 +47,18 @@ class FLocalizationsRo extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Casetă de dialog'; + + @override + String get sheetLabel => 'Foaie'; + + @override + String get barrierLabel => 'Material'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Închideți \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_ru.dart b/forui/lib/src/localizations/localizations_ru.dart index 1a3cf4a04..8670f349f 100644 --- a/forui/lib/src/localizations/localizations_ru.dart +++ b/forui/lib/src/localizations/localizations_ru.dart @@ -47,4 +47,18 @@ class FLocalizationsRu extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Диалоговое окно'; + + @override + String get sheetLabel => 'экран'; + + @override + String get barrierLabel => 'Маска'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Закрыть \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_si.dart b/forui/lib/src/localizations/localizations_si.dart index 7b76b9d32..51abd75c6 100644 --- a/forui/lib/src/localizations/localizations_si.dart +++ b/forui/lib/src/localizations/localizations_si.dart @@ -47,4 +47,18 @@ class FLocalizationsSi extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'සංවාදය'; + + @override + String get sheetLabel => 'පත්‍රය'; + + @override + String get barrierLabel => 'ස්ක්‍රිම්'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName වසන්න'; + } } diff --git a/forui/lib/src/localizations/localizations_sk.dart b/forui/lib/src/localizations/localizations_sk.dart index f2f1f06cc..4d6065148 100644 --- a/forui/lib/src/localizations/localizations_sk.dart +++ b/forui/lib/src/localizations/localizations_sk.dart @@ -47,4 +47,18 @@ class FLocalizationsSk extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialógové okno'; + + @override + String get sheetLabel => 'hárok'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Zavrieť \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_sl.dart b/forui/lib/src/localizations/localizations_sl.dart index d2289fea8..e7cbba291 100644 --- a/forui/lib/src/localizations/localizations_sl.dart +++ b/forui/lib/src/localizations/localizations_sl.dart @@ -47,4 +47,18 @@ class FLocalizationsSl extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Pogovorno okno'; + + @override + String get sheetLabel => 'Razdelek'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Zapiranje »\$modalRouteContentName«'; + } } diff --git a/forui/lib/src/localizations/localizations_sq.dart b/forui/lib/src/localizations/localizations_sq.dart index d3cc35084..d789133b8 100644 --- a/forui/lib/src/localizations/localizations_sq.dart +++ b/forui/lib/src/localizations/localizations_sq.dart @@ -47,4 +47,18 @@ class FLocalizationsSq extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialogu'; + + @override + String get sheetLabel => 'Fleta'; + + @override + String get barrierLabel => 'Kanavacë'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Mbyll \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_sr.dart b/forui/lib/src/localizations/localizations_sr.dart index 0e7c6947f..65d80df43 100644 --- a/forui/lib/src/localizations/localizations_sr.dart +++ b/forui/lib/src/localizations/localizations_sr.dart @@ -47,9 +47,37 @@ class FLocalizationsSr extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Дијалог'; + + @override + String get sheetLabel => 'табела'; + + @override + String get barrierLabel => 'Скрим'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Затвори: \$modalRouteContentName'; + } } /// The translations for Serbian, using the Latin script (`sr_Latn`). class FLocalizationsSrLatn extends FLocalizationsSr { FLocalizationsSrLatn() : super('sr_Latn'); + + @override + String get dialogLabel => 'Dijalog'; + + @override + String get sheetLabel => 'tabela'; + + @override + String get barrierLabel => 'Skrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Zatvori: \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_sv.dart b/forui/lib/src/localizations/localizations_sv.dart index b3b2b8b20..34c45e910 100644 --- a/forui/lib/src/localizations/localizations_sv.dart +++ b/forui/lib/src/localizations/localizations_sv.dart @@ -47,4 +47,18 @@ class FLocalizationsSv extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialogruta'; + + @override + String get sheetLabel => 'Ark'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Stäng \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_sw.dart b/forui/lib/src/localizations/localizations_sw.dart index 55c2c3fe3..6f9d30bbe 100644 --- a/forui/lib/src/localizations/localizations_sw.dart +++ b/forui/lib/src/localizations/localizations_sw.dart @@ -47,4 +47,18 @@ class FLocalizationsSw extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Kidirisha'; + + @override + String get sheetLabel => 'Safu'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Funga \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_ta.dart b/forui/lib/src/localizations/localizations_ta.dart index 015838537..30012c468 100644 --- a/forui/lib/src/localizations/localizations_ta.dart +++ b/forui/lib/src/localizations/localizations_ta.dart @@ -47,4 +47,18 @@ class FLocalizationsTa extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'உரையாடல்'; + + @override + String get sheetLabel => 'திரை'; + + @override + String get barrierLabel => 'ஸ்க்ரிம்'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName ஐ மூடுக'; + } } diff --git a/forui/lib/src/localizations/localizations_te.dart b/forui/lib/src/localizations/localizations_te.dart index 0ea2691a3..fcfe5999b 100644 --- a/forui/lib/src/localizations/localizations_te.dart +++ b/forui/lib/src/localizations/localizations_te.dart @@ -47,4 +47,18 @@ class FLocalizationsTe extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'డైలాగ్'; + + @override + String get sheetLabel => 'షీట్'; + + @override + String get barrierLabel => 'స్క్రిమ్'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName‌ను మూసివేయండి'; + } } diff --git a/forui/lib/src/localizations/localizations_th.dart b/forui/lib/src/localizations/localizations_th.dart index b96cb97c1..795e48bd1 100644 --- a/forui/lib/src/localizations/localizations_th.dart +++ b/forui/lib/src/localizations/localizations_th.dart @@ -47,4 +47,18 @@ class FLocalizationsTh extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'กล่องโต้ตอบ'; + + @override + String get sheetLabel => 'Sheet'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'ปิด \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_tl.dart b/forui/lib/src/localizations/localizations_tl.dart index 5be76e858..ab780dc26 100644 --- a/forui/lib/src/localizations/localizations_tl.dart +++ b/forui/lib/src/localizations/localizations_tl.dart @@ -47,4 +47,18 @@ class FLocalizationsTl extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Dialog'; + + @override + String get sheetLabel => 'sheet'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Isara ang \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_tr.dart b/forui/lib/src/localizations/localizations_tr.dart index 2851243cb..384fc1dc1 100644 --- a/forui/lib/src/localizations/localizations_tr.dart +++ b/forui/lib/src/localizations/localizations_tr.dart @@ -47,4 +47,18 @@ class FLocalizationsTr extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'İletişim kutusu'; + + @override + String get sheetLabel => 'sayfa'; + + @override + String get barrierLabel => 'opaklık katmanı'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName içeriğini kapat'; + } } diff --git a/forui/lib/src/localizations/localizations_uk.dart b/forui/lib/src/localizations/localizations_uk.dart index 037e2faf0..48ab856f3 100644 --- a/forui/lib/src/localizations/localizations_uk.dart +++ b/forui/lib/src/localizations/localizations_uk.dart @@ -47,4 +47,18 @@ class FLocalizationsUk extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Вікно'; + + @override + String get sheetLabel => 'екран'; + + @override + String get barrierLabel => 'Маскувальний фон'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Закрити: \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_ur.dart b/forui/lib/src/localizations/localizations_ur.dart index 2f20c5dee..8b0cb7c1c 100644 --- a/forui/lib/src/localizations/localizations_ur.dart +++ b/forui/lib/src/localizations/localizations_ur.dart @@ -47,4 +47,18 @@ class FLocalizationsUr extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'ڈائلاگ'; + + @override + String get sheetLabel => 'شیٹ'; + + @override + String get barrierLabel => 'اسکریم'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '\$modalRouteContentName بند کریں'; + } } diff --git a/forui/lib/src/localizations/localizations_uz.dart b/forui/lib/src/localizations/localizations_uz.dart index 5c3a253d4..cff824125 100644 --- a/forui/lib/src/localizations/localizations_uz.dart +++ b/forui/lib/src/localizations/localizations_uz.dart @@ -47,4 +47,18 @@ class FLocalizationsUz extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Muloqot oynasi'; + + @override + String get sheetLabel => 'ekran'; + + @override + String get barrierLabel => 'Kanop'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Yopish: \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_vi.dart b/forui/lib/src/localizations/localizations_vi.dart index 7666cf668..c6193244e 100644 --- a/forui/lib/src/localizations/localizations_vi.dart +++ b/forui/lib/src/localizations/localizations_vi.dart @@ -47,4 +47,18 @@ class FLocalizationsVi extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Hộp thoại'; + + @override + String get sheetLabel => 'Bảng'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Đóng \$modalRouteContentName'; + } } diff --git a/forui/lib/src/localizations/localizations_zh.dart b/forui/lib/src/localizations/localizations_zh.dart index 28a1fead5..3052b2c75 100644 --- a/forui/lib/src/localizations/localizations_zh.dart +++ b/forui/lib/src/localizations/localizations_zh.dart @@ -47,14 +47,56 @@ class FLocalizationsZh extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => '对话框'; + + @override + String get sheetLabel => '动作条'; + + @override + String get barrierLabel => '纱罩'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '关闭 \$modalRouteContentName'; + } } /// The translations for Chinese, as used in Hong Kong (`zh_HK`). class FLocalizationsZhHk extends FLocalizationsZh { FLocalizationsZhHk() : super('zh_HK'); + + @override + String get dialogLabel => '對話方塊'; + + @override + String get sheetLabel => '面板'; + + @override + String get barrierLabel => 'Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '關閉 \$modalRouteContentName'; + } } /// The translations for Chinese, as used in Taiwan (`zh_TW`). class FLocalizationsZhTw extends FLocalizationsZh { FLocalizationsZhTw() : super('zh_TW'); + + @override + String get dialogLabel => '對話方塊'; + + @override + String get sheetLabel => '功能表'; + + @override + String get barrierLabel => '紗罩'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return '關閉「\$modalRouteContentName」'; + } } diff --git a/forui/lib/src/localizations/localizations_zu.dart b/forui/lib/src/localizations/localizations_zu.dart index 9cbeec7a6..74d1a7dba 100644 --- a/forui/lib/src/localizations/localizations_zu.dart +++ b/forui/lib/src/localizations/localizations_zu.dart @@ -47,4 +47,18 @@ class FLocalizationsZu extends FLocalizations { return '$dateString'; } + + @override + String get dialogLabel => 'Ingxoxo'; + + @override + String get sheetLabel => 'Ishidi'; + + @override + String get barrierLabel => 'I-Scrim'; + + @override + String barrierOnTapHint(String modalRouteContentName) { + return 'Vala i-\$modalRouteContentName'; + } } diff --git a/forui/lib/src/theme/color_scheme.dart b/forui/lib/src/theme/color_scheme.dart index 1cae9b34d..c66112239 100644 --- a/forui/lib/src/theme/color_scheme.dart +++ b/forui/lib/src/theme/color_scheme.dart @@ -30,6 +30,11 @@ final class FColorScheme with Diagnosticable { /// This is typically used to determine the appearance of native UI elements such as on-screen keyboards. final Brightness brightness; + /// The barrier color. + /// + /// Typically used as a background for modal/pop-up routes. + final Color barrier; + /// The background color. /// /// Typically used as a background for [foreground] colored widgets. @@ -111,6 +116,7 @@ final class FColorScheme with Diagnosticable { /// Unless you are creating a completely new color scheme, modifying [FThemes]' predefined color schemes is preferred. const FColorScheme({ required this.brightness, + required this.barrier, required this.background, required this.foreground, required this.primary, @@ -165,6 +171,7 @@ final class FColorScheme with Diagnosticable { @useResult FColorScheme copyWith({ Brightness? brightness, + Color? barrier, Color? background, Color? foreground, Color? primary, @@ -183,6 +190,7 @@ final class FColorScheme with Diagnosticable { }) => FColorScheme( brightness: brightness ?? this.brightness, + barrier: barrier ?? this.barrier, background: background ?? this.background, foreground: foreground ?? this.foreground, primary: primary ?? this.primary, @@ -205,6 +213,7 @@ final class FColorScheme with Diagnosticable { super.debugFillProperties(properties); properties ..add(EnumProperty('brightness', brightness)) + ..add(ColorProperty('barrier', barrier)) ..add(ColorProperty('background', background)) ..add(ColorProperty('foreground', foreground)) ..add(ColorProperty('primary', primary)) @@ -227,6 +236,7 @@ final class FColorScheme with Diagnosticable { identical(this, other) || other is FColorScheme && brightness == other.brightness && + barrier == other.barrier && background == other.background && foreground == other.foreground && primary == other.primary && @@ -246,6 +256,7 @@ final class FColorScheme with Diagnosticable { @override int get hashCode => brightness.hashCode ^ + barrier.hashCode ^ background.hashCode ^ foreground.hashCode ^ primary.hashCode ^ diff --git a/forui/lib/src/theme/theme_data.dart b/forui/lib/src/theme/theme_data.dart index 8256045e1..fdf936a09 100644 --- a/forui/lib/src/theme/theme_data.dart +++ b/forui/lib/src/theme/theme_data.dart @@ -91,6 +91,9 @@ final class FThemeData with Diagnosticable { /// The select menu tile style. final FSelectMenuTileStyle selectMenuTileStyle; + /// The sheet style. + final FSheetStyle sheetStyle; + /// The slider styles. final FSliderStyles sliderStyles; @@ -139,6 +142,7 @@ final class FThemeData with Diagnosticable { required this.scaffoldStyle, required this.selectGroupStyle, required this.selectMenuTileStyle, + required this.sheetStyle, required this.sliderStyles, required this.switchStyle, required this.tabsStyle, @@ -186,6 +190,7 @@ final class FThemeData with Diagnosticable { scaffoldStyle: FScaffoldStyle.inherit(colorScheme: colorScheme, style: style), selectGroupStyle: FSelectGroupStyle.inherit(colorScheme: colorScheme, typography: typography, style: style), selectMenuTileStyle: FSelectMenuTileStyle.inherit(colorScheme: colorScheme, typography: typography, style: style), + sheetStyle: FSheetStyle.inherit(colorScheme: colorScheme), sliderStyles: FSliderStyles.inherit(colorScheme: colorScheme, typography: typography, style: style), switchStyle: FSwitchStyle.inherit(colorScheme: colorScheme, style: style), tabsStyle: FTabsStyle.inherit(colorScheme: colorScheme, typography: typography, style: style), @@ -263,6 +268,7 @@ final class FThemeData with Diagnosticable { FScaffoldStyle? scaffoldStyle, FSelectGroupStyle? selectGroupStyle, FSelectMenuTileStyle? selectMenuTileStyle, + FSheetStyle? sheetStyle, FSliderStyles? sliderStyles, FSwitchStyle? switchStyle, FTabsStyle? tabsStyle, @@ -295,6 +301,7 @@ final class FThemeData with Diagnosticable { scaffoldStyle: scaffoldStyle ?? this.scaffoldStyle, selectGroupStyle: selectGroupStyle ?? this.selectGroupStyle, selectMenuTileStyle: selectMenuTileStyle ?? this.selectMenuTileStyle, + sheetStyle: sheetStyle ?? this.sheetStyle, sliderStyles: sliderStyles ?? this.sliderStyles, switchStyle: switchStyle ?? this.switchStyle, tabsStyle: tabsStyle ?? this.tabsStyle, @@ -332,6 +339,7 @@ final class FThemeData with Diagnosticable { ..add(DiagnosticsProperty('scaffoldStyle', scaffoldStyle, level: DiagnosticLevel.debug)) ..add(DiagnosticsProperty('selectGroupStyle', selectGroupStyle, level: DiagnosticLevel.debug)) ..add(DiagnosticsProperty('selectMenuTileStyle', selectMenuTileStyle, level: DiagnosticLevel.debug)) + ..add(DiagnosticsProperty('sheetStyle', sheetStyle, level: DiagnosticLevel.debug)) ..add(DiagnosticsProperty('sliderStyles', sliderStyles, level: DiagnosticLevel.debug)) ..add(DiagnosticsProperty('switchStyle', switchStyle, level: DiagnosticLevel.debug)) ..add(DiagnosticsProperty('tabsStyle', tabsStyle, level: DiagnosticLevel.debug)) @@ -370,6 +378,7 @@ final class FThemeData with Diagnosticable { scaffoldStyle == other.scaffoldStyle && selectGroupStyle == other.selectGroupStyle && selectMenuTileStyle == other.selectMenuTileStyle && + sheetStyle == other.sheetStyle && sliderStyles == other.sliderStyles && switchStyle == other.switchStyle && tabsStyle == other.tabsStyle && @@ -404,6 +413,7 @@ final class FThemeData with Diagnosticable { scaffoldStyle.hashCode ^ selectGroupStyle.hashCode ^ selectMenuTileStyle.hashCode ^ + sheetStyle.hashCode ^ sliderStyles.hashCode ^ switchStyle.hashCode ^ tabsStyle.hashCode ^ diff --git a/forui/lib/src/theme/themes.dart b/forui/lib/src/theme/themes.dart index e5ef2e8cf..ce196fa88 100644 --- a/forui/lib/src/theme/themes.dart +++ b/forui/lib/src/theme/themes.dart @@ -10,6 +10,7 @@ extension FThemes on Never { light: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.light, + barrier: Color(0x33000000), background: Color(0xFFFFFFFF), foreground: Color(0xFF09090B), primary: Color(0xFF18181B), @@ -28,6 +29,7 @@ extension FThemes on Never { dark: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.dark, + barrier: Color(0x7A000000), background: Color(0xFF09090B), foreground: Color(0xFFFAFAFA), primary: Color(0xFFFAFAFA), @@ -50,6 +52,7 @@ extension FThemes on Never { light: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.light, + barrier: Color(0x33000000), background: Color(0xFFFFFFFF), foreground: Color(0xFF020817), primary: Color(0xFF0F172A), @@ -68,6 +71,7 @@ extension FThemes on Never { dark: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.dark, + barrier: Color(0x7A000000), background: Color(0xFF020817), foreground: Color(0xFFF8FAFC), primary: Color(0xFFF8FAFC), @@ -90,6 +94,7 @@ extension FThemes on Never { light: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.light, + barrier: Color(0x33000000), background: Color(0xFFFFFFFF), foreground: Color(0xFF09090B), primary: Color(0xFFDC2626), @@ -108,6 +113,7 @@ extension FThemes on Never { dark: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.dark, + barrier: Color(0x7A000000), background: Color(0xFF0A0A0A), foreground: Color(0xFFFAFAFA), primary: Color(0xFFDC2626), @@ -130,6 +136,7 @@ extension FThemes on Never { light: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.light, + barrier: Color(0x33000000), background: Color(0xFFFFFFFF), foreground: Color(0xFF09090B), primary: Color(0xFFE11D48), @@ -148,6 +155,7 @@ extension FThemes on Never { dark: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.dark, + barrier: Color(0x7A000000), background: Color(0xFF0C0A09), foreground: Color(0xFFF2F2F2), primary: Color(0xFFE11D48), @@ -170,6 +178,7 @@ extension FThemes on Never { light: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.light, + barrier: Color(0x33000000), background: Color(0xFFFFFFFF), foreground: Color(0xFF0C0A09), primary: Color(0xFFF97316), @@ -188,6 +197,7 @@ extension FThemes on Never { dark: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.dark, + barrier: Color(0x7A000000), background: Color(0xFF0C0A09), foreground: Color(0xFFFAFAF9), primary: Color(0xFFEA580C), @@ -210,6 +220,7 @@ extension FThemes on Never { light: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.light, + barrier: Color(0x33000000), background: Color(0xFFFFFFFF), foreground: Color(0xFF09090B), primary: Color(0xFF16A34A), @@ -228,6 +239,7 @@ extension FThemes on Never { dark: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.dark, + barrier: Color(0x7A000000), background: Color(0xFF0C0A09), foreground: Color(0xFFF2F2F2), primary: Color(0xFF22C55E), @@ -250,6 +262,7 @@ extension FThemes on Never { light: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.light, + barrier: Color(0x33000000), background: Color(0xFFFFFFFF), foreground: Color(0xFF020817), primary: Color(0xFF2563EB), @@ -268,6 +281,7 @@ extension FThemes on Never { dark: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.dark, + barrier: Color(0x7A000000), background: Color(0xFF020817), foreground: Color(0xFFF8FAFC), primary: Color(0xFF3B82F6), @@ -290,6 +304,7 @@ extension FThemes on Never { light: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.light, + barrier: Color(0x33000000), background: Color(0xFFFFFFFF), foreground: Color(0xFF0C0A09), primary: Color(0xFFFACC15), @@ -308,6 +323,7 @@ extension FThemes on Never { dark: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.dark, + barrier: Color(0x7A000000), background: Color(0xFF0C0A09), foreground: Color(0xFFFAFAF9), primary: Color(0xFFFACC15), @@ -330,6 +346,7 @@ extension FThemes on Never { light: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.light, + barrier: Color(0x33000000), background: Color(0xFFFFFFFF), foreground: Color(0xFF030712), primary: Color(0xFF7C3AED), @@ -348,6 +365,7 @@ extension FThemes on Never { dark: FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.dark, + barrier: Color(0x7A000000), background: Color(0xFF030712), foreground: Color(0xFFF9FAFB), primary: Color(0xFF6D28D9), diff --git a/forui/lib/src/widgets/scaffold.dart b/forui/lib/src/widgets/scaffold.dart index 859758e55..abb6b86e2 100644 --- a/forui/lib/src/widgets/scaffold.dart +++ b/forui/lib/src/widgets/scaffold.dart @@ -13,7 +13,7 @@ import 'package:forui/forui.dart'; /// See: /// * https://forui.dev/docs/layout/scaffold for working examples. /// * [FScaffoldStyle] for customizing a scaffold's appearance. -class FScaffold extends StatelessWidget { +class FScaffold extends StatefulWidget { /// The content. final Widget content; @@ -40,25 +40,7 @@ class FScaffold extends StatelessWidget { }); @override - Widget build(BuildContext context) { - final style = this.style ?? context.theme.scaffoldStyle; - Widget content = this.content; - - if (contentPad) { - content = Padding(padding: style.contentPadding, child: content); - } - - return ColoredBox( - color: style.backgroundColor, - child: Column( - children: [ - if (header != null) DecoratedBox(decoration: style.headerDecoration, child: header!), - Expanded(child: content), - if (footer != null) DecoratedBox(decoration: style.footerDecoration, child: footer!), - ], - ), - ); - } + State createState() => _State(); @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { @@ -69,6 +51,31 @@ class FScaffold extends StatelessWidget { } } +class _State extends State { + @override + Widget build(BuildContext context) { + final style = widget.style ?? context.theme.scaffoldStyle; + Widget content = widget.content; + + if (widget.contentPad) { + content = Padding(padding: style.contentPadding, child: content); + } + + return FSheets( + child: ColoredBox( + color: style.backgroundColor, + child: Column( + children: [ + if (widget.header != null) DecoratedBox(decoration: style.headerDecoration, child: widget.header!), + Expanded(child: content), + if (widget.footer != null) DecoratedBox(decoration: style.footerDecoration, child: widget.footer!), + ], + ), + ), + ); + } +} + /// [FScaffold]'s style. final class FScaffoldStyle with Diagnosticable { /// The background color. diff --git a/forui/lib/src/widgets/sheet/gesture_detector.dart b/forui/lib/src/widgets/sheet/gesture_detector.dart new file mode 100644 index 000000000..810db3b41 --- /dev/null +++ b/forui/lib/src/widgets/sheet/gesture_detector.dart @@ -0,0 +1,67 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/widgets.dart'; + +import 'package:meta/meta.dart'; + +import 'package:forui/forui.dart'; + +/// The sheet's gesture detector. We use a [RawGestureDetector] instead of a [GestureDetector] because the latter +/// doesn't allow `onlyAcceptDragOnThreshold` to be configured. +/// +/// This is based on Material's _BottomSheetGestureDetector. +@internal +class SheetGestureDetector extends StatelessWidget { + final Layout layout; + final GestureDragStartCallback? onStart; + final GestureDragUpdateCallback? onUpdate; + final GestureDragEndCallback? onEnd; + final Widget child; + + const SheetGestureDetector({ + required this.layout, + required this.onStart, + required this.onUpdate, + required this.onEnd, + required this.child, + super.key, + }); + + @override + Widget build(BuildContext context) { + void initialize(DragGestureRecognizer recognizer) { + recognizer + ..onStart = onStart + ..onUpdate = onUpdate + ..onEnd = onEnd + ..onlyAcceptDragOnThreshold = true; + } + + return RawGestureDetector( + excludeFromSemantics: true, + gestures: { + if (layout.vertical) + VerticalDragGestureRecognizer: GestureRecognizerFactoryWithHandlers( + () => VerticalDragGestureRecognizer(debugOwner: this), + initialize, + ) + else + HorizontalDragGestureRecognizer: GestureRecognizerFactoryWithHandlers( + () => HorizontalDragGestureRecognizer(debugOwner: this), + initialize, + ), + }, + child: child, + ); + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(EnumProperty('layout', layout)) + ..add(ObjectFlagProperty.has('onStart', onStart)) + ..add(ObjectFlagProperty.has('onUpdate', onUpdate)) + ..add(ObjectFlagProperty.has('onEnd', onEnd)); + } +} diff --git a/forui/lib/src/widgets/sheet/modal_sheet.dart b/forui/lib/src/widgets/sheet/modal_sheet.dart new file mode 100644 index 000000000..48891d05b --- /dev/null +++ b/forui/lib/src/widgets/sheet/modal_sheet.dart @@ -0,0 +1,295 @@ +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; + +import 'package:forui/forui.dart'; +import 'package:forui/src/widgets/sheet/sheet.dart'; + +/// Shows a modal sheet that appears from the given [side]. +/// +/// A modal sheet is an alternative to a menu or a dialog and prevents the user from interacting with the rest of the +/// app. +/// +/// [context] is used to look up the [Navigator] and [FSheetStyle] for the sheet. It is only used when the method is +/// called. Its corresponding widget can be safely removed from the tree before the sheet is closed. +/// +/// [useRootNavigator] ensures that the root navigator displays the sheet when`true`. This is useful in the case that a +/// modal sheet needs to be displayed above all other content but the caller is inside another [Navigator]. +/// +/// [style] defaults to [FSheetStyle] from the closest [FTheme] ancestor. +/// +/// [mainAxisMaxRatio] represents the main axis's max constraint ratio for the sheet, depending on [side]. +/// Defaults to 9 / 16. The main axis is the width if [side] is [Layout.ltr] or [Layout.rtl], and the height if [side] +/// is [Layout.ttb] or [Layout.btt]. Consider setting [mainAxisMaxRatio] to null if this sheet has a scrollable child, +/// i.e. [ListView], along the main axis, to have the sheet be draggable. +/// +/// [barrierLabel] defaults to [FLocalizations.barrierLabel]. +/// +/// Returns a `Future` that resolves to the value (if any) that was passed to [Navigator.pop] when the modal sheet was +/// closed. +/// +/// See: +/// * https://forui.dev/docs/overlay/sheet for working examples. +/// * [showFPersistentSheet] for displaying a sheet above the current widget. +/// * [FModalSheetRoute] for more information about the various arguments. +/// * [FSheetStyle] for customizing a switch's appearance. +/// * [DraggableScrollableSheet], creates a bottom sheet that grows and then becomes scrollable once it reaches its +/// maximum size. +Future showFSheet({ + required BuildContext context, + required WidgetBuilder builder, + required Layout side, + bool useRootNavigator = false, + FSheetStyle? style, + double? mainAxisMaxRatio = 9 / 16, + String? barrierLabel, + bool barrierDismissible = true, + BoxConstraints constraints = const BoxConstraints(), + bool draggable = true, + RouteSettings? routeSettings, + AnimationController? transitionAnimationController, + Offset? anchorPoint, + bool useSafeArea = false, +}) { + assert(debugCheckHasMediaQuery(context), ''); + + final navigator = Navigator.of(context, rootNavigator: useRootNavigator); + final localizations = FLocalizations.of(context); + + return navigator.push( + FModalSheetRoute( + style: style ?? context.theme.sheetStyle, + side: side, + builder: builder, + mainAxisMaxRatio: mainAxisMaxRatio, + capturedThemes: InheritedTheme.capture(from: context, to: navigator.context), + barrierOnTapHint: localizations.barrierOnTapHint(localizations.sheetLabel), + barrierLabel: barrierLabel ?? localizations.barrierLabel, + barrierDismissible: barrierDismissible, + barrierColor: (style ?? context.theme.sheetStyle).barrierColor, + constraints: constraints, + draggable: draggable, + settings: routeSettings, + transitionAnimationController: transitionAnimationController, + anchorPoint: anchorPoint, + useSafeArea: useSafeArea, + ), + ); +} + +/// A route that represents a modal sheet. [showFSheet] should be preferred in most cases. +/// +/// A modal sheet is an alternative to a menu or a dialog and prevents the user from interacting with the rest of the +/// app. +/// +/// A closely related widget is a persistent sheet, which shows information that supplements the primary content of the +/// app without preventing the user from interacting with the app. +/// +/// See: +/// * https://forui.dev/docs/overlay/sheet for working examples. +/// * [FSheetStyle] for customizing a switch's appearance. +/// * [showFSheet] for displaying a FModalSheetRoute. +/// * [showFPersistentSheet] for displaying a sheet above the current widget. +/// * [DraggableScrollableSheet], creates a bottom sheet that grows and then becomes scrollable once it reaches its +/// maximum size. +/// +/// This is based on Material's `ModalBottomSheetRoute`. +class FModalSheetRoute extends PopupRoute { + /// The style. + final FSheetStyle style; + + /// The side. + final Layout side; + + /// Stores a list of captured [InheritedTheme]s that are wrapped around the sheet. + /// + /// Consider setting this attribute when the [FModalSheetRoute] is created through [Navigator.push] and its friends. + final CapturedThemes? capturedThemes; + + /// The main axis's max constraint ratio for the sheet, depending on [side]. Defaults to 9 / 16. + /// + /// The main axis is the width if [side] is [Layout.ltr] or [Layout.rtl], and the height if [side] is [Layout.ttb] or + /// [Layout.btt]. + /// + /// Consider setting this to null if this sheet has a scrollable child, i.e. [ListView], along the main axis, to have + /// the sheet be draggable. + final double? mainAxisMaxRatio; + + /// The minimum and maximum sizes for a sheet. Default to being unconstrained. + final BoxConstraints constraints; + + /// True if the sheet can be dragged up and down/left and right. Defaults is true. + final bool draggable; + + /// The animation controller that controls the sheet's entrance and exit animations. + /// + /// The sheet widget will manipulate the position of this animation, it is not just a passive observer. + final AnimationController? transitionAnimationController; + + /// The anchor point used to pick the closest sub-screen. + /// + /// If the anchor point sits inside one of these sub-screens, then that sub-screen is picked. If not, then the + /// sub-screen with the closest edge to the point is used. + /// + /// [Offset.zero] is the top-left corner of the available screen space. For a vertically split dual-screen device, + /// this is the top-left corner of the left screen. + /// + /// When this is null, [Directionality] is used: + /// * for [TextDirection.ltr], [anchorPoint] is [Offset.zero], which will cause the top-left sub-screen to be picked. + /// * for [TextDirection.rtl], [anchorPoint] is `Offset(double.maxFinite, 0)`, which will cause the top-right + /// sub-screen to be picked. + final Offset? anchorPoint; + + /// True if a [SafeArea] should be inserted o keep the sheet away from system intrusions on the sides other than + /// [side]. Defaults to false. + /// + /// If false, the sheet will extend through any system intrusions other than [side]. In addition, + /// [MediaQuery.removePadding] is used to remove opposite [side]'s padding so that a [SafeArea] widget inside the + /// sheet will not have any effect on the opposite side. If this is undesired, consider setting [useSafeArea] to true. + /// Alternatively, wrap the [SafeArea] in a [MediaQuery] that restates an ambient [MediaQueryData] from outside + /// [builder]. + /// + /// In either case, the sheet extends all the way to the [side] of the screen, including any system intrusions. + final bool useSafeArea; + + /// The semantic hint text that informs users what will happen if they tap on the widget. Announced in the format of + /// 'Double tap to ...'. + /// + /// If the field is null, the default hint will be used, which results in an announcement of 'Double tap to activate'. + /// + /// See: + /// * [barrierDismissible], which controls the behavior of the barrier when tapped. + /// * [ModalBarrier], which uses this field as onTapHint when it has an onTap action. + final String? barrierOnTapHint; + + /// A builder for the contents of the sheet. + final WidgetBuilder builder; + + @override + final String? barrierLabel; + + @override + final bool barrierDismissible; + + @override + final Color barrierColor; + + final ValueNotifier _clipDetailsNotifier = ValueNotifier(EdgeInsets.zero); + + AnimationController? _animationController; + + /// Creates a [FModalSheetRoute]. + FModalSheetRoute({ + required this.style, + required this.side, + required this.barrierColor, + required this.builder, + this.mainAxisMaxRatio = 9 / 16, + this.capturedThemes, + this.barrierOnTapHint, + this.barrierLabel, + this.barrierDismissible = true, + this.constraints = const BoxConstraints(), + this.draggable = true, + this.transitionAnimationController, + this.anchorPoint, + this.useSafeArea = false, + super.settings, + }); + + @override + AnimationController createAnimationController() { + if (transitionAnimationController != null) { + _animationController = transitionAnimationController; + willDisposeAnimationController = false; + } else { + _animationController = Sheet.createAnimationController(navigator!, style); + } + + return _animationController!; + } + + @override + Widget buildPage(BuildContext context, Animation animation, Animation secondaryAnimation) { + final sheet = Sheet( + controller: controller, + animation: animation, + side: side, + style: style, + constraints: constraints, + mainAxisMaxRatio: mainAxisMaxRatio, + anchorPoint: anchorPoint, + draggable: draggable, + useSafeArea: useSafeArea, + builder: builder, + onChange: (size) => _didChangeBarrierSemanticsClip( + switch (side) { + Layout.ttb => EdgeInsets.fromLTRB(0, size.height, 0, 0), + Layout.btt => EdgeInsets.fromLTRB(0, 0, 0, size.height), + Layout.ltr => EdgeInsets.fromLTRB(size.width, 0, 0, 0), + Layout.rtl => EdgeInsets.fromLTRB(0, 0, size.width, 0), + }, + ), + onClosing: () { + if (isCurrent) { + Navigator.pop(context); + } + }, + ); + + return capturedThemes?.wrap(sheet) ?? sheet; + } + + @override + Widget buildModalBarrier() { + if (barrierColor.alpha != 0 && !offstage) { + // changedInternalState is called if barrierColor or offstage updates + final color = animation!.drive( + ColorTween( + begin: barrierColor.withOpacity(0.0), + end: barrierColor, // changedInternalState is called if barrierColor updates + ).chain(CurveTween(curve: barrierCurve)), // changedInternalState is called if barrierCurve updates + ); + return AnimatedModalBarrier( + color: color, + dismissible: barrierDismissible, // changedInternalState is called if barrierDismissible updates + semanticsLabel: barrierLabel, // changedInternalState is called if barrierLabel updates + barrierSemanticsDismissible: semanticsDismissible, + clipDetailsNotifier: _clipDetailsNotifier, + semanticsOnTapHint: barrierOnTapHint, + ); + } else { + return ModalBarrier( + dismissible: barrierDismissible, // changedInternalState is called if barrierDismissible updates + semanticsLabel: barrierLabel, // changedInternalState is called if barrierLabel updates + barrierSemanticsDismissible: semanticsDismissible, + clipDetailsNotifier: _clipDetailsNotifier, + semanticsOnTapHint: barrierOnTapHint, + ); + } + } + + /// Updates the details regarding how the [SemanticsNode.rect] (focus) of the barrier for this [FModalSheetRoute] + /// should be clipped. + /// + /// Returns true if the clipDetails did change and false otherwise. + bool _didChangeBarrierSemanticsClip(EdgeInsets details) { + if (_clipDetailsNotifier.value == details) { + return false; + } + + _clipDetailsNotifier.value = details; + return true; + } + + @override + void dispose() { + _clipDetailsNotifier.dispose(); + super.dispose(); + } + + @override + Duration get transitionDuration => style.enterDuration; + + @override + Duration get reverseTransitionDuration => style.exitDuration; +} diff --git a/forui/lib/src/widgets/sheet/persistent_sheet.dart b/forui/lib/src/widgets/sheet/persistent_sheet.dart new file mode 100644 index 000000000..95a60f2db --- /dev/null +++ b/forui/lib/src/widgets/sheet/persistent_sheet.dart @@ -0,0 +1,255 @@ +import 'dart:math'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter/widgets.dart'; + +import 'package:meta/meta.dart'; + +import 'package:forui/forui.dart'; +import 'package:forui/src/widgets/sheet/sheet.dart'; + +/// Shows a persistent sheet that appears above the current widget. It should have a [FSheets] or [FScaffold] ancestor. +/// +/// The returned [FPersistentSheetController] should always be disposed after use. Not doing so can lead to the sheets +/// accumulating over time, which can negatively impact performance. +/// +/// A closely related widget is a modal sheet which prevents the user from interacting with the rest of the app. +/// +/// [context] is used to look up the [Navigator] and [FSheetStyle] for the sheet. It is only used when the method is +/// called. Its corresponding widget can be safely removed from the tree before the sheet is closed. +/// +/// [style] defaults to [FSheetStyle] from the closest [FTheme] ancestor. +/// +/// [mainAxisMaxRatio] represents the main axis's max constraint ratio for the sheet, depending on [side]. +/// Defaults to 9 / 16. The main axis is the width if [side] is [Layout.ltr] or [Layout.rtl], and the height if [side] +/// is [Layout.ttb] or [Layout.btt]. Consider setting [mainAxisMaxRatio] to null if this sheet has a scrollable child, +/// i.e. [ListView], along the main axis, to have the sheet be draggable. +/// +/// [anchorPoint] is used to pick the closest sub-screen. +/// +/// [keepAliveOffstage] determines whether the sheet should be kept alive even when it is offstage. Setting it to true +/// retains the sheet's state even when it is not visible. Defaults to false. Keeping multiple sheets alive even when +/// offstage can negatively impact performance. +/// +/// [key] is used to identify the sheet. If a key is not provided, a random key will be generated. All sheets in a +/// [FScaffold]/[FSheets] must have unique keys. +/// +/// ## Contract +/// Throws [FlutterError] if: +/// * the [context] does not contain a [FSheets] or [FScaffold] ancestor. +/// * a sheet with the same [key] already exists. +/// +/// See: +/// * https://forui.dev/docs/overlay/persistent-sheet for working examples. +/// * [showFSheet] for showing a sheet in a modal that prevents the user from interacting with the rest of the app. +/// * [FSheetStyle] for customizing a switch's appearance. +/// * [DraggableScrollableSheet], creates a bottom sheet that grows and then becomes scrollable once it reaches its +/// maximum size. +@useResult +FPersistentSheetController showFPersistentSheet({ + required BuildContext context, + required Layout side, + required Widget Function(BuildContext, FPersistentSheetController) builder, + FSheetStyle? style, + double? mainAxisMaxRatio = 9 / 16, + BoxConstraints constraints = const BoxConstraints(), + bool draggable = true, + Offset? anchorPoint, + bool useSafeArea = false, + bool keepAliveOffstage = false, + Key? key, +}) { + final state = context.findAncestorStateOfType(); + if (state == null) { + throw FlutterError.fromParts([ + ErrorSummary( + 'showFSheet(...) called with a context that does not contain a FSheets/FScaffold.', + ), + ErrorDescription( + 'No FSheets/FScaffold ancestor could be found starting from the context that was passed to FSheets/FScaffold.of(). ' + 'This usually happens when the context provided is from the same StatefulWidget as that whose build function ' + 'actually creates the FSheets/FScaffold widget being sought.', + ), + ErrorHint( + 'There are several ways to avoid this problem. The simplest is to use a Builder to get a ' + 'context that is "under" the FSheets/FScaffold.', + ), + context.describeElement('The context used was'), + ]); + } + + key ??= ValueKey(Random().nextInt(2147483647)); + style ??= context.theme.sheetStyle; + + final controller = FPersistentSheetController._( + vsync: state, + style: style, + key: key, + keepAliveOffstage: keepAliveOffstage, + setState: (function) { + if (state.mounted) { + // ignore: invalid_use_of_protected_member + state.setState(function); + } + }, + onDispose: () => state._remove(key!), + ); + + state._add( + controller, + Sheet( + controller: controller._controller, + style: style, + side: side, + mainAxisMaxRatio: mainAxisMaxRatio, + constraints: constraints, + draggable: draggable, + anchorPoint: anchorPoint, + useSafeArea: useSafeArea, + builder: (context) => builder(context, controller), + ), + ); + + controller.show(); + + return controller; +} + +/// A sheet controller. +class FPersistentSheetController { + /// The sheet's key. + final Key key; + + /// True if the sheet to which this controller is attached should be kept alive even when it is offstage. Setting it + /// to true retains the sheet's state even when it is not visible. Defaults to false. Keeping multiple sheets alive + /// even when offstage can negatively impact performance. + final bool keepAliveOffstage; + + /// Marks the sheet as needing to be rebuilt. + final StateSetter setState; + + final AnimationController _controller; + final VoidCallback _onDispose; + + FPersistentSheetController._({ + required TickerProvider vsync, + required FSheetStyle style, + required VoidCallback onDispose, + required this.key, + required this.keepAliveOffstage, + required this.setState, + }) : _controller = Sheet.createAnimationController(vsync, style), + _onDispose = onDispose { + if (kFlutterMemoryAllocationsEnabled) { + FlutterMemoryAllocations.instance.dispatchObjectCreated( + library: 'package:flutter/forui.dart', + className: '$FPersistentSheetController', + object: this, + ); + } + + _controller.addStatusListener((status) => setState.call(() {})); + } + + /// Shows the sheet if it is hidden. + TickerFuture show() => _controller.forward(); + + /// Shows the sheet if it is hidden and hides it if it is shown. + TickerFuture toggle() => _controller.toggle(); + + /// Hides the sheet if it is shown. + TickerFuture hide() => _controller.reverse(); + + /// True if the sheet is shown. + bool get shown => _controller.value != 0; + + /// Disposes of the controller. + void dispose() { + _controller.dispose(); + _onDispose(); + } +} + +/// Sheets that are displayed above its [child]. It is part of [FScaffold], which should be preferred in most cases. +/// +/// A sheet shows information that supplements the primary content of the app without preventing the user from +/// interacting with the app. +/// +/// A closely related widget is a modal sheet, which is an alternative to a menu or a dialog and prevents the user from +/// interacting with the rest of the app. +/// +/// See: +/// * https://forui.dev/docs/overlay/sheet for working examples. +/// * [FSheetStyle] for customizing a switch's appearance. +/// * [showFPersistentSheet] for for displaying a sheet above the current widget. +/// * [showFSheet] for displaying a modal sheet. +/// * [DraggableScrollableSheet], creates a bottom sheet that grows and then becomes scrollable once it reaches its +/// maximum size. +class FSheets extends StatefulWidget { + /// The child. + final Widget child; + + /// Creates a [FSheets]. + const FSheets({required this.child, super.key}); + + @override + State createState() => FSheetsState(); +} + +@visibleForTesting +@internal +class FSheetsState extends State with TickerProviderStateMixin { + final Map sheets = {}; + + @override + Widget build(BuildContext context) => Stack( + children: [ + widget.child, + for (final (controller, sheet) in sheets.values) + if (controller.shown || controller.keepAliveOffstage || controller._controller.status.isAnimating) sheet, + ], + ); + + void _add(FPersistentSheetController controller, Sheet sheet) { + if (!mounted) { + return; + } + + if (sheets.containsKey(controller.key)) { + throw FlutterError.fromParts([ + ErrorSummary('showFSheet(...) called with a key that already exists.'), + ErrorDescription( + 'A sheet with the key, "${controller.key}", already exists. Each sheet must have a unique key.', + ), + ErrorHint( + 'To solve this problem, pass a different key to `showFSheet(...)` or dispose of the other sheet with the same ' + 'key first', + ), + ]); + } + + setState(() => sheets[controller.key] = (controller, sheet)); + } + + Future _remove(Key key) async { + // This checks if the method was called during the build phase, and schedules the removal for the next frame. + // This done as _remove is called in FSheetController.dispose, and subsequently StatefulWidget.dispose, which is + // part of the build phase. + if (mounted && SchedulerBinding.instance.schedulerPhase == SchedulerPhase.idle) { + setState(() => sheets.remove(key)); + } else { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + setState(() => sheets.remove(key)); + } + }); + } + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty>('sheets', sheets)); + } +} diff --git a/forui/lib/src/widgets/sheet/sheet.dart b/forui/lib/src/widgets/sheet/sheet.dart new file mode 100644 index 000000000..194ec447d --- /dev/null +++ b/forui/lib/src/widgets/sheet/sheet.dart @@ -0,0 +1,328 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/widgets.dart'; + +import 'package:meta/meta.dart'; + +import 'package:forui/forui.dart'; +import 'package:forui/src/widgets/sheet/gesture_detector.dart'; +import 'package:forui/src/widgets/sheet/shifted_sheet.dart'; + +@internal +class Sheet extends StatefulWidget { + static AnimationController createAnimationController(TickerProvider vsync, FSheetStyle style) => AnimationController( + duration: style.enterDuration, + reverseDuration: style.exitDuration, + vsync: vsync, + ); + + static void _onClosing() {} + + final AnimationController? controller; + final Animation? animation; + final FSheetStyle style; + final Layout side; + final double? mainAxisMaxRatio; + final BoxConstraints constraints; + final Offset? anchorPoint; + final bool draggable; + final bool useSafeArea; + final WidgetBuilder builder; + final ValueChanged? onChange; + final VoidCallback onClosing; + + const Sheet({ + required this.controller, + required this.style, + required this.side, + required this.mainAxisMaxRatio, + required this.anchorPoint, + required this.useSafeArea, + required this.builder, + this.animation, + this.constraints = const BoxConstraints(), + this.draggable = true, + this.onChange, + this.onClosing = _onClosing, + super.key, + }) : assert(!draggable || controller != null, 'Draggable sheets must have a controller.'); + + @override + State createState() => _SheetState(); + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('controller', controller)) + ..add(DiagnosticsProperty('animation', animation)) + ..add(DiagnosticsProperty('style', style)) + ..add(EnumProperty('side', side)) + ..add(DoubleProperty('mainAxisMaxRatio', mainAxisMaxRatio)) + ..add(DiagnosticsProperty('constraints', constraints)) + ..add(DiagnosticsProperty('anchorPoint', anchorPoint)) + ..add(FlagProperty('draggable', value: draggable, ifTrue: 'draggable')) + ..add(FlagProperty('useSafeArea', value: useSafeArea, ifTrue: 'useSafeArea')) + ..add(ObjectFlagProperty.has('builder', builder)) + ..add(ObjectFlagProperty.has('onChange', onChange)) + ..add(ObjectFlagProperty.has('onClosing', onClosing)); + } +} + +class _SheetState extends State with SingleTickerProviderStateMixin { + static const _cubic = Cubic(0.0, 0.0, 0.2, 1.0); + + final GlobalKey _key = GlobalKey(debugLabel: 'Sheet child'); + late AnimationController _controller; + late Animation _animation; + ParametricCurve _curve = _cubic; + + @override + void initState() { + super.initState(); + _controller = widget.controller ?? Sheet.createAnimationController(this, widget.style); + _animation = widget.animation ?? _controller.view; + } + + @override + void didUpdateWidget(covariant Sheet old) { + super.didUpdateWidget(old); + if (widget.controller != old.controller) { + if (old.controller == null) { + _controller.dispose(); + } + + _controller = widget.controller ?? Sheet.createAnimationController(this, widget.style); + } + } + + @override + Widget build(BuildContext context) { + assert(debugCheckHasMediaQuery(context), ''); + + Widget sheet = DisplayFeatureSubScreen( + anchorPoint: widget.anchorPoint, + child: Align( + alignment: switch (widget.side) { + Layout.ttb => Alignment.topCenter, + Layout.btt => Alignment.bottomCenter, + Layout.ltr => Alignment.centerLeft, + Layout.rtl => Alignment.centerRight, + }, + heightFactor: widget.side.vertical ? 1 : null, + widthFactor: widget.side.vertical ? null : 1, + child: ConstrainedBox( + constraints: widget.constraints, + child: NotificationListener( + key: _key, + onNotification: (notification) { + if (notification.extent == notification.minExtent && notification.shouldCloseOnMinExtent) { + widget.onClosing(); + } + return false; + }, + child: widget.builder(context), + ), + ), + ), + ); + + if (widget.draggable) { + sheet = SheetGestureDetector( + layout: widget.side, + // Allow the sheet to track the user's finger accurately. + onStart: (details) => _curve = Curves.linear, + onUpdate: _dragUpdate, + onEnd: _dragEnd, + child: sheet, + ); + } + + sheet = switch ((widget.side, widget.useSafeArea)) { + (Layout.ttb, true) => SafeArea(top: false, child: sheet), + (Layout.btt, true) => SafeArea(bottom: false, child: sheet), + (Layout.ltr, true) => SafeArea(left: false, child: sheet), + (Layout.rtl, true) => SafeArea(right: false, child: sheet), + (Layout.ttb, false) => MediaQuery.removePadding(context: context, removeBottom: true, child: sheet), + (Layout.btt, false) => MediaQuery.removePadding(context: context, removeTop: true, child: sheet), + (Layout.ltr, false) => MediaQuery.removePadding(context: context, removeRight: true, child: sheet), + (Layout.rtl, false) => MediaQuery.removePadding(context: context, removeLeft: true, child: sheet), + }; + + return AnimatedBuilder( + animation: _animation, + builder: (context, child) => Semantics( + scopesRoute: true, + namesRoute: true, + label: switch (defaultTargetPlatform) { + TargetPlatform.iOS || TargetPlatform.macOS => null, + _ => FLocalizations.of(context).dialogLabel, + }, + explicitChildNodes: true, + child: ClipRect( + child: ShiftedSheet( + side: widget.side, + onChange: widget.onChange, + value: _curve.transform(_animation.value), + mainAxisMaxRatio: widget.mainAxisMaxRatio, + child: child, + ), + ), + ), + child: sheet, + ); + } + + GestureDragUpdateCallback get _dragUpdate => switch (widget.side) { + Layout.ttb => (details) { + if (!_dismissing) { + _controller.value += details.primaryDelta! / _key.currentChildHeight; + } + }, + Layout.btt => (details) { + if (!_dismissing) { + _controller.value -= details.primaryDelta! / _key.currentChildHeight; + } + }, + Layout.ltr => (details) { + if (!_dismissing) { + _controller.value += details.primaryDelta! / _key.currentChildWidth; + } + }, + Layout.rtl => (details) { + if (!_dismissing) { + _controller.value -= details.primaryDelta! / _key.currentChildWidth; + } + }, + }; + + GestureDragEndCallback get _dragEnd { + final double Function(DragEndDetails) velocity = switch (widget.side) { + Layout.ttb => (details) => details.primaryVelocity! / _key.currentChildHeight, + Layout.btt => (details) => -details.primaryVelocity! / _key.currentChildHeight, + Layout.ltr => (details) => details.primaryVelocity! / _key.currentChildWidth, + Layout.rtl => (details) => -details.primaryVelocity! / _key.currentChildWidth, + }; + + return (details) { + if (_dismissing) { + return; + } + + var closing = false; + if (widget.style.flingVelocity < details.primaryVelocity!) { + final flingVelocity = velocity(details); + if (0 < _controller.value) { + _controller.fling(velocity: flingVelocity); + } + + if (flingVelocity < 0) { + closing = true; + } + } else if (_controller.value < widget.style.closeProgressThreshold) { + if (0 < _controller.value) { + _controller.fling(velocity: -1); + } + closing = true; + } else { + _controller.forward(); + } + + // Allow the sheet to animate smoothly from its current position. + _curve = Split(_animation.value, endCurve: _cubic); + if (closing) { + widget.onClosing(); + } + }; + } + + bool get _dismissing => _controller.status == AnimationStatus.reverse; + + @override + void dispose() { + if (widget.controller == null) { + _controller.dispose(); + } + super.dispose(); + } +} + +extension on GlobalKey { + double get currentChildWidth => (currentContext!.findRenderObject()! as RenderBox).size.width; + + double get currentChildHeight => (currentContext!.findRenderObject()! as RenderBox).size.height; +} + +/// A sheet's style. +class FSheetStyle with Diagnosticable { + /// The barrier's color. + final Color barrierColor; + + /// The sheet's background color. + final Color backgroundColor; + + /// The entrance duration. Defaults to 200ms. + final Duration enterDuration; + + /// The exit duration. Defaults to 200ms. + final Duration exitDuration; + + /// The minimum velocity to initiate a fling. Defaults to 700. + /// + /// ## Contract + /// Throws an [AssertionError] if the value is not positive. + final double flingVelocity; + + /// The threshold for determining whether the sheet is closing. Defaults to 0.5. + /// + /// ## Contract + /// Throws an [AssertionError] if the value is not in the range [0, 1]. + final double closeProgressThreshold; + + /// Creates a [FSheetStyle]. + const FSheetStyle({ + required this.barrierColor, + required this.backgroundColor, + this.enterDuration = const Duration(milliseconds: 200), + this.exitDuration = const Duration(milliseconds: 200), + this.flingVelocity = 700, + this.closeProgressThreshold = 0.5, + }); + + /// Creates a [FSheetStyle] that inherits its colors from the given [FColorScheme]. + FSheetStyle.inherit({required FColorScheme colorScheme}) + : this( + barrierColor: colorScheme.barrier, + backgroundColor: colorScheme.background, + ); + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(ColorProperty('barrierColor', barrierColor)) + ..add(ColorProperty('backgroundColor', backgroundColor)) + ..add(DiagnosticsProperty('enterDuration', enterDuration)) + ..add(DiagnosticsProperty('exitDuration', exitDuration)) + ..add(DoubleProperty('flingVelocity', flingVelocity)) + ..add(DoubleProperty('closeProgressThreshold', closeProgressThreshold)); + } + + @override + bool operator ==(Object other) => + identical(this, other) || + other is FSheetStyle && + runtimeType == other.runtimeType && + backgroundColor == other.backgroundColor && + enterDuration == other.enterDuration && + exitDuration == other.exitDuration && + flingVelocity == other.flingVelocity && + closeProgressThreshold == other.closeProgressThreshold; + + @override + int get hashCode => + backgroundColor.hashCode ^ + enterDuration.hashCode ^ + exitDuration.hashCode ^ + flingVelocity.hashCode ^ + closeProgressThreshold.hashCode; +} diff --git a/forui/lib/src/widgets/sheet/shifted_sheet.dart b/forui/lib/src/widgets/sheet/shifted_sheet.dart new file mode 100644 index 000000000..a963a3c10 --- /dev/null +++ b/forui/lib/src/widgets/sheet/shifted_sheet.dart @@ -0,0 +1,189 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; + +import 'package:meta/meta.dart'; + +import 'package:forui/src/foundation/rendering.dart'; + +/// This is based on Material's _BottomSheetLayoutWithSizeListener. +@internal +class ShiftedSheet extends SingleChildRenderObjectWidget { + final Layout side; + final double value; + final double? mainAxisMaxRatio; + final ValueChanged? onChange; + + const ShiftedSheet({ + required this.side, + required this.value, + required this.mainAxisMaxRatio, + required this.onChange, + required super.child, + super.key, + }); + + @override + RenderBox createRenderObject(BuildContext context) => _ShiftedSheet( + side: side, + value: value, + mainAxisMaxRatio: mainAxisMaxRatio, + onChange: onChange, + ); + + @override + // ignore: library_private_types_in_public_api + void updateRenderObject(BuildContext context, _ShiftedSheet renderObject) { + renderObject + ..side = side + ..value = value + ..mainAxisMaxRatio = mainAxisMaxRatio + ..onChange = onChange; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(EnumProperty('side', side)) + ..add(DoubleProperty('value', value)) + ..add(DoubleProperty('mainAxisMaxRatio', mainAxisMaxRatio)) + ..add(ObjectFlagProperty.has('onChange', onChange)); + } +} + +class _ShiftedSheet extends RenderShiftedBox { + Layout _side; + double _value; + double? _mainAxisMaxRatio; + ValueChanged? _onChange; + Size _previous = Size.zero; + + _ShiftedSheet({ + required Layout side, + required double value, + required double? mainAxisMaxRatio, + required ValueChanged? onChange, + }) : _side = side, + _value = value, + _mainAxisMaxRatio = mainAxisMaxRatio, + _onChange = onChange, + super(null); + + @override + void performLayout() { + size = constraints.biggest; + + if (child case final child?) { + final childConstraints = constrainChild(constraints); + assert(childConstraints.debugAssertIsValid(isAppliedConstraint: true), ''); + + child.layout(childConstraints, parentUsesSize: !childConstraints.isTight); + + final childSize = childConstraints.isTight ? childConstraints.smallest : child.size; + child.data.offset = positionChild(size, childSize); + + if (_previous != childSize) { + _previous = childSize; + _onChange?.call(_previous); + } + } + } + + @override + double? computeDryBaseline(covariant BoxConstraints constraints, TextBaseline baseline) { + final child = this.child; + if (child == null) { + return null; + } + + final childConstraints = constrainChild(constraints); + final result = child.getDryBaseline(childConstraints, baseline); + if (result == null) { + return null; + } + + final childSize = childConstraints.isTight ? childConstraints.smallest : child.getDryLayout(childConstraints); + return result + positionChild(constraints.biggest, childSize).dy; + } + + BoxConstraints constrainChild(BoxConstraints constraints) => side.vertical + ? BoxConstraints( + minWidth: constraints.maxWidth, + maxWidth: constraints.maxWidth, + maxHeight: _mainAxisMaxRatio == null ? constraints.maxHeight : constraints.maxHeight * _mainAxisMaxRatio!, + ) + : BoxConstraints( + maxWidth: _mainAxisMaxRatio == null ? constraints.maxWidth : constraints.maxWidth * _mainAxisMaxRatio!, + minHeight: constraints.maxHeight, + maxHeight: constraints.maxHeight, + ); + + Offset positionChild(Size size, Size childSize) => switch (side) { + Layout.ttb => Offset(0, childSize.height * (_value - 1)), + Layout.btt => Offset(0, size.height - childSize.height * _value), + Layout.ltr => Offset(childSize.width * (_value - 1), 0), + Layout.rtl => Offset(size.width - childSize.width * _value, 0), + }; + + @override + Size computeDryLayout(BoxConstraints constraints) => constraints.biggest; + + @override + double computeMinIntrinsicWidth(double height) => 0.0; + + @override + double computeMaxIntrinsicWidth(double height) => 0.0; + + @override + double computeMinIntrinsicHeight(double width) => 0.0; + + @override + double computeMaxIntrinsicHeight(double width) => 0.0; + + Layout get side => _side; + + set side(Layout value) { + if (_side != value) { + _side = value; + markNeedsLayout(); + } + } + + double get value => _value; + + set value(double value) { + if (_value != value) { + _value = value; + markNeedsLayout(); + } + } + + double? get mainAxisMaxRatio => _mainAxisMaxRatio; + + set mainAxisMaxRatio(double? value) { + if (_mainAxisMaxRatio != value) { + _mainAxisMaxRatio = value; + markNeedsLayout(); + } + } + + ValueChanged? get onChange => _onChange; + + set onChange(ValueChanged? value) { + if (_onChange != value) { + _onChange = value; + markNeedsLayout(); + } + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(EnumProperty('side', side)) + ..add(DoubleProperty('value', value)) + ..add(DoubleProperty('mainAxisRatio', mainAxisMaxRatio)) + ..add(ObjectFlagProperty.has('onChange', onChange)); + } +} diff --git a/forui/lib/widgets/sheet.dart b/forui/lib/widgets/sheet.dart new file mode 100644 index 000000000..e87745a3f --- /dev/null +++ b/forui/lib/widgets/sheet.dart @@ -0,0 +1,11 @@ +/// {@category Widgets} +/// +/// A sheet is a panel that slides in from the edge of a screen. +/// +/// See: +/// * https://forui.dev/docs/overlay/sheet for working examples of a modal sheet. +library forui.widgets.sheet; + +export '../src/widgets/sheet/modal_sheet.dart'; +export '../src/widgets/sheet/persistent_sheet.dart' hide FSheetsState; +export '../src/widgets/sheet/sheet.dart' show FSheetStyle; diff --git a/forui/lib/widgets/tile.dart b/forui/lib/widgets/tile.dart index 641a3c84e..c1475827d 100644 --- a/forui/lib/widgets/tile.dart +++ b/forui/lib/widgets/tile.dart @@ -2,7 +2,7 @@ /// /// A tile is typically used to group related information together. /// -/// See https://forui.dev/tile for working examples. +/// See https://forui.dev/docs/tile/tile for working examples. library forui.widgets.tile; export '../src/widgets/tile/tile.dart' hide extractTile; diff --git a/forui/test/golden/scaffold/zinc-dark-sheets.png b/forui/test/golden/scaffold/zinc-dark-sheets.png new file mode 100644 index 000000000..27e6f66d1 Binary files /dev/null and b/forui/test/golden/scaffold/zinc-dark-sheets.png differ diff --git a/forui/test/golden/scaffold/zinc-light-sheets.png b/forui/test/golden/scaffold/zinc-light-sheets.png new file mode 100644 index 000000000..76b26bebc Binary files /dev/null and b/forui/test/golden/scaffold/zinc-light-sheets.png differ diff --git a/forui/test/golden/sheet/modal/constrained-Layout.btt.png b/forui/test/golden/sheet/modal/constrained-Layout.btt.png new file mode 100644 index 000000000..e9a3594a3 Binary files /dev/null and b/forui/test/golden/sheet/modal/constrained-Layout.btt.png differ diff --git a/forui/test/golden/sheet/modal/constrained-Layout.ltr.png b/forui/test/golden/sheet/modal/constrained-Layout.ltr.png new file mode 100644 index 000000000..75d291a0f Binary files /dev/null and b/forui/test/golden/sheet/modal/constrained-Layout.ltr.png differ diff --git a/forui/test/golden/sheet/modal/constrained-Layout.rtl.png b/forui/test/golden/sheet/modal/constrained-Layout.rtl.png new file mode 100644 index 000000000..3f96cc9ec Binary files /dev/null and b/forui/test/golden/sheet/modal/constrained-Layout.rtl.png differ diff --git a/forui/test/golden/sheet/modal/constrained-Layout.ttb.png b/forui/test/golden/sheet/modal/constrained-Layout.ttb.png new file mode 100644 index 000000000..3a0bff0d4 Binary files /dev/null and b/forui/test/golden/sheet/modal/constrained-Layout.ttb.png differ diff --git a/forui/test/golden/sheet/modal/default-Layout.btt.png b/forui/test/golden/sheet/modal/default-Layout.btt.png new file mode 100644 index 000000000..682a8aad4 Binary files /dev/null and b/forui/test/golden/sheet/modal/default-Layout.btt.png differ diff --git a/forui/test/golden/sheet/modal/default-Layout.ltr.png b/forui/test/golden/sheet/modal/default-Layout.ltr.png new file mode 100644 index 000000000..c6dec91bc Binary files /dev/null and b/forui/test/golden/sheet/modal/default-Layout.ltr.png differ diff --git a/forui/test/golden/sheet/modal/default-Layout.rtl.png b/forui/test/golden/sheet/modal/default-Layout.rtl.png new file mode 100644 index 000000000..4887476c8 Binary files /dev/null and b/forui/test/golden/sheet/modal/default-Layout.rtl.png differ diff --git a/forui/test/golden/sheet/modal/default-Layout.ttb.png b/forui/test/golden/sheet/modal/default-Layout.ttb.png new file mode 100644 index 000000000..179d6f703 Binary files /dev/null and b/forui/test/golden/sheet/modal/default-Layout.ttb.png differ diff --git a/forui/test/golden/sheet/modal/scrollable-Layout.btt.png b/forui/test/golden/sheet/modal/scrollable-Layout.btt.png new file mode 100644 index 000000000..44bbf8f28 Binary files /dev/null and b/forui/test/golden/sheet/modal/scrollable-Layout.btt.png differ diff --git a/forui/test/golden/sheet/modal/scrollable-Layout.ltr.png b/forui/test/golden/sheet/modal/scrollable-Layout.ltr.png new file mode 100644 index 000000000..1fb608d80 Binary files /dev/null and b/forui/test/golden/sheet/modal/scrollable-Layout.ltr.png differ diff --git a/forui/test/golden/sheet/modal/scrollable-Layout.rtl.png b/forui/test/golden/sheet/modal/scrollable-Layout.rtl.png new file mode 100644 index 000000000..1fb608d80 Binary files /dev/null and b/forui/test/golden/sheet/modal/scrollable-Layout.rtl.png differ diff --git a/forui/test/golden/sheet/modal/scrollable-Layout.ttb.png b/forui/test/golden/sheet/modal/scrollable-Layout.ttb.png new file mode 100644 index 000000000..44bbf8f28 Binary files /dev/null and b/forui/test/golden/sheet/modal/scrollable-Layout.ttb.png differ diff --git a/forui/test/golden/sheet/persistent/constrained-Layout.btt.png b/forui/test/golden/sheet/persistent/constrained-Layout.btt.png new file mode 100644 index 000000000..a7fe2c551 Binary files /dev/null and b/forui/test/golden/sheet/persistent/constrained-Layout.btt.png differ diff --git a/forui/test/golden/sheet/persistent/constrained-Layout.ltr.png b/forui/test/golden/sheet/persistent/constrained-Layout.ltr.png new file mode 100644 index 000000000..535853022 Binary files /dev/null and b/forui/test/golden/sheet/persistent/constrained-Layout.ltr.png differ diff --git a/forui/test/golden/sheet/persistent/constrained-Layout.rtl.png b/forui/test/golden/sheet/persistent/constrained-Layout.rtl.png new file mode 100644 index 000000000..42926476e Binary files /dev/null and b/forui/test/golden/sheet/persistent/constrained-Layout.rtl.png differ diff --git a/forui/test/golden/sheet/persistent/constrained-Layout.ttb.png b/forui/test/golden/sheet/persistent/constrained-Layout.ttb.png new file mode 100644 index 000000000..ebfec917a Binary files /dev/null and b/forui/test/golden/sheet/persistent/constrained-Layout.ttb.png differ diff --git a/forui/test/golden/sheet/persistent/default-Layout.btt.png b/forui/test/golden/sheet/persistent/default-Layout.btt.png new file mode 100644 index 000000000..1b551076b Binary files /dev/null and b/forui/test/golden/sheet/persistent/default-Layout.btt.png differ diff --git a/forui/test/golden/sheet/persistent/default-Layout.ltr.png b/forui/test/golden/sheet/persistent/default-Layout.ltr.png new file mode 100644 index 000000000..f4d6956bb Binary files /dev/null and b/forui/test/golden/sheet/persistent/default-Layout.ltr.png differ diff --git a/forui/test/golden/sheet/persistent/default-Layout.rtl.png b/forui/test/golden/sheet/persistent/default-Layout.rtl.png new file mode 100644 index 000000000..a1ff39695 Binary files /dev/null and b/forui/test/golden/sheet/persistent/default-Layout.rtl.png differ diff --git a/forui/test/golden/sheet/persistent/default-Layout.ttb.png b/forui/test/golden/sheet/persistent/default-Layout.ttb.png new file mode 100644 index 000000000..8204b832f Binary files /dev/null and b/forui/test/golden/sheet/persistent/default-Layout.ttb.png differ diff --git a/forui/test/golden/sheet/persistent/scrollable-Layout.btt.png b/forui/test/golden/sheet/persistent/scrollable-Layout.btt.png new file mode 100644 index 000000000..6c4fe6265 Binary files /dev/null and b/forui/test/golden/sheet/persistent/scrollable-Layout.btt.png differ diff --git a/forui/test/golden/sheet/persistent/scrollable-Layout.ltr.png b/forui/test/golden/sheet/persistent/scrollable-Layout.ltr.png new file mode 100644 index 000000000..3be3228b3 Binary files /dev/null and b/forui/test/golden/sheet/persistent/scrollable-Layout.ltr.png differ diff --git a/forui/test/golden/sheet/persistent/scrollable-Layout.rtl.png b/forui/test/golden/sheet/persistent/scrollable-Layout.rtl.png new file mode 100644 index 000000000..3be3228b3 Binary files /dev/null and b/forui/test/golden/sheet/persistent/scrollable-Layout.rtl.png differ diff --git a/forui/test/golden/sheet/persistent/scrollable-Layout.ttb.png b/forui/test/golden/sheet/persistent/scrollable-Layout.ttb.png new file mode 100644 index 000000000..6c4fe6265 Binary files /dev/null and b/forui/test/golden/sheet/persistent/scrollable-Layout.ttb.png differ diff --git a/forui/test/src/test_scaffold.dart b/forui/test/src/test_scaffold.dart index 5be167bfe..761a20d1a 100644 --- a/forui/test/src/test_scaffold.dart +++ b/forui/test/src/test_scaffold.dart @@ -14,6 +14,7 @@ class TestScaffold extends StatelessWidget { static final blueScreen = FThemeData.inherit( colorScheme: const FColorScheme( brightness: Brightness.light, + barrier: Color(0xFF03A9F4), background: Color(0xFF03A9F4), foreground: Color(0xFF03A9F4), primary: Color(0xFF03A9F4), diff --git a/forui/test/src/theme/color_scheme_test.dart b/forui/test/src/theme/color_scheme_test.dart index e6143f828..e85934231 100644 --- a/forui/test/src/theme/color_scheme_test.dart +++ b/forui/test/src/theme/color_scheme_test.dart @@ -9,6 +9,7 @@ void main() { group('FColorScheme', () { const scheme = FColorScheme( brightness: Brightness.light, + barrier: Color(0xFF03A9F4), background: Colors.black, foreground: Colors.black12, primary: Colors.black26, @@ -30,6 +31,7 @@ void main() { test('all arguments', () { final copy = scheme.copyWith( brightness: Brightness.dark, + barrier: Colors.red, background: Colors.red, foreground: Colors.greenAccent, primary: Colors.yellow, @@ -48,6 +50,7 @@ void main() { ); expect(copy.brightness, equals(Brightness.dark)); + expect(copy.barrier, equals(Colors.red)); expect(copy.background, equals(Colors.red)); expect(copy.foreground, equals(Colors.greenAccent)); expect(copy.primary, equals(Colors.yellow)); @@ -74,6 +77,7 @@ void main() { builder.properties.map((p) => p.toString()), [ EnumProperty('brightness', Brightness.light), + ColorProperty('barrier', const Color(0xFF03A9F4)), ColorProperty('background', Colors.black), ColorProperty('foreground', Colors.black12), ColorProperty('primary', Colors.black26), diff --git a/forui/test/src/theme/typography_test.dart b/forui/test/src/theme/typography_test.dart index 0474ac7c0..99f6cf615 100644 --- a/forui/test/src/theme/typography_test.dart +++ b/forui/test/src/theme/typography_test.dart @@ -52,6 +52,7 @@ void main() { group('inherit constructor', () { const colorScheme = FColorScheme( brightness: Brightness.light, + barrier: Colors.black12, background: Colors.black, foreground: Colors.black12, primary: Colors.black26, diff --git a/forui/test/src/widgets/scaffold_golden_test.dart b/forui/test/src/widgets/scaffold_golden_test.dart index 8c33e43eb..f1109f066 100644 --- a/forui/test/src/widgets/scaffold_golden_test.dart +++ b/forui/test/src/widgets/scaffold_golden_test.dart @@ -43,6 +43,59 @@ void main() { await expectLater(find.byType(TestScaffold), matchesGoldenFile('scaffold/${theme.name}.png')); }); + + testWidgets('${theme.name} - have sheets', (tester) async { + await tester.pumpWidget( + TestScaffold( + theme: theme.data, + child: FScaffold( + header: Row( + children: [ + Expanded( + child: Builder( + builder: (context) => FButton.icon( + child: FIcon(FAssets.icons.chevronRight), + onPress: () { + showFPersistentSheet( + context: context, + side: Layout.ltr, + draggable: false, + builder: (context, controller) => Container( + height: double.infinity, + width: double.infinity, + decoration: BoxDecoration( + border: Border.all(color: context.theme.colorScheme.primary), + color: context.theme.colorScheme.background, + ), + child: const Center(child: Text('sheet')), + ), + ); + }, + ), + ), + ), + ], + ), + content: const Placeholder(), + footer: Row( + children: [ + Expanded( + child: Container( + decoration: const BoxDecoration(color: Colors.green), + height: 100, + ), + ), + ], + ), + ), + ), + ); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(const Duration(seconds: 1)); + + await expectLater(find.byType(TestScaffold), matchesGoldenFile('scaffold/${theme.name}-sheets.png')); + }); } }); } diff --git a/forui/test/src/widgets/sheet/modal_sheet_golden_test.dart b/forui/test/src/widgets/sheet/modal_sheet_golden_test.dart new file mode 100644 index 000000000..e5bf803f7 --- /dev/null +++ b/forui/test/src/widgets/sheet/modal_sheet_golden_test.dart @@ -0,0 +1,105 @@ +@Tags(['golden']) +library; + +import 'package:flutter/material.dart'; + +import 'package:flutter_test/flutter_test.dart'; + +import 'package:forui/forui.dart'; +import '../../test_scaffold.dart'; + +void main() { + group('FModalSheet', () { + for (final side in Layout.values) { + testWidgets('default - $side', (tester) async { + await tester.pumpWidget( + TestScaffold.app( + child: Builder( + builder: (context) => FButton.icon( + child: FIcon(FAssets.icons.chevronRight), + onPress: () => showFSheet( + context: context, + side: side, + builder: (context) => Container( + height: double.infinity, + width: double.infinity, + color: context.theme.colorScheme.background, + child: const Center(child: Text('Sheet')), + ), + ), + ), + ), + ), + ); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(); + + await expectLater(find.byType(TestScaffold), matchesGoldenFile('sheet/modal/default-$side.png')); + }); + + testWidgets('constrained - $side', (tester) async { + await tester.pumpWidget( + TestScaffold.app( + child: Builder( + builder: (context) => FButton.icon( + child: FIcon(FAssets.icons.chevronRight), + onPress: () => showFSheet( + context: context, + side: side, + constraints: const BoxConstraints(maxHeight: 200, maxWidth: 200), + builder: (context) => Container( + height: double.infinity, + width: double.infinity, + color: context.theme.colorScheme.background, + child: const Center(child: Text('Sheet')), + ), + ), + ), + ), + ), + ); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(); + + await expectLater(find.byType(TestScaffold), matchesGoldenFile('sheet/modal/constrained-$side.png')); + }); + + testWidgets('scrollable - $side', (tester) async { + await tester.pumpWidget( + TestScaffold.app( + child: Builder( + builder: (context) => FButton.icon( + child: FIcon(FAssets.icons.chevronRight), + onPress: () => showFSheet( + context: context, + side: side, + mainAxisMaxRatio: null, + builder: (context) => Container( + height: double.infinity, + width: double.infinity, + color: context.theme.colorScheme.background, + child: ListView.builder( + scrollDirection: side.vertical ? Axis.vertical : Axis.horizontal, + itemBuilder: (context, index) => Padding( + padding: const EdgeInsets.all(8.0), + child: Text('Tile $index'), + ), + itemCount: 20, + ), + ), + ), + ), + ), + ), + ); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(); + + await expectLater(find.byType(TestScaffold), matchesGoldenFile('sheet/modal/scrollable-$side.png')); + }); + } + }); +} diff --git a/forui/test/src/widgets/sheet/modal_sheet_test.dart b/forui/test/src/widgets/sheet/modal_sheet_test.dart new file mode 100644 index 000000000..91606b011 --- /dev/null +++ b/forui/test/src/widgets/sheet/modal_sheet_test.dart @@ -0,0 +1,108 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter_test/flutter_test.dart'; + +import 'package:forui/forui.dart'; +import '../../test_scaffold.dart'; + +void main() { + group('FModalSheet', () { + testWidgets('tap on barrier dismisses', (tester) async { + await tester.pumpWidget( + TestScaffold.app( + child: Builder( + builder: (context) => FButton.icon( + child: FIcon(FAssets.icons.chevronRight), + onPress: () => showFSheet( + context: context, + side: Layout.btt, + builder: (context) => Container( + height: double.infinity, + width: double.infinity, + color: context.theme.colorScheme.background, + child: const Center(child: Text('sheet')), + ), + ), + ), + ), + ), + ); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(const Duration(seconds: 1)); + expect(find.text('sheet'), findsOne); + + await tester.tapAt(const Offset(100, 100)); + await tester.pumpAndSettle(const Duration(seconds: 1)); + expect(find.text('sheet'), findsNothing); + }); + + for (final (side, offset) in [ + (Layout.btt, const Offset(0, 300)), + (Layout.ttb, const Offset(0, -300)), + (Layout.ltr, const Offset(-300, 0)), + (Layout.rtl, const Offset(300, 0)), + ]) { + testWidgets('drag to dismiss - $side', (tester) async { + await tester.pumpWidget( + TestScaffold.app( + child: Builder( + builder: (context) => FButton.icon( + child: FIcon(FAssets.icons.chevronRight), + onPress: () => showFSheet( + context: context, + side: side, + builder: (context) => Container( + height: double.infinity, + width: double.infinity, + color: context.theme.colorScheme.background, + child: const Center(child: Text('sheet')), + ), + ), + ), + ), + ), + ); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(const Duration(seconds: 1)); + expect(find.text('sheet'), findsOne); + + await tester.drag(find.text('sheet'), offset); + await tester.pumpAndSettle(const Duration(seconds: 1)); + expect(find.text('sheet'), findsNothing); + }); + + testWidgets('drag to dismiss on non-draggable - $side', (tester) async { + await tester.pumpWidget( + TestScaffold.app( + child: Builder( + builder: (context) => FButton.icon( + child: FIcon(FAssets.icons.chevronRight), + onPress: () => showFSheet( + context: context, + side: side, + draggable: false, + builder: (context) => Container( + height: double.infinity, + width: double.infinity, + color: context.theme.colorScheme.background, + child: const Center(child: Text('sheet')), + ), + ), + ), + ), + ), + ); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(const Duration(seconds: 1)); + expect(find.text('sheet'), findsOne); + + await tester.drag(find.text('sheet'), offset); + await tester.pumpAndSettle(const Duration(seconds: 1)); + expect(find.text('sheet'), findsOne); + }); + } + }); +} diff --git a/forui/test/src/widgets/sheet/persistent_sheet_golden_test.dart b/forui/test/src/widgets/sheet/persistent_sheet_golden_test.dart new file mode 100644 index 000000000..7d17ca50a --- /dev/null +++ b/forui/test/src/widgets/sheet/persistent_sheet_golden_test.dart @@ -0,0 +1,139 @@ +@Tags(['golden']) +library; + +import 'package:flutter/material.dart'; + +import 'package:flutter_test/flutter_test.dart'; + +import 'package:forui/forui.dart'; +import '../../test_scaffold.dart'; + +void main() { + FPersistentSheetController? controller; + + group('showFSheet', () { + for (final side in Layout.values) { + testWidgets('default - $side', (tester) async { + await tester.pumpWidget( + TestScaffold.app( + child: FSheets( + child: Builder( + builder: (context) => Center( + child: FButton.icon( + child: FIcon(FAssets.icons.chevronRight), + onPress: () { + controller = showFPersistentSheet( + context: context, + side: side, + builder: (context, controller) => Container( + height: double.infinity, + width: double.infinity, + decoration: BoxDecoration( + border: Border.all(color: context.theme.colorScheme.primary), + color: context.theme.colorScheme.background, + ), + child: const Center(child: Text('Sheet')), + ), + ); + }, + ), + ), + ), + ), + ), + ); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(); + + await expectLater(find.byType(TestScaffold), matchesGoldenFile('sheet/persistent/default-$side.png')); + }); + + testWidgets('constrained - $side', (tester) async { + await tester.pumpWidget( + TestScaffold.app( + child: FSheets( + child: Builder( + builder: (context) => Center( + child: FButton.icon( + child: FIcon(FAssets.icons.chevronRight), + onPress: () { + controller = showFPersistentSheet( + context: context, + side: side, + constraints: const BoxConstraints(maxHeight: 200, maxWidth: 200), + builder: (context, controller) => Container( + height: double.infinity, + width: double.infinity, + decoration: BoxDecoration( + border: Border.all(color: context.theme.colorScheme.primary), + color: context.theme.colorScheme.background, + ), + child: const Center(child: Text('Sheet')), + ), + ); + }, + ), + ), + ), + ), + ), + ); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(); + + await expectLater(find.byType(TestScaffold), matchesGoldenFile('sheet/persistent/constrained-$side.png')); + }); + + testWidgets('scrollable - $side', (tester) async { + await tester.pumpWidget( + TestScaffold.app( + child: FSheets( + child: Builder( + builder: (context) => Center( + child: FButton.icon( + child: FIcon(FAssets.icons.chevronRight), + onPress: () { + controller = showFPersistentSheet( + context: context, + side: side, + mainAxisMaxRatio: null, + builder: (context, controller) => Container( + height: double.infinity, + width: double.infinity, + decoration: BoxDecoration( + border: Border.all(color: context.theme.colorScheme.primary), + color: context.theme.colorScheme.background, + ), + child: ListView.builder( + scrollDirection: side.vertical ? Axis.vertical : Axis.horizontal, + itemBuilder: (context, index) => Padding( + padding: const EdgeInsets.all(8.0), + child: Text('Tile $index'), + ), + itemCount: 20, + ), + ), + ); + }, + ), + ), + ), + ), + ), + ); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(); + + await expectLater(find.byType(TestScaffold), matchesGoldenFile('sheet/persistent/scrollable-$side.png')); + }); + } + }); + + tearDown(() { + controller?.dispose(); + controller = null; + }); +} diff --git a/forui/test/src/widgets/sheet/persistent_sheet_test.dart b/forui/test/src/widgets/sheet/persistent_sheet_test.dart new file mode 100644 index 000000000..86806ba3e --- /dev/null +++ b/forui/test/src/widgets/sheet/persistent_sheet_test.dart @@ -0,0 +1,264 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter_test/flutter_test.dart'; + +import 'package:forui/forui.dart'; +import 'package:forui/src/widgets/sheet/persistent_sheet.dart'; +import '../../test_scaffold.dart'; + +void main() { + FPersistentSheetController? controller; + + group('showFPersistentSheet', () { + testWidgets('shows sheet', (tester) async { + await tester.pumpWidget( + TestScaffold.app( + child: FSheets( + child: Builder( + builder: (context) => FButton.icon( + child: FIcon(FAssets.icons.chevronRight), + onPress: () { + controller = showFPersistentSheet( + context: context, + side: Layout.btt, + builder: (context, controller) => Container( + height: double.infinity, + width: double.infinity, + color: context.theme.colorScheme.background, + child: const Center(child: Text('sheet')), + ), + ); + }, + ), + ), + ), + ), + ); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(const Duration(seconds: 1)); + expect(find.text('sheet'), findsOne); + + await tester.drag(find.text('sheet'), const Offset(0, 200)); + await tester.pumpAndSettle(const Duration(seconds: 1)); + expect(find.text('sheet'), findsNothing); + }); + + testWidgets('shows sheet when keepAliveOffstage is true', (tester) async { + await tester.pumpWidget( + TestScaffold.app( + child: FSheets( + child: Builder( + builder: (context) => FButton.icon( + child: FIcon(FAssets.icons.chevronRight), + onPress: () { + controller = showFPersistentSheet( + context: context, + side: Layout.btt, + keepAliveOffstage: true, + builder: (context, controller) => Container( + height: double.infinity, + width: double.infinity, + color: context.theme.colorScheme.background, + child: const Center(child: Text('sheet')), + ), + ); + }, + ), + ), + ), + ), + ); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(const Duration(seconds: 1)); + expect(find.text('sheet'), findsOne); + + await tester.drag(find.text('sheet'), const Offset(0, 200)); + await tester.pumpAndSettle(const Duration(seconds: 1)); + expect(find.text('sheet'), findsOne); + }); + + testWidgets('no FSheets ancestor', (tester) async { + await tester.pumpWidget( + TestScaffold.app( + child: Builder( + builder: (context) => FButton.icon( + child: FIcon(FAssets.icons.chevronRight), + onPress: () { + controller = showFPersistentSheet( + context: context, + side: Layout.btt, + builder: (context, controller) => Container( + height: double.infinity, + width: double.infinity, + color: context.theme.colorScheme.background, + child: const Center(child: Text('sheet')), + ), + ); + }, + ), + ), + ), + ); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(const Duration(seconds: 1)); + + expect(tester.takeException(), isA()); + }); + + testWidgets('duplicate key', (tester) async { + await tester.pumpWidget( + TestScaffold.app( + child: FSheets( + child: Builder( + builder: (context) => FButton.icon( + child: FIcon(FAssets.icons.chevronRight), + onPress: () { + controller = showFPersistentSheet( + key: const Key('test'), + context: context, + side: Layout.btt, + builder: (context, controller) => Container( + height: double.infinity, + width: double.infinity, + color: context.theme.colorScheme.background, + child: const Center(child: Text('sheet')), + ), + ); + }, + ), + ), + ), + ), + ); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(const Duration(seconds: 1)); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(const Duration(seconds: 1)); + + expect(tester.takeException(), isA()); + }); + + testWidgets('dispose removes sheet', (tester) async { + late FPersistentSheetController controller; + const key = Key('test'); + + await tester.pumpWidget( + TestScaffold.app( + child: FSheets( + key: key, + child: Builder( + builder: (context) => FButton.icon( + child: FIcon(FAssets.icons.chevronRight), + onPress: () { + controller = showFPersistentSheet( + context: context, + side: Layout.btt, + builder: (context, controller) => Container( + height: double.infinity, + width: double.infinity, + color: context.theme.colorScheme.background, + child: const Center(child: Text('sheet')), + ), + ); + }, + ), + ), + ), + ), + ); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(const Duration(seconds: 1)); + expect(tester.state(find.byKey(key)).sheets.isEmpty, false); + + controller.dispose(); + expect(tester.state(find.byKey(key)).sheets.isEmpty, true); + }); + + for (final (side, offset) in [ + (Layout.btt, const Offset(0, 300)), + (Layout.ttb, const Offset(0, -300)), + (Layout.ltr, const Offset(-300, 0)), + (Layout.rtl, const Offset(300, 0)), + ]) { + testWidgets('drag to dismiss - $side', (tester) async { + await tester.pumpWidget( + TestScaffold.app( + child: FSheets( + child: Builder( + builder: (context) => FButton.icon( + child: FIcon(FAssets.icons.chevronRight), + onPress: () { + controller = showFPersistentSheet( + context: context, + side: side, + builder: (context, controller) => Container( + height: double.infinity, + width: double.infinity, + color: context.theme.colorScheme.background, + child: const Center(child: Text('sheet')), + ), + ); + }, + ), + ), + ), + ), + ); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(const Duration(seconds: 1)); + expect(find.text('sheet'), findsOne); + + await tester.drag(find.text('sheet'), offset); + await tester.pumpAndSettle(const Duration(seconds: 1)); + expect(find.text('sheet'), findsNothing); + }); + + testWidgets('drag to dismiss on non-draggable - $side', (tester) async { + await tester.pumpWidget( + TestScaffold.app( + child: FSheets( + child: Builder( + builder: (context) => FButton.icon( + child: FIcon(FAssets.icons.chevronRight), + onPress: () { + controller = showFPersistentSheet( + context: context, + side: side, + draggable: false, + builder: (context, controller) => Container( + height: double.infinity, + width: double.infinity, + color: context.theme.colorScheme.background, + child: const Center(child: Text('sheet')), + ), + ); + }, + ), + ), + ), + ), + ); + + await tester.tap(find.byType(FButton)); + await tester.pumpAndSettle(const Duration(seconds: 1)); + expect(find.text('sheet'), findsOne); + + await tester.drag(find.text('sheet'), offset); + await tester.pumpAndSettle(const Duration(seconds: 1)); + expect(find.text('sheet'), findsOne); + }); + } + + tearDown(() { + controller?.dispose(); + controller = null; + }); + }); +} diff --git a/forui/tool/add_arb_value.dart b/forui/tool/add_arb_value.dart new file mode 100644 index 000000000..4b1530d4c --- /dev/null +++ b/forui/tool/add_arb_value.dart @@ -0,0 +1,31 @@ +// ignore_for_file: avoid_dynamic_calls + +import 'dart:convert'; +import 'dart:io'; + +final pattern = RegExp(r'material_([\w_]+)\.arb'); + +// Change this to add other keys. +const key = 'scrimLabel'; + +void main() { + // I usually just download all Material localization files into the .temp folder. + for (final source in Directory('.temp').listSync().whereType()) { + final material = json.decode(source.readAsStringSync()); + if (!material.containsKey(key)) { + continue; + } + + final locale = pattern.firstMatch(source.path)?.group(1); + if (locale == 'en') { + continue; + } + + final target = File('lib/l10n/f_$locale.arb'); + + final forui = json.decode(target.readAsStringSync()); + forui[key] = material[key]; + + target.writeAsStringSync(const JsonEncoder.withIndent(' ').convert(forui)); + } +} diff --git a/samples/lib/main.dart b/samples/lib/main.dart index b60e08667..e6089ab9f 100644 --- a/samples/lib/main.dart +++ b/samples/lib/main.dart @@ -67,6 +67,8 @@ class _AppRouter extends RootStackRouter { AutoRoute(path: '/icon/image', page: ImageIconRoute.page), AutoRoute(path: '/label/vertical', page: VerticalLabelRoute.page), AutoRoute(path: '/label/horizontal', page: HorizontalLabelRoute.page), + AutoRoute(path: '/modal-sheet/default', page: ModalSheetRoute.page), + AutoRoute(path: '/modal-sheet/draggable', page: DraggableModalSheetRoute.page), AutoRoute(path: '/popover/default', page: PopoverRoute.page), AutoRoute(path: '/popover-menu/default', page: PopoverMenuRoute.page), AutoRoute(path: '/portal/default', page: PortalRoute.page), @@ -91,6 +93,8 @@ class _AppRouter extends RootStackRouter { AutoRoute(path: '/select-tile-group/multi-value', page: SelectTileGroupMultiValueRoute.page), AutoRoute(path: '/select-tile-group/radio', page: SelectTileGroupRadioRoute.page), AutoRoute(path: '/select-tile-group/suffix', page: SelectTileGroupSuffixRoute.page), + AutoRoute(path: '/persistent-sheet/default', page: PersistentSheetRoute.page), + AutoRoute(path: '/persistent-sheet/draggable', page: DraggablePersistentSheetRoute.page), AutoRoute(path: '/slider/default', page: SliderRoute.page), AutoRoute(path: '/slider/tooltip', page: TooltipSliderRoute.page), AutoRoute(path: '/slider/marks', page: MarksSliderRoute.page), diff --git a/samples/lib/widgets/modal_sheet.dart b/samples/lib/widgets/modal_sheet.dart new file mode 100644 index 000000000..7dd023b30 --- /dev/null +++ b/samples/lib/widgets/modal_sheet.dart @@ -0,0 +1,158 @@ +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; + +import 'package:auto_route/auto_route.dart'; +import 'package:forui/forui.dart'; + +import 'package:forui_samples/sample.dart'; + +@RoutePage() +class ModalSheetPage extends Sample { + ModalSheetPage({ + @queryParam super.theme, + }); + + @override + Widget sample(BuildContext context) => Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + FButton( + label: const Text('Left'), + onPress: () => showFSheet( + context: context, + side: Layout.ltr, + builder: (context) => const Form(side: Layout.ltr), + ), + ), + const SizedBox(height: 5), + FButton( + label: const Text('Top'), + onPress: () => showFSheet( + context: context, + side: Layout.ttb, + builder: (context) => const Form(side: Layout.ttb), + ), + ), + const SizedBox(height: 5), + FButton( + label: const Text('Right'), + onPress: () => showFSheet( + context: context, + side: Layout.rtl, + builder: (context) => const Form(side: Layout.rtl), + ), + ), + const SizedBox(height: 5), + FButton( + label: const Text('Bottom'), + onPress: () => showFSheet( + context: context, + side: Layout.btt, + builder: (context) => const Form(side: Layout.btt), + ), + ), + ], + ); +} + +class Form extends StatelessWidget { + final Layout side; + + const Form({required this.side, super.key}); + + @override + Widget build(BuildContext context) => Container( + height: double.infinity, + width: double.infinity, + decoration: BoxDecoration( + color: context.theme.colorScheme.background, + border: side.vertical + ? Border.symmetric(horizontal: BorderSide(color: context.theme.colorScheme.border)) + : Border.symmetric(vertical: BorderSide(color: context.theme.colorScheme.border)), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8.0), + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Account', + style: context.theme.typography.xl2.copyWith( + fontWeight: FontWeight.w600, + color: context.theme.colorScheme.foreground, + height: 1.5, + ), + ), + Text( + 'Make changes to your account here. Click save when you are done.', + style: context.theme.typography.sm.copyWith( + color: context.theme.colorScheme.mutedForeground, + ), + ), + const SizedBox(height: 8), + SizedBox( + width: 450, + child: Column( + children: [ + const FTextField( + label: Text('Name'), + hint: 'John Renalo', + ), + const SizedBox(height: 10), + const FTextField( + label: Text('Email'), + hint: 'john@doe.com', + ), + const SizedBox(height: 16), + FButton( + label: const Text('Save'), + onPress: () => Navigator.of(context).pop(), + ), + ], + ), + ), + ], + ), + ), + ), + ); +} + +@RoutePage() +class DraggableModalSheetPage extends Sample { + DraggableModalSheetPage({ + @queryParam super.theme, + }); + + @override + Widget sample(BuildContext context) => FButton( + label: const Text('Click me'), + onPress: () => showFSheet( + context: context, + side: Layout.btt, + mainAxisMaxRatio: null, + builder: (context) => DraggableScrollableSheet( + expand: false, + builder: (context, controller) => ScrollConfiguration( + // This is required to enable dragging on desktop. + // See https://github.com/flutter/flutter/issues/101903 for more information. + behavior: ScrollConfiguration.of(context).copyWith( + dragDevices: { + PointerDeviceKind.touch, + PointerDeviceKind.mouse, + PointerDeviceKind.trackpad, + }, + ), + child: FTileGroup.builder( + count: 25, + controller: controller, + tileBuilder: (context, index) => FTile(title: Text('Tile $index')), + ), + ), + ), + ), + ); +} diff --git a/samples/lib/widgets/persistent_sheet.dart b/samples/lib/widgets/persistent_sheet.dart new file mode 100644 index 000000000..0e5be8da6 --- /dev/null +++ b/samples/lib/widgets/persistent_sheet.dart @@ -0,0 +1,203 @@ +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; + +import 'package:auto_route/auto_route.dart'; +import 'package:forui/forui.dart'; + +import 'package:forui_samples/sample.dart'; + +@RoutePage() +class PersistentSheetPage extends StatefulSample { + final bool keepAliveOffstage; + + PersistentSheetPage({ + @queryParam super.theme, + @queryParam this.keepAliveOffstage = false, + }); + + @override + State createState() => _SheetsState(); +} + +class _SheetsState extends StatefulSampleState { + final Map _controllers = {}; + + @override + Widget sample(BuildContext context) { + VoidCallback onPress(Layout side) => () { + for (final MapEntry(:key, :value) in _controllers.entries) { + if (key != side && value.shown) { + return; + } + } + + var controller = _controllers[side]; + if (controller == null) { + controller = _controllers[side] ??= showFPersistentSheet( + context: context, + side: side, + keepAliveOffstage: widget.keepAliveOffstage, + builder: (context, controller) => Form(side: side, controller: controller), + ); + } else { + controller.toggle(); + } + }; + + return Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + FButton( + label: const Text('Left'), + onPress: onPress(Layout.ltr), + ), + const SizedBox(height: 5), + FButton( + label: const Text('Top'), + onPress: onPress(Layout.ttb), + ), + const SizedBox(height: 5), + FButton( + label: const Text('Right'), + onPress: onPress(Layout.rtl), + ), + const SizedBox(height: 5), + FButton( + label: const Text('Bottom'), + onPress: onPress(Layout.btt), + ), + ], + ); + } + + @override + void dispose() { + for (final controller in _controllers.values) { + controller.dispose(); + } + super.dispose(); + } +} + +class Form extends StatelessWidget { + final Layout side; + final FPersistentSheetController controller; + + const Form({required this.side, required this.controller, super.key}); + + @override + Widget build(BuildContext context) => Container( + height: double.infinity, + width: double.infinity, + decoration: BoxDecoration( + color: context.theme.colorScheme.background, + border: side.vertical + ? Border.symmetric(horizontal: BorderSide(color: context.theme.colorScheme.border)) + : Border.symmetric(vertical: BorderSide(color: context.theme.colorScheme.border)), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8.0), + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Account', + style: context.theme.typography.xl2.copyWith( + fontWeight: FontWeight.w600, + color: context.theme.colorScheme.foreground, + height: 1.5, + ), + ), + Text( + 'Make changes to your account here. Click save when you are done.', + style: context.theme.typography.sm.copyWith( + color: context.theme.colorScheme.mutedForeground, + ), + ), + const SizedBox(height: 8), + SizedBox( + width: 450, + child: Column( + children: [ + const FTextField( + label: Text('Name'), + hint: 'John Renalo', + ), + const SizedBox(height: 10), + const FTextField( + label: Text('Email'), + hint: 'john@doe.com', + ), + const SizedBox(height: 16), + FButton( + label: const Text('Save'), + onPress: controller.toggle, + ), + ], + ), + ), + ], + ), + ), + ), + ); +} + +@RoutePage() +class DraggablePersistentSheetPage extends StatefulSample { + DraggablePersistentSheetPage({ + @queryParam super.theme, + }); + + @override + State createState() => _DraggableState(); +} + +class _DraggableState extends StatefulSampleState { + FPersistentSheetController? controller; + + @override + Widget sample(BuildContext context) => FButton( + label: const Text('Click me'), + onPress: () { + if (controller != null) { + controller!.toggle(); + return; + } + + controller = showFPersistentSheet( + context: context, + side: Layout.btt, + mainAxisMaxRatio: null, + builder: (context, _) => DraggableScrollableSheet( + expand: false, + builder: (context, controller) => ScrollConfiguration( + // This is required to enable dragging on desktop. + // See https://github.com/flutter/flutter/issues/101903 for more information. + behavior: ScrollConfiguration.of(context).copyWith( + dragDevices: { + PointerDeviceKind.touch, + PointerDeviceKind.mouse, + PointerDeviceKind.trackpad, + }, + ), + child: FTileGroup.builder( + count: 25, + controller: controller, + tileBuilder: (context, index) => FTile(title: Text('Tile $index')), + ), + ), + ), + ); + }, + ); + + @override + void dispose() { + controller?.dispose(); + super.dispose(); + } +}