diff --git a/package/lib/smooth_sheets.dart b/package/lib/smooth_sheets.dart index 5d1137fb..76846e4f 100644 --- a/package/lib/smooth_sheets.dart +++ b/package/lib/smooth_sheets.dart @@ -14,6 +14,7 @@ export 'src/foundation/sheet_content_scaffold.dart'; export 'src/foundation/sheet_controller.dart' hide SheetControllerScope; export 'src/foundation/sheet_extent.dart'; export 'src/foundation/sheet_physics.dart'; +export 'src/foundation/theme.dart'; export 'src/modal/cupertino.dart'; export 'src/modal/modal_sheet.dart'; export 'src/navigation/navigation_route.dart'; diff --git a/package/lib/src/foundation/sized_content_sheet.dart b/package/lib/src/foundation/sized_content_sheet.dart index 7d4f8fd1..a9a931b3 100644 --- a/package/lib/src/foundation/sized_content_sheet.dart +++ b/package/lib/src/foundation/sized_content_sheet.dart @@ -4,6 +4,7 @@ import 'package:smooth_sheets/src/foundation/keyboard_dismissible.dart'; import 'package:smooth_sheets/src/foundation/sheet_controller.dart'; import 'package:smooth_sheets/src/foundation/sheet_extent.dart'; import 'package:smooth_sheets/src/foundation/sheet_physics.dart'; +import 'package:smooth_sheets/src/foundation/theme.dart'; /// [SheetExtent] for a [SizedContentSheet]. abstract class SizedContentSheetExtent extends SheetExtent { @@ -118,15 +119,19 @@ abstract class SizedContentSheetState @override Widget build(BuildContext context) { + final theme = SheetTheme.maybeOf(context); + final keyboardDismissBehavior = + widget.keyboardDismissBehavior ?? theme?.keyboardDismissBehavior; + Widget result = SheetContainer( factory: factory, controller: widget.controller, child: buildContent(context), ); - if (widget.keyboardDismissBehavior != null) { + if (keyboardDismissBehavior != null) { result = SheetKeyboardDismissible( - dismissBehavior: widget.keyboardDismissBehavior!, + dismissBehavior: keyboardDismissBehavior, child: result, ); } diff --git a/package/lib/src/foundation/theme.dart b/package/lib/src/foundation/theme.dart new file mode 100644 index 00000000..42546d53 --- /dev/null +++ b/package/lib/src/foundation/theme.dart @@ -0,0 +1,78 @@ +import 'package:flutter/widgets.dart'; +import 'package:smooth_sheets/src/foundation/keyboard_dismissible.dart'; + +/// A theme for descendant sheets. +/// +/// The [SheetTheme] is used to configure the default appearance and behavior of +/// descendant sheets. The current theme's [SheetThemeData] object can be +/// obtained by calling [SheetTheme.maybeOf] or [SheetTheme.of]. +class SheetTheme extends InheritedWidget { + /// Creates a heme for descendant sheets. + const SheetTheme({ + super.key, + required this.data, + required super.child, + }); + + /// The default appearance and behavior for descendant sheets. + final SheetThemeData data; + + @override + bool updateShouldNotify(SheetTheme oldWidget) => data != oldWidget.data; + + /// Obtains the closest [SheetThemeData] object from the given [context] + /// if it exists. + static SheetThemeData? maybeOf(BuildContext context) { + return context.dependOnInheritedWidgetOfExactType()?.data; + } + + /// Obtains the closest [SheetThemeData] object from the given [context]. + static SheetThemeData of(BuildContext context) { + final themeData = maybeOf(context); + assert( + themeData != null, + 'SheetTheme.of() called with a context that' + 'does not contain a SheetTheme.', + ); + + return themeData!; + } +} + +/// A set of properties that describe the appearance and behavior of a sheet. +/// +/// Typically, this object is exposed by a [SheetTheme] to +/// the descendant widgets. +class SheetThemeData { + /// Creates a set of properties that describe the appearance and + /// behavior of a sheet. + const SheetThemeData({ + this.keyboardDismissBehavior, + }); + + /// Determines when the on-screen keyboard should be dismissed. + final SheetKeyboardDismissBehavior? keyboardDismissBehavior; + + /// Creates a copy of this object but with the given fields replaced with + /// the new values. + SheetThemeData copyWith({ + SheetKeyboardDismissBehavior? keyboardDismissBehavior, + }) => + SheetThemeData( + keyboardDismissBehavior: + keyboardDismissBehavior ?? this.keyboardDismissBehavior, + ); + + @override + bool operator ==(Object other) => + identical(this, other) || + other is SheetThemeData && + runtimeType == other.runtimeType && + keyboardDismissBehavior == other.keyboardDismissBehavior; + + @override + int get hashCode => Object.hash( + runtimeType, + keyboardDismissBehavior, + ); +} diff --git a/package/lib/src/navigation/navigation_sheet.dart b/package/lib/src/navigation/navigation_sheet.dart index 4d9d6400..c69f1a26 100644 --- a/package/lib/src/navigation/navigation_sheet.dart +++ b/package/lib/src/navigation/navigation_sheet.dart @@ -9,6 +9,7 @@ import 'package:smooth_sheets/src/foundation/sheet_controller.dart'; import 'package:smooth_sheets/src/foundation/sheet_extent.dart'; import 'package:smooth_sheets/src/foundation/sheet_physics.dart'; import 'package:smooth_sheets/src/foundation/sheet_status.dart'; +import 'package:smooth_sheets/src/foundation/theme.dart'; import 'package:smooth_sheets/src/internal/transition_observer.dart'; typedef NavigationSheetTransitionObserver = TransitionObserver; @@ -95,6 +96,10 @@ class NavigationSheetState extends State @override Widget build(BuildContext context) { + final theme = SheetTheme.maybeOf(context); + final keyboardDismissBehavior = + widget.keyboardDismissBehavior ?? theme?.keyboardDismissBehavior; + Widget result = SheetContainer( factory: const _NavigationSheetExtentFactory(), controller: widget.controller, @@ -104,9 +109,9 @@ class NavigationSheetState extends State child: widget.child, ); - if (widget.keyboardDismissBehavior != null) { + if (keyboardDismissBehavior != null) { result = SheetKeyboardDismissible( - dismissBehavior: widget.keyboardDismissBehavior!, + dismissBehavior: keyboardDismissBehavior, child: result, ); }