make sync script Posix-compliant; update framework to 98b3e48ed4e722acb0c4bb897397fc817057b5f6
diff --git a/engine/analysis_options.yaml b/engine/analysis_options.yaml
index 92e155d..edeb29f 100644
--- a/engine/analysis_options.yaml
+++ b/engine/analysis_options.yaml
@@ -17,9 +17,6 @@
   exclude:
     # Fixture depends on dart:ui and raises false positives.
     - flutter_frontend_server/test/fixtures/lib/main.dart
-  strong-mode:
-    implicit-casts: false
-    implicit-dynamic: false
   errors:
     # treat missing required parameters as a warning (not a hint)
     missing_required_param: warning
diff --git a/engine/lib/src/math.dart b/engine/lib/src/math.dart
index a52fdc0..240e79b 100644
--- a/engine/lib/src/math.dart
+++ b/engine/lib/src/math.dart
@@ -24,6 +24,20 @@
   return x;
 }
 
+double clampDouble(double x, double min, double max) {
+  assert(min <= max && !max.isNaN && !min.isNaN);
+  if (x < min) {
+    return min;
+  }
+  if (x > max) {
+    return max;
+  }
+  if (x.isNaN) {
+    return max;
+  }
+  return x;
+}
+
 Float32List _toMatrix32(Float64List matrix64) {
   final Float32List matrix32 = Float32List(16);
   matrix32[15] = matrix64[15];
diff --git a/engine/lib/src/painting.dart b/engine/lib/src/painting.dart
index 08e5750..78e8bc3 100644
--- a/engine/lib/src/painting.dart
+++ b/engine/lib/src/painting.dart
@@ -1360,7 +1360,8 @@
   }
 }
 class ImageShader extends Shader {
-    ImageShader(Image image, TileMode tmx, TileMode tmy, Float64List matrix4) :
+    // ignore: avoid_unused_constructor_parameters
+    ImageShader(Image image, TileMode tmx, TileMode tmy, Float64List matrix4, { FilterQuality? filterQuality }) :
     // ignore: unnecessary_null_comparison
     assert(image != null), // image is checked on the engine side
     assert(tmx != null), // ignore: unnecessary_null_comparison
@@ -2152,7 +2153,12 @@
     throw UnsupportedError('ImmutableBuffer.fromFilePath is not supported in flute.');
   }
 
-  void _init(Uint8List list, _Callback<void> callback) {  }
+  void _init(Uint8List list, _Callback<void> callback) {
+    _list = Uint8List.fromList(list);
+  }
+
+  Uint8List? _list;
+
   final int length;
   void dispose() {  }
 }
@@ -2315,3 +2321,83 @@
     targetHeight: targetHeight,
   );
 }
+
+
+Future<Codec> instantiateImageCodecWithSize(
+  ImmutableBuffer buffer, {
+  TargetImageSizeCallback? getTargetSize,
+}) async {
+  if (getTargetSize == null) {
+    return instantiateImageCodec(buffer._list!);
+  } else {
+    final Codec codec = await instantiateImageCodec(buffer._list!);
+    try {
+      final FrameInfo info = await codec.getNextFrame();
+      try {
+        final int width = info.image.width;
+        final int height = info.image.height;
+        final TargetImageSize targetSize = getTargetSize(width, height);
+        return instantiateImageCodec(buffer._list!,
+            targetWidth: targetSize.width, targetHeight: targetSize.height, allowUpscaling: false);
+      } finally {
+        info.image.dispose();
+      }
+    } finally {
+      codec.dispose();
+    }
+  }
+}
+
+/// Signature for a callback that determines the size to which an image should
+/// be decoded given its intrinsic size.
+///
+/// See also:
+///
+///  * [instantiateImageCodecWithSize], which used this signature for its
+///    `getTargetSize` argument.
+typedef TargetImageSizeCallback = TargetImageSize Function(
+  int intrinsicWidth,
+  int intrinsicHeight,
+);
+
+/// A specification of the size to which an image should be decoded.
+///
+/// See also:
+///
+///  * [TargetImageSizeCallback], a callback that returns instances of this
+///    class when consulted by image decoding methods such as
+///    [instantiateImageCodecWithSize].
+class TargetImageSize {
+  /// Creates a new instance of this class.
+  ///
+  /// The `width` and `height` may both be null, but if they're non-null, they
+  /// must be positive.
+  const TargetImageSize({this.width, this.height})
+      : assert(width == null || width > 0),
+        assert(height == null || height > 0);
+
+  /// The width into which to load the image.
+  ///
+  /// If this is non-null, the image will be decoded into the specified width.
+  /// If this is null and [height] is also null, the image will be decoded into
+  /// its intrinsic size. If this is null and [height] is non-null, the image
+  /// will be decoded into a width that maintains its intrinsic aspect ratio
+  /// while respecting the [height] value.
+  ///
+  /// If this value is non-null, it must be positive.
+  final int? width;
+
+  /// The height into which to load the image.
+  ///
+  /// If this is non-null, the image will be decoded into the specified height.
+  /// If this is null and [width] is also null, the image will be decoded into
+  /// its intrinsic size. If this is null and [width] is non-null, the image
+  /// will be decoded into a height that maintains its intrinsic aspect ratio
+  /// while respecting the [width] value.
+  ///
+  /// If this value is non-null, it must be positive.
+  final int? height;
+
+  @override
+  String toString() => 'TargetImageSize($width x $height)';
+}
diff --git a/framework/lib/foundation.dart b/framework/lib/foundation.dart
index 40b35f2..dff7553 100644
--- a/framework/lib/foundation.dart
+++ b/framework/lib/foundation.dart
@@ -24,6 +24,7 @@
 export 'src/foundation/basic_types.dart';
 export 'src/foundation/binding.dart';
 export 'src/foundation/bitfield.dart';
+export 'src/foundation/capabilities.dart';
 export 'src/foundation/change_notifier.dart';
 export 'src/foundation/collections.dart';
 export 'src/foundation/consolidate_response.dart';
diff --git a/framework/lib/material.dart b/framework/lib/material.dart
index 99b9a67..fb07102 100644
--- a/framework/lib/material.dart
+++ b/framework/lib/material.dart
@@ -65,6 +65,7 @@
 export 'src/material/data_table_theme.dart';
 export 'src/material/date.dart';
 export 'src/material/date_picker.dart';
+export 'src/material/date_picker_theme.dart';
 export 'src/material/debug.dart';
 export 'src/material/desktop_text_selection.dart';
 export 'src/material/desktop_text_selection_toolbar.dart';
@@ -159,6 +160,8 @@
 export 'src/material/slider_theme.dart';
 export 'src/material/snack_bar.dart';
 export 'src/material/snack_bar_theme.dart';
+export 'src/material/spell_check_suggestions_toolbar.dart';
+export 'src/material/spell_check_suggestions_toolbar_layout_delegate.dart';
 export 'src/material/stepper.dart';
 export 'src/material/switch.dart';
 export 'src/material/switch_list_tile.dart';
diff --git a/framework/lib/painting.dart b/framework/lib/painting.dart
index bd3e029..35f056e 100644
--- a/framework/lib/painting.dart
+++ b/framework/lib/painting.dart
@@ -47,6 +47,7 @@
 export 'src/painting/image_resolution.dart';
 export 'src/painting/image_stream.dart';
 export 'src/painting/inline_span.dart';
+export 'src/painting/linear_border.dart';
 export 'src/painting/matrix_utils.dart';
 export 'src/painting/notched_shapes.dart';
 export 'src/painting/oval_border.dart';
diff --git a/framework/lib/services.dart b/framework/lib/services.dart
index a0ff42f..7e7fb02 100644
--- a/framework/lib/services.dart
+++ b/framework/lib/services.dart
@@ -11,15 +11,18 @@
 library services;
 
 export 'src/services/asset_bundle.dart';
+export 'src/services/asset_manifest.dart';
 export 'src/services/autofill.dart';
 export 'src/services/binary_messenger.dart';
 export 'src/services/binding.dart';
+export 'src/services/browser_context_menu.dart';
 export 'src/services/clipboard.dart';
 export 'src/services/debug.dart';
 export 'src/services/deferred_component.dart';
 export 'src/services/font_loader.dart';
 export 'src/services/haptic_feedback.dart';
 export 'src/services/hardware_keyboard.dart';
+export 'src/services/keyboard_inserted_content.dart';
 export 'src/services/keyboard_key.g.dart';
 export 'src/services/keyboard_maps.g.dart';
 export 'src/services/message_codec.dart';
diff --git a/framework/lib/src/animation/animation.dart b/framework/lib/src/animation/animation.dart
index 09cf78c..cafcdfe 100644
--- a/framework/lib/src/animation/animation.dart
+++ b/framework/lib/src/animation/animation.dart
@@ -81,9 +81,9 @@
   ///       final double opacity = (value / 1000).clamp(0, 1);
   ///       return Opacity(opacity: opacity, child: child);
   ///     },
-  ///     child: Container(
+  ///     child: const ColoredBox(
   ///       color: Colors.red,
-  ///       child: const Text('Hello, Animation'),
+  ///       child: Text('Hello, Animation'),
   ///     ),
   ///   );
   /// }
@@ -100,9 +100,9 @@
   ///     opacity: Animation<double>.fromValueListenable(_scrollPosition, transformer: (double value) {
   ///       return (value / 1000).clamp(0, 1);
   ///     }),
-  ///     child: Container(
+  ///     child: const ColoredBox(
   ///       color: Colors.red,
-  ///       child: const Text('Hello, Animation'),
+  ///       child: Text('Hello, Animation'),
   ///     ),
   ///   );
   /// }
@@ -269,7 +269,6 @@
   /// * "&#x23ED;": [AnimationStatus.completed] ([value] == 1.0)
   /// * "&#x23EE;": [AnimationStatus.dismissed] ([value] == 0.0)
   String toStringDetails() {
-    assert(status != null);
     switch (status) {
       case AnimationStatus.forward:
         return '\u25B6'; // >
diff --git a/framework/lib/src/animation/animation_controller.dart b/framework/lib/src/animation/animation_controller.dart
index a048589..4cc7e83 100644
--- a/framework/lib/src/animation/animation_controller.dart
+++ b/framework/lib/src/animation/animation_controller.dart
@@ -242,10 +242,7 @@
     this.upperBound = 1.0,
     this.animationBehavior = AnimationBehavior.normal,
     required TickerProvider vsync,
-  }) : assert(lowerBound != null),
-       assert(upperBound != null),
-       assert(upperBound >= lowerBound),
-       assert(vsync != null),
+  }) : assert(upperBound >= lowerBound),
        _direction = _AnimationDirection.forward {
     _ticker = vsync.createTicker(_tick);
     _internalSetValue(value ?? lowerBound);
@@ -275,9 +272,7 @@
     this.debugLabel,
     required TickerProvider vsync,
     this.animationBehavior = AnimationBehavior.preserve,
-  }) : assert(value != null),
-       assert(vsync != null),
-       lowerBound = double.negativeInfinity,
+  }) : lowerBound = double.negativeInfinity,
        upperBound = double.infinity,
        _direction = _AnimationDirection.forward {
     _ticker = vsync.createTicker(_tick);
@@ -363,7 +358,6 @@
   ///  * [forward], [reverse], [animateTo], [animateWith], [fling], and [repeat],
   ///    which start the animation controller.
   set value(double newValue) {
-    assert(newValue != null);
     stop();
     _internalSetValue(newValue);
     notifyListeners();
@@ -657,7 +651,6 @@
     }());
     assert(max >= min);
     assert(max <= upperBound && min >= lowerBound);
-    assert(reverse != null);
     stop();
     return _startSimulation(_RepeatingSimulation(_value, min, max, reverse, period!, _directionSetter));
   }
@@ -744,7 +737,6 @@
   }
 
   TickerFuture _startSimulation(Simulation simulation) {
-    assert(simulation != null);
     assert(!isAnimating);
     _simulation = simulation;
     _lastElapsedDuration = Duration.zero;
@@ -856,9 +848,7 @@
 
 class _InterpolationSimulation extends Simulation {
   _InterpolationSimulation(this._begin, this._end, Duration duration, this._curve, double scale)
-    : assert(_begin != null),
-      assert(_end != null),
-      assert(duration != null && duration.inMicroseconds > 0),
+    : assert(duration.inMicroseconds > 0),
       _durationInSeconds = (duration.inMicroseconds * scale) / Duration.microsecondsPerSecond;
 
   final double _durationInSeconds;
diff --git a/framework/lib/src/animation/animations.dart b/framework/lib/src/animation/animations.dart
index a4e17c5..47fc7f2 100644
--- a/framework/lib/src/animation/animations.dart
+++ b/framework/lib/src/animation/animations.dart
@@ -255,8 +255,8 @@
 /// If the parent animation is running forward from 0.0 to 1.0, this animation
 /// is running in reverse from 1.0 to 0.0.
 ///
-/// Using a [ReverseAnimation] is different from simply using a [Tween] with a
-/// begin of 1.0 and an end of 0.0 because the tween does not change the status
+/// Using a [ReverseAnimation] is different from using a [Tween] with a
+/// `begin` of 1.0 and an `end` of 0.0 because the tween does not change the status
 /// or direction of the animation.
 ///
 /// See also:
@@ -271,8 +271,7 @@
   /// Creates a reverse animation.
   ///
   /// The parent argument must not be null.
-  ReverseAnimation(this.parent)
-    : assert(parent != null);
+  ReverseAnimation(this.parent);
 
   /// The animation whose value and direction this animation is reversing.
   final Animation<double> parent;
@@ -310,7 +309,6 @@
   double get value => 1.0 - parent.value;
 
   AnimationStatus _reverseStatus(AnimationStatus status) {
-    assert(status != null);
     switch (status) {
       case AnimationStatus.forward: return AnimationStatus.reverse;
       case AnimationStatus.reverse: return AnimationStatus.forward;
@@ -384,8 +382,7 @@
     required this.parent,
     required this.curve,
     this.reverseCurve,
-  }) : assert(parent != null),
-       assert(curve != null) {
+  }) {
     _updateCurveDirection(parent.status);
     parent.addStatusListener(_updateCurveDirection);
   }
@@ -518,7 +515,7 @@
     Animation<double> this._currentTrain,
     this._nextTrain, {
     this.onSwitchedTrain,
-  }) : assert(_currentTrain != null) {
+  }) {
     if (_nextTrain != null) {
       if (_currentTrain!.value == _nextTrain!.value) {
         _currentTrain = _nextTrain;
@@ -644,8 +641,7 @@
   CompoundAnimation({
     required this.first,
     required this.next,
-  }) : assert(first != null),
-       assert(next != null);
+  });
 
   /// The first sub-animation. Its status takes precedence if neither are
   /// animating.
diff --git a/framework/lib/src/animation/curves.dart b/framework/lib/src/animation/curves.dart
index bc52684..29755f8 100644
--- a/framework/lib/src/animation/curves.dart
+++ b/framework/lib/src/animation/curves.dart
@@ -35,7 +35,6 @@
   /// implementation of [transform], which delegates the remaining logic to
   /// [transformInternal].
   T transform(double t) {
-    assert(t != null);
     assert(t >= 0.0 && t <= 1.0, 'parametric value $t is outside of [0, 1] range.');
     return transformInternal(t);
   }
@@ -129,7 +128,7 @@
   /// Creates a sawtooth curve.
   ///
   /// The [count] argument must not be null.
-  const SawTooth(this.count) : assert(count != null);
+  const SawTooth(this.count);
 
   /// The number of repetitions of the sawtooth pattern in the unit interval.
   final int count;
@@ -159,10 +158,7 @@
   /// Creates an interval curve.
   ///
   /// The arguments must not be null.
-  const Interval(this.begin, this.end, { this.curve = Curves.linear })
-    : assert(begin != null),
-      assert(end != null),
-      assert(curve != null);
+  const Interval(this.begin, this.end, { this.curve = Curves.linear });
 
   /// The largest value for which this interval is 0.0.
   ///
@@ -207,7 +203,7 @@
   /// Creates a threshold curve.
   ///
   /// The [threshold] argument must not be null.
-  const Threshold(this.threshold) : assert(threshold != null);
+  const Threshold(this.threshold);
 
   /// The value before which the curve is 0.0 and after which the curve is 1.0.
   ///
@@ -307,11 +303,7 @@
   /// cubic curves in [Curves].
   ///
   /// The [a] (x1), [b] (y1), [c] (x2) and [d] (y2) arguments must not be null.
-  const Cubic(this.a, this.b, this.c, this.d)
-    : assert(a != null),
-      assert(b != null),
-      assert(c != null),
-      assert(d != null);
+  const Cubic(this.a, this.b, this.c, this.d);
 
   /// The x coordinate of the first control point.
   ///
@@ -518,9 +510,6 @@
     // 4. Recursively sample the two parts.
     //
     // This algorithm concentrates samples in areas of high curvature.
-    assert(tolerance != null);
-    assert(start != null);
-    assert(end != null);
     assert(end > start);
     // We want to pick a random seed that will keep the result stable if
     // evaluated again, so we use the first non-generated control point.
@@ -577,7 +566,6 @@
   /// single-valued, it will return the parameter for only one of the values at
   /// the given `x` location.
   double findInverse(double x) {
-    assert(x != null);
     double start = 0.0;
     double end = 1.0;
     late double mid;
@@ -612,7 +600,7 @@
   /// Creates an object that holds a sample; used with [Curve2D] subclasses.
   ///
   /// All arguments must not be null.
-  const Curve2DSample(this.t, this.value) : assert(t != null), assert(value != null);
+  const Curve2DSample(this.t, this.value);
 
   /// The parametric location of this sample point along the curve.
   final double t;
@@ -682,9 +670,7 @@
         double tension = 0.0,
         Offset? startHandle,
         Offset? endHandle,
-      }) : assert(controlPoints != null),
-           assert(tension != null),
-           assert(tension <= 1.0, 'tension $tension must not be greater than 1.0.'),
+      }) : assert(tension <= 1.0, 'tension $tension must not be greater than 1.0.'),
            assert(tension >= 0.0, 'tension $tension must not be negative.'),
            assert(controlPoints.length > 3, 'There must be at least four control points to create a CatmullRomSpline.'),
            _controlPoints = controlPoints,
@@ -702,9 +688,7 @@
         double tension = 0.0,
         Offset? startHandle,
         Offset? endHandle,
-      }) : assert(controlPoints != null),
-           assert(tension != null),
-           assert(tension <= 1.0, 'tension $tension must not be greater than 1.0.'),
+      }) : assert(tension <= 1.0, 'tension $tension must not be greater than 1.0.'),
            assert(tension >= 0.0, 'tension $tension must not be negative.'),
            assert(controlPoints.length > 3, 'There must be at least four control points to create a CatmullRomSpline.'),
            _controlPoints = null,
@@ -860,8 +844,7 @@
   ///
   ///  * This [paper on using Catmull-Rom splines](http://faculty.cs.tamu.edu/schaefer/research/cr_cad.pdf).
   CatmullRomCurve(this.controlPoints, {this.tension = 0.0})
-      : assert(tension != null),
-        assert(() {
+      : assert(() {
           return validateControlPoints(
             controlPoints,
             tension: tension,
@@ -877,8 +860,7 @@
   /// Same as [CatmullRomCurve.new], but it precomputes the internal curve data
   /// structures for a more predictable computation load.
   CatmullRomCurve.precompute(this.controlPoints, {this.tension = 0.0})
-      : assert(tension != null),
-        assert(() {
+      : assert(() {
           return validateControlPoints(
             controlPoints,
             tension: tension,
@@ -963,7 +945,6 @@
     double tension = 0.0,
     List<String>? reasons,
   }) {
-    assert(tension != null);
     if (controlPoints == null) {
       assert(() {
         reasons?.add('Supplied control points cannot be null');
@@ -1143,7 +1124,7 @@
   /// Creates a flipped curve.
   ///
   /// The [curve] argument must not be null.
-  const FlippedCurve(this.curve) : assert(curve != null);
+  const FlippedCurve(this.curve);
 
   /// The curve that is being flipped.
   final Curve curve;
diff --git a/framework/lib/src/animation/tween.dart b/framework/lib/src/animation/tween.dart
index d6c12b9..817e948 100644
--- a/framework/lib/src/animation/tween.dart
+++ b/framework/lib/src/animation/tween.dart
@@ -364,8 +364,7 @@
 class ReverseTween<T extends Object?> extends Tween<T> {
   /// Construct a [Tween] that evaluates its [parent] in reverse.
   ReverseTween(this.parent)
-    : assert(parent != null),
-      super(begin: parent.end, end: parent.begin);
+    : super(begin: parent.end, end: parent.begin);
 
   /// This tween's value is the same as the parent's value evaluated in reverse.
   ///
@@ -544,8 +543,7 @@
   /// Creates a curve tween.
   ///
   /// The [curve] argument must not be null.
-  CurveTween({ required this.curve })
-    : assert(curve != null);
+  CurveTween({ required this.curve });
 
   /// The curve to use when transforming the value of the animation.
   Curve curve;
diff --git a/framework/lib/src/animation/tween_sequence.dart b/framework/lib/src/animation/tween_sequence.dart
index 252d273..a8e3208 100644
--- a/framework/lib/src/animation/tween_sequence.dart
+++ b/framework/lib/src/animation/tween_sequence.dart
@@ -51,8 +51,7 @@
   /// best to reuse one, rather than rebuilding it on every frame, when that's
   /// possible.
   TweenSequence(List<TweenSequenceItem<T>> items)
-      : assert(items != null),
-        assert(items.isNotEmpty) {
+      : assert(items.isNotEmpty) {
     _items.addAll(items);
 
     double totalWeight = 0.0;
@@ -113,8 +112,7 @@
   /// There's a small cost associated with building a `TweenSequence` so it's
   /// best to reuse one, rather than rebuilding it on every frame, when that's
   /// possible.
-  FlippedTweenSequence(super.items)
-    : assert(items != null);
+  FlippedTweenSequence(super.items);
 
   @override
   double transform(double t) => 1 - super.transform(1 - t);
@@ -128,9 +126,7 @@
   const TweenSequenceItem({
     required this.tween,
     required this.weight,
-  }) : assert(tween != null),
-       assert(weight != null),
-       assert(weight > 0.0);
+  }) : assert(weight > 0.0);
 
   /// Defines the value of the [TweenSequence] for the interval within the
   /// animation's duration indicated by [weight] and this item's position
diff --git a/framework/lib/src/cupertino/activity_indicator.dart b/framework/lib/src/cupertino/activity_indicator.dart
index 8089d10..b4d3799 100644
--- a/framework/lib/src/cupertino/activity_indicator.dart
+++ b/framework/lib/src/cupertino/activity_indicator.dart
@@ -36,9 +36,7 @@
     this.color,
     this.animating = true,
     this.radius = _kDefaultIndicatorRadius,
-  })  : assert(animating != null),
-        assert(radius != null),
-        assert(radius > 0.0),
+  })  : assert(radius > 0.0),
         progress = 1.0;
 
   /// Creates a non-animated iOS-style activity indicator that displays
@@ -52,9 +50,7 @@
     this.color,
     this.radius = _kDefaultIndicatorRadius,
     this.progress = 1.0,
-  })  : assert(radius != null),
-        assert(radius > 0.0),
-        assert(progress != null),
+  })  : assert(radius > 0.0),
         assert(progress >= 0.0),
         assert(progress <= 1.0),
         animating = false;
diff --git a/framework/lib/src/cupertino/adaptive_text_selection_toolbar.dart b/framework/lib/src/cupertino/adaptive_text_selection_toolbar.dart
index 7f64616..43abb02 100644
--- a/framework/lib/src/cupertino/adaptive_text_selection_toolbar.dart
+++ b/framework/lib/src/cupertino/adaptive_text_selection_toolbar.dart
@@ -157,7 +157,7 @@
   final List<ContextMenuButtonItem>? buttonItems;
 
   /// Returns a List of Widgets generated by turning [buttonItems] into the
-  /// the default context menu buttons for Cupertino on the current platform.
+  /// default context menu buttons for Cupertino on the current platform.
   ///
   /// This is useful when building a text selection toolbar with the default
   /// button appearance for the given platform, but where the toolbar and/or the
@@ -165,7 +165,7 @@
   ///
   /// Does not build Material buttons. On non-Apple platforms, Cupertino buttons
   /// will still be used, because the Cupertino library does not access the
-  /// Material library. To get the native-looking buttons on every platform, use
+  /// Material library. To get the native-looking buttons on every platform,
   /// use [AdaptiveTextSelectionToolbar.getAdaptiveButtons] in the Material
   /// library.
   ///
diff --git a/framework/lib/src/cupertino/app.dart b/framework/lib/src/cupertino/app.dart
index 1e98a03..dab2763 100644
--- a/framework/lib/src/cupertino/app.dart
+++ b/framework/lib/src/cupertino/app.dart
@@ -176,16 +176,13 @@
     this.actions,
     this.restorationScopeId,
     this.scrollBehavior,
+    @Deprecated(
+      'Remove this parameter as it is now ignored. '
+      'CupertinoApp never introduces its own MediaQuery; the View widget takes care of that. '
+      'This feature was deprecated after v3.7.0-29.0.pre.'
+    )
     this.useInheritedMediaQuery = false,
-  }) : assert(routes != null),
-       assert(navigatorObservers != null),
-       assert(title != null),
-       assert(showPerformanceOverlay != null),
-       assert(checkerboardRasterCacheImages != null),
-       assert(checkerboardOffscreenLayers != null),
-       assert(showSemanticsDebugger != null),
-       assert(debugShowCheckedModeBanner != null),
-       routeInformationProvider = null,
+  }) : routeInformationProvider = null,
        routeInformationParser = null,
        routerDelegate = null,
        backButtonDispatcher = null,
@@ -220,14 +217,13 @@
     this.actions,
     this.restorationScopeId,
     this.scrollBehavior,
+    @Deprecated(
+      'Remove this parameter as it is now ignored. '
+      'CupertinoApp never introduces its own MediaQuery; the View widget takes care of that. '
+      'This feature was deprecated after v3.7.0-29.0.pre.'
+    )
     this.useInheritedMediaQuery = false,
   }) : assert(routerDelegate != null || routerConfig != null),
-       assert(title != null),
-       assert(showPerformanceOverlay != null),
-       assert(checkerboardRasterCacheImages != null),
-       assert(checkerboardOffscreenLayers != null),
-       assert(showSemanticsDebugger != null),
-       assert(debugShowCheckedModeBanner != null),
        navigatorObservers = null,
        navigatorKey = null,
        onGenerateRoute = null,
@@ -422,6 +418,11 @@
   final ScrollBehavior? scrollBehavior;
 
   /// {@macro flutter.widgets.widgetsApp.useInheritedMediaQuery}
+  @Deprecated(
+    'This setting is now ignored. '
+    'CupertinoApp never introduces its own MediaQuery; the View widget takes care of that. '
+    'This feature was deprecated after v3.7.0-29.0.pre.'
+  )
   final bool useInheritedMediaQuery;
 
   @override
@@ -555,7 +556,6 @@
         shortcuts: widget.shortcuts,
         actions: widget.actions,
         restorationScopeId: widget.restorationScopeId,
-        useInheritedMediaQuery: widget.useInheritedMediaQuery,
       );
     }
     return WidgetsApp(
@@ -590,7 +590,6 @@
       shortcuts: widget.shortcuts,
       actions: widget.actions,
       restorationScopeId: widget.restorationScopeId,
-      useInheritedMediaQuery: widget.useInheritedMediaQuery,
     );
   }
 
diff --git a/framework/lib/src/cupertino/bottom_tab_bar.dart b/framework/lib/src/cupertino/bottom_tab_bar.dart
index bc96fb1..286cd02 100644
--- a/framework/lib/src/cupertino/bottom_tab_bar.dart
+++ b/framework/lib/src/cupertino/bottom_tab_bar.dart
@@ -74,16 +74,12 @@
         width: 0.0, // 0.0 means one physical pixel
       ),
     ),
-  }) : assert(items != null),
-       assert(
+  }) : assert(
          items.length >= 2,
          "Tabs need at least 2 items to conform to Apple's HIG",
        ),
-       assert(currentIndex != null),
        assert(0 <= currentIndex && currentIndex < items.length),
-       assert(iconSize != null),
-       assert(height != null && height >= 0.0),
-       assert(inactiveColor != null);
+       assert(height >= 0.0);
 
   /// The interactive items laid out within the bottom navigation bar.
   ///
@@ -156,7 +152,7 @@
   @override
   Widget build(BuildContext context) {
     assert(debugCheckHasMediaQuery(context));
-    final double bottomPadding = MediaQuery.of(context).viewPadding.bottom;
+    final double bottomPadding = MediaQuery.viewPaddingOf(context).bottom;
 
     final Color backgroundColor = CupertinoDynamicColor.resolve(
       this.backgroundColor ?? CupertinoTheme.of(context).barBackgroundColor,
diff --git a/framework/lib/src/cupertino/button.dart b/framework/lib/src/cupertino/button.dart
index ac84891..917481d 100644
--- a/framework/lib/src/cupertino/button.dart
+++ b/framework/lib/src/cupertino/button.dart
@@ -50,8 +50,6 @@
     this.alignment = Alignment.center,
     required this.onPressed,
   }) : assert(pressedOpacity == null || (pressedOpacity >= 0.0 && pressedOpacity <= 1.0)),
-       assert(disabledColor != null),
-       assert(alignment != null),
        _filled = false;
 
   /// Creates an iOS-style button with a filled background.
@@ -71,8 +69,6 @@
     this.alignment = Alignment.center,
     required this.onPressed,
   }) : assert(pressedOpacity == null || (pressedOpacity >= 0.0 && pressedOpacity <= 1.0)),
-       assert(disabledColor != null),
-       assert(alignment != null),
        color = null,
        _filled = true;
 
diff --git a/framework/lib/src/cupertino/colors.dart b/framework/lib/src/cupertino/colors.dart
index 7c5b9f6..2249ed2 100644
--- a/framework/lib/src/cupertino/colors.dart
+++ b/framework/lib/src/cupertino/colors.dart
@@ -144,6 +144,21 @@
     darkHighContrastColor: Color.fromARGB(255, 48, 219, 91),
   );
 
+  /// A mint color that can adapt to the given [BuildContext].
+  ///
+  /// See also:
+  ///
+  ///  * [UIColor.systemMint](https://developer.apple.com/documentation/uikit/uicolor/3852741-systemmint),
+  ///    the `UIKit` equivalent.
+  static const CupertinoDynamicColor systemMint =
+      CupertinoDynamicColor.withBrightnessAndContrast(
+    debugLabel: 'systemMint',
+    color: Color.fromARGB(255, 0, 199, 190),
+    darkColor: Color.fromARGB(255, 99, 230, 226),
+    highContrastColor: Color.fromARGB(255, 12, 129, 123),
+    darkHighContrastColor: Color.fromARGB(255, 102, 212, 207),
+  );
+
   /// An indigo color that can adapt to the given [BuildContext].
   ///
   /// See also:
@@ -186,6 +201,21 @@
     darkHighContrastColor: Color.fromARGB(255, 255, 100, 130),
   );
 
+  /// A brown color that can adapt to the given [BuildContext].
+  ///
+  /// See also:
+  ///
+  ///  * [UIColor.systemBrown](https://developer.apple.com/documentation/uikit/uicolor/3173142-systembrown),
+  ///    the `UIKit` equivalent.
+  static const CupertinoDynamicColor systemBrown =
+      CupertinoDynamicColor.withBrightnessAndContrast(
+    debugLabel: 'systemBrown',
+    color: Color.fromARGB(255, 162, 132, 94),
+    darkColor: Color.fromARGB(255, 172, 142, 104),
+    highContrastColor: Color.fromARGB(255, 127, 101, 69),
+    darkHighContrastColor: Color.fromARGB(255, 181, 148, 105),
+  );
+
   /// A purple color that can adapt to the given [BuildContext].
   ///
   /// See also:
@@ -228,6 +258,21 @@
     darkHighContrastColor: Color.fromARGB(255, 112, 215, 255),
   );
 
+  /// A cyan color that can adapt to the given [BuildContext].
+  ///
+  /// See also:
+  ///
+  ///  * [UIColor.systemCyan](https://developer.apple.com/documentation/uikit/uicolor/3852740-systemcyan),
+  ///    the `UIKit` equivalent.
+  static const CupertinoDynamicColor systemCyan =
+      CupertinoDynamicColor.withBrightnessAndContrast(
+    debugLabel: 'systemCyan',
+    color: Color.fromARGB(255, 50, 173, 230),
+    darkColor: Color.fromARGB(255, 100, 210, 255),
+    highContrastColor: Color.fromARGB(255, 0, 113, 164),
+    darkHighContrastColor: Color.fromARGB(255, 112, 215, 255),
+  );
+
   /// A yellow color that can adapt to the given [BuildContext].
   ///
   /// See also:
@@ -780,16 +825,7 @@
     this.darkHighContrastElevatedColor,
     this._debugResolveContext,
     this._debugLabel,
-  ) : assert(color != null),
-      assert(darkColor != null),
-      assert(highContrastColor != null),
-      assert(darkHighContrastColor != null),
-      assert(elevatedColor != null),
-      assert(darkElevatedColor != null),
-      assert(highContrastElevatedColor != null),
-      assert(darkHighContrastElevatedColor != null),
-      assert(_effectiveColor != null),
-      // The super constructor has to be called with a dummy value in order to mark
+  ) : // The super constructor has to be called with a dummy value in order to mark
       // this constructor const.
       // The field `value` is overridden in the class implementation.
       super(0);
@@ -908,7 +944,6 @@
   ///  * [maybeResolve], which is similar to this function, but will allow a
   ///    null `resolvable` color.
   static Color resolve(Color resolvable, BuildContext context) {
-    assert(context != null);
     return (resolvable is CupertinoDynamicColor)
       ? resolvable.resolveFrom(context)
       : resolvable;
@@ -931,7 +966,6 @@
     if (resolvable == null) {
       return null;
     }
-    assert(context != null);
     return (resolvable is CupertinoDynamicColor)
       ? resolvable.resolveFrom(context)
       : resolvable;
@@ -990,11 +1024,11 @@
   CupertinoDynamicColor resolveFrom(BuildContext context) {
     Brightness brightness = Brightness.light;
     if (_isPlatformBrightnessDependent) {
-      brightness =  CupertinoTheme.maybeBrightnessOf(context) ?? Brightness.light;
+      brightness = CupertinoTheme.maybeBrightnessOf(context) ?? Brightness.light;
     }
     bool isHighContrastEnabled = false;
     if (_isHighContrastDependent) {
-      isHighContrastEnabled = MediaQuery.maybeOf(context)?.highContrast ?? false;
+      isHighContrastEnabled = MediaQuery.maybeHighContrastOf(context) ?? false;
     }
 
     final CupertinoUserInterfaceLevelData level = _isInterfaceElevationDependent
diff --git a/framework/lib/src/cupertino/context_menu.dart b/framework/lib/src/cupertino/context_menu.dart
index 5909065..15788df 100644
--- a/framework/lib/src/cupertino/context_menu.dart
+++ b/framework/lib/src/cupertino/context_menu.dart
@@ -99,10 +99,10 @@
 /// [Expanded] widget so that it will grow to fill the Overlay if its size is
 /// unconstrained.
 ///
-/// When closed, the CupertinoContextMenu simply displays the child as if the
-/// CupertinoContextMenu were not there. Sizing and positioning is unaffected.
+/// When closed, the [CupertinoContextMenu] displays the child as if the
+/// [CupertinoContextMenu] were not there. Sizing and positioning is unaffected.
 /// The menu can be closed like other [PopupRoute]s, such as by tapping the
-/// background or by calling `Navigator.pop(context)`. Unlike PopupRoute, it can
+/// background or by calling `Navigator.pop(context)`. Unlike [PopupRoute], it can
 /// also be closed by swiping downwards.
 ///
 /// The [previewBuilder] parameter is most commonly used to display a slight
@@ -111,8 +111,8 @@
 /// Photos app on iOS.
 ///
 /// {@tool dartpad}
-/// This sample shows a very simple CupertinoContextMenu for the Flutter logo.
-/// Simply long press on it to open.
+/// This sample shows a very simple [CupertinoContextMenu] for the Flutter logo.
+/// Long press on it to open.
 ///
 /// ** See code in examples/api/lib/cupertino/context_menu/cupertino_context_menu.0.dart **
 /// {@end-tool}
@@ -142,8 +142,7 @@
       'This feature was deprecated after v3.4.0-34.1.pre.',
     )
     this.previewBuilder = _defaultPreviewBuilder,
-  }) : assert(actions != null && actions.isNotEmpty),
-       assert(child != null),
+  }) : assert(actions.isNotEmpty),
        builder = ((BuildContext context, Animation<double> animation) => child);
 
   /// Creates a context menu with a custom [builder] controlling the widget.
@@ -158,7 +157,7 @@
     super.key,
     required this.actions,
     required this.builder,
-  }) : assert(actions != null && actions.isNotEmpty),
+  }) : assert(actions.isNotEmpty),
        child = null,
        previewBuilder = null;
 
@@ -256,10 +255,9 @@
   /// and when it is fully open. This will overwrite the default animation that
   /// matches the behavior of an iOS 16.0 context menu.
   ///
-  /// This builder can be used instead of the child when either the intended
-  /// child has a property that would conflict with the default animation, like
-  /// a border radius or a shadow, or if simply a more custom animation is
-  /// needed.
+  /// This builder can be used instead of the child when the intended child has
+  /// a property that would conflict with the default animation, such as a
+  /// border radius or a shadow, or if a more custom animation is needed.
   ///
   /// In addition to the current [BuildContext], the function is also called
   /// with an [Animation]. The complete animation goes from 0 to 1 when
@@ -493,7 +491,7 @@
   // it.
   _ContextMenuLocation get _contextMenuLocation {
     final Rect childRect = _getRect(_childGlobalKey);
-    final double screenWidth = MediaQuery.of(context).size.width;
+    final double screenWidth = MediaQuery.sizeOf(context).width;
 
     final double center = screenWidth / 2;
     final bool centerDividesChild = childRect.left < center
@@ -795,8 +793,7 @@
     super.filter,
     required Rect previousChildRect,
     super.settings,
-  }) : assert(actions != null && actions.isNotEmpty),
-       assert(contextMenuLocation != null),
+  }) : assert(actions.isNotEmpty),
        _actions = actions,
        _builder = builder,
        _contextMenuLocation = contextMenuLocation,
@@ -1082,8 +1079,7 @@
     this.onDismiss,
     required this.orientation,
     this.sheetGlobalKey,
-  }) : assert(contextMenuLocation != null),
-       assert(orientation != null);
+  });
 
   final List<Widget>? actions;
   final Widget child;
@@ -1311,7 +1307,7 @@
   Widget _buildChildAnimation(BuildContext context, Widget? child) {
     _lastScale = _getScale(
       widget.orientation,
-      MediaQuery.of(context).size.height,
+      MediaQuery.sizeOf(context).height,
       _moveAnimation.value.dy,
     );
     return Transform.scale(
@@ -1410,9 +1406,7 @@
     required this.actions,
     required _ContextMenuLocation contextMenuLocation,
     required Orientation orientation,
-  }) : assert(actions != null && actions.isNotEmpty),
-       assert(contextMenuLocation != null),
-       assert(orientation != null),
+  }) : assert(actions.isNotEmpty),
        _contextMenuLocation = contextMenuLocation,
        _orientation = orientation;
 
diff --git a/framework/lib/src/cupertino/context_menu_action.dart b/framework/lib/src/cupertino/context_menu_action.dart
index 2906e4f..0f011ea 100644
--- a/framework/lib/src/cupertino/context_menu_action.dart
+++ b/framework/lib/src/cupertino/context_menu_action.dart
@@ -20,9 +20,7 @@
     this.isDestructiveAction = false,
     this.onPressed,
     this.trailingIcon,
-  }) : assert(child != null),
-       assert(isDefaultAction != null),
-       assert(isDestructiveAction != null);
+  });
 
   /// The widget that will be placed inside the action.
   final Widget child;
diff --git a/framework/lib/src/cupertino/date_picker.dart b/framework/lib/src/cupertino/date_picker.dart
index 92234d3..94522f1 100644
--- a/framework/lib/src/cupertino/date_picker.dart
+++ b/framework/lib/src/cupertino/date_picker.dart
@@ -81,8 +81,7 @@
   _DatePickerLayoutDelegate({
     required this.columnWidths,
     required this.textDirectionFactor,
-  }) : assert(columnWidths != null),
-       assert(textDirectionFactor != null);
+  });
 
   // The list containing widths of all columns.
   final List<double> columnWidths;
@@ -277,14 +276,10 @@
     this.dateOrder,
     this.backgroundColor,
   }) : initialDateTime = initialDateTime ?? DateTime.now(),
-       assert(mode != null),
-       assert(onDateTimeChanged != null),
-       assert(minimumYear != null),
        assert(
          minuteInterval > 0 && 60 % minuteInterval == 0,
          'minute interval is not a positive integer factor of 60',
        ) {
-    assert(this.initialDateTime != null);
     assert(
       mode != CupertinoDatePickerMode.dateAndTime || minimumDate == null || !this.initialDateTime.isBefore(minimumDate!),
       'initial date is before minimum date',
@@ -944,7 +939,6 @@
   }
 
   void _scrollToDate(DateTime newDate, DateTime fromDate, bool minCheck) {
-    assert(newDate != null);
     SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) {
       if (fromDate.year != newDate.year || fromDate.month != newDate.month || fromDate.day != newDate.day) {
         _animateColumnControllerToItem(dateController, selectedDayFromInitial);
@@ -1349,7 +1343,6 @@
   }
 
   void _scrollToDate(DateTime newDate) {
-    assert(newDate != null);
     SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) {
       if (selectedYear != newDate.year) {
         _animateColumnControllerToItem(yearController, newDate.year);
@@ -1551,15 +1544,12 @@
     this.alignment = Alignment.center,
     this.backgroundColor,
     required this.onTimerDurationChanged,
-  }) : assert(mode != null),
-       assert(onTimerDurationChanged != null),
-       assert(initialTimerDuration >= Duration.zero),
+  }) : assert(initialTimerDuration >= Duration.zero),
        assert(initialTimerDuration < const Duration(days: 1)),
        assert(minuteInterval > 0 && 60 % minuteInterval == 0),
        assert(secondInterval > 0 && 60 % secondInterval == 0),
        assert(initialTimerDuration.inMinutes % minuteInterval == 0),
-       assert(initialTimerDuration.inSeconds % secondInterval == 0),
-       assert(alignment != null);
+       assert(initialTimerDuration.inSeconds % secondInterval == 0);
 
   /// The mode of the timer picker.
   final CupertinoTimerPickerMode mode;
diff --git a/framework/lib/src/cupertino/desktop_text_selection.dart b/framework/lib/src/cupertino/desktop_text_selection.dart
index 6f529bc..b5dbada 100644
--- a/framework/lib/src/cupertino/desktop_text_selection.dart
+++ b/framework/lib/src/cupertino/desktop_text_selection.dart
@@ -158,12 +158,12 @@
     }
 
     assert(debugCheckHasMediaQuery(context));
-    final MediaQueryData mediaQuery = MediaQuery.of(context);
+    final EdgeInsets mediaQueryPadding = MediaQuery.paddingOf(context);
 
     final Offset midpointAnchor = Offset(
       clampDouble(widget.selectionMidpoint.dx - widget.globalEditableRegion.left,
-        mediaQuery.padding.left,
-        mediaQuery.size.width - mediaQuery.padding.right,
+        mediaQueryPadding.left,
+        MediaQuery.sizeOf(context).width - mediaQueryPadding.right,
       ),
       widget.selectionMidpoint.dy - widget.globalEditableRegion.top,
     );
@@ -171,7 +171,7 @@
     final List<Widget> items = <Widget>[];
     final CupertinoLocalizations localizations = CupertinoLocalizations.of(context);
     final Widget onePhysicalPixelVerticalDivider =
-        SizedBox(width: 1.0 / MediaQuery.of(context).devicePixelRatio);
+        SizedBox(width: 1.0 / MediaQuery.devicePixelRatioOf(context));
 
     void addToolbarButton(
       String text,
diff --git a/framework/lib/src/cupertino/desktop_text_selection_toolbar.dart b/framework/lib/src/cupertino/desktop_text_selection_toolbar.dart
index 831a758..939b3e4 100644
--- a/framework/lib/src/cupertino/desktop_text_selection_toolbar.dart
+++ b/framework/lib/src/cupertino/desktop_text_selection_toolbar.dart
@@ -85,9 +85,8 @@
   @override
   Widget build(BuildContext context) {
     assert(debugCheckHasMediaQuery(context));
-    final MediaQueryData mediaQuery = MediaQuery.of(context);
 
-    final double paddingAbove = mediaQuery.padding.top + _kToolbarScreenPadding;
+    final double paddingAbove = MediaQuery.paddingOf(context).top + _kToolbarScreenPadding;
     final Offset localAdjustment = Offset(_kToolbarScreenPadding, paddingAbove);
 
     return Padding(
diff --git a/framework/lib/src/cupertino/desktop_text_selection_toolbar_button.dart b/framework/lib/src/cupertino/desktop_text_selection_toolbar_button.dart
index f9e11cb..0a88961 100644
--- a/framework/lib/src/cupertino/desktop_text_selection_toolbar_button.dart
+++ b/framework/lib/src/cupertino/desktop_text_selection_toolbar_button.dart
@@ -37,8 +37,7 @@
     super.key,
     required this.onPressed,
     required Widget this.child,
-  }) : assert(child != null),
-       buttonItem = null;
+  }) : buttonItem = null;
 
   /// Create an instance of [CupertinoDesktopTextSelectionToolbarButton] whose child is
   /// a [Text] widget styled like the default Mac context menu button.
@@ -66,8 +65,7 @@
   CupertinoDesktopTextSelectionToolbarButton.buttonItem({
     super.key,
     required ContextMenuButtonItem this.buttonItem,
-  }) : assert(buttonItem != null),
-       onPressed = buttonItem.onPressed,
+  }) : onPressed = buttonItem.onPressed,
        child = null;
 
   /// {@macro flutter.cupertino.CupertinoTextSelectionToolbarButton.onPressed}
diff --git a/framework/lib/src/cupertino/dialog.dart b/framework/lib/src/cupertino/dialog.dart
index 876026b..d398462 100644
--- a/framework/lib/src/cupertino/dialog.dart
+++ b/framework/lib/src/cupertino/dialog.dart
@@ -149,8 +149,8 @@
 // Accessibility mode on iOS is determined by the text scale factor that the
 // user has selected.
 bool _isInAccessibilityMode(BuildContext context) {
-  final MediaQueryData? data = MediaQuery.maybeOf(context);
-  return data != null && data.textScaleFactor > _kMaxRegularTextScaleFactor;
+  final double? factor = MediaQuery.maybeTextScaleFactorOf(context);
+  return factor != null && factor > _kMaxRegularTextScaleFactor;
 }
 
 /// An iOS-style alert dialog.
@@ -201,7 +201,7 @@
     this.actionScrollController,
     this.insetAnimationDuration = const Duration(milliseconds: 100),
     this.insetAnimationCurve = Curves.decelerate,
-  }) : assert(actions != null);
+  });
 
   /// The (optional) title of the dialog is displayed in a large font at the top
   /// of the dialog.
@@ -257,7 +257,7 @@
   final Curve insetAnimationCurve;
 
   Widget _buildContent(BuildContext context) {
-    final double textScaleFactor = MediaQuery.of(context).textScaleFactor;
+    final double textScaleFactor = MediaQuery.textScaleFactorOf(context);
 
     final List<Widget> children = <Widget>[
       if (title != null || content != null)
@@ -289,7 +289,7 @@
         ),
     ];
 
-    return Container(
+    return ColoredBox(
       color: CupertinoDynamicColor.resolve(_kDialogColor, context),
       child: Column(
         mainAxisSize: MainAxisSize.min,
@@ -317,7 +317,7 @@
   Widget build(BuildContext context) {
     final CupertinoLocalizations localizations = CupertinoLocalizations.of(context);
     final bool isInAccessibilityMode = _isInAccessibilityMode(context);
-    final double textScaleFactor = MediaQuery.of(context).textScaleFactor;
+    final double textScaleFactor = MediaQuery.textScaleFactorOf(context);
     return CupertinoUserInterfaceLevel(
       data: CupertinoUserInterfaceLevelData.elevated,
       child: MediaQuery(
@@ -331,7 +331,7 @@
           child: LayoutBuilder(
             builder: (BuildContext context, BoxConstraints constraints) {
               return AnimatedPadding(
-                padding: MediaQuery.of(context).viewInsets +
+                padding: MediaQuery.viewInsetsOf(context) +
                     const EdgeInsets.symmetric(horizontal: 40.0, vertical: 24.0),
                 duration: insetAnimationDuration,
                 curve: insetAnimationCurve,
@@ -555,7 +555,7 @@
       content.add(Flexible(child: titleSection));
     }
 
-    return Container(
+    return ColoredBox(
       color: CupertinoDynamicColor.resolve(_kActionSheetBackgroundColor, context),
       child: Column(
         mainAxisSize: MainAxisSize.min,
@@ -611,12 +611,12 @@
       if (cancelButton != null) _buildCancelButton(),
     ];
 
-    final Orientation orientation = MediaQuery.of(context).orientation;
+    final Orientation orientation = MediaQuery.orientationOf(context);
     final double actionSheetWidth;
     if (orientation == Orientation.portrait) {
-      actionSheetWidth = MediaQuery.of(context).size.width - (_kActionSheetEdgeHorizontalPadding * 2);
+      actionSheetWidth = MediaQuery.sizeOf(context).width - (_kActionSheetEdgeHorizontalPadding * 2);
     } else {
-      actionSheetWidth = MediaQuery.of(context).size.height - (_kActionSheetEdgeHorizontalPadding * 2);
+      actionSheetWidth = MediaQuery.sizeOf(context).height - (_kActionSheetEdgeHorizontalPadding * 2);
     }
 
     return SafeArea(
@@ -665,8 +665,7 @@
     this.isDefaultAction = false,
     this.isDestructiveAction = false,
     required this.child,
-  }) : assert(child != null),
-       assert(onPressed != null);
+  });
 
   /// The callback that is called when the button is tapped.
   ///
@@ -701,7 +700,7 @@
     }
 
     return MouseRegion(
-      cursor: onPressed != null && kIsWeb ? SystemMouseCursors.click : MouseCursor.defer,
+      cursor: kIsWeb ? SystemMouseCursors.click : MouseCursor.defer,
       child: GestureDetector(
         onTap: onPressed,
         behavior: HitTestBehavior.opaque,
@@ -797,7 +796,7 @@
   @override
   RenderObject createRenderObject(BuildContext context) {
     return _RenderCupertinoDialog(
-      dividerThickness: _kDividerThickness / MediaQuery.of(context).devicePixelRatio,
+      dividerThickness: _kDividerThickness / MediaQuery.devicePixelRatioOf(context),
       isInAccessibilityMode: _isInAccessibilityMode(context) && !isActionSheet,
       dividerColor: CupertinoDynamicColor.resolve(dividerColor, context),
       isActionSheet: isActionSheet,
@@ -896,7 +895,6 @@
   }
 
   void _placeChildInSlot(RenderObject child, _AlertDialogSections slot) {
-    assert(slot != null);
     switch (slot) {
       case _AlertDialogSections.contentSection:
         renderObject.contentSection = child as RenderBox;
@@ -1443,7 +1441,7 @@
     this.scrollController,
     this.hasCancelButton = false,
     this.isActionSheet = false,
-  }) : assert(children != null);
+  });
 
   final List<Widget> children;
 
@@ -1464,7 +1462,7 @@
 
   @override
   Widget build(BuildContext context) {
-    final double devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
+    final double devicePixelRatio = MediaQuery.devicePixelRatioOf(context);
 
     final List<Widget> interactiveButtons = <Widget>[];
     for (int i = 0; i < children.length; i += 1) {
@@ -1593,9 +1591,7 @@
     this.isDestructiveAction = false,
     this.textStyle,
     required this.child,
-  }) : assert(child != null),
-       assert(isDefaultAction != null),
-       assert(isDestructiveAction != null);
+  });
 
   /// The callback that is called when the button is tapped or otherwise
   /// activated.
@@ -1767,7 +1763,7 @@
 //
 // See [_RenderCupertinoDialogActions] for specific layout policy details.
 class _CupertinoDialogActionsRenderWidget extends MultiChildRenderObjectWidget {
-  _CupertinoDialogActionsRenderWidget({
+  const _CupertinoDialogActionsRenderWidget({
     required List<Widget> actionButtons,
     double dividerThickness = 0.0,
     bool hasCancelButton = false,
diff --git a/framework/lib/src/cupertino/icons.dart b/framework/lib/src/cupertino/icons.dart
index 94188e6..3332770 100644
--- a/framework/lib/src/cupertino/icons.dart
+++ b/framework/lib/src/cupertino/icons.dart
@@ -30,9 +30,9 @@
 /// ![The following code snippet would generate a row of icons consisting of a pink heart, a green bell, and a blue umbrella, each progressively bigger than the last.](https://flutter.github.io/assets-for-api-docs/assets/cupertino/cupertino_icon.png)
 ///
 /// ```dart
-/// Row(
+/// const Row(
 ///   mainAxisAlignment: MainAxisAlignment.spaceAround,
-///   children: const <Widget>[
+///   children: <Widget>[
 ///     Icon(
 ///       CupertinoIcons.heart_fill,
 ///       color: Colors.pink,
@@ -59,6 +59,7 @@
 /// See also:
 ///
 ///  * [Icon], used to show these icons.
+@staticIconProvider
 class CupertinoIcons {
   // This class is not meant to be instantiated or extended; this constructor
   // prevents instantiation and extension.
diff --git a/framework/lib/src/cupertino/interface_level.dart b/framework/lib/src/cupertino/interface_level.dart
index 6f35554..c11f17f 100644
--- a/framework/lib/src/cupertino/interface_level.dart
+++ b/framework/lib/src/cupertino/interface_level.dart
@@ -45,8 +45,7 @@
     super.key,
     required CupertinoUserInterfaceLevelData data,
     required super.child,
-  }) : assert(data != null),
-      _data = data;
+  }) : _data = data;
 
   final CupertinoUserInterfaceLevelData _data;
 
@@ -65,7 +64,6 @@
   ///  * [maybeOf], which is similar, but will return null if no
   ///    [CupertinoUserInterfaceLevel] encloses the given context.
   static CupertinoUserInterfaceLevelData of(BuildContext context) {
-    assert(context != null);
     final CupertinoUserInterfaceLevel? query = context.dependOnInheritedWidgetOfExactType<CupertinoUserInterfaceLevel>();
     if (query != null) {
       return query._data;
@@ -95,7 +93,6 @@
   ///  * [of], which is similar, but will throw an exception if no
   ///    [CupertinoUserInterfaceLevel] encloses the given context.
   static CupertinoUserInterfaceLevelData? maybeOf(BuildContext context) {
-    assert(context != null);
     final CupertinoUserInterfaceLevel? query = context.dependOnInheritedWidgetOfExactType<CupertinoUserInterfaceLevel>();
     if (query != null) {
       return query._data;
diff --git a/framework/lib/src/cupertino/list_section.dart b/framework/lib/src/cupertino/list_section.dart
index 26bf0d9..e917133 100644
--- a/framework/lib/src/cupertino/list_section.dart
+++ b/framework/lib/src/cupertino/list_section.dart
@@ -347,7 +347,7 @@
   @override
   Widget build(BuildContext context) {
     final Color dividerColor = CupertinoColors.separator.resolveFrom(context);
-    final double dividerHeight = 1.0 / MediaQuery.of(context).devicePixelRatio;
+    final double dividerHeight = 1.0 / MediaQuery.devicePixelRatioOf(context);
 
     // Long divider is used for wrapping the top and bottom of rows.
     // Only used in CupertinoListSectionType.base mode.
diff --git a/framework/lib/src/cupertino/magnifier.dart b/framework/lib/src/cupertino/magnifier.dart
index a1ed06e..05a92b9 100644
--- a/framework/lib/src/cupertino/magnifier.dart
+++ b/framework/lib/src/cupertino/magnifier.dart
@@ -174,7 +174,7 @@
               CupertinoMagnifier.kMagnifierAboveFocalPoint),
     );
 
-    final Rect screenRect = Offset.zero & MediaQuery.of(context).size;
+    final Rect screenRect = Offset.zero & MediaQuery.sizeOf(context);
 
     // Adjust the magnifier position so that it never exists outside the horizontal
     // padding.
diff --git a/framework/lib/src/cupertino/nav_bar.dart b/framework/lib/src/cupertino/nav_bar.dart
index 405e02b..6d73f55 100644
--- a/framework/lib/src/cupertino/nav_bar.dart
+++ b/framework/lib/src/cupertino/nav_bar.dart
@@ -33,6 +33,8 @@
 
 const double _kNavBarEdgePadding = 16.0;
 
+const double _kNavBarBottomPadding = 8.0;
+
 const double _kNavBarBackButtonTapWidth = 50.0;
 
 /// Title text transfer fade.
@@ -147,8 +149,20 @@
         overlayStyle = SystemUiOverlayStyle.dark;
         break;
     }
+    // [SystemUiOverlayStyle.light] and [SystemUiOverlayStyle.dark] set some system
+    // navigation bar properties,
+    // Before https://github.com/flutter/flutter/pull/104827 those properties
+    // had no effect, now they are used if there is no AnnotatedRegion on the
+    // bottom of the screen.
+    // For backward compatibility, create a `SystemUiOverlayStyle` without the
+    // system navigation bar properties.
     result = AnnotatedRegion<SystemUiOverlayStyle>(
-      value: overlayStyle,
+      value: SystemUiOverlayStyle(
+        statusBarColor: overlayStyle.statusBarColor,
+        statusBarBrightness: overlayStyle.statusBarBrightness,
+        statusBarIconBrightness: overlayStyle.statusBarIconBrightness,
+        systemStatusBarContrastEnforced: overlayStyle.systemStatusBarContrastEnforced,
+      ),
       child: result,
     );
   }
@@ -255,15 +269,7 @@
     this.padding,
     this.transitionBetweenRoutes = true,
     this.heroTag = _defaultHeroTag,
-  }) : assert(automaticallyImplyLeading != null),
-       assert(automaticallyImplyMiddle != null),
-       assert(transitionBetweenRoutes != null),
-       assert(
-         heroTag != null,
-         'heroTag cannot be null. Use transitionBetweenRoutes = false to '
-         'disable Hero transition on this navigation bar.',
-       ),
-       assert(
+  }) : assert(
          !transitionBetweenRoutes || identical(heroTag, _defaultHeroTag),
          'Cannot specify a heroTag override if this navigation bar does not '
          'transition due to transitionBetweenRoutes = false.',
@@ -597,9 +603,7 @@
     this.transitionBetweenRoutes = true,
     this.heroTag = _defaultHeroTag,
     this.stretch = false,
-  }) : assert(automaticallyImplyLeading != null),
-       assert(automaticallyImplyTitle != null),
-       assert(
+  }) : assert(
          automaticallyImplyTitle == true || largeTitle != null,
          'No largeTitle has been provided but automaticallyImplyTitle is also '
          'false. Either provide a largeTitle or set automaticallyImplyTitle to '
@@ -754,7 +758,7 @@
           actionsForegroundColor: CupertinoTheme.of(context).primaryColor,
           transitionBetweenRoutes: widget.transitionBetweenRoutes,
           heroTag: widget.heroTag,
-          persistentHeight: _kNavBarPersistentHeight + MediaQuery.of(context).padding.top,
+          persistentHeight: _kNavBarPersistentHeight + MediaQuery.paddingOf(context).top,
           alwaysShowMiddle: widget.alwaysShowMiddle && widget.middle != null,
           stretchConfiguration: widget.stretch ? OverScrollHeaderStretchConfiguration() : null,
         ),
@@ -779,9 +783,7 @@
     required this.persistentHeight,
     required this.alwaysShowMiddle,
     required this.stretchConfiguration,
-  }) : assert(persistentHeight != null),
-       assert(alwaysShowMiddle != null),
-       assert(transitionBetweenRoutes != null);
+  });
 
   final _NavigationBarStaticComponentsKeys keys;
   final _NavigationBarStaticComponents components;
@@ -833,31 +835,27 @@
               right: 0.0,
               bottom: 0.0,
               child: ClipRect(
-                // The large title starts at the persistent bar.
-                // It's aligned with the bottom of the sliver and expands clipped
-                // and behind the persistent bar.
-                child: OverflowBox(
-                  minHeight: 0.0,
-                  maxHeight: double.infinity,
-                  alignment: AlignmentDirectional.bottomStart,
-                  child: Padding(
-                    padding: const EdgeInsetsDirectional.only(
-                      start: _kNavBarEdgePadding,
-                      bottom: 8.0, // Bottom has a different padding.
-                    ),
-                    child: SafeArea(
-                      top: false,
-                      bottom: false,
-                      child: AnimatedOpacity(
-                        opacity: showLargeTitle ? 1.0 : 0.0,
-                        duration: _kNavBarTitleFadeDuration,
-                        child: Semantics(
-                          header: true,
-                          child: DefaultTextStyle(
-                            style: CupertinoTheme.of(context).textTheme.navLargeTitleTextStyle,
-                            maxLines: 1,
-                            overflow: TextOverflow.ellipsis,
-                            child: components.largeTitle!,
+                child: Padding(
+                  padding: const EdgeInsetsDirectional.only(
+                    start: _kNavBarEdgePadding,
+                    bottom: _kNavBarBottomPadding
+                  ),
+                  child: SafeArea(
+                    top: false,
+                    bottom: false,
+                    child: AnimatedOpacity(
+                      opacity: showLargeTitle ? 1.0 : 0.0,
+                      duration: _kNavBarTitleFadeDuration,
+                      child: Semantics(
+                        header: true,
+                        child: DefaultTextStyle(
+                          style: CupertinoTheme.of(context)
+                              .textTheme
+                              .navLargeTitleTextStyle,
+                          maxLines: 1,
+                          overflow: TextOverflow.ellipsis,
+                          child: _LargeTitle(
+                            child: components.largeTitle,
                           ),
                         ),
                       ),
@@ -921,6 +919,123 @@
   }
 }
 
+/// The large title of the navigation bar.
+///
+/// Magnifies on over-scroll when [CupertinoSliverNavigationBar.stretch]
+/// parameter is true.
+class _LargeTitle extends SingleChildRenderObjectWidget {
+  const _LargeTitle({ super.child });
+
+  @override
+  _RenderLargeTitle createRenderObject(BuildContext context) {
+    return _RenderLargeTitle(alignment: AlignmentDirectional.bottomStart.resolve(Directionality.of(context)));
+  }
+
+  @override
+  void updateRenderObject(BuildContext context, _RenderLargeTitle renderObject) {
+    renderObject.alignment = AlignmentDirectional.bottomStart.resolve(Directionality.of(context));
+  }
+}
+
+class _RenderLargeTitle extends RenderShiftedBox {
+  _RenderLargeTitle({
+    required Alignment alignment,
+  })  : _alignment = alignment,
+        super(null);
+
+  Alignment get alignment => _alignment;
+  Alignment _alignment;
+  set alignment(Alignment value) {
+    if (_alignment == value) {
+      return;
+    }
+    _alignment = value;
+
+    markNeedsLayout();
+  }
+
+  double _scale = 1.0;
+
+  @override
+  void performLayout() {
+    final RenderBox? child = this.child;
+    Size childSize = Size.zero;
+
+    size = constraints.biggest;
+
+    if (child == null) {
+      return;
+    }
+
+    final BoxConstraints childConstriants = constraints.widthConstraints().loosen();
+    child.layout(childConstriants, parentUsesSize: true);
+
+    final double maxScale = child.size.width != 0.0
+      ? clampDouble(constraints.maxWidth / child.size.width, 1.0, 1.1)
+      : 1.1;
+    _scale = clampDouble(
+      1.0 + (constraints.maxHeight - (_kNavBarLargeTitleHeightExtension - _kNavBarBottomPadding)) / (_kNavBarLargeTitleHeightExtension - _kNavBarBottomPadding) * 0.03,
+      1.0,
+      maxScale,
+    );
+
+    childSize = child.size * _scale;
+    final BoxParentData childParentData = child.parentData! as BoxParentData;
+    childParentData.offset = alignment.alongOffset(size - childSize as Offset);
+  }
+
+  @override
+  void applyPaintTransform(RenderBox child, Matrix4 transform) {
+    assert(child == this.child);
+
+    super.applyPaintTransform(child, transform);
+
+    transform.scale(_scale, _scale);
+  }
+
+  @override
+  void paint(PaintingContext context, Offset offset) {
+    final RenderBox? child = this.child;
+
+    if (child == null) {
+      layer = null;
+    } else {
+      final BoxParentData childParentData = child.parentData! as BoxParentData;
+
+      layer = context.pushTransform(
+        needsCompositing,
+        offset + childParentData.offset,
+        Matrix4.diagonal3Values(_scale, _scale, 1.0),
+        (PaintingContext context, Offset offset) => context.paintChild(child, offset),
+        oldLayer: layer as TransformLayer?,
+      );
+    }
+  }
+
+  @override
+  bool hitTestChildren(BoxHitTestResult result, {required Offset position}) {
+    final RenderBox? child = this.child;
+
+    if (child == null) {
+      return false;
+    }
+
+    final Offset childOffset = (child.parentData! as BoxParentData).offset;
+
+    final Matrix4 transform = Matrix4.identity()
+      ..scale(1.0/_scale, 1.0/_scale, 1.0)
+      ..translate(-childOffset.dx, -childOffset.dy);
+
+    return result.addWithRawTransform(
+      transform: transform,
+      position: position,
+      hitTest: (BoxHitTestResult result, Offset transformed) {
+        return child.hitTest(result, position: transformed);
+      }
+    );
+  }
+}
+
 /// The top part of the navigation bar that's never scrolled away.
 ///
 /// Consists of the entire navigation bar without background and border when used
@@ -989,7 +1104,7 @@
     }
 
     return SizedBox(
-      height: _kNavBarPersistentHeight + MediaQuery.of(context).padding.top,
+      height: _kNavBarPersistentHeight + MediaQuery.paddingOf(context).top,
       child: SafeArea(
         bottom: false,
         child: paddedToolbar,
@@ -1453,7 +1568,7 @@
   // null here and unused.
   Widget _buildPreviousTitleWidget(BuildContext context, String? previousTitle, Widget? child) {
     if (previousTitle == null) {
-      return const SizedBox(height: 0.0, width: 0.0);
+      return const SizedBox.shrink();
     }
 
     Text textWidget = Text(
@@ -1487,7 +1602,7 @@
         builder: _buildPreviousTitleWidget,
       );
     } else {
-      return const SizedBox(height: 0.0, width: 0.0);
+      return const SizedBox.shrink();
     }
   }
 }
@@ -1511,9 +1626,7 @@
     required this.hasUserMiddle,
     required this.largeExpanded,
     required this.child,
-  }) : assert(componentsKeys != null),
-       assert(largeExpanded != null),
-       assert(!largeExpanded || largeTitleTextStyle != null),
+  }) : assert(!largeExpanded || largeTitleTextStyle != null),
        super(key: componentsKeys.navBarBoxKey);
 
   final _NavigationBarStaticComponentsKeys componentsKeys;
@@ -1655,12 +1768,16 @@
     // The actual outer box is big enough to contain both the bottom and top
     // navigation bars. It's not a direct Rect lerp because some components
     // can actually be outside the linearly lerp'ed Rect in the middle of
-    // the animation, such as the topLargeTitle.
-    return SizedBox(
-      height: math.max(heightTween.begin!, heightTween.end!) + MediaQuery.of(context).padding.top,
-      width: double.infinity,
-      child: Stack(
-        children: children,
+    // the animation, such as the topLargeTitle. The textScaleFactor is kept
+    // at 1 to avoid odd transitions between pages.
+    return MediaQuery(
+      data: MediaQuery.of(context).copyWith(textScaleFactor: 1),
+      child: SizedBox(
+        height: math.max(heightTween.begin!, heightTween.end!) + MediaQuery.paddingOf(context).top,
+        width: double.infinity,
+        child: Stack(
+          children: children,
+        ),
       ),
     );
   }
@@ -1981,7 +2098,7 @@
       return null;
     }
 
-    if (bottomLargeTitle != null && topBackLabel != null) {
+    if (topBackLabel != null) {
       // Move from current position to the top page's back label position.
       return slideFromLeadingEdge(
         fromKey: bottomComponents.largeTitleKey,
@@ -2008,7 +2125,7 @@
       );
     }
 
-    if (bottomLargeTitle != null && topLeading != null) {
+    if (topLeading != null) {
       // Unlike bottom middle, the bottom large title moves when it can't
       // transition to the top back label position.
       final RelativeRect from = positionInTransitionBox(bottomComponents.largeTitleKey, from: bottomNavBarBox);
@@ -2139,7 +2256,6 @@
     // text is too long, the topBackLabel will say 'Back' instead of the original
     // text.
     if (bottomLargeTitle != null &&
-        topBackLabel != null &&
         bottomLargeExpanded) {
       return slideFromLeadingEdge(
         fromKey: bottomComponents.largeTitleKey,
@@ -2163,7 +2279,7 @@
 
     // The topBackLabel always comes from the large title first if available
     // and expanded instead of middle.
-    if (bottomMiddle != null && topBackLabel != null) {
+    if (bottomMiddle != null) {
       return slideFromLeadingEdge(
         fromKey: bottomComponents.middleKey,
         fromNavBarBox: bottomNavBarBox,
@@ -2333,10 +2449,6 @@
   BuildContext fromHeroContext,
   BuildContext toHeroContext,
 ) {
-  assert(animation != null);
-  assert(flightDirection != null);
-  assert(fromHeroContext != null);
-  assert(toHeroContext != null);
   assert(fromHeroContext.widget is Hero);
   assert(toHeroContext.widget is Hero);
 
@@ -2349,8 +2461,6 @@
   final _TransitionableNavigationBar fromNavBar = fromHeroWidget.child as _TransitionableNavigationBar;
   final _TransitionableNavigationBar toNavBar = toHeroWidget.child as _TransitionableNavigationBar;
 
-  assert(fromNavBar.componentsKeys != null);
-  assert(toNavBar.componentsKeys != null);
 
   assert(
     fromNavBar.componentsKeys.navBarBoxKey.currentContext!.owner != null,
diff --git a/framework/lib/src/cupertino/page_scaffold.dart b/framework/lib/src/cupertino/page_scaffold.dart
index 05e740b..a605143 100644
--- a/framework/lib/src/cupertino/page_scaffold.dart
+++ b/framework/lib/src/cupertino/page_scaffold.dart
@@ -39,8 +39,7 @@
     this.backgroundColor,
     this.resizeToAvoidBottomInset = true,
     required this.child,
-  }) : assert(child != null),
-       assert(resizeToAvoidBottomInset != null);
+  });
 
   /// The [navigationBar], typically a [CupertinoNavigationBar], is drawn at the
   /// top of the screen.
diff --git a/framework/lib/src/cupertino/picker.dart b/framework/lib/src/cupertino/picker.dart
index b6fa83c..7f42a1e 100644
--- a/framework/lib/src/cupertino/picker.dart
+++ b/framework/lib/src/cupertino/picker.dart
@@ -83,13 +83,9 @@
     required List<Widget> children,
     this.selectionOverlay = const CupertinoPickerDefaultSelectionOverlay(),
     bool looping = false,
-  }) : assert(children != null),
-       assert(diameterRatio != null),
-       assert(diameterRatio > 0.0, RenderListWheelViewport.diameterRatioZeroMessage),
+  }) : assert(diameterRatio > 0.0, RenderListWheelViewport.diameterRatioZeroMessage),
        assert(magnification > 0),
-       assert(itemExtent != null),
        assert(itemExtent > 0),
-       assert(squeeze != null),
        assert(squeeze > 0),
        childDelegate = looping
                        ? ListWheelChildLoopingListDelegate(children: children)
@@ -126,13 +122,9 @@
     required NullableIndexedWidgetBuilder itemBuilder,
     int? childCount,
     this.selectionOverlay = const CupertinoPickerDefaultSelectionOverlay(),
-  }) : assert(itemBuilder != null),
-       assert(diameterRatio != null),
-       assert(diameterRatio > 0.0, RenderListWheelViewport.diameterRatioZeroMessage),
+  }) : assert(diameterRatio > 0.0, RenderListWheelViewport.diameterRatioZeroMessage),
        assert(magnification > 0),
-       assert(itemExtent != null),
        assert(itemExtent > 0),
-       assert(squeeze != null),
        assert(squeeze > 0),
        childDelegate = ListWheelChildBuilderDelegate(builder: itemBuilder, childCount: childCount);
 
@@ -254,7 +246,6 @@
         hasSuitableHapticHardware = false;
         break;
     }
-    assert(hasSuitableHapticHardware != null);
     if (hasSuitableHapticHardware && index != _lastHapticIndex) {
       _lastHapticIndex = index;
       HapticFeedback.selectionClick();
@@ -355,9 +346,7 @@
     this.background = CupertinoColors.tertiarySystemFill,
     this.capStartEdge = true,
     this.capEndEdge = true,
-  }) : assert(background != null),
-       assert(capStartEdge != null),
-       assert(capEndEdge != null);
+  });
 
   /// Whether to use the default use rounded corners and margin on the start side.
   final bool capStartEdge;
diff --git a/framework/lib/src/cupertino/refresh.dart b/framework/lib/src/cupertino/refresh.dart
index 0c122ba..3ada10c 100644
--- a/framework/lib/src/cupertino/refresh.dart
+++ b/framework/lib/src/cupertino/refresh.dart
@@ -20,9 +20,7 @@
     this.refreshIndicatorLayoutExtent = 0.0,
     this.hasLayoutExtent = false,
     super.child,
-  }) : assert(refreshIndicatorLayoutExtent != null),
-       assert(refreshIndicatorLayoutExtent >= 0.0),
-       assert(hasLayoutExtent != null);
+  }) : assert(refreshIndicatorLayoutExtent >= 0.0);
 
   // The amount of space the indicator should occupy in the sliver in a
   // resting state when in the refreshing mode.
@@ -61,9 +59,7 @@
     required double refreshIndicatorExtent,
     required bool hasLayoutExtent,
     RenderBox? child,
-  }) : assert(refreshIndicatorExtent != null),
-       assert(refreshIndicatorExtent >= 0.0),
-       assert(hasLayoutExtent != null),
+  }) : assert(refreshIndicatorExtent >= 0.0),
        _refreshIndicatorExtent = refreshIndicatorExtent,
        _hasLayoutExtent = hasLayoutExtent {
     this.child = child;
@@ -74,7 +70,6 @@
   double get refreshIndicatorLayoutExtent => _refreshIndicatorExtent;
   double _refreshIndicatorExtent;
   set refreshIndicatorLayoutExtent(double value) {
-    assert(value != null);
     assert(value >= 0.0);
     if (value == _refreshIndicatorExtent) {
       return;
@@ -89,7 +84,6 @@
   bool get hasLayoutExtent => _hasLayoutExtent;
   bool _hasLayoutExtent;
   set hasLayoutExtent(bool value) {
-    assert(value != null);
     if (value == _hasLayoutExtent) {
       return;
     }
@@ -303,9 +297,7 @@
     this.refreshIndicatorExtent = _defaultRefreshIndicatorExtent,
     this.builder = buildRefreshIndicator,
     this.onRefresh,
-  }) : assert(refreshTriggerPullDistance != null),
-       assert(refreshTriggerPullDistance > 0.0),
-       assert(refreshIndicatorExtent != null),
+  }) : assert(refreshTriggerPullDistance > 0.0),
        assert(refreshIndicatorExtent >= 0.0),
        assert(
          refreshTriggerPullDistance >= refreshIndicatorExtent,
diff --git a/framework/lib/src/cupertino/route.dart b/framework/lib/src/cupertino/route.dart
index 587fa13..bb158ad 100644
--- a/framework/lib/src/cupertino/route.dart
+++ b/framework/lib/src/cupertino/route.dart
@@ -225,21 +225,11 @@
   @override
   Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
     final Widget child = buildContent(context);
-    final Widget result = Semantics(
+    return Semantics(
       scopesRoute: true,
       explicitChildNodes: true,
       child: child,
     );
-    assert(() {
-      if (child == null) {
-        throw FlutterError.fromParts(<DiagnosticsNode>[
-          ErrorSummary('The builder for route "${settings.name}" returned null.'),
-          ErrorDescription('Route builders must never return null.'),
-        ]);
-      }
-      return true;
-    }());
-    return result;
   }
 
   // Called by _CupertinoBackGestureDetector when a pop ("back") drag start
@@ -343,9 +333,7 @@
     this.maintainState = true,
     super.fullscreenDialog,
     super.allowSnapshotting = true,
-  }) : assert(builder != null),
-       assert(maintainState != null),
-       assert(fullscreenDialog != null) {
+  }) {
     assert(opaque);
   }
 
@@ -373,8 +361,7 @@
   _PageBasedCupertinoPageRoute({
     required CupertinoPage<T> page,
     super.allowSnapshotting = true,
-  }) : assert(page != null),
-       super(settings: page) {
+  }) : super(settings: page) {
     assert(opaque);
   }
 
@@ -424,9 +411,7 @@
     super.name,
     super.arguments,
     super.restorationId,
-  }) : assert(child != null),
-       assert(maintainState != null),
-       assert(fullscreenDialog != null);
+  });
 
   /// The content to be shown in the [Route] created by this page.
   final Widget child;
@@ -468,8 +453,7 @@
     required Animation<double> secondaryRouteAnimation,
     required this.child,
     required bool linearTransition,
-  }) : assert(linearTransition != null),
-       _primaryPositionAnimation =
+  }) : _primaryPositionAnimation =
            (linearTransition
              ? primaryRouteAnimation
              : CurvedAnimation(
@@ -607,9 +591,7 @@
     required this.enabledCallback,
     required this.onStartPopGesture,
     required this.child,
-  }) : assert(enabledCallback != null),
-       assert(onStartPopGesture != null),
-       assert(child != null);
+  });
 
   final Widget child;
 
@@ -690,8 +672,8 @@
     // For devices with notches, the drag area needs to be larger on the side
     // that has the notch.
     double dragAreaWidth = Directionality.of(context) == TextDirection.ltr ?
-                           MediaQuery.of(context).padding.left :
-                           MediaQuery.of(context).padding.right;
+                           MediaQuery.paddingOf(context).left :
+                           MediaQuery.paddingOf(context).right;
     dragAreaWidth = max(dragAreaWidth, _kBackGestureWidth);
     return Stack(
       fit: StackFit.passthrough,
@@ -731,8 +713,7 @@
   _CupertinoBackGestureController({
     required this.navigator,
     required this.controller,
-  }) : assert(navigator != null),
-       assert(controller != null) {
+  }) {
     navigator.didStartUserGesture();
   }
 
@@ -854,7 +835,6 @@
     _CupertinoEdgeShadowDecoration? b,
     double t,
   ) {
-    assert(t != null);
     if (a == null && b == null) {
       return null;
     }
@@ -921,8 +901,7 @@
   _CupertinoEdgeShadowPainter(
     this._decoration,
     super.onChange,
-  ) : assert(_decoration != null),
-      assert(_decoration._colors == null || _decoration._colors!.length > 1);
+  ) : assert(_decoration._colors == null || _decoration._colors!.length > 1);
 
   final _CupertinoEdgeShadowDecoration _decoration;
 
@@ -1031,14 +1010,12 @@
     this.barrierLabel = 'Dismiss',
     this.barrierColor = kCupertinoModalBarrierColor,
     bool barrierDismissible = true,
-    bool? semanticsDismissible,
+    bool semanticsDismissible = false,
     super.filter,
     super.settings,
     this.anchorPoint,
-  }) {
-    _barrierDismissible = barrierDismissible;
-    _semanticsDismissible = semanticsDismissible;
-  }
+  }) : _barrierDismissible = barrierDismissible,
+       _semanticsDismissible = semanticsDismissible;
 
   /// A builder that builds the widget tree for the [CupertinoModalPopupRoute].
   ///
@@ -1050,9 +1027,9 @@
   /// widget needs to update dynamically.
   final WidgetBuilder builder;
 
-  bool? _barrierDismissible;
+  final bool _barrierDismissible;
 
-  bool? _semanticsDismissible;
+  final bool _semanticsDismissible;
 
   @override
   final String barrierLabel;
@@ -1061,10 +1038,10 @@
   final Color? barrierColor;
 
   @override
-  bool get barrierDismissible => _barrierDismissible ?? true;
+  bool get barrierDismissible => _barrierDismissible;
 
   @override
-  bool get semanticsDismissible => _semanticsDismissible ?? false;
+  bool get semanticsDismissible => _semanticsDismissible;
 
   @override
   Duration get transitionDuration => _kModalPopupTransitionDuration;
@@ -1188,11 +1165,10 @@
   Color barrierColor = kCupertinoModalBarrierColor,
   bool barrierDismissible = true,
   bool useRootNavigator = true,
-  bool? semanticsDismissible,
+  bool semanticsDismissible = false,
   RouteSettings? routeSettings,
   Offset? anchorPoint,
 }) {
-  assert(useRootNavigator != null);
   return Navigator.of(context, rootNavigator: useRootNavigator).push(
     CupertinoModalPopupRoute<T>(
       builder: builder,
@@ -1297,8 +1273,6 @@
   RouteSettings? routeSettings,
   Offset? anchorPoint,
 }) {
-  assert(builder != null);
-  assert(useRootNavigator != null);
 
   return Navigator.of(context, rootNavigator: useRootNavigator).push<T>(CupertinoDialogRoute<T>(
     builder: builder,
@@ -1361,8 +1335,7 @@
     super.transitionBuilder = _buildCupertinoDialogTransitions,
     super.settings,
     super.anchorPoint,
-  }) : assert(barrierDismissible != null),
-      super(
+  }) : super(
         pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
           return builder(context);
         },
diff --git a/framework/lib/src/cupertino/scrollbar.dart b/framework/lib/src/cupertino/scrollbar.dart
index b7bce96..ee75dc1 100644
--- a/framework/lib/src/cupertino/scrollbar.dart
+++ b/framework/lib/src/cupertino/scrollbar.dart
@@ -29,7 +29,7 @@
 
 /// An iOS style scrollbar.
 ///
-/// To add a scrollbar to a [ScrollView], simply wrap the scroll view widget in
+/// To add a scrollbar to a [ScrollView], wrap the scroll view widget in
 /// a [CupertinoScrollbar] widget.
 ///
 /// {@youtube 560 315 https://www.youtube.com/watch?v=DbkIQSvwnZc}
@@ -87,12 +87,8 @@
       'This feature was deprecated after v2.9.0-1.0.pre.',
     )
     bool? isAlwaysShown,
-  }) : assert(thickness != null),
-       assert(thickness < double.infinity),
-       assert(thicknessWhileDragging != null),
+  }) : assert(thickness < double.infinity),
        assert(thicknessWhileDragging < double.infinity),
-       assert(radius != null),
-       assert(radiusWhileDragging != null),
        assert(
          isAlwaysShown == null || thumbVisibility == null,
          'Scrollbar thumb appearance should only be controlled with thumbVisibility, '
@@ -171,7 +167,7 @@
       ..mainAxisMargin = _kScrollbarMainAxisMargin
       ..crossAxisMargin = _kScrollbarCrossAxisMargin
       ..radius = _radius
-      ..padding = MediaQuery.of(context).padding
+      ..padding = MediaQuery.paddingOf(context)
       ..minLength = _kScrollbarMinLength
       ..minOverscrollLength = _kScrollbarMinOverscrollLength
       ..scrollbarOrientation = widget.scrollbarOrientation;
diff --git a/framework/lib/src/cupertino/search_field.dart b/framework/lib/src/cupertino/search_field.dart
index e42ac78..e973781 100644
--- a/framework/lib/src/cupertino/search_field.dart
+++ b/framework/lib/src/cupertino/search_field.dart
@@ -122,18 +122,12 @@
     this.focusNode,
     this.smartQuotesType,
     this.smartDashesType,
+    this.enableIMEPersonalizedLearning = true,
     this.autofocus = false,
     this.onTap,
     this.autocorrect = true,
     this.enabled,
-  })  : assert(padding != null),
-        assert(itemColor != null),
-        assert(itemSize != null),
-        assert(prefixInsets != null),
-        assert(suffixInsets != null),
-        assert(suffixIcon != null),
-        assert(suffixMode != null),
-        assert(
+  })  : assert(
           !((decoration != null) && (backgroundColor != null)),
           'Cannot provide both a background color and a decoration\n'
           'To provide both, use "decoration: BoxDecoration(color: '
@@ -318,6 +312,9 @@
   ///  * <https://developer.apple.com/documentation/uikit/uitextinputtraits>
   final SmartDashesType? smartDashesType;
 
+  /// {@macro flutter.services.TextInputConfiguration.enableIMEPersonalizedLearning}
+  final bool enableIMEPersonalizedLearning;
+
   /// Disables the text field when false.
   ///
   /// Text fields in disabled states have a light grey background and don't
@@ -460,6 +457,7 @@
       autocorrect: widget.autocorrect,
       smartQuotesType: widget.smartQuotesType,
       smartDashesType: widget.smartDashesType,
+      enableIMEPersonalizedLearning: widget.enableIMEPersonalizedLearning,
       textInputAction: TextInputAction.search,
     );
   }
diff --git a/framework/lib/src/cupertino/segmented_control.dart b/framework/lib/src/cupertino/segmented_control.dart
index 4df14ac..1292642 100644
--- a/framework/lib/src/cupertino/segmented_control.dart
+++ b/framework/lib/src/cupertino/segmented_control.dart
@@ -99,9 +99,7 @@
     this.borderColor,
     this.pressedColor,
     this.padding,
-  }) : assert(children != null),
-       assert(children.length >= 2),
-       assert(onValueChanged != null),
+  }) : assert(children.length >= 2),
        assert(
          groupValue == null || children.keys.any((T child) => child == groupValue),
          'The groupValue must be either null or one of the keys in the children map.',
@@ -407,7 +405,7 @@
 }
 
 class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget {
-  _SegmentedControlRenderWidget({
+  const _SegmentedControlRenderWidget({
     super.key,
     super.children,
     required this.selectedIndex,
@@ -458,8 +456,7 @@
     required TextDirection textDirection,
     required List<Color> backgroundColors,
     required Color borderColor,
-  }) : assert(textDirection != null),
-       _textDirection = textDirection,
+  }) : _textDirection = textDirection,
        _selectedIndex = selectedIndex,
        _pressedIndex = pressedIndex,
        _backgroundColors = backgroundColors,
@@ -685,7 +682,6 @@
   }
 
   void _paintChild(PaintingContext context, Offset offset, RenderBox child, int childIndex) {
-    assert(child != null);
 
     final _SegmentedControlContainerBoxParentData childParentData = child.parentData! as _SegmentedControlContainerBoxParentData;
 
@@ -708,7 +704,6 @@
 
   @override
   bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
-    assert(position != null);
     RenderBox? child = lastChild;
     while (child != null) {
       final _SegmentedControlContainerBoxParentData childParentData = child.parentData! as _SegmentedControlContainerBoxParentData;
diff --git a/framework/lib/src/cupertino/slider.dart b/framework/lib/src/cupertino/slider.dart
index ecc6cb0..cd962c9 100644
--- a/framework/lib/src/cupertino/slider.dart
+++ b/framework/lib/src/cupertino/slider.dart
@@ -71,12 +71,8 @@
     this.divisions,
     this.activeColor,
     this.thumbColor = CupertinoColors.white,
-  }) : assert(value != null),
-       assert(min != null),
-       assert(max != null),
-       assert(value >= min && value <= max),
-       assert(divisions == null || divisions > 0),
-       assert(thumbColor != null);
+  }) : assert(value >= min && value <= max),
+       assert(divisions == null || divisions > 0);
 
   /// The currently selected value for this slider.
   ///
@@ -337,9 +333,7 @@
     required TickerProvider vsync,
     required TextDirection textDirection,
     MouseCursor cursor = MouseCursor.defer,
-  }) : assert(value != null && value >= 0.0 && value <= 1.0),
-       assert(textDirection != null),
-       assert(cursor != null),
+  }) : assert(value >= 0.0 && value <= 1.0),
        _cursor = cursor,
        _value = value,
        _divisions = divisions,
@@ -363,7 +357,7 @@
   double get value => _value;
   double _value;
   set value(double newValue) {
-    assert(newValue != null && newValue >= 0.0 && newValue <= 1.0);
+    assert(newValue >= 0.0 && newValue <= 1.0);
     if (newValue == _value) {
       return;
     }
@@ -435,7 +429,6 @@
   TextDirection get textDirection => _textDirection;
   TextDirection _textDirection;
   set textDirection(TextDirection value) {
-    assert(value != null);
     if (_textDirection == value) {
       return;
     }
diff --git a/framework/lib/src/cupertino/sliding_segmented_control.dart b/framework/lib/src/cupertino/sliding_segmented_control.dart
index 1e94b55..ca0affe 100644
--- a/framework/lib/src/cupertino/sliding_segmented_control.dart
+++ b/framework/lib/src/cupertino/sliding_segmented_control.dart
@@ -320,10 +320,7 @@
     this.thumbColor = _kThumbColor,
     this.padding = _kHorizontalItemPadding,
     this.backgroundColor = CupertinoColors.tertiarySystemFill,
-  }) : assert(children != null),
-       assert(children.length >= 2),
-       assert(padding != null),
-       assert(onValueChanged != null),
+  }) : assert(children.length >= 2),
        assert(
          groupValue == null || children.keys.contains(groupValue),
          'The groupValue must be either null or one of the keys in the children map.',
@@ -523,7 +520,6 @@
   // _Segment widget) to make the overall animation look natural when the thumb
   // is not sliding.
   void _playThumbScaleAnimation({ required bool isExpanding }) {
-    assert(isExpanding != null);
     thumbScaleAnimation = thumbScaleController.drive(
       Tween<double>(
         begin: thumbScaleAnimation.value,
@@ -715,7 +711,7 @@
 }
 
 class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget {
-  _SegmentedControlRenderWidget({
+  const _SegmentedControlRenderWidget({
     super.key,
     super.children,
     required this.highlightedIndex,
@@ -793,8 +789,7 @@
     required this.state,
   }) : _highlightedIndex = highlightedIndex,
        _thumbColor = thumbColor,
-       _thumbScale = thumbScale,
-       assert(state != null);
+       _thumbScale = thumbScale;
 
   final _SegmentedControlState<T> state;
 
@@ -1074,13 +1069,11 @@
   // Paint the separator to the right of the given child.
   final Paint separatorPaint = Paint();
   void _paintSeparator(PaintingContext context, Offset offset, RenderBox child) {
-    assert(child != null);
     final _SegmentedControlContainerBoxParentData childParentData = child.parentData! as _SegmentedControlContainerBoxParentData;
     context.paintChild(child, offset + childParentData.offset);
   }
 
   void _paintChild(PaintingContext context, Offset offset, RenderBox child) {
-    assert(child != null);
     final _SegmentedControlContainerBoxParentData childParentData = child.parentData! as _SegmentedControlContainerBoxParentData;
     context.paintChild(child, childParentData.offset + offset);
   }
@@ -1119,7 +1112,6 @@
 
   @override
   bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
-    assert(position != null);
     RenderBox? child = lastChild;
     while (child != null) {
       final _SegmentedControlContainerBoxParentData childParentData =
diff --git a/framework/lib/src/cupertino/switch.dart b/framework/lib/src/cupertino/switch.dart
index bec0371..dedaf4e 100644
--- a/framework/lib/src/cupertino/switch.dart
+++ b/framework/lib/src/cupertino/switch.dart
@@ -14,6 +14,7 @@
 import 'package:flute/widgets.dart';
 
 import 'colors.dart';
+import 'theme.dart';
 import 'thumb_painter.dart';
 
 // Examples can assume:
@@ -72,9 +73,10 @@
     this.activeColor,
     this.trackColor,
     this.thumbColor,
+    this.applyTheme,
+    this.focusColor,
     this.dragStartBehavior = DragStartBehavior.start,
-  }) : assert(value != null),
-       assert(dragStartBehavior != null);
+  });
 
   /// Whether this switch is on or off.
   ///
@@ -105,13 +107,15 @@
   /// ```
   final ValueChanged<bool>? onChanged;
 
-  /// The color to use when this switch is on.
+  /// The color to use for the track when the switch is on.
   ///
-  /// Defaults to [CupertinoColors.systemGreen] when null and ignores
-  /// the [CupertinoTheme] in accordance to native iOS behavior.
+  /// If null and [applyTheme] is false, defaults to [CupertinoColors.systemGreen]
+  /// in accordance to native iOS behavior. Otherwise, defaults to
+  /// [CupertinoThemeData.primaryColor].
   final Color? activeColor;
 
-  /// The color to use for the background when the switch is off.
+
+  /// The color to use for the track when the switch is off.
   ///
   /// Defaults to [CupertinoColors.secondarySystemFill] when null.
   final Color? trackColor;
@@ -121,6 +125,21 @@
   /// Defaults to [CupertinoColors.white] when null.
   final Color? thumbColor;
 
+  /// The color to use for the focus highlight for keyboard interactions.
+  ///
+  /// Defaults to a slightly transparent [activeColor].
+  final Color? focusColor;
+
+  /// {@template flutter.cupertino.CupertinoSwitch.applyTheme}
+  /// Whether to apply the ambient [CupertinoThemeData].
+  ///
+  /// If true, the track uses [CupertinoThemeData.primaryColor] for the track
+  /// when the switch is on.
+  ///
+  /// Defaults to [CupertinoThemeData.applyThemeToAll].
+  /// {@endtemplate}
+  final bool? applyTheme;
+
   /// {@template flutter.cupertino.CupertinoSwitch.dragStartBehavior}
   /// Determines the way that drag start behavior is handled.
   ///
@@ -164,8 +183,14 @@
   late AnimationController _reactionController;
   late Animation<double> _reaction;
 
+  late bool isFocused;
+
   bool get isInteractive => widget.onChanged != null;
 
+  late final Map<Type, Action<Intent>> _actionMap = <Type, Action<Intent>>{
+    ActivateIntent: CallbackAction<ActivateIntent>(onInvoke: _handleTap),
+  };
+
   // A non-null boolean value that changes to true at the end of a drag if the
   // switch must be animated to the position indicated by the widget's value.
   bool needsPositionAnimation = false;
@@ -174,6 +199,8 @@
   void initState() {
     super.initState();
 
+    isFocused = false;
+
     _tap = TapGestureRecognizer()
       ..onTapDown = _handleTapDown
       ..onTapUp = _handleTapUp
@@ -239,7 +266,7 @@
       _reactionController.forward();
   }
 
-  void _handleTap() {
+  void _handleTap([Intent? _]) {
     if (isInteractive) {
       widget.onChanged!(!widget.value);
       _emitVibration();
@@ -308,8 +335,19 @@
     }
   }
 
+  void _onShowFocusHighlight(bool showHighlight) {
+    setState(() { isFocused = showHighlight; });
+  }
+
   @override
   Widget build(BuildContext context) {
+    final CupertinoThemeData theme = CupertinoTheme.of(context);
+    final Color activeColor = CupertinoDynamicColor.resolve(
+      widget.activeColor
+      ?? ((widget.applyTheme ?? theme.applyThemeToAll) ? theme.primaryColor : null)
+      ?? CupertinoColors.systemGreen,
+      context,
+    );
     if (needsPositionAnimation) {
       _resumePositionAnimation();
     }
@@ -317,17 +355,29 @@
       cursor: isInteractive && kIsWeb ? SystemMouseCursors.click : MouseCursor.defer,
       child: Opacity(
         opacity: widget.onChanged == null ? _kCupertinoSwitchDisabledOpacity : 1.0,
-        child: _CupertinoSwitchRenderObjectWidget(
-          value: widget.value,
-          activeColor: CupertinoDynamicColor.resolve(
-            widget.activeColor ?? CupertinoColors.systemGreen,
-            context,
+        child: FocusableActionDetector(
+          onShowFocusHighlight: _onShowFocusHighlight,
+          actions: _actionMap,
+          enabled: isInteractive,
+          child: _CupertinoSwitchRenderObjectWidget(
+            value: widget.value,
+            activeColor: activeColor,
+            trackColor: CupertinoDynamicColor.resolve(widget.trackColor ?? CupertinoColors.secondarySystemFill, context),
+            thumbColor: CupertinoDynamicColor.resolve(widget.thumbColor ?? CupertinoColors.white, context),
+            // Opacity, lightness, and saturation values were aproximated with
+            // color pickers on the switches in the macOS settings.
+            focusColor: CupertinoDynamicColor.resolve(
+              widget.focusColor ??
+              HSLColor
+                    .fromColor(activeColor.withOpacity(0.80))
+                    .withLightness(0.69).withSaturation(0.835)
+                    .toColor(),
+              context),
+            onChanged: widget.onChanged,
+            textDirection: Directionality.of(context),
+            isFocused: isFocused,
+            state: this,
           ),
-          trackColor: CupertinoDynamicColor.resolve(widget.trackColor ?? CupertinoColors.secondarySystemFill, context),
-          thumbColor: CupertinoDynamicColor.resolve(widget.thumbColor ?? CupertinoColors.white, context),
-          onChanged: widget.onChanged,
-          textDirection: Directionality.of(context),
-          state: this,
         ),
       ),
     );
@@ -350,8 +400,10 @@
     required this.activeColor,
     required this.trackColor,
     required this.thumbColor,
+    required this.focusColor,
     required this.onChanged,
     required this.textDirection,
+    required this.isFocused,
     required this.state,
   });
 
@@ -359,9 +411,11 @@
   final Color activeColor;
   final Color trackColor;
   final Color thumbColor;
+  final Color focusColor;
   final ValueChanged<bool>? onChanged;
   final _CupertinoSwitchState state;
   final TextDirection textDirection;
+  final bool isFocused;
 
   @override
   _RenderCupertinoSwitch createRenderObject(BuildContext context) {
@@ -370,8 +424,10 @@
       activeColor: activeColor,
       trackColor: trackColor,
       thumbColor: thumbColor,
+      focusColor: focusColor,
       onChanged: onChanged,
       textDirection: textDirection,
+      isFocused: isFocused,
       state: state,
     );
   }
@@ -384,8 +440,10 @@
       ..activeColor = activeColor
       ..trackColor = trackColor
       ..thumbColor = thumbColor
+      ..focusColor = focusColor
       ..onChanged = onChanged
-      ..textDirection = textDirection;
+      ..textDirection = textDirection
+      ..isFocused = isFocused;
   }
 }
 
@@ -409,18 +467,19 @@
     required Color activeColor,
     required Color trackColor,
     required Color thumbColor,
+    required Color focusColor,
     ValueChanged<bool>? onChanged,
     required TextDirection textDirection,
+    required bool isFocused,
     required _CupertinoSwitchState state,
-  }) : assert(value != null),
-       assert(activeColor != null),
-       assert(state != null),
-       _value = value,
+  }) : _value = value,
        _activeColor = activeColor,
        _trackColor = trackColor,
+       _focusColor = focusColor,
        _thumbPainter = CupertinoThumbPainter.switchThumb(color: thumbColor),
        _onChanged = onChanged,
        _textDirection = textDirection,
+       _isFocused = isFocused,
        _state = state,
        super(additionalConstraints: const BoxConstraints.tightFor(width: _kSwitchWidth, height: _kSwitchHeight)) {
          state.position.addListener(markNeedsPaint);
@@ -432,7 +491,6 @@
   bool get value => _value;
   bool _value;
   set value(bool value) {
-    assert(value != null);
     if (value == _value) {
       return;
     }
@@ -443,7 +501,6 @@
   Color get activeColor => _activeColor;
   Color _activeColor;
   set activeColor(Color value) {
-    assert(value != null);
     if (value == _activeColor) {
       return;
     }
@@ -454,7 +511,6 @@
   Color get trackColor => _trackColor;
   Color _trackColor;
   set trackColor(Color value) {
-    assert(value != null);
     if (value == _trackColor) {
       return;
     }
@@ -465,7 +521,6 @@
   Color get thumbColor => _thumbPainter.color;
   CupertinoThumbPainter _thumbPainter;
   set thumbColor(Color value) {
-    assert(value != null);
     if (value == thumbColor) {
       return;
     }
@@ -473,6 +528,16 @@
     markNeedsPaint();
   }
 
+  Color get focusColor => _focusColor;
+  Color _focusColor;
+  set focusColor(Color value) {
+    if (value == _focusColor) {
+      return;
+    }
+    _focusColor = value;
+    markNeedsPaint();
+  }
+
   ValueChanged<bool>? get onChanged => _onChanged;
   ValueChanged<bool>? _onChanged;
   set onChanged(ValueChanged<bool>? value) {
@@ -490,7 +555,6 @@
   TextDirection get textDirection => _textDirection;
   TextDirection _textDirection;
   set textDirection(TextDirection value) {
-    assert(value != null);
     if (_textDirection == value) {
       return;
     }
@@ -498,6 +562,16 @@
     markNeedsPaint();
   }
 
+  bool get isFocused => _isFocused;
+  bool _isFocused;
+  set isFocused(bool value) {
+    if(value == _isFocused) {
+      return;
+    }
+    _isFocused = value;
+    markNeedsPaint();
+  }
+
   bool get isInteractive => onChanged != null;
 
   @override
@@ -553,6 +627,18 @@
     final RRect trackRRect = RRect.fromRectAndRadius(trackRect, const Radius.circular(_kTrackRadius));
     canvas.drawRRect(trackRRect, paint);
 
+    if(_isFocused) {
+      // Paints a border around the switch in the focus color.
+      final RRect borderTrackRRect = trackRRect.inflate(1.75);
+
+      final Paint borderPaint = Paint()
+        ..color = focusColor
+        ..style = PaintingStyle.stroke
+        ..strokeWidth = 3.5;
+
+      canvas.drawRRect(borderTrackRRect, borderPaint);
+    }
+
     final double currentThumbExtension = CupertinoThumbPainter.extension * currentReactionValue;
     final double thumbLeft = lerpDouble(
       trackRect.left + _kTrackInnerStart - CupertinoThumbPainter.radius,
diff --git a/framework/lib/src/cupertino/tab_scaffold.dart b/framework/lib/src/cupertino/tab_scaffold.dart
index 8eddfe8..20ce8b8 100644
--- a/framework/lib/src/cupertino/tab_scaffold.dart
+++ b/framework/lib/src/cupertino/tab_scaffold.dart
@@ -36,7 +36,6 @@
   /// greater than or equal to 0, and less than the total number of tabs.
   CupertinoTabController({ int initialIndex = 0 })
     : _index = initialIndex,
-      assert(initialIndex != null),
       assert(initialIndex >= 0);
 
   bool _isDisposed = false;
@@ -52,7 +51,6 @@
   int get index => _index;
   int _index;
   set index(int value) {
-    assert(value != null);
     assert(value >= 0);
     if (_index == value) {
       return;
@@ -135,9 +133,7 @@
     this.backgroundColor,
     this.resizeToAvoidBottomInset = true,
     this.restorationId,
-  }) : assert(tabBar != null),
-       assert(tabBuilder != null),
-       assert(
+  }) : assert(
          controller == null || controller.index < tabBar.items.length,
          "The CupertinoTabController's current index ${controller.index} is "
          'out of bounds for the tab bar with ${tabBar.items.length} tabs',
@@ -324,12 +320,10 @@
       contentPadding = EdgeInsets.only(bottom: existingMediaQuery.viewInsets.bottom);
     }
 
-    if (widget.tabBar != null &&
-        // Only pad the content with the height of the tab bar if the tab
-        // isn't already entirely obstructed by a keyboard or other view insets.
-        // Don't double pad.
-        (!widget.resizeToAvoidBottomInset ||
-            widget.tabBar.preferredSize.height > existingMediaQuery.viewInsets.bottom)) {
+    // Only pad the content with the height of the tab bar if the tab
+    // isn't already entirely obstructed by a keyboard or other view insets.
+    // Don't double pad.
+    if (!widget.resizeToAvoidBottomInset || widget.tabBar.preferredSize.height > existingMediaQuery.viewInsets.bottom) {
       // TODO(xster): Use real size after partial layout instead of preferred size.
       // https://github.com/flutter/flutter/issues/12912
       final double bottomPadding =
@@ -406,9 +400,7 @@
     required this.currentTabIndex,
     required this.tabCount,
     required this.tabBuilder,
-  }) : assert(currentTabIndex != null),
-       assert(tabCount != null && tabCount > 0),
-       assert(tabBuilder != null);
+  }) : assert(tabCount > 0);
 
   final int currentTabIndex;
   final int tabCount;
@@ -530,8 +522,7 @@
   /// The `initialIndex` must not be null and defaults to 0. The value must be
   /// greater than or equal to 0, and less than the total number of tabs.
   RestorableCupertinoTabController({ int initialIndex = 0 })
-    : assert(initialIndex != null),
-      assert(initialIndex >= 0),
+    : assert(initialIndex >= 0),
       _initialIndex = initialIndex;
 
   final int _initialIndex;
diff --git a/framework/lib/src/cupertino/tab_view.dart b/framework/lib/src/cupertino/tab_view.dart
index 4c4d791..d091c86 100644
--- a/framework/lib/src/cupertino/tab_view.dart
+++ b/framework/lib/src/cupertino/tab_view.dart
@@ -50,7 +50,7 @@
     this.onUnknownRoute,
     this.navigatorObservers = const <NavigatorObserver>[],
     this.restorationScopeId,
-  }) : assert(navigatorObservers != null);
+  });
 
   /// The widget builder for the default route of the tab view
   /// ([Navigator.defaultRouteName], which is `/`).
@@ -175,13 +175,13 @@
 
   Route<dynamic>? _onGenerateRoute(RouteSettings settings) {
     final String? name = settings.name;
-    WidgetBuilder? routeBuilder;
+    final WidgetBuilder? routeBuilder;
     String? title;
     if (name == Navigator.defaultRouteName && widget.builder != null) {
       routeBuilder = widget.builder;
       title = widget.defaultTitle;
-    } else if (widget.routes != null) {
-      routeBuilder = widget.routes![name];
+    } else {
+      routeBuilder = widget.routes?[name];
     }
     if (routeBuilder != null) {
       return CupertinoPageRoute<dynamic>(
@@ -190,10 +190,7 @@
         settings: settings,
       );
     }
-    if (widget.onGenerateRoute != null) {
-      return widget.onGenerateRoute!(settings);
-    }
-    return null;
+    return widget.onGenerateRoute?.call(settings);
   }
 
   Route<dynamic>? _onUnknownRoute(RouteSettings settings) {
diff --git a/framework/lib/src/cupertino/text_field.dart b/framework/lib/src/cupertino/text_field.dart
index 9ac4d24..a8ec7e6 100644
--- a/framework/lib/src/cupertino/text_field.dart
+++ b/framework/lib/src/cupertino/text_field.dart
@@ -102,7 +102,7 @@
   final _CupertinoTextFieldState _state;
 
   @override
-  void onSingleTapUp(TapUpDetails details) {
+  void onSingleTapUp(TapDragUpDetails details) {
     // Because TextSelectionGestureDetector listens to taps that happen on
     // widgets in front of it, tapping the clear button will also trigger
     // this handler. If the clear button widget recognizes the up event,
@@ -120,7 +120,7 @@
   }
 
   @override
-  void onDragSelectionEnd(DragEndDetails details) {
+  void onDragSelectionEnd(TapDragEndDetails details) {
     _state._requestKeyboard();
   }
 }
@@ -274,6 +274,7 @@
     this.scrollController,
     this.scrollPhysics,
     this.autofillHints = const <String>[],
+    this.contentInsertionConfiguration,
     this.clipBehavior = Clip.hardEdge,
     this.restorationId,
     this.scribbleEnabled = true,
@@ -281,35 +282,21 @@
     this.contextMenuBuilder = _defaultContextMenuBuilder,
     this.spellCheckConfiguration,
     this.magnifierConfiguration,
-  }) : assert(textAlign != null),
-       assert(readOnly != null),
-       assert(autofocus != null),
-       assert(obscuringCharacter != null && obscuringCharacter.length == 1),
-       assert(obscureText != null),
-       assert(autocorrect != null),
+  }) : assert(obscuringCharacter.length == 1),
        smartDashesType = smartDashesType ?? (obscureText ? SmartDashesType.disabled : SmartDashesType.enabled),
        smartQuotesType = smartQuotesType ?? (obscureText ? SmartQuotesType.disabled : SmartQuotesType.enabled),
-       assert(enableSuggestions != null),
-       assert(scrollPadding != null),
-       assert(dragStartBehavior != null),
-       assert(selectionHeightStyle != null),
-       assert(selectionWidthStyle != null),
        assert(maxLines == null || maxLines > 0),
        assert(minLines == null || minLines > 0),
        assert(
          (maxLines == null) || (minLines == null) || (maxLines >= minLines),
          "minLines can't be greater than maxLines",
        ),
-       assert(expands != null),
        assert(
          !expands || (maxLines == null && minLines == null),
          'minLines and maxLines must be null when expands is true.',
        ),
        assert(!obscureText || maxLines == 1, 'Obscured fields cannot be multiline.'),
        assert(maxLength == null || maxLength > 0),
-       assert(clearButtonMode != null),
-       assert(prefixMode != null),
-       assert(suffixMode != null),
        // Assert the following instead of setting it directly to avoid surprising the user by silently changing the value they set.
        assert(
          !identical(textInputAction, TextInputAction.newline) ||
@@ -317,7 +304,6 @@
          !identical(keyboardType, TextInputType.text),
          'Use keyboardType TextInputType.multiline when using TextInputAction.newline on a multiline TextField.',
        ),
-       assert(enableIMEPersonalizedLearning != null),
        keyboardType = keyboardType ?? (maxLines == 1 ? TextInputType.text : TextInputType.multiline),
        enableInteractiveSelection = enableInteractiveSelection ?? (!readOnly || !obscureText);
 
@@ -418,6 +404,7 @@
     this.scrollController,
     this.scrollPhysics,
     this.autofillHints = const <String>[],
+    this.contentInsertionConfiguration,
     this.clipBehavior = Clip.hardEdge,
     this.restorationId,
     this.scribbleEnabled = true,
@@ -425,35 +412,21 @@
     this.contextMenuBuilder = _defaultContextMenuBuilder,
     this.spellCheckConfiguration,
     this.magnifierConfiguration,
-  }) : assert(textAlign != null),
-       assert(readOnly != null),
-       assert(autofocus != null),
-       assert(obscuringCharacter != null && obscuringCharacter.length == 1),
-       assert(obscureText != null),
-       assert(autocorrect != null),
+  }) : assert(obscuringCharacter.length == 1),
        smartDashesType = smartDashesType ?? (obscureText ? SmartDashesType.disabled : SmartDashesType.enabled),
        smartQuotesType = smartQuotesType ?? (obscureText ? SmartQuotesType.disabled : SmartQuotesType.enabled),
-       assert(enableSuggestions != null),
-       assert(scrollPadding != null),
-       assert(dragStartBehavior != null),
-       assert(selectionHeightStyle != null),
-       assert(selectionWidthStyle != null),
        assert(maxLines == null || maxLines > 0),
        assert(minLines == null || minLines > 0),
        assert(
          (maxLines == null) || (minLines == null) || (maxLines >= minLines),
          "minLines can't be greater than maxLines",
        ),
-       assert(expands != null),
        assert(
          !expands || (maxLines == null && minLines == null),
          'minLines and maxLines must be null when expands is true.',
        ),
        assert(!obscureText || maxLines == 1, 'Obscured fields cannot be multiline.'),
        assert(maxLength == null || maxLength > 0),
-       assert(clearButtonMode != null),
-       assert(prefixMode != null),
-       assert(suffixMode != null),
        // Assert the following instead of setting it directly to avoid surprising the user by silently changing the value they set.
        assert(
          !identical(textInputAction, TextInputAction.newline) ||
@@ -461,8 +434,6 @@
          !identical(keyboardType, TextInputType.text),
          'Use keyboardType TextInputType.multiline when using TextInputAction.newline on a multiline TextField.',
        ),
-       assert(clipBehavior != null),
-       assert(enableIMEPersonalizedLearning != null),
        keyboardType = keyboardType ?? (maxLines == 1 ? TextInputType.text : TextInputType.multiline),
        enableInteractiveSelection = enableInteractiveSelection ?? (!readOnly || !obscureText);
 
@@ -754,6 +725,9 @@
   /// {@macro flutter.services.TextInputConfiguration.enableIMEPersonalizedLearning}
   final bool enableIMEPersonalizedLearning;
 
+  /// {@macro flutter.widgets.editableText.contentInsertionConfiguration}
+  final ContentInsertionConfiguration? contentInsertionConfiguration;
+
   /// {@macro flutter.widgets.EditableText.contextMenuBuilder}
   ///
   /// If not provided, will build a default menu based on the platform.
@@ -850,6 +824,7 @@
     properties.add(DiagnosticsProperty<bool>('scribbleEnabled', scribbleEnabled, defaultValue: true));
     properties.add(DiagnosticsProperty<bool>('enableIMEPersonalizedLearning', enableIMEPersonalizedLearning, defaultValue: true));
     properties.add(DiagnosticsProperty<SpellCheckConfiguration>('spellCheckConfiguration', spellCheckConfiguration, defaultValue: null));
+    properties.add(DiagnosticsProperty<List<String>>('contentCommitMimeTypes', contentInsertionConfiguration?.allowedMimeTypes ?? const <String>[], defaultValue: contentInsertionConfiguration == null ? const <String>[] : kDefaultContentInsertionMimeTypes));
   }
 
   static final TextMagnifierConfiguration _iosMagnifierConfiguration = TextMagnifierConfiguration(
@@ -1102,9 +1077,6 @@
   }
 
   Widget _addTextDependentAttachments(Widget editableText, TextStyle textStyle, TextStyle placeholderStyle) {
-    assert(editableText != null);
-    assert(textStyle != null);
-    assert(placeholderStyle != null);
     // If there are no surrounding widgets, just return the core editable text
     // part.
     if (!_hasDecoration) {
@@ -1224,7 +1196,7 @@
     }
 
     final bool enabled = widget.enabled ?? true;
-    final Offset cursorOffset = Offset(_iOSHorizontalCursorOffsetPixels / MediaQuery.of(context).devicePixelRatio, 0);
+    final Offset cursorOffset = Offset(_iOSHorizontalCursorOffsetPixels / MediaQuery.devicePixelRatioOf(context), 0);
     final List<TextInputFormatter> formatters = <TextInputFormatter>[
       ...?widget.inputFormatters,
       if (widget.maxLength != null)
@@ -1267,7 +1239,7 @@
           ? side
           : side.copyWith(color: CupertinoDynamicColor.resolve(side.color, context));
       }
-      resolvedBorder = border == null || border.runtimeType != Border
+      resolvedBorder = border.runtimeType != Border
         ? border
         : Border(
           top: resolveBorderSide(border.top),
@@ -1362,6 +1334,7 @@
             restorationId: 'editable',
             scribbleEnabled: widget.scribbleEnabled,
             enableIMEPersonalizedLearning: widget.enableIMEPersonalizedLearning,
+            contentInsertionConfiguration: widget.contentInsertionConfiguration,
             contextMenuBuilder: widget.contextMenuBuilder,
             spellCheckConfiguration: spellCheckConfiguration,
           ),
diff --git a/framework/lib/src/cupertino/text_form_field_row.dart b/framework/lib/src/cupertino/text_form_field_row.dart
index 17227c2..f7991e3 100644
--- a/framework/lib/src/cupertino/text_form_field_row.dart
+++ b/framework/lib/src/cupertino/text_form_field_row.dart
@@ -13,7 +13,7 @@
 /// Creates a [CupertinoFormRow] containing a [FormField] that wraps
 /// a [CupertinoTextField].
 ///
-/// A [Form] ancestor is not required. The [Form] simply makes it easier to
+/// A [Form] ancestor is not required. The [Form] allows one to
 /// save, reset, or validate multiple fields at once. To use without a [Form],
 /// pass a [GlobalKey] to the constructor and use [GlobalKey.currentState] to
 /// save or reset the form field.
@@ -158,28 +158,19 @@
     ),
     EditableTextContextMenuBuilder? contextMenuBuilder = _defaultContextMenuBuilder,
   })  : assert(initialValue == null || controller == null),
-        assert(textAlign != null),
-        assert(autofocus != null),
-        assert(readOnly != null),
-        assert(obscuringCharacter != null && obscuringCharacter.length == 1),
-        assert(obscureText != null),
-        assert(autocorrect != null),
-        assert(enableSuggestions != null),
-        assert(scrollPadding != null),
+        assert(obscuringCharacter.length == 1),
         assert(maxLines == null || maxLines > 0),
         assert(minLines == null || minLines > 0),
         assert(
           (maxLines == null) || (minLines == null) || (maxLines >= minLines),
           "minLines can't be greater than maxLines",
         ),
-        assert(expands != null),
         assert(
           !expands || (maxLines == null && minLines == null),
           'minLines and maxLines must be null when expands is true.',
         ),
         assert(!obscureText || maxLines == 1, 'Obscured fields cannot be multiline.'),
         assert(maxLength == null || maxLength > 0),
-        assert(enableInteractiveSelection != null),
         super(
           initialValue: controller?.text ?? initialValue ?? '',
           builder: (FormFieldState<String> field) {
diff --git a/framework/lib/src/cupertino/text_selection.dart b/framework/lib/src/cupertino/text_selection.dart
index 7aef851..3cf5d19 100644
--- a/framework/lib/src/cupertino/text_selection.dart
+++ b/framework/lib/src/cupertino/text_selection.dart
@@ -260,14 +260,14 @@
     }
 
     assert(debugCheckHasMediaQuery(context));
-    final MediaQueryData mediaQuery = MediaQuery.of(context);
+    final EdgeInsets mediaQueryPadding = MediaQuery.paddingOf(context);
 
     // The toolbar should appear below the TextField when there is not enough
     // space above the TextField to show it, assuming there's always enough
     // space at the bottom in this case.
     final double anchorX = clampDouble(widget.selectionMidpoint.dx + widget.globalEditableRegion.left,
-      _kArrowScreenPadding + mediaQuery.padding.left,
-      mediaQuery.size.width - mediaQuery.padding.right - _kArrowScreenPadding,
+      _kArrowScreenPadding + mediaQueryPadding.left,
+      MediaQuery.sizeOf(context).width - mediaQueryPadding.right - _kArrowScreenPadding,
     );
 
     final double topAmountInEditableRegion = widget.endpoints.first.point.dy - widget.textLineHeight;
@@ -289,7 +289,7 @@
     final List<Widget> items = <Widget>[];
     final CupertinoLocalizations localizations = CupertinoLocalizations.of(context);
     final Widget onePhysicalPixelVerticalDivider =
-        SizedBox(width: 1.0 / MediaQuery.of(context).devicePixelRatio);
+        SizedBox(width: 1.0 / MediaQuery.devicePixelRatioOf(context));
 
     void addToolbarButton(
       String text,
diff --git a/framework/lib/src/cupertino/text_selection_toolbar.dart b/framework/lib/src/cupertino/text_selection_toolbar.dart
index b92ea6a..3d55da0 100644
--- a/framework/lib/src/cupertino/text_selection_toolbar.dart
+++ b/framework/lib/src/cupertino/text_selection_toolbar.dart
@@ -5,11 +5,13 @@
 import 'dart:collection';
 import 'package:engine/ui.dart' as ui;
 
-import 'package:flute/foundation.dart' show clampDouble;
+import 'package:flute/foundation.dart' show Brightness, clampDouble;
 import 'package:flute/rendering.dart';
 import 'package:flute/widgets.dart';
 
+import 'colors.dart';
 import 'text_selection_toolbar_button.dart';
+import 'theme.dart';
 
 // Values extracted from https://developer.apple.com/design/resources/.
 // The height of the toolbar, including the arrow.
@@ -17,9 +19,6 @@
 // Vertical distance between the tip of the arrow and the line of text the arrow
 // is pointing to. The value used here is eyeballed.
 const double _kToolbarContentDistance = 8.0;
-// Minimal padding from all edges of the selection toolbar to all edges of the
-// screen.
-const double _kToolbarScreenPadding = 8.0;
 const Size _kToolbarArrowSize = Size(14.0, 7.0);
 
 // Minimal padding from tip of the selection toolbar arrow to horizontal edges of the
@@ -29,9 +28,27 @@
 // Values extracted from https://developer.apple.com/design/resources/.
 const Radius _kToolbarBorderRadius = Radius.circular(8);
 
-// Colors extracted from https://developer.apple.com/design/resources/.
-// TODO(LongCatIsLooong): https://github.com/flutter/flutter/issues/41507.
-const Color _kToolbarDividerColor = Color(0xFF808080);
+const CupertinoDynamicColor _kToolbarDividerColor = CupertinoDynamicColor.withBrightness(
+  // This value was extracted from a screenshot of iOS 16.0.3, as light mode
+  // didn't appear in the Apple design resources assets linked below.
+  color: Color(0xFFB6B6B6),
+  // Color extracted from https://developer.apple.com/design/resources/.
+  // TODO(LongCatIsLooong): https://github.com/flutter/flutter/issues/41507.
+  darkColor: Color(0xFF808080),
+);
+
+// These values were extracted from a screenshot of iOS 16.0.3, as light mode
+// didn't appear in the Apple design resources assets linked above.
+final BoxDecoration _kToolbarShadow = BoxDecoration(
+  borderRadius: const BorderRadius.all(_kToolbarBorderRadius),
+  boxShadow: <BoxShadow>[
+    BoxShadow(
+      color: CupertinoColors.black.withOpacity(0.1),
+      blurRadius: 16.0,
+      offset: Offset(0, _kToolbarArrowSize.height / 2),
+    ),
+  ],
+);
 
 /// The type for a Function that builds a toolbar's container with the given
 /// child.
@@ -53,7 +70,7 @@
 class _CupertinoToolbarButtonDivider extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
-    return SizedBox(width: 1.0 / MediaQuery.of(context).devicePixelRatio);
+    return SizedBox(width: 1.0 / MediaQuery.devicePixelRatioOf(context));
   }
 }
 
@@ -103,7 +120,17 @@
   /// default Cupertino toolbar.
   final CupertinoToolbarBuilder toolbarBuilder;
 
-  // Add the visial vertical line spacer between children buttons.
+  /// Minimal padding from all edges of the selection toolbar to all edges of the
+  /// viewport.
+  ///
+  /// See also:
+  ///
+  ///  * [SpellCheckSuggestionsToolbar], which uses this same value for its
+  ///    padding from the edges of the viewport.
+  ///  * [TextSelectionToolbar], which uses this same value as well.
+  static const double kToolbarScreenPadding = 8.0;
+
+  // Add the visual vertical line spacer between children buttons.
   static List<Widget> _addChildrenSpacers(List<Widget> children) {
     final List<Widget> nextChildren = <Widget>[];
     for (int i = 0; i < children.length; i++) {
@@ -119,22 +146,31 @@
   // Builds a toolbar just like the default iOS toolbar, with the right color
   // background and a rounded cutout with an arrow.
   static Widget _defaultToolbarBuilder(BuildContext context, Offset anchor, bool isAbove, Widget child) {
-    return _CupertinoTextSelectionToolbarShape(
+    final Widget outputChild = _CupertinoTextSelectionToolbarShape(
       anchor: anchor,
       isAbove: isAbove,
       child: DecoratedBox(
-        decoration: const BoxDecoration(color: _kToolbarDividerColor),
+        decoration: BoxDecoration(
+          color: _kToolbarDividerColor.resolveFrom(context),
+        ),
         child: child,
       ),
     );
+    if (CupertinoTheme.brightnessOf(context) == Brightness.dark) {
+      return outputChild;
+    }
+    return DecoratedBox(
+      decoration: _kToolbarShadow,
+      child: outputChild,
+    );
   }
 
   @override
   Widget build(BuildContext context) {
     assert(debugCheckHasMediaQuery(context));
-    final MediaQueryData mediaQuery = MediaQuery.of(context);
+    final EdgeInsets mediaQueryPadding = MediaQuery.paddingOf(context);
 
-    final double paddingAbove = mediaQuery.padding.top + _kToolbarScreenPadding;
+    final double paddingAbove = mediaQueryPadding.top + kToolbarScreenPadding;
     final double toolbarHeightNeeded = paddingAbove
         + _kToolbarContentDistance
         + _kToolbarHeight;
@@ -142,8 +178,8 @@
 
     // The arrow, which points to the anchor, has some margin so it can't get
     // too close to the horizontal edges of the screen.
-    final double leftMargin = _kArrowScreenPadding + mediaQuery.padding.left;
-    final double rightMargin = mediaQuery.size.width - mediaQuery.padding.right - _kArrowScreenPadding;
+    final double leftMargin = _kArrowScreenPadding + mediaQueryPadding.left;
+    final double rightMargin = MediaQuery.sizeOf(context).width - mediaQueryPadding.right - _kArrowScreenPadding;
 
     final Offset anchorAboveAdjusted = Offset(
       clampDouble(anchorAbove.dx, leftMargin, rightMargin),
@@ -151,15 +187,15 @@
     );
     final Offset anchorBelowAdjusted = Offset(
       clampDouble(anchorBelow.dx, leftMargin, rightMargin),
-      anchorBelow.dy - _kToolbarContentDistance + paddingAbove,
+      anchorBelow.dy + _kToolbarContentDistance - paddingAbove,
     );
 
     return Padding(
       padding: EdgeInsets.fromLTRB(
-        _kToolbarScreenPadding,
+        kToolbarScreenPadding,
         paddingAbove,
-        _kToolbarScreenPadding,
-        _kToolbarScreenPadding,
+        kToolbarScreenPadding,
+        kToolbarScreenPadding,
       ),
       child: CustomSingleChildLayout(
         delegate: TextSelectionToolbarLayoutDelegate(
@@ -226,7 +262,6 @@
     super.child,
   );
 
-
   @override
   bool get isRepaintBoundary => true;
 
@@ -398,8 +433,7 @@
     required this.isAbove,
     required this.toolbarBuilder,
     required this.children,
-  }) : assert(children != null),
-       assert(children.length > 0);
+  }) : assert(children.length > 0);
 
   final Offset anchor;
   final List<Widget> children;
@@ -480,12 +514,12 @@
           onPressed: _handlePreviousPage,
           text: '◀',
         ),
-        dividerWidth: 1.0 / MediaQuery.of(context).devicePixelRatio,
+        dividerWidth: 1.0 / MediaQuery.devicePixelRatioOf(context),
         nextButton: CupertinoTextSelectionToolbarButton.text(
           onPressed: _handleNextPage,
           text: '▶',
         ),
-        nextButtonDisabled: CupertinoTextSelectionToolbarButton.text(
+        nextButtonDisabled: const CupertinoTextSelectionToolbarButton.text(
           text: '▶',
         ),
         children: widget.children,
@@ -505,13 +539,7 @@
     required this.dividerWidth,
     required this.nextButton,
     required this.nextButtonDisabled,
-  }) : assert(children != null),
-       assert(children.isNotEmpty),
-       assert(backButton != null),
-       assert(dividerWidth != null),
-       assert(nextButton != null),
-       assert(nextButtonDisabled != null),
-       assert(page != null);
+  }) : assert(children.isNotEmpty);
 
   final Widget backButton;
   final List<Widget> children;
@@ -704,9 +732,7 @@
   _RenderCupertinoTextSelectionToolbarItems({
     required double dividerWidth,
     required int page,
-  }) : assert(dividerWidth != null),
-       assert(page != null),
-       _dividerWidth = dividerWidth,
+  }) : _dividerWidth = dividerWidth,
        _page = page,
        super();
 
@@ -801,8 +827,9 @@
       double paginationButtonsWidth = 0.0;
       if (currentPage == 0) {
         // If this is the last child, it's ok to fit without a forward button.
+        // Note childCount doesn't include slotted children which come before the list ones.
         paginationButtonsWidth =
-            i == childCount - 1 ? 0.0 : _nextButton!.size.width;
+            i == childCount + 2 ? 0.0 : _nextButton!.size.width;
       } else {
         paginationButtonsWidth = subsequentPageButtonsWidth;
       }
diff --git a/framework/lib/src/cupertino/text_selection_toolbar_button.dart b/framework/lib/src/cupertino/text_selection_toolbar_button.dart
index c302fe3..0807b4d 100644
--- a/framework/lib/src/cupertino/text_selection_toolbar_button.dart
+++ b/framework/lib/src/cupertino/text_selection_toolbar_button.dart
@@ -18,7 +18,17 @@
 
 // Colors extracted from https://developer.apple.com/design/resources/.
 // TODO(LongCatIsLooong): https://github.com/flutter/flutter/issues/41507.
-const Color _kToolbarBackgroundColor = Color(0xEB202020);
+const CupertinoDynamicColor _kToolbarBackgroundColor = CupertinoDynamicColor.withBrightness(
+  // This value was extracted from a screenshot of iOS 16.0.3, as light mode
+  // didn't appear in the Apple design resources assets linked above.
+  color: Color(0xEBF7F7F7),
+  darkColor: Color(0xEB202020),
+);
+
+const CupertinoDynamicColor _kToolbarTextColor = CupertinoDynamicColor.withBrightness(
+  color: CupertinoColors.black,
+  darkColor: CupertinoColors.white,
+);
 
 // Eyeballed value.
 const EdgeInsets _kToolbarButtonPadding = EdgeInsets.symmetric(vertical: 16.0, horizontal: 18.0);
@@ -32,23 +42,17 @@
     super.key,
     this.onPressed,
     required Widget this.child,
-  }) : assert(child != null),
+  }) : text = null,
        buttonItem = null;
 
   /// Create an instance of [CupertinoTextSelectionToolbarButton] whose child is
   /// a [Text] widget styled like the default iOS text selection toolbar button.
-  CupertinoTextSelectionToolbarButton.text({
+  const CupertinoTextSelectionToolbarButton.text({
     super.key,
     this.onPressed,
-    required String text,
+    required this.text,
   }) : buttonItem = null,
-       child = Text(
-         text,
-         overflow: TextOverflow.ellipsis,
-         style: _kToolbarButtonFontStyle.copyWith(
-           color: onPressed != null ? CupertinoColors.white : CupertinoColors.inactiveGray,
-         ),
-       );
+       child = null;
 
   /// Create an instance of [CupertinoTextSelectionToolbarButton] from the given
   /// [ContextMenuButtonItem].
@@ -57,8 +61,8 @@
   CupertinoTextSelectionToolbarButton.buttonItem({
     super.key,
     required ContextMenuButtonItem this.buttonItem,
-  }) : assert(buttonItem != null),
-       child = null,
+  }) : child = null,
+       text = null,
        onPressed = buttonItem.onPressed;
 
   /// {@template flutter.cupertino.CupertinoTextSelectionToolbarButton.child}
@@ -79,6 +83,10 @@
   /// {@endtemplate}
   final ContextMenuButtonItem? buttonItem;
 
+  /// The text used in the button's label when using
+  /// [CupertinoTextSelectionToolbarButton.text].
+  final String? text;
+
   /// Returns the default button label String for the button of the given
   /// [ContextMenuButtonItem]'s [ContextMenuButtonType].
   static String getButtonLabel(BuildContext context, ContextMenuButtonItem buttonItem) {
@@ -97,6 +105,7 @@
         return localizations.pasteButtonLabel;
       case ContextMenuButtonType.selectAll:
         return localizations.selectAllButtonLabel;
+      case ContextMenuButtonType.delete:
       case ContextMenuButtonType.custom:
         return '';
     }
@@ -105,12 +114,15 @@
   @override
   Widget build(BuildContext context) {
     final Widget child = this.child ?? Text(
-      getButtonLabel(context, buttonItem!),
-      overflow: TextOverflow.ellipsis,
-      style: _kToolbarButtonFontStyle.copyWith(
-        color: onPressed != null ? CupertinoColors.white : CupertinoColors.inactiveGray,
-      ),
-    );
+       text ?? getButtonLabel(context, buttonItem!),
+       overflow: TextOverflow.ellipsis,
+       style: _kToolbarButtonFontStyle.copyWith(
+         color: onPressed != null
+             ? _kToolbarTextColor.resolveFrom(context)
+             : CupertinoColors.inactiveGray,
+       ),
+     );
+
     return CupertinoButton(
       borderRadius: null,
       color: _kToolbarBackgroundColor,
diff --git a/framework/lib/src/cupertino/text_theme.dart b/framework/lib/src/cupertino/text_theme.dart
index 5252fc8..908504e 100644
--- a/framework/lib/src/cupertino/text_theme.dart
+++ b/framework/lib/src/cupertino/text_theme.dart
@@ -260,6 +260,41 @@
     properties.add(DiagnosticsProperty<TextStyle>('pickerTextStyle', pickerTextStyle, defaultValue: defaultData.pickerTextStyle));
     properties.add(DiagnosticsProperty<TextStyle>('dateTimePickerTextStyle', dateTimePickerTextStyle, defaultValue: defaultData.dateTimePickerTextStyle));
   }
+
+  @override
+  bool operator == (Object other) {
+    if (identical(this, other)) {
+      return true;
+    }
+    if (other.runtimeType != runtimeType) {
+      return false;
+    }
+    return other is CupertinoTextThemeData
+      && other._defaults == _defaults
+      && other._primaryColor == _primaryColor
+      && other._textStyle == _textStyle
+      && other._actionTextStyle == _actionTextStyle
+      && other._tabLabelTextStyle == _tabLabelTextStyle
+      && other._navTitleTextStyle == _navTitleTextStyle
+      && other._navLargeTitleTextStyle == _navLargeTitleTextStyle
+      && other._navActionTextStyle == _navActionTextStyle
+      && other._pickerTextStyle == _pickerTextStyle
+      && other._dateTimePickerTextStyle == _dateTimePickerTextStyle;
+  }
+
+  @override
+  int get hashCode => Object.hash(
+    _defaults,
+    _primaryColor,
+    _textStyle,
+    _actionTextStyle,
+    _tabLabelTextStyle,
+    _navTitleTextStyle,
+    _navLargeTitleTextStyle,
+    _navActionTextStyle,
+    _pickerTextStyle,
+    _dateTimePickerTextStyle,
+  );
 }
 
 
@@ -268,8 +303,7 @@
   const _TextThemeDefaultsBuilder(
     this.labelColor,
     this.inactiveGrayColor,
-  ) : assert(labelColor != null),
-      assert(inactiveGrayColor != null);
+  );
 
   final Color labelColor;
   final Color inactiveGrayColor;
@@ -297,4 +331,20 @@
       ? this
       : _TextThemeDefaultsBuilder(resolvedLabelColor, resolvedInactiveGray);
   }
+
+  @override
+  bool operator == (Object other) {
+    if (identical(this, other)) {
+      return true;
+    }
+    if (other.runtimeType != runtimeType) {
+      return false;
+    }
+    return other is _TextThemeDefaultsBuilder
+      && other.labelColor == labelColor
+      && other.inactiveGrayColor == inactiveGrayColor;
+  }
+
+  @override
+  int get hashCode => Object.hash(labelColor, inactiveGrayColor);
 }
diff --git a/framework/lib/src/cupertino/theme.dart b/framework/lib/src/cupertino/theme.dart
index 78729d7..1eb09aa 100644
--- a/framework/lib/src/cupertino/theme.dart
+++ b/framework/lib/src/cupertino/theme.dart
@@ -22,6 +22,7 @@
     // Values extracted from navigation bar. For toolbar or tabbar the dark color is 0xF0161616.
   ),
   CupertinoColors.systemBackground,
+  false,
   _CupertinoTextThemeDefaults(CupertinoColors.label, CupertinoColors.inactiveGray),
 );
 
@@ -52,8 +53,7 @@
     super.key,
     required this.data,
     required this.child,
-  }) : assert(child != null),
-       assert(data != null);
+  });
 
   /// The [CupertinoThemeData] styling for this theme.
   final CupertinoThemeData data;
@@ -86,7 +86,7 @@
   ///   [MediaQueryData.platformBrightness] for descendant Cupertino widgets.
   static Brightness brightnessOf(BuildContext context) {
     final _InheritedCupertinoTheme? inheritedTheme = context.dependOnInheritedWidgetOfExactType<_InheritedCupertinoTheme>();
-    return inheritedTheme?.theme.data.brightness ?? MediaQuery.of(context).platformBrightness;
+    return inheritedTheme?.theme.data.brightness ?? MediaQuery.platformBrightnessOf(context);
   }
 
   /// Retrieves the [Brightness] to use for descendant Cupertino widgets, based
@@ -106,7 +106,7 @@
   ///   [MediaQuery] exists, instead of returning null.
   static Brightness? maybeBrightnessOf(BuildContext context) {
     final _InheritedCupertinoTheme? inheritedTheme = context.dependOnInheritedWidgetOfExactType<_InheritedCupertinoTheme>();
-    return inheritedTheme?.theme.data.brightness ?? MediaQuery.maybeOf(context)?.platformBrightness;
+    return inheritedTheme?.theme.data.brightness ?? MediaQuery.maybePlatformBrightnessOf(context);
   }
 
   /// The widget below this widget in the tree.
@@ -136,7 +136,7 @@
   const _InheritedCupertinoTheme({
     required this.theme,
     required super.child,
-  }) : assert(theme != null);
+  });
 
   final CupertinoTheme theme;
 
@@ -172,6 +172,7 @@
     CupertinoTextThemeData? textTheme,
     Color? barBackgroundColor,
     Color? scaffoldBackgroundColor,
+    bool? applyThemeToAll,
   }) : this.raw(
         brightness,
         primaryColor,
@@ -179,6 +180,7 @@
         textTheme,
         barBackgroundColor,
         scaffoldBackgroundColor,
+        applyThemeToAll,
       );
 
   /// Same as the default constructor but with positional arguments to avoid
@@ -193,6 +195,7 @@
     CupertinoTextThemeData? textTheme,
     Color? barBackgroundColor,
     Color? scaffoldBackgroundColor,
+    bool? applyThemeToAll,
   ) : this._rawWithDefaults(
     brightness,
     primaryColor,
@@ -200,6 +203,7 @@
     textTheme,
     barBackgroundColor,
     scaffoldBackgroundColor,
+    applyThemeToAll,
     _kDefaultTheme,
   );
 
@@ -210,6 +214,7 @@
     CupertinoTextThemeData? textTheme,
     Color? barBackgroundColor,
     Color? scaffoldBackgroundColor,
+    bool? applyThemeToAll,
     this._defaults,
   ) : super(
     brightness: brightness,
@@ -218,6 +223,7 @@
     textTheme: textTheme,
     barBackgroundColor: barBackgroundColor,
     scaffoldBackgroundColor: scaffoldBackgroundColor,
+    applyThemeToAll: applyThemeToAll,
   );
 
   final _CupertinoThemeDefaults _defaults;
@@ -240,6 +246,9 @@
   Color get scaffoldBackgroundColor => super.scaffoldBackgroundColor ?? _defaults.scaffoldBackgroundColor;
 
   @override
+  bool get applyThemeToAll => super.applyThemeToAll ?? _defaults.applyThemeToAll;
+
+  @override
   NoDefaultCupertinoThemeData noDefault() {
     return NoDefaultCupertinoThemeData(
       brightness: super.brightness,
@@ -248,6 +257,7 @@
       textTheme: super.textTheme,
       barBackgroundColor: super.barBackgroundColor,
       scaffoldBackgroundColor: super.scaffoldBackgroundColor,
+      applyThemeToAll: super.applyThemeToAll,
     );
   }
 
@@ -262,6 +272,7 @@
       super.textTheme?.resolveFrom(context),
       convertColor(super.barBackgroundColor),
       convertColor(super.scaffoldBackgroundColor),
+      applyThemeToAll,
       _defaults.resolveFrom(context, super.textTheme == null),
     );
   }
@@ -274,6 +285,7 @@
     CupertinoTextThemeData? textTheme,
     Color? barBackgroundColor,
     Color? scaffoldBackgroundColor,
+    bool? applyThemeToAll,
   }) {
     return CupertinoThemeData._rawWithDefaults(
       brightness ?? super.brightness,
@@ -282,6 +294,7 @@
       textTheme ?? super.textTheme,
       barBackgroundColor ?? super.barBackgroundColor,
       scaffoldBackgroundColor ?? super.scaffoldBackgroundColor,
+      applyThemeToAll ?? super.applyThemeToAll,
       _defaults,
     );
   }
@@ -295,8 +308,38 @@
     properties.add(createCupertinoColorProperty('primaryContrastingColor', primaryContrastingColor, defaultValue: defaultData.primaryContrastingColor));
     properties.add(createCupertinoColorProperty('barBackgroundColor', barBackgroundColor, defaultValue: defaultData.barBackgroundColor));
     properties.add(createCupertinoColorProperty('scaffoldBackgroundColor', scaffoldBackgroundColor, defaultValue: defaultData.scaffoldBackgroundColor));
+    properties.add(DiagnosticsProperty<bool>('applyThemeToAll', applyThemeToAll, defaultValue: defaultData.applyThemeToAll));
     textTheme.debugFillProperties(properties);
   }
+
+  @override
+  bool operator == (Object other) {
+    if (identical(this, other)) {
+      return true;
+    }
+    if (other.runtimeType != runtimeType) {
+      return false;
+    }
+    return other is CupertinoThemeData
+      && other.brightness == brightness
+      && other.primaryColor == primaryColor
+      && other.primaryContrastingColor == primaryContrastingColor
+      && other.textTheme == textTheme
+      && other.barBackgroundColor == barBackgroundColor
+      && other.scaffoldBackgroundColor == scaffoldBackgroundColor
+      && other.applyThemeToAll == applyThemeToAll;
+  }
+
+  @override
+  int get hashCode => Object.hash(
+    brightness,
+    primaryColor,
+    primaryContrastingColor,
+    textTheme,
+    barBackgroundColor,
+    scaffoldBackgroundColor,
+    applyThemeToAll,
+  );
 }
 
 /// Styling specifications for a cupertino theme without default values for
@@ -322,6 +365,7 @@
     this.textTheme,
     this.barBackgroundColor,
     this.scaffoldBackgroundColor,
+    this.applyThemeToAll,
   });
 
   /// The brightness override for Cupertino descendants.
@@ -389,6 +433,22 @@
   /// Defaults to [CupertinoColors.systemBackground].
   final Color? scaffoldBackgroundColor;
 
+  /// Flag to apply this theme to all descendant Cupertino widgets.
+  ///
+  /// Certain Cupertino widgets previously didn't use theming, matching past
+  /// versions of iOS. For example, [CupertinoSwitch]s always used
+  /// [CupertinoColors.systemGreen] when active.
+  ///
+  /// Today, however, these widgets can indeed be themed on iOS. Moreover on
+  /// macOS, the accent color is reflected in these widgets. Turning this flag
+  /// on ensures that descendant Cupertino widgets will be themed accordingly.
+  ///
+  /// This flag currently applies to the following widgets:
+  /// - [CupertinoSwitch] & [Switch.adaptive]
+  ///
+  /// Defaults to false.
+  final bool? applyThemeToAll;
+
   /// Returns an instance of the theme data whose property getters only return
   /// the construction time specifications with no derived values.
   ///
@@ -412,6 +472,7 @@
       textTheme: textTheme?.resolveFrom(context),
       barBackgroundColor: convertColor(barBackgroundColor),
       scaffoldBackgroundColor: convertColor(scaffoldBackgroundColor),
+      applyThemeToAll: applyThemeToAll,
     );
   }
 
@@ -428,6 +489,7 @@
     CupertinoTextThemeData? textTheme,
     Color? barBackgroundColor ,
     Color? scaffoldBackgroundColor,
+    bool? applyThemeToAll,
   }) {
     return NoDefaultCupertinoThemeData(
       brightness: brightness ?? this.brightness,
@@ -436,6 +498,7 @@
       textTheme: textTheme ?? this.textTheme,
       barBackgroundColor: barBackgroundColor ?? this.barBackgroundColor,
       scaffoldBackgroundColor: scaffoldBackgroundColor ?? this.scaffoldBackgroundColor,
+      applyThemeToAll: applyThemeToAll ?? this.applyThemeToAll,
     );
   }
 }
@@ -448,6 +511,7 @@
     this.primaryContrastingColor,
     this.barBackgroundColor,
     this.scaffoldBackgroundColor,
+    this.applyThemeToAll,
     this.textThemeDefaults,
   );
 
@@ -456,6 +520,7 @@
   final Color primaryContrastingColor;
   final Color barBackgroundColor;
   final Color scaffoldBackgroundColor;
+  final bool applyThemeToAll;
   final _CupertinoTextThemeDefaults textThemeDefaults;
 
   _CupertinoThemeDefaults resolveFrom(BuildContext context, bool resolveTextTheme) {
@@ -467,6 +532,7 @@
       convertColor(primaryContrastingColor),
       convertColor(barBackgroundColor),
       convertColor(scaffoldBackgroundColor),
+      applyThemeToAll,
       resolveTextTheme ? textThemeDefaults.resolveFrom(context) : textThemeDefaults,
     );
   }
@@ -490,7 +556,6 @@
   }
 
   CupertinoTextThemeData createDefaults({ required Color primaryColor }) {
-    assert(primaryColor != null);
     return _DefaultCupertinoTextThemeData(
       primaryColor: primaryColor,
       labelColor: labelColor,
@@ -507,9 +572,7 @@
     required this.labelColor,
     required this.inactiveGray,
     required super.primaryColor,
-  }) : assert(labelColor != null),
-       assert(inactiveGray != null),
-       assert(primaryColor != null);
+  });
 
   final Color labelColor;
   final Color inactiveGray;
diff --git a/framework/lib/src/cupertino/thumb_painter.dart b/framework/lib/src/cupertino/thumb_painter.dart
index feeab3e..b0ebeca 100644
--- a/framework/lib/src/cupertino/thumb_painter.dart
+++ b/framework/lib/src/cupertino/thumb_painter.dart
@@ -47,7 +47,7 @@
   const CupertinoThumbPainter({
     this.color = CupertinoColors.white,
     this.shadows = _kSliderBoxShadows,
-  }) : assert(shadows != null);
+  });
 
   /// Creates an object that paints an iOS-style switch thumb.
   const CupertinoThumbPainter.switchThumb({
diff --git a/framework/lib/src/foundation/_capabilities_io.dart b/framework/lib/src/foundation/_capabilities_io.dart
new file mode 100644
index 0000000..202dc7b
--- /dev/null
+++ b/framework/lib/src/foundation/_capabilities_io.dart
@@ -0,0 +1,10 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/// The dart:io implementation of [isCanvasKit].
+///
+/// This bool shouldn't be used outside of web.
+bool get isCanvasKit {
+  throw UnimplementedError('isCanvasKit is not implemented for dart:io.');
+}
diff --git a/framework/lib/src/foundation/_capabilities_web.dart b/framework/lib/src/foundation/_capabilities_web.dart
new file mode 100644
index 0000000..5b5de84
--- /dev/null
+++ b/framework/lib/src/foundation/_capabilities_web.dart
@@ -0,0 +1,13 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:js/js.dart';
+
+// This value is set by the engine. It is used to determine if the application is
+// using canvaskit.
+@JS('window.flutterCanvasKit')
+external Object? get _windowFlutterCanvasKit;
+
+/// The web implementation of [isCanvasKit]
+bool get isCanvasKit => _windowFlutterCanvasKit != null;
diff --git a/framework/lib/src/foundation/_isolates_io.dart b/framework/lib/src/foundation/_isolates_io.dart
index 63c5f54..08bd8ca 100644
--- a/framework/lib/src/foundation/_isolates_io.dart
+++ b/framework/lib/src/foundation/_isolates_io.dart
@@ -11,7 +11,8 @@
 export 'isolates.dart' show ComputeCallback;
 
 /// The dart:io implementation of [isolate.compute].
-Future<R> compute<Q, R>(isolates.ComputeCallback<Q, R> callback, Q message, {String? debugLabel}) async {
+@pragma('vm:prefer-inline')
+Future<R> compute<M, R>(isolates.ComputeCallback<M, R> callback, M message, {String? debugLabel}) async {
   debugLabel ??= kReleaseMode ? 'compute' : callback.toString();
 
   return Isolate.run<R>(() {
diff --git a/framework/lib/src/foundation/_isolates_web.dart b/framework/lib/src/foundation/_isolates_web.dart
index 2a2d343..4350e54 100644
--- a/framework/lib/src/foundation/_isolates_web.dart
+++ b/framework/lib/src/foundation/_isolates_web.dart
@@ -7,7 +7,8 @@
 export 'isolates.dart' show ComputeCallback;
 
 /// The dart:html implementation of [isolate.compute].
-Future<R> compute<Q, R>(isolates.ComputeCallback<Q, R> callback, Q message, { String? debugLabel }) async {
+@pragma('dart2js:tryInline')
+Future<R> compute<M, R>(isolates.ComputeCallback<M, R> callback, M message, { String? debugLabel }) async {
   // To avoid blocking the UI immediately for an expensive function call, we
   // pump a single frame to allow the framework to complete the current set
   // of work.
diff --git a/framework/lib/src/foundation/annotations.dart b/framework/lib/src/foundation/annotations.dart
index b57bfac..3bc5e02 100644
--- a/framework/lib/src/foundation/annotations.dart
+++ b/framework/lib/src/foundation/annotations.dart
@@ -39,7 +39,7 @@
 ///    class that overrides the inline documentations' own description.
 class Category {
   /// Create an annotation to provide a categorization of a class.
-  const Category(this.sections) : assert(sections != null);
+  const Category(this.sections);
 
   /// The strings the correspond to the section and subsection of the
   /// category represented by this object.
@@ -74,7 +74,7 @@
 ///    class that overrides the inline documentations' own description.
 class DocumentationIcon {
   /// Create an annotation to provide a URL to an image describing a class.
-  const DocumentationIcon(this.url) : assert(url != null);
+  const DocumentationIcon(this.url);
 
   /// The URL to an image that represents the annotated class.
   final String url;
@@ -111,7 +111,7 @@
 ///    represents the class.
 class Summary {
   /// Create an annotation to provide a short description of a class.
-  const Summary(this.text) : assert(text != null);
+  const Summary(this.text);
 
   /// The text of the summary of the annotated class.
   final String text;
diff --git a/framework/lib/src/foundation/assertions.dart b/framework/lib/src/foundation/assertions.dart
index 67455b2..59abde7 100644
--- a/framework/lib/src/foundation/assertions.dart
+++ b/framework/lib/src/foundation/assertions.dart
@@ -54,9 +54,7 @@
     required this.package,
     required this.className,
     required this.method,
-  }) : assert(className != null),
-       assert(method != null),
-       assert(package != null);
+  });
 
   /// An `<asynchronous suspension>` line in a stack trace.
   static const PartialStackFrame asynchronousSuspension = PartialStackFrame(
@@ -128,8 +126,7 @@
   const RepetitiveStackFrameFilter({
     required this.frames,
     required this.replacement,
-  }) : assert(frames != null),
-       assert(replacement != null);
+  });
 
   /// The shape of this repetitive stack pattern.
   final List<PartialStackFrame> frames;
@@ -140,7 +137,7 @@
   /// The string to replace the frames with.
   ///
   /// If the same replacement string is used multiple times in a row, the
-  /// [FlutterError.defaultStackFilter] will simply update a counter after this
+  /// [FlutterError.defaultStackFilter] will insert a repeat count after this
   /// line rather than repeating it.
   final String replacement;
 
@@ -177,8 +174,7 @@
     String message, {
     DiagnosticsTreeStyle style = DiagnosticsTreeStyle.flat,
     DiagnosticLevel level = DiagnosticLevel.info,
-  }) : assert(message != null),
-       super(
+  }) : super(
          null,
          <Object>[message],
          showName: false,
@@ -217,8 +213,7 @@
     List<Object> messageParts, {
     DiagnosticsTreeStyle style = DiagnosticsTreeStyle.flat,
     DiagnosticLevel level = DiagnosticLevel.info,
-  }) : assert(messageParts != null),
-       super(
+  }) : super(
          null,
          messageParts,
          showName: false,
@@ -406,7 +401,7 @@
     this.stackFilter,
     this.informationCollector,
     this.silent = false,
-  }) : assert(exception != null);
+  });
 
   /// Creates a copy of the error details but with the given fields replaced
   /// with new values.
@@ -672,9 +667,7 @@
     super.debugFillProperties(properties);
     final DiagnosticsNode verb = ErrorDescription('thrown${ context != null ? ErrorDescription(" $context") : ""}');
     final Diagnosticable? diagnosticable = _exceptionToDiagnosticable();
-    if (false) { // ignore: deprecated_member_use
-      properties.add(ErrorDescription('The null value was $verb.'));
-    } else if (exception is num) {
+    if (exception is num) {
       properties.add(ErrorDescription('The number $exception was $verb.'));
     } else {
       final DiagnosticsNode errorName;
@@ -1003,8 +996,6 @@
   ///
   /// The default behavior for the [onError] handler is to call this function.
   static void dumpErrorToConsole(FlutterErrorDetails details, { bool forceReport = false }) {
-    assert(details != null);
-    assert(details.exception != null);
     bool isInDebugMode = false;
     assert(() {
       // In debug mode, we ignore the "silent" flag.
@@ -1184,8 +1175,6 @@
   /// ```
   /// {@end-tool}
   static void reportError(FlutterErrorDetails details) {
-    assert(details != null);
-    assert(details.exception != null);
     onError?.call(details);
   }
 }
diff --git a/framework/lib/src/foundation/basic_types.dart b/framework/lib/src/foundation/basic_types.dart
index dc58411..9bc8c6a 100644
--- a/framework/lib/src/foundation/basic_types.dart
+++ b/framework/lib/src/foundation/basic_types.dart
@@ -231,7 +231,7 @@
   /// Creates a new factory.
   ///
   /// The `constructor` parameter must not be null.
-  const Factory(this.constructor) : assert(constructor != null);
+  const Factory(this.constructor);
 
   /// Creates a new object of type T.
   final ValueGetter<T> constructor;
diff --git a/framework/lib/src/foundation/binding.dart b/framework/lib/src/foundation/binding.dart
index 4babc7f..ac6d4ac 100644
--- a/framework/lib/src/foundation/binding.dart
+++ b/framework/lib/src/foundation/binding.dart
@@ -187,7 +187,7 @@
   /// such as a [TestWindow].
   ///
   /// The [window] is a singleton meant for use by applications that only have a
-  /// single main window. In addition to the properties of [ui.FlutterWindow],
+  /// single main window. In addition to the properties of [ui.FlutterView],
   /// [window] provides access to platform-specific properties and callbacks
   /// available on the [platformDispatcher].
   ///
@@ -327,7 +327,6 @@
         ]);
       }
       try {
-        assert(instance != null);
         if (instance._debugConstructed && _debugInitializedType == null) {
           throw FlutterError.fromParts(<DiagnosticsNode>[
             ErrorSummary('Binding initialized without calling initInstances.'),
@@ -553,10 +552,8 @@
   Future<void> lockEvents(Future<void> Function() callback) {
     final developer.TimelineTask timelineTask = developer.TimelineTask()..start('Lock events');
 
-    assert(callback != null);
     _lockCount += 1;
     final Future<void> future = callback();
-    assert(future != null, 'The lockEvents() callback returned null; it should return a Future<void> that completes when the lock is to expire.');
     future.whenComplete(() {
       _lockCount -= 1;
       if (!locked) {
@@ -627,8 +624,6 @@
     required String name,
     required AsyncCallback callback,
   }) {
-    assert(name != null);
-    assert(callback != null);
     registerServiceExtension(
       name: name,
       callback: (Map<String, String> parameters) async {
@@ -658,9 +653,6 @@
     required AsyncValueGetter<bool> getter,
     required AsyncValueSetter<bool> setter,
   }) {
-    assert(name != null);
-    assert(getter != null);
-    assert(setter != null);
     registerServiceExtension(
       name: name,
       callback: (Map<String, String> parameters) async {
@@ -692,9 +684,6 @@
     required AsyncValueGetter<double> getter,
     required AsyncValueSetter<double> setter,
   }) {
-    assert(name != null);
-    assert(getter != null);
-    assert(setter != null);
     registerServiceExtension(
       name: name,
       callback: (Map<String, String> parameters) async {
@@ -754,9 +743,6 @@
     required AsyncValueGetter<String> getter,
     required AsyncValueSetter<String> setter,
   }) {
-    assert(name != null);
-    assert(getter != null);
-    assert(setter != null);
     registerServiceExtension(
       name: name,
       callback: (Map<String, String> parameters) async {
@@ -825,8 +811,6 @@
     required String name,
     required ServiceExtensionCallback callback,
   }) {
-    assert(name != null);
-    assert(callback != null);
     final String methodName = 'ext.flutter.$name';
     developer.registerExtension(methodName, (String method, Map<String, String> parameters) async {
       assert(method == methodName);
diff --git a/framework/lib/src/foundation/capabilities.dart b/framework/lib/src/foundation/capabilities.dart
new file mode 100644
index 0000000..11c82ee
--- /dev/null
+++ b/framework/lib/src/foundation/capabilities.dart
@@ -0,0 +1,11 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import '_capabilities_io.dart'
+    as capabilities;
+
+/// Returns true if the application is using CanvasKit.
+///
+/// Only to be used for web.
+bool get isCanvasKit => capabilities.isCanvasKit;
diff --git a/framework/lib/src/foundation/change_notifier.dart b/framework/lib/src/foundation/change_notifier.dart
index a65df16..1706bc8 100644
--- a/framework/lib/src/foundation/change_notifier.dart
+++ b/framework/lib/src/foundation/change_notifier.dart
@@ -104,7 +104,7 @@
 /// It is O(1) for adding listeners and O(N) for removing listeners and dispatching
 /// notifications (where N is the number of listeners).
 ///
-/// {@macro flutter.flutter.animatedbuilder_changenotifier.rebuild}
+/// {@macro flutter.flutter.ListenableBuilder.ChangeNotifier.rebuild}
 ///
 /// See also:
 ///
diff --git a/framework/lib/src/foundation/consolidate_response.dart b/framework/lib/src/foundation/consolidate_response.dart
index 4d0f44c..94160ec 100644
--- a/framework/lib/src/foundation/consolidate_response.dart
+++ b/framework/lib/src/foundation/consolidate_response.dart
@@ -51,7 +51,6 @@
   bool autoUncompress = true,
   BytesReceivedCallback? onBytesReceived,
 }) {
-  assert(autoUncompress != null);
   final Completer<Uint8List> completer = Completer<Uint8List>.sync();
 
   final _OutputBuffer output = _OutputBuffer();
diff --git a/framework/lib/src/foundation/constants.dart b/framework/lib/src/foundation/constants.dart
index 0e5ccb6..576de1e 100644
--- a/framework/lib/src/foundation/constants.dart
+++ b/framework/lib/src/foundation/constants.dart
@@ -69,6 +69,3 @@
 
 /// A constant that is true if the application was compiled to run on the web.
 const bool kIsWeb = bool.fromEnvironment('dart.library.js_util');
-
-/// A constant that is true if the application is using canvasKit
-const bool isCanvasKit = bool.fromEnvironment('FLUTTER_WEB_USE_SKIA');
diff --git a/framework/lib/src/foundation/diagnostics.dart b/framework/lib/src/foundation/diagnostics.dart
index 80906dd..fa15201 100644
--- a/framework/lib/src/foundation/diagnostics.dart
+++ b/framework/lib/src/foundation/diagnostics.dart
@@ -253,28 +253,7 @@
     this.beforeName = '',
     this.suffixLineOne = '',
     this.mandatoryFooter = '',
-  }) : assert(prefixLineOne != null),
-       assert(prefixOtherLines != null),
-       assert(prefixLastChildLineOne != null),
-       assert(prefixOtherLinesRootNode != null),
-       assert(linkCharacter != null),
-       assert(propertyPrefixIfChildren != null),
-       assert(propertyPrefixNoChildren != null),
-       assert(lineBreak != null),
-       assert(lineBreakProperties != null),
-       assert(afterName != null),
-       assert(afterDescriptionIfBody != null),
-       assert(afterDescription != null),
-       assert(beforeProperties != null),
-       assert(afterProperties != null),
-       assert(propertySeparator != null),
-       assert(bodyIndent != null),
-       assert(footer != null),
-       assert(showChildren != null),
-       assert(addBlankLineIfNoChildren != null),
-       assert(isNameOnOwnLine != null),
-       assert(isBlankLineBetweenPropertiesAndChildren != null),
-       childLinkSpace = ' ' * linkCharacter.length;
+  }) : childLinkSpace = ' ' * linkCharacter.length;
 
   /// Prefix to add to the first line to display a child with this style.
   final String prefixLineOne;
@@ -1113,8 +1092,7 @@
     int wrapWidth = 100,
     int wrapWidthProperties = 65,
     int maxDescendentsTruncatableNode = -1,
-  }) : assert(minLevel != null),
-       _minLevel = minLevel,
+  }) : _minLevel = minLevel,
        _wrapWidth = wrapWidth,
        _wrapWidthProperties = wrapWidthProperties,
        _maxDescendentsTruncatableNode = maxDescendentsTruncatableNode;
@@ -1218,7 +1196,7 @@
 
     List<DiagnosticsNode> children = node.getChildren();
 
-    String? description = node.toDescription(parentConfiguration: parentConfiguration);
+    String description = node.toDescription(parentConfiguration: parentConfiguration);
     if (config.beforeName.isNotEmpty) {
       builder.write(config.beforeName);
     }
@@ -1229,7 +1207,7 @@
     if (uppercaseTitle) {
       name = name?.toUpperCase();
     }
-    if (description == null || description.isEmpty) {
+    if (description.isEmpty) {
       if (node.showName && name != null) {
         builder.write(name, allowWrap: wrapName);
       }
@@ -1388,7 +1366,6 @@
 
       for (int i = 0; i < children.length; i++) {
         final DiagnosticsNode child = children[i];
-        assert(child != null);
         final TextTreeConfiguration childConfig = _childTextConfiguration(child, config)!;
         if (i == children.length - 1) {
           final String lastChildPrefixLineOne = '$prefixChildrenRaw${childConfig.prefixLastChildLineOne}';
@@ -1463,12 +1440,10 @@
     this.showName = true,
     this.showSeparator = true,
     this.linePrefix,
-  }) : assert(showName != null),
-       assert(showSeparator != null),
-       // A name ending with ':' indicates that the user forgot that the ':' will
-       // be automatically added for them when generating descriptions of the
-       // property.
-       assert(
+  }) : assert(
+         // A name ending with ':' indicates that the user forgot that the ':' will
+         // be automatically added for them when generating descriptions of the
+         // property.
          name == null || !name.endsWith(':'),
          'Names of diagnostic nodes must not end with colons.\n'
          'name:\n'
@@ -1490,8 +1465,6 @@
     DiagnosticLevel level = DiagnosticLevel.info,
     bool allowWrap = true,
   }) {
-    assert(style != null);
-    assert(level != null);
     return DiagnosticsProperty<void>(
       '',
       null,
@@ -1728,7 +1701,6 @@
   }) {
     String result = super.toString();
     assert(style != null);
-    assert(minLevel != null);
     assert(() {
       if (_isSingleLine(style)) {
         result = toStringDeep(parentConfiguration: parentConfiguration, minLevel: minLevel);
@@ -1866,11 +1838,7 @@
     String message, {
     DiagnosticsTreeStyle style = DiagnosticsTreeStyle.singleLine,
     DiagnosticLevel level = DiagnosticLevel.info,
-  }) : assert(name != null),
-       assert(message != null),
-       assert(style != null),
-       assert(level != null),
-       super(name, null, description: message, style: style, level: level);
+  }) : super(name, null, description: message, style: style, level: level);
 }
 
 /// Property which encloses its string [value] in quotes.
@@ -1894,10 +1862,7 @@
     super.ifEmpty,
     super.style,
     super.level,
-  }) : assert(showName != null),
-       assert(quoted != null),
-       assert(style != null),
-       assert(level != null);
+  });
 
   /// Whether the value is enclosed in double quotes.
   final bool quoted;
@@ -2005,9 +1970,7 @@
     super.showName,
     super.style,
     super.level,
-  }) : assert(showName != null),
-       assert(style != null),
-       assert(level != null);
+  });
 
   /// Property with a [value] that is computed only when needed.
   ///
@@ -2024,9 +1987,7 @@
     super.tooltip,
     super.defaultValue,
     super.level,
-  }) : assert(showName != null),
-       assert(level != null),
-       super.lazy();
+  }) : super.lazy();
 
   @override
   String numberToString() => debugFormatDouble(value);
@@ -2048,9 +2009,7 @@
     super.defaultValue,
     super.style,
     super.level,
-  }) : assert(showName != null),
-       assert(level != null),
-       assert(style != null);
+  });
 
   @override
   String numberToString() => value.toString();
@@ -2075,8 +2034,7 @@
     super.tooltip,
     super.unit,
     super.level,
-  }) : assert(showName != null),
-       assert(level != null);
+  });
 
   @override
   String valueToString({ TextTreeConfiguration? parentConfiguration }) {
@@ -2150,9 +2108,7 @@
     bool showName = false,
     Object? defaultValue,
     DiagnosticLevel level = DiagnosticLevel.info,
-  }) : assert(showName != null),
-       assert(level != null),
-       assert(ifTrue != null || ifFalse != null),
+  }) : assert(ifTrue != null || ifFalse != null),
        super(
          name,
          value,
@@ -2254,10 +2210,7 @@
     super.showName,
     super.showSeparator,
     super.level,
-  }) : assert(style != null),
-       assert(showName != null),
-       assert(showSeparator != null),
-       assert(level != null);
+  });
 
   @override
   String valueToString({TextTreeConfiguration? parentConfiguration}) {
@@ -2335,7 +2288,7 @@
     super.value, {
     super.defaultValue,
     super.level,
-  }) : assert(level != null);
+  });
 
   @override
   String valueToString({ TextTreeConfiguration? parentConfiguration }) {
@@ -2382,9 +2335,7 @@
     super.ifNull,
     super.showName = false,
     super.level,
-  }) : assert(ifPresent != null || ifNull != null),
-       assert(showName != null),
-       assert(level != null);
+  }) : assert(ifPresent != null || ifNull != null);
 
   /// Shorthand constructor to describe whether the property has a value.
   ///
@@ -2396,9 +2347,7 @@
     String super.name,
     super.value, {
     super.level,
-  }) : assert(name != null),
-       assert(level != null),
-       ifPresent = 'has $name',
+  }) : ifPresent = 'has $name',
        super(
     showName: false,
   );
@@ -2495,17 +2444,13 @@
     super.showName,
     super.showSeparator,
     super.level,
-  }) : assert(value != null),
-       assert(showName != null),
-       assert(showSeparator != null),
-       assert(level != null);
+  });
 
   @override
   Map<String, T?> get value => super.value!;
 
   @override
   String valueToString({TextTreeConfiguration? parentConfiguration}) {
-    assert(value != null);
     if (!_hasNonNullEntry() && ifEmpty != null) {
       return ifEmpty!;
     }
@@ -2598,11 +2543,7 @@
     this.allowNameWrap = true,
     DiagnosticsTreeStyle super.style = DiagnosticsTreeStyle.singleLine,
     DiagnosticLevel level = DiagnosticLevel.info,
-  }) : assert(showName != null),
-       assert(showSeparator != null),
-       assert(style != null),
-       assert(level != null),
-       _description = description,
+  }) : _description = description,
        _valueComputed = true,
        _value = value,
        _computeValue = null,
@@ -2620,7 +2561,7 @@
   /// The [showName], [showSeparator], [style], [missingIfNull], and [level]
   /// arguments must not be null.
   ///
-  /// The [level] argument is just a suggestion and can be overridden if
+  /// The [level] argument is just a suggestion and can be overridden
   /// if something else about the property causes it to have a lower or higher
   /// level. For example, if calling `computeValue` throws an exception, [level]
   /// will always return [DiagnosticLevel.error].
@@ -2640,12 +2581,7 @@
     this.allowNameWrap = true,
     DiagnosticsTreeStyle super.style = DiagnosticsTreeStyle.singleLine,
     DiagnosticLevel level = DiagnosticLevel.info,
-  }) : assert(showName != null),
-       assert(showSeparator != null),
-       assert(defaultValue == kNoDefaultValue || defaultValue is T?),
-       assert(missingIfNull != null),
-       assert(style != null),
-       assert(level != null),
+  }) : assert(defaultValue == kNoDefaultValue || defaultValue is T?),
        _description = description,
        _valueComputed = false,
        _value = null,
@@ -2765,7 +2701,6 @@
   ///
   /// `text` must not be null.
   String _addTooltip(String text) {
-    assert(text != null);
     return tooltip == null ? text : '$text ($tooltip)';
   }
 
@@ -2938,7 +2873,7 @@
     super.name,
     required this.value,
     required super.style,
-  }) : assert(value != null);
+  });
 
   @override
   final T value;
@@ -3153,6 +3088,8 @@
 
   /// Add additional properties associated with the node.
   ///
+  /// {@youtube 560 315 https://www.youtube.com/watch?v=DnC7eT-vh1k}
+  ///
   /// Use the most specific [DiagnosticsProperty] existing subclass to describe
   /// each property instead of the [DiagnosticsProperty] base class. There are
   /// only a small number of [DiagnosticsProperty] subclasses each covering a
diff --git a/framework/lib/src/foundation/isolates.dart b/framework/lib/src/foundation/isolates.dart
index 29c9991..cea2408 100644
--- a/framework/lib/src/foundation/isolates.dart
+++ b/framework/lib/src/foundation/isolates.dart
@@ -9,33 +9,17 @@
 
 /// Signature for the callback passed to [compute].
 ///
-/// {@macro flutter.foundation.compute.types}
-///
-/// Instances of [ComputeCallback] must be functions that can be sent to an
-/// isolate.
 /// {@macro flutter.foundation.compute.callback}
 ///
-/// {@macro flutter.foundation.compute.types}
-typedef ComputeCallback<Q, R> = FutureOr<R> Function(Q message);
+typedef ComputeCallback<M, R> = FutureOr<R> Function(M message);
 
 /// The signature of [compute], which spawns an isolate, runs `callback` on
 /// that isolate, passes it `message`, and (eventually) returns the value
 /// returned by `callback`.
-///
-/// {@macro flutter.foundation.compute.usecase}
-///
-/// The function used as `callback` must be one that can be sent to an isolate.
-/// {@macro flutter.foundation.compute.callback}
-///
-/// {@macro flutter.foundation.compute.types}
-///
-/// The `debugLabel` argument can be specified to provide a name to add to the
-/// [Timeline]. This is useful when profiling an application.
-typedef ComputeImpl = Future<R> Function<Q, R>(ComputeCallback<Q, R> callback, Q message, { String? debugLabel });
+typedef ComputeImpl = Future<R> Function<M, R>(ComputeCallback<M, R> callback, M message, { String? debugLabel });
 
-/// A function that spawns an isolate and runs the provided `callback` on that
-/// isolate, passes it the provided `message`, and (eventually) returns the
-/// value returned by `callback`.
+/// Asynchronously runs the given [callback] - with the provided [message] -
+/// in the background and completes with the result.
 ///
 /// {@template flutter.foundation.compute.usecase}
 /// This is useful for operations that take longer than a few milliseconds, and
@@ -68,34 +52,26 @@
 /// ```
 /// {@end-tool}
 ///
-/// The function used as `callback` must be one that can be sent to an isolate.
+/// On web platforms this will run [callback] on the current eventloop.
+/// On native platforms this will run [callback] in a separate isolate.
+///
 /// {@template flutter.foundation.compute.callback}
-/// Qualifying functions include:
 ///
-///   * top-level functions
-///   * static methods
-///   * closures that only capture objects that can be sent to an isolate
+/// The `callback`, the `message` given to it as well as the result have to be
+/// objects that can be sent across isolates (as they may be transitively copied
+/// if needed). The majority of objects can be sent across isolates.
 ///
-/// Using closures must be done with care. Due to
-/// [dart-lang/sdk#36983](https://github.com/dart-lang/sdk/issues/36983) a
-/// closure may capture objects that, while not directly used in the closure
-/// itself, may prevent it from being sent to an isolate.
+/// See [SendPort.send] for more information about exceptions as well as a note
+/// of warning about sending closures, which can capture more state than needed.
+///
 /// {@endtemplate}
 ///
-/// {@template flutter.foundation.compute.types}
-/// The [compute] method accepts the following parameters:
+/// On native platforms `await compute(fun, message)` is equivalent to
+/// `await Isolate.run(() => fun(message))`. See also [Isolate.run].
 ///
-///  * `Q` is the type of the message that kicks off the computation.
-///  * `R` is the type of the value returned.
-///
-/// There are limitations on the values that can be sent and received to and
-/// from isolates. These limitations constrain the values of `Q` and `R` that
-/// are possible. See the discussion at [SendPort.send].
-///
-/// The same limitations apply to any errors generated by the computation.
-/// {@endtemplate}
-///
-/// See also:
-///
-///   * [ComputeImpl], for the [compute] function's signature.
-const ComputeImpl compute = isolates.compute;
+/// The `debugLabel` - if provided - is used as name for the isolate that
+/// executes `callback`. [Timeline] events produced by that isolate will have
+/// the name associated with them. This is useful when profiling an application.
+Future<R> compute<M, R>(ComputeCallback<M, R> callback, M message, {String? debugLabel}) {
+  return isolates.compute<M, R>(callback, message, debugLabel: debugLabel);
+}
diff --git a/framework/lib/src/foundation/math.dart b/framework/lib/src/foundation/math.dart
index 053192a..7c559bb 100644
--- a/framework/lib/src/foundation/math.dart
+++ b/framework/lib/src/foundation/math.dart
@@ -8,16 +8,5 @@
 /// floating point numbers.
 //
 // See also: //dev/benchmarks/microbenchmarks/lib/foundation/clamp.dart
-double clampDouble(double x, double min, double max) {
-  assert(min <= max && !max.isNaN && !min.isNaN);
-  if (x < min) {
-    return min;
-  }
-  if (x > max) {
-    return max;
-  }
-  if (x.isNaN) {
-    return max;
-  }
-  return x;
-}
+
+export 'package:engine/ui.dart' show clampDouble;
\ No newline at end of file
diff --git a/framework/lib/src/foundation/node.dart b/framework/lib/src/foundation/node.dart
index f8c377b..6e830f1 100644
--- a/framework/lib/src/foundation/node.dart
+++ b/framework/lib/src/foundation/node.dart
@@ -92,7 +92,6 @@
   /// method, as in `super.attach(owner)`.
   @mustCallSuper
   void attach(covariant Object owner) {
-    assert(owner != null);
     assert(_owner == null);
     _owner = owner;
   }
@@ -124,7 +123,6 @@
   @protected
   @mustCallSuper
   void adoptChild(covariant AbstractNode child) {
-    assert(child != null);
     assert(child._parent == null);
     assert(() {
       AbstractNode node = this;
@@ -147,7 +145,6 @@
   @protected
   @mustCallSuper
   void dropChild(covariant AbstractNode child) {
-    assert(child != null);
     assert(child._parent == this);
     assert(child.attached == attached);
     child._parent = null;
diff --git a/framework/lib/src/foundation/serialization.dart b/framework/lib/src/foundation/serialization.dart
index b0ade7d..bdeaecc 100644
--- a/framework/lib/src/foundation/serialization.dart
+++ b/framework/lib/src/foundation/serialization.dart
@@ -170,8 +170,7 @@
 /// The byte order used is [Endian.host] throughout.
 class ReadBuffer {
   /// Creates a [ReadBuffer] for reading from the specified [data].
-  ReadBuffer(this.data)
-    : assert(data != null);
+  ReadBuffer(this.data);
 
   /// The underlying data being read.
   final ByteData data;
diff --git a/framework/lib/src/foundation/stack_frame.dart b/framework/lib/src/foundation/stack_frame.dart
index 1a18d2d..5e22e1e 100644
--- a/framework/lib/src/foundation/stack_frame.dart
+++ b/framework/lib/src/foundation/stack_frame.dart
@@ -35,16 +35,7 @@
     required this.method,
     this.isConstructor = false,
     required this.source,
-  })  : assert(number != null),
-        assert(column != null),
-        assert(line != null),
-        assert(method != null),
-        assert(packageScheme != null),
-        assert(package != null),
-        assert(packagePath != null),
-        assert(className != null),
-        assert(isConstructor != null),
-        assert(source != null);
+  });
 
   /// A stack frame representing an asynchronous suspension.
   static const StackFrame asynchronousSuspension = StackFrame(
@@ -74,13 +65,11 @@
   ///
   /// This is normally useful with [StackTrace.current].
   static List<StackFrame> fromStackTrace(StackTrace stack) {
-    assert(stack != null);
     return fromStackString(stack.toString());
   }
 
   /// Parses a list of [StackFrame]s from the [StackTrace.toString] method.
   static List<StackFrame> fromStackString(String stack) {
-    assert(stack != null);
     return stack
         .trim()
         .split('\n')
@@ -181,7 +170,6 @@
 
   /// Parses a single [StackFrame] from a single line of a [StackTrace].
   static StackFrame? fromStackTraceLine(String line) {
-    assert(line != null);
     if (line == '<asynchronous suspension>') {
       return asynchronousSuspension;
     } else if (line == '...') {
diff --git a/framework/lib/src/gestures/arena.dart b/framework/lib/src/gestures/arena.dart
index f8a399e..b832a5d 100644
--- a/framework/lib/src/gestures/arena.dart
+++ b/framework/lib/src/gestures/arena.dart
@@ -97,6 +97,10 @@
   }
 }
 
+/// Used for disambiguating the meaning of sequences of pointer events.
+///
+/// {@youtube 560 315 https://www.youtube.com/watch?v=Q85LBtBdi0U}
+///
 /// The first member to accept or the last member to not reject wins.
 ///
 /// See <https://flutter.dev/gestures/#gesture-disambiguation> for more
@@ -266,7 +270,6 @@
 
   void _resolveInFavorOf(int pointer, _GestureArena state, GestureArenaMember member) {
     assert(state == _arenas[pointer]);
-    assert(state != null);
     assert(state.eagerWinner == null || state.eagerWinner == member);
     assert(!state.isOpen);
     _arenas.remove(pointer);
diff --git a/framework/lib/src/gestures/binding.dart b/framework/lib/src/gestures/binding.dart
index 707381c..c937a63 100644
--- a/framework/lib/src/gestures/binding.dart
+++ b/framework/lib/src/gestures/binding.dart
@@ -83,8 +83,6 @@
   // Add `event` for resampling or dispatch it directly if
   // not a touch event.
   void addOrDispatch(PointerEvent event) {
-    final SchedulerBinding scheduler = SchedulerBinding.instance;
-    assert(scheduler != null);
     // Add touch event to resampler or dispatch pointer event directly.
     if (event.kind == PointerDeviceKind.touch) {
       // Save last event time for debugPrint of resampling margin.
@@ -108,7 +106,6 @@
   // The `samplingClock` is the clock used to determine frame time age.
   void sample(Duration samplingOffset, SamplingClock clock) {
     final SchedulerBinding scheduler = SchedulerBinding.instance;
-    assert(scheduler != null);
 
     // Initialize `_frameTime` if needed. This will be used for periodic
     // sampling when frame callbacks are not received.
@@ -290,9 +287,18 @@
   void _handlePointerDataPacket(ui.PointerDataPacket packet) {
     // We convert pointer data to logical pixels so that e.g. the touch slop can be
     // defined in a device-independent manner.
-    _pendingPointerEvents.addAll(PointerEventConverter.expand(packet.data, window.devicePixelRatio));
-    if (!locked) {
-      _flushPointerEventQueue();
+    try {
+      _pendingPointerEvents.addAll(PointerEventConverter.expand(packet.data, window.devicePixelRatio));
+      if (!locked) {
+        _flushPointerEventQueue();
+      }
+    } catch (error, stack) {
+      FlutterError.reportError(FlutterErrorDetails(
+        exception: error,
+        stack: stack,
+        library: 'gestures library',
+        context: ErrorDescription('while handling a pointer data packet'),
+      ));
     }
   }
 
@@ -360,7 +366,7 @@
   void _handlePointerEventImmediately(PointerEvent event) {
     HitTestResult? hitTestResult;
     if (event is PointerDownEvent || event is PointerSignalEvent || event is PointerHoverEvent || event is PointerPanZoomStartEvent) {
-      assert(!_hitTests.containsKey(event.pointer), 'Pointer of $event unexpectedly has a HitTestResult associated with it.');
+      assert(!_hitTests.containsKey(event.pointer), 'Pointer of ${event.toString(minLevel: DiagnosticLevel.debug)} unexpectedly has a HitTestResult associated with it.');
       hitTestResult = HitTestResult();
       hitTest(hitTestResult, event.position);
       if (event is PointerDownEvent || event is PointerPanZoomStartEvent) {
@@ -368,7 +374,7 @@
       }
       assert(() {
         if (debugPrintHitTestResults) {
-          debugPrint('$event: $hitTestResult');
+          debugPrint('${event.toString(minLevel: DiagnosticLevel.debug)}: $hitTestResult');
         }
         return true;
       }());
@@ -391,7 +397,6 @@
     if (hitTestResult != null ||
         event is PointerAddedEvent ||
         event is PointerRemovedEvent) {
-      assert(event.position != null);
       dispatchEvent(event, hitTestResult);
     }
   }
diff --git a/framework/lib/src/gestures/converter.dart b/framework/lib/src/gestures/converter.dart
index 9d00c3a..6aa7741 100644
--- a/framework/lib/src/gestures/converter.dart
+++ b/framework/lib/src/gestures/converter.dart
@@ -52,9 +52,8 @@
   static Iterable<PointerEvent> expand(Iterable<ui.PointerData> data, double devicePixelRatio) {
     return data
         .where((ui.PointerData datum) => datum.signalKind != ui.PointerSignalKind.unknown)
-        .map((ui.PointerData datum) {
+        .map<PointerEvent?>((ui.PointerData datum) {
           final Offset position = Offset(datum.physicalX, datum.physicalY) / devicePixelRatio;
-          assert(position != null);
           final Offset delta = Offset(datum.physicalDeltaX, datum.physicalDeltaY) / devicePixelRatio;
           final double radiusMinor = _toLogicalPixels(datum.radiusMinor, devicePixelRatio);
           final double radiusMajor = _toLogicalPixels(datum.radiusMajor, devicePixelRatio);
@@ -62,7 +61,6 @@
           final double radiusMax = _toLogicalPixels(datum.radiusMax, devicePixelRatio);
           final Duration timeStamp = datum.timeStamp;
           final PointerDeviceKind kind = datum.kind;
-          assert(datum.change != null);
           switch (datum.signalKind ?? ui.PointerSignalKind.none) {
             case ui.PointerSignalKind.none:
               switch (datum.change) {
@@ -249,6 +247,9 @@
                   );
               }
             case ui.PointerSignalKind.scroll:
+              if (!datum.scrollDeltaX.isFinite || !datum.scrollDeltaY.isFinite || devicePixelRatio <= 0) {
+                return null;
+              }
               final Offset scrollDelta =
                   Offset(datum.scrollDeltaX, datum.scrollDeltaY) / devicePixelRatio;
               return PointerScrollEvent(
@@ -282,7 +283,7 @@
               // enumeration to PointerSignalKind.
               throw StateError('Unreachable');
           }
-        });
+        }).whereType<PointerEvent>();
   }
 
   static double _toLogicalPixels(double physicalPixels, double devicePixelRatio) => physicalPixels / devicePixelRatio;
diff --git a/framework/lib/src/gestures/drag_details.dart b/framework/lib/src/gestures/drag_details.dart
index cd85feb..39cf290 100644
--- a/framework/lib/src/gestures/drag_details.dart
+++ b/framework/lib/src/gestures/drag_details.dart
@@ -25,8 +25,7 @@
   DragDownDetails({
     this.globalPosition = Offset.zero,
     Offset? localPosition,
-  }) : assert(globalPosition != null),
-       localPosition = localPosition ?? globalPosition;
+  }) : localPosition = localPosition ?? globalPosition;
 
   /// The global position at which the pointer contacted the screen.
   ///
@@ -73,8 +72,7 @@
     this.globalPosition = Offset.zero,
     Offset? localPosition,
     this.kind,
-  }) : assert(globalPosition != null),
-       localPosition = localPosition ?? globalPosition;
+  }) : localPosition = localPosition ?? globalPosition;
 
   /// Recorded timestamp of the source pointer event that triggered the drag
   /// event.
@@ -109,10 +107,12 @@
   String toString() => '${objectRuntimeType(this, 'DragStartDetails')}($globalPosition)';
 }
 
+/// {@template flutter.gestures.dragdetails.GestureDragStartCallback}
 /// Signature for when a pointer has contacted the screen and has begun to move.
 ///
 /// The `details` object provides the position of the touch when it first
 /// touched the surface.
+/// {@endtemplate}
 ///
 /// See [DragGestureRecognizer.onStart].
 typedef GestureDragStartCallback = void Function(DragStartDetails details);
@@ -126,7 +126,7 @@
 ///  * [DragStartDetails], the details for [GestureDragStartCallback].
 ///  * [DragEndDetails], the details for [GestureDragEndCallback].
 class DragUpdateDetails {
-  /// Creates details for a [DragUpdateDetails].
+  /// Creates details for a [GestureDragUpdateCallback].
   ///
   /// The [delta] argument must not be null.
   ///
@@ -140,8 +140,7 @@
     this.primaryDelta,
     required this.globalPosition,
     Offset? localPosition,
-  }) : assert(delta != null),
-       assert(
+  }) : assert(
          primaryDelta == null
            || (primaryDelta == delta.dx && delta.dy == 0.0)
            || (primaryDelta == delta.dy && delta.dx == 0.0),
@@ -195,11 +194,13 @@
   String toString() => '${objectRuntimeType(this, 'DragUpdateDetails')}($delta)';
 }
 
+/// {@template flutter.gestures.dragdetails.GestureDragUpdateCallback}
 /// Signature for when a pointer that is in contact with the screen and moving
 /// has moved again.
 ///
 /// The `details` object provides the position of the touch and the distance it
 /// has traveled since the last update.
+/// {@endtemplate}
 ///
 /// See [DragGestureRecognizer.onUpdate].
 typedef GestureDragUpdateCallback = void Function(DragUpdateDetails details);
@@ -219,8 +220,7 @@
   DragEndDetails({
     this.velocity = Velocity.zero,
     this.primaryVelocity,
-  }) : assert(velocity != null),
-       assert(
+  }) : assert(
          primaryVelocity == null
            || primaryVelocity == velocity.pixelsPerSecond.dx
            || primaryVelocity == velocity.pixelsPerSecond.dy,
diff --git a/framework/lib/src/gestures/eager.dart b/framework/lib/src/gestures/eager.dart
index 6193a20..3c83435 100644
--- a/framework/lib/src/gestures/eager.dart
+++ b/framework/lib/src/gestures/eager.dart
@@ -18,12 +18,8 @@
   ///
   /// {@macro flutter.gestures.GestureRecognizer.supportedDevices}
   EagerGestureRecognizer({
-    @Deprecated(
-      'Migrate to supportedDevices. '
-      'This feature was deprecated after v2.3.0-1.0.pre.',
-    )
-    super.kind,
     super.supportedDevices,
+    super.allowedButtonsFilter,
   });
 
   @override
diff --git a/framework/lib/src/gestures/events.dart b/framework/lib/src/gestures/events.dart
index 7e02867..7e6277c 100644
--- a/framework/lib/src/gestures/events.dart
+++ b/framework/lib/src/gestures/events.dart
@@ -843,8 +843,7 @@
 }
 
 class _TransformedPointerAddedEvent extends _TransformedPointerEvent with _CopyPointerAddedEvent implements PointerAddedEvent {
-  _TransformedPointerAddedEvent(this.original, this.transform)
-    : assert(original != null), assert(transform != null);
+  _TransformedPointerAddedEvent(this.original, this.transform);
 
   @override
   final PointerAddedEvent original;
@@ -934,8 +933,7 @@
 }
 
 class _TransformedPointerRemovedEvent extends _TransformedPointerEvent with _CopyPointerRemovedEvent implements PointerRemovedEvent {
-  _TransformedPointerRemovedEvent(this.original, this.transform)
-    : assert(original != null), assert(transform != null);
+  _TransformedPointerRemovedEvent(this.original, this.transform);
 
   @override
   final PointerRemovedEvent original;
@@ -1051,8 +1049,7 @@
 }
 
 class _TransformedPointerHoverEvent extends _TransformedPointerEvent with _CopyPointerHoverEvent implements PointerHoverEvent {
-  _TransformedPointerHoverEvent(this.original, this.transform)
-    : assert(original != null), assert(transform != null);
+  _TransformedPointerHoverEvent(this.original, this.transform);
 
   @override
   final PointerHoverEvent original;
@@ -1198,8 +1195,7 @@
 }
 
 class _TransformedPointerEnterEvent extends _TransformedPointerEvent with _CopyPointerEnterEvent implements PointerEnterEvent {
-  _TransformedPointerEnterEvent(this.original, this.transform)
-    : assert(original != null), assert(transform != null);
+  _TransformedPointerEnterEvent(this.original, this.transform);
 
   @override
   final PointerEnterEvent original;
@@ -1344,8 +1340,7 @@
 }
 
 class _TransformedPointerExitEvent extends _TransformedPointerEvent with _CopyPointerExitEvent implements PointerExitEvent {
-  _TransformedPointerExitEvent(this.original, this.transform)
-    : assert(original != null), assert(transform != null);
+  _TransformedPointerExitEvent(this.original, this.transform);
 
   @override
   final PointerExitEvent original;
@@ -1453,8 +1448,7 @@
 }
 
 class _TransformedPointerDownEvent extends _TransformedPointerEvent with _CopyPointerDownEvent implements PointerDownEvent {
-  _TransformedPointerDownEvent(this.original, this.transform)
-    : assert(original != null), assert(transform != null);
+  _TransformedPointerDownEvent(this.original, this.transform);
 
   @override
   final PointerDownEvent original;
@@ -1571,8 +1565,7 @@
 }
 
 class _TransformedPointerMoveEvent extends _TransformedPointerEvent with _CopyPointerMoveEvent implements PointerMoveEvent {
-  _TransformedPointerMoveEvent(this.original, this.transform)
-    : assert(original != null), assert(transform != null);
+  _TransformedPointerMoveEvent(this.original, this.transform);
 
   @override
   final PointerMoveEvent original;
@@ -1684,8 +1677,7 @@
 }
 
 class _TransformedPointerUpEvent extends _TransformedPointerEvent with _CopyPointerUpEvent implements PointerUpEvent {
-  _TransformedPointerUpEvent(this.original, this.transform)
-    : assert(original != null), assert(transform != null);
+  _TransformedPointerUpEvent(this.original, this.transform);
 
   @override
   final PointerUpEvent original;
@@ -1784,12 +1776,7 @@
     super.position,
     this.scrollDelta = Offset.zero,
     super.embedderId,
-  }) : assert(timeStamp != null),
-       assert(kind != null),
-       assert(device != null),
-       assert(position != null),
-       assert(scrollDelta != null),
-       assert(!identical(kind, PointerDeviceKind.trackpad));
+  });
 
   @override
   final Offset scrollDelta;
@@ -1810,8 +1797,7 @@
 }
 
 class _TransformedPointerScrollEvent extends _TransformedPointerEvent with _CopyPointerScrollEvent implements PointerScrollEvent {
-  _TransformedPointerScrollEvent(this.original, this.transform)
-    : assert(original != null), assert(transform != null);
+  _TransformedPointerScrollEvent(this.original, this.transform);
 
   @override
   final PointerScrollEvent original;
@@ -1889,10 +1875,7 @@
     super.device,
     super.position,
     super.embedderId,
-  }) : assert(timeStamp != null),
-       assert(kind != null),
-       assert(device != null),
-       assert(position != null);
+  });
 
   @override
   PointerScrollInertiaCancelEvent transformed(Matrix4? transform) {
@@ -1904,8 +1887,7 @@
 }
 
 class _TransformedPointerScrollInertiaCancelEvent extends _TransformedPointerEvent with _CopyPointerScrollInertiaCancelEvent implements PointerScrollInertiaCancelEvent {
-  _TransformedPointerScrollInertiaCancelEvent(this.original, this.transform)
-    : assert(original != null), assert(transform != null);
+  _TransformedPointerScrollInertiaCancelEvent(this.original, this.transform);
 
   @override
   final PointerScrollInertiaCancelEvent original;
@@ -1980,12 +1962,7 @@
     super.position,
     super.embedderId,
     this.scale = 1.0,
-  }) : assert(timeStamp != null),
-       assert(kind != null),
-       assert(device != null),
-       assert(position != null),
-       assert(embedderId != null),
-       assert(scale != null);
+  });
 
   @override
   final double scale;
@@ -2000,8 +1977,7 @@
 }
 
 class _TransformedPointerScaleEvent extends _TransformedPointerEvent with _CopyPointerScaleEvent implements PointerScaleEvent {
-  _TransformedPointerScaleEvent(this.original, this.transform)
-    : assert(original != null), assert(transform != null);
+  _TransformedPointerScaleEvent(this.original, this.transform);
 
   @override
   final PointerScaleEvent original;
@@ -2069,13 +2045,7 @@
     super.position,
     super.embedderId,
     super.synthesized,
-  }) : assert(timeStamp != null),
-       assert(device != null),
-       assert(pointer != null),
-       assert(position != null),
-       assert(embedderId != null),
-       assert(synthesized != null),
-       super(kind: PointerDeviceKind.trackpad);
+  }) : super(kind: PointerDeviceKind.trackpad);
 
   @override
   PointerPanZoomStartEvent transformed(Matrix4? transform) {
@@ -2087,8 +2057,7 @@
 }
 
 class _TransformedPointerPanZoomStartEvent extends _TransformedPointerEvent with _CopyPointerPanZoomStartEvent implements PointerPanZoomStartEvent {
-  _TransformedPointerPanZoomStartEvent(this.original, this.transform)
-    : assert(original != null), assert(transform != null);
+  _TransformedPointerPanZoomStartEvent(this.original, this.transform);
 
   @override
   final PointerPanZoomStartEvent original;
@@ -2180,17 +2149,7 @@
     this.scale = 1.0,
     this.rotation = 0.0,
     super.synthesized,
-  }) : assert(timeStamp != null),
-       assert(device != null),
-       assert(pointer != null),
-       assert(position != null),
-       assert(embedderId != null),
-       assert(pan != null),
-       assert(panDelta != null),
-       assert(scale != null),
-       assert(rotation != null),
-       assert(synthesized != null),
-       super(kind: PointerDeviceKind.trackpad);
+  }) : super(kind: PointerDeviceKind.trackpad);
 
   @override
   final Offset pan;
@@ -2215,8 +2174,7 @@
 }
 
 class _TransformedPointerPanZoomUpdateEvent extends _TransformedPointerEvent with _CopyPointerPanZoomUpdateEvent implements PointerPanZoomUpdateEvent {
-  _TransformedPointerPanZoomUpdateEvent(this.original, this.transform)
-    : assert(original != null), assert(transform != null);
+  _TransformedPointerPanZoomUpdateEvent(this.original, this.transform);
 
   @override
   Offset get pan => original.pan;
@@ -2304,13 +2262,7 @@
     super.position,
     super.embedderId,
     super.synthesized,
-  }) : assert(timeStamp != null),
-       assert(device != null),
-       assert(pointer != null),
-       assert(position != null),
-       assert(embedderId != null),
-       assert(synthesized != null),
-       super(kind: PointerDeviceKind.trackpad);
+  }) : super(kind: PointerDeviceKind.trackpad);
 
   @override
   PointerPanZoomEndEvent transformed(Matrix4? transform) {
@@ -2322,8 +2274,7 @@
 }
 
 class _TransformedPointerPanZoomEndEvent extends _TransformedPointerEvent with _CopyPointerPanZoomEndEvent implements PointerPanZoomEndEvent {
-  _TransformedPointerPanZoomEndEvent(this.original, this.transform)
-    : assert(original != null), assert(transform != null);
+  _TransformedPointerPanZoomEndEvent(this.original, this.transform);
 
   @override
   final PointerPanZoomEndEvent original;
@@ -2473,8 +2424,7 @@
 }
 
 class _TransformedPointerCancelEvent extends _TransformedPointerEvent with _CopyPointerCancelEvent implements PointerCancelEvent {
-  _TransformedPointerCancelEvent(this.original, this.transform)
-    : assert(original != null), assert(transform != null);
+  _TransformedPointerCancelEvent(this.original, this.transform);
 
   @override
   final PointerCancelEvent original;
diff --git a/framework/lib/src/gestures/force_press.dart b/framework/lib/src/gestures/force_press.dart
index 5fe458b..b2d27e0 100644
--- a/framework/lib/src/gestures/force_press.dart
+++ b/framework/lib/src/gestures/force_press.dart
@@ -52,9 +52,7 @@
     required this.globalPosition,
     Offset? localPosition,
     required this.pressure,
-  }) : assert(globalPosition != null),
-       assert(pressure != null),
-       localPosition = localPosition ?? globalPosition;
+  }) : localPosition = localPosition ?? globalPosition;
 
   /// The global position at which the function was called.
   final Offset globalPosition;
@@ -127,16 +125,9 @@
     this.peakPressure = 0.85,
     this.interpolation = _inverseLerp,
     super.debugOwner,
-    @Deprecated(
-      'Migrate to supportedDevices. '
-      'This feature was deprecated after v2.3.0-1.0.pre.',
-    )
-    super.kind,
     super.supportedDevices,
-  }) : assert(startPressure != null),
-       assert(peakPressure != null),
-       assert(interpolation != null),
-       assert(peakPressure > startPressure);
+    super.allowedButtonsFilter,
+  }) : assert(peakPressure > startPressure);
 
   /// A pointer is in contact with the screen and has just pressed with a force
   /// exceeding the [startPressure]. Consequently, if there were other gesture
diff --git a/framework/lib/src/gestures/gesture_settings.dart b/framework/lib/src/gestures/gesture_settings.dart
index 496a2d2..afaa5ed 100644
--- a/framework/lib/src/gestures/gesture_settings.dart
+++ b/framework/lib/src/gestures/gesture_settings.dart
@@ -24,11 +24,11 @@
     this.touchSlop,
   });
 
-  /// Create a new [DeviceGestureSettings] from the provided [window].
-  factory DeviceGestureSettings.fromWindow(ui.FlutterView window) {
-    final double? physicalTouchSlop = window.viewConfiguration.gestureSettings.physicalTouchSlop;
+  /// Create a new [DeviceGestureSettings] from the provided [view].
+  factory DeviceGestureSettings.fromView(ui.FlutterView view) {
+    final double? physicalTouchSlop = view.viewConfiguration.gestureSettings.physicalTouchSlop;
     return DeviceGestureSettings(
-      touchSlop: physicalTouchSlop == null ? null : physicalTouchSlop / window.devicePixelRatio
+      touchSlop: physicalTouchSlop == null ? null : physicalTouchSlop / view.devicePixelRatio
     );
   }
 
diff --git a/framework/lib/src/gestures/hit_test.dart b/framework/lib/src/gestures/hit_test.dart
index 221d9d6..547c9d8 100644
--- a/framework/lib/src/gestures/hit_test.dart
+++ b/framework/lib/src/gestures/hit_test.dart
@@ -215,7 +215,6 @@
   ///    around this function for hit testing on [RenderBox]s.
   @protected
   void pushTransform(Matrix4 transform) {
-    assert(transform != null);
     assert(
       _debugVectorMoreOrLessEquals(transform.getRow(2), Vector4(0, 0, 1, 0)) &&
       _debugVectorMoreOrLessEquals(transform.getColumn(2), Vector4(0, 0, 1, 0)),
@@ -255,7 +254,6 @@
   ///    around this function for hit testing on [RenderSliver]s.
   @protected
   void pushOffset(Offset offset) {
-    assert(offset != null);
     _localTransforms.add(_OffsetTransformPart(offset));
   }
 
diff --git a/framework/lib/src/gestures/long_press.dart b/framework/lib/src/gestures/long_press.dart
index febef8c..d91b8c9 100644
--- a/framework/lib/src/gestures/long_press.dart
+++ b/framework/lib/src/gestures/long_press.dart
@@ -115,8 +115,7 @@
     this.globalPosition = Offset.zero,
     Offset? localPosition,
     this.kind,
-  }) : assert(globalPosition != null),
-       localPosition = localPosition ?? globalPosition;
+  }) : localPosition = localPosition ?? globalPosition;
 
   /// The global position at which the pointer contacted the screen.
   final Offset globalPosition;
@@ -142,8 +141,7 @@
   const LongPressStartDetails({
     this.globalPosition = Offset.zero,
     Offset? localPosition,
-  }) : assert(globalPosition != null),
-       localPosition = localPosition ?? globalPosition;
+  }) : localPosition = localPosition ?? globalPosition;
 
   /// The global position at which the pointer initially contacted the screen.
   final Offset globalPosition;
@@ -168,9 +166,7 @@
     Offset? localPosition,
     this.offsetFromOrigin = Offset.zero,
     Offset? localOffsetFromOrigin,
-  }) : assert(globalPosition != null),
-       assert(offsetFromOrigin != null),
-       localPosition = localPosition ?? globalPosition,
+  }) : localPosition = localPosition ?? globalPosition,
        localOffsetFromOrigin = localOffsetFromOrigin ?? offsetFromOrigin;
 
   /// The global position of the pointer when it triggered this update.
@@ -205,8 +201,7 @@
     this.globalPosition = Offset.zero,
     Offset? localPosition,
     this.velocity = Velocity.zero,
-  }) : assert(globalPosition != null),
-       localPosition = localPosition ?? globalPosition;
+  }) : localPosition = localPosition ?? globalPosition;
 
   /// The global position at which the pointer lifted from the screen.
   final Offset globalPosition;
@@ -247,17 +242,15 @@
   /// The [duration] argument can be used to overwrite the default duration
   /// after which the long press will be recognized.
   ///
+  /// {@macro flutter.gestures.tap.TapGestureRecognizer.allowedButtonsFilter}
+  ///
   /// {@macro flutter.gestures.GestureRecognizer.supportedDevices}
   LongPressGestureRecognizer({
     Duration? duration,
     super.postAcceptSlopTolerance = null,
-    @Deprecated(
-      'Migrate to supportedDevices. '
-      'This feature was deprecated after v2.3.0-1.0.pre.',
-    )
-    super.kind,
     super.supportedDevices,
     super.debugOwner,
+    super.allowedButtonsFilter = _defaultButtonAcceptBehavior,
   }) : super(
          deadline: duration ?? kLongPressTimeout,
        );
@@ -268,6 +261,12 @@
   // different set of buttons, the gesture is canceled.
   int? _initialButtons;
 
+  // Accept the input if, and only if, a single button is pressed.
+  static bool _defaultButtonAcceptBehavior(int buttons) =>
+      buttons == kPrimaryButton ||
+      buttons == kSecondaryButton ||
+      buttons == kTertiaryButton;
+
   /// Called when a pointer has contacted the screen at a particular location
   /// with a primary button, which might be the start of a long-press.
   ///
diff --git a/framework/lib/src/gestures/monodrag.dart b/framework/lib/src/gestures/monodrag.dart
index 5b87812..4930910 100644
--- a/framework/lib/src/gestures/monodrag.dart
+++ b/framework/lib/src/gestures/monodrag.dart
@@ -26,11 +26,13 @@
   accepted,
 }
 
+/// {@template flutter.gestures.monodrag.GestureDragEndCallback}
 /// Signature for when a pointer that was previously in contact with the screen
 /// and moving is no longer in contact with the screen.
 ///
 /// The velocity at which the pointer was moving when it stopped contacting
 /// the screen is available in the `details`.
+/// {@endtemplate}
 ///
 /// Used by [DragGestureRecognizer.onEnd].
 typedef GestureDragEndCallback = void Function(DragEndDetails details);
@@ -57,9 +59,8 @@
 /// consider using one of its subclasses to recognize specific types for drag
 /// gestures.
 ///
-/// [DragGestureRecognizer] competes on pointer events of [kPrimaryButton]
-/// only when it has at least one non-null callback. If it has no callbacks, it
-/// is a no-op.
+/// [DragGestureRecognizer] competes on pointer events only when it has at
+/// least one non-null callback. If it has no callbacks, it is a no-op.
 ///
 /// See also:
 ///
@@ -74,18 +75,17 @@
   /// {@macro flutter.gestures.GestureRecognizer.supportedDevices}
   DragGestureRecognizer({
     super.debugOwner,
-    @Deprecated(
-      'Migrate to supportedDevices. '
-      'This feature was deprecated after v2.3.0-1.0.pre.',
-    )
-    super.kind,
     this.dragStartBehavior = DragStartBehavior.start,
     this.velocityTrackerBuilder = _defaultBuilder,
     super.supportedDevices,
-  }) : assert(dragStartBehavior != null);
+    super.allowedButtonsFilter = _defaultButtonAcceptBehavior,
+  });
 
   static VelocityTracker _defaultBuilder(PointerEvent event) => VelocityTracker.withKind(event.kind);
 
+  // Accept the input if, and only if, [kPrimaryButton] is pressed.
+  static bool _defaultButtonAcceptBehavior(int buttons) => buttons == kPrimaryButton;
+
   /// Configure the behavior of offsets passed to [onStart].
   ///
   /// If set to [DragStartBehavior.start], the [onStart] callback will be called
@@ -120,12 +120,14 @@
   ///
   /// See also:
   ///
-  ///  * [kPrimaryButton], the button this callback responds to.
+  ///  * [allowedButtonsFilter], which decides which button will be allowed.
   ///  * [DragDownDetails], which is passed as an argument to this callback.
   GestureDragDownCallback? onDown;
 
+  /// {@template flutter.gestures.monodrag.DragGestureRecognizer.onStart}
   /// A pointer has contacted the screen with a primary button and has begun to
   /// move.
+  /// {@endtemplate}
   ///
   /// The position of the pointer is provided in the callback's `details`
   /// argument, which is a [DragStartDetails] object. The [dragStartBehavior]
@@ -133,32 +135,36 @@
   ///
   /// See also:
   ///
-  ///  * [kPrimaryButton], the button this callback responds to.
+  ///  * [allowedButtonsFilter], which decides which button will be allowed.
   ///  * [DragStartDetails], which is passed as an argument to this callback.
   GestureDragStartCallback? onStart;
 
+  /// {@template flutter.gestures.monodrag.DragGestureRecognizer.onUpdate}
   /// A pointer that is in contact with the screen with a primary button and
   /// moving has moved again.
+  /// {@endtemplate}
   ///
   /// The distance traveled by the pointer since the last update is provided in
   /// the callback's `details` argument, which is a [DragUpdateDetails] object.
   ///
   /// See also:
   ///
-  ///  * [kPrimaryButton], the button this callback responds to.
+  ///  * [allowedButtonsFilter], which decides which button will be allowed.
   ///  * [DragUpdateDetails], which is passed as an argument to this callback.
   GestureDragUpdateCallback? onUpdate;
 
+  /// {@template flutter.gestures.monodrag.DragGestureRecognizer.onEnd}
   /// A pointer that was previously in contact with the screen with a primary
   /// button and moving is no longer in contact with the screen and was moving
   /// at a specific velocity when it stopped contacting the screen.
+  /// {@endtemplate}
   ///
   /// The velocity is provided in the callback's `details` argument, which is a
   /// [DragEndDetails] object.
   ///
   /// See also:
   ///
-  ///  * [kPrimaryButton], the button this callback responds to.
+  ///  * [allowedButtonsFilter], which decides which button will be allowed.
   ///  * [DragEndDetails], which is passed as an argument to this callback.
   GestureDragEndCallback? onEnd;
 
@@ -166,10 +172,10 @@
   ///
   /// See also:
   ///
-  ///  * [kPrimaryButton], the button this callback responds to.
+  ///  * [allowedButtonsFilter], which decides which button will be allowed.
   GestureDragCancelCallback? onCancel;
 
-  /// The minimum distance an input pointer drag must have moved to
+  /// The minimum distance an input pointer drag must have moved
   /// to be considered a fling gesture.
   ///
   /// This value is typically compared with the distance traveled along the
@@ -243,18 +249,12 @@
   @override
   bool isPointerAllowed(PointerEvent event) {
     if (_initialButtons == null) {
-      switch (event.buttons) {
-        case kPrimaryButton:
-          if (onDown == null &&
-              onStart == null &&
-              onUpdate == null &&
-              onEnd == null &&
-              onCancel == null) {
-            return false;
-          }
-          break;
-        default:
-          return false;
+      if (onDown == null &&
+          onStart == null &&
+          onUpdate == null &&
+          onEnd == null &&
+          onCancel == null) {
+        return false;
       }
     } else {
       // There can be multiple drags simultaneously. Their effects are combined.
@@ -308,7 +308,6 @@
          event is PointerPanZoomStartEvent ||
          event is PointerPanZoomUpdateEvent)) {
       final VelocityTracker tracker = _velocityTrackers[event.pointer]!;
-      assert(tracker != null);
       if (event is PointerPanZoomStartEvent) {
         tracker.addPosition(event.timeStamp, Offset.zero);
       } else if (event is PointerPanZoomUpdateEvent) {
@@ -441,7 +440,6 @@
   }
 
   void _checkDown() {
-    assert(_initialButtons == kPrimaryButton);
     if (onDown != null) {
       final DragDownDetails details = DragDownDetails(
         globalPosition: _initialPosition.global,
@@ -452,7 +450,6 @@
   }
 
   void _checkStart(Duration timestamp, int pointer) {
-    assert(_initialButtons == kPrimaryButton);
     if (onStart != null) {
       final DragStartDetails details = DragStartDetails(
         sourceTimeStamp: timestamp,
@@ -471,7 +468,6 @@
     required Offset globalPosition,
     Offset? localPosition,
   }) {
-    assert(_initialButtons == kPrimaryButton);
     if (onUpdate != null) {
       final DragUpdateDetails details = DragUpdateDetails(
         sourceTimeStamp: sourceTimeStamp,
@@ -485,13 +481,11 @@
   }
 
   void _checkEnd(int pointer) {
-    assert(_initialButtons == kPrimaryButton);
     if (onEnd == null) {
       return;
     }
 
     final VelocityTracker tracker = _velocityTrackers[pointer]!;
-    assert(tracker != null);
 
     final DragEndDetails details;
     final String Function() debugReport;
@@ -522,7 +516,6 @@
   }
 
   void _checkCancel() {
-    assert(_initialButtons == kPrimaryButton);
     if (onCancel != null) {
       invokeCallback<void>('onCancel', onCancel!);
     }
@@ -556,12 +549,8 @@
   /// {@macro flutter.gestures.GestureRecognizer.supportedDevices}
   VerticalDragGestureRecognizer({
     super.debugOwner,
-    @Deprecated(
-      'Migrate to supportedDevices. '
-      'This feature was deprecated after v2.3.0-1.0.pre.',
-    )
-    super.kind,
     super.supportedDevices,
+    super.allowedButtonsFilter,
   });
 
   @override
@@ -602,12 +591,8 @@
   /// {@macro flutter.gestures.GestureRecognizer.supportedDevices}
   HorizontalDragGestureRecognizer({
     super.debugOwner,
-    @Deprecated(
-      'Migrate to supportedDevices. '
-      'This feature was deprecated after v2.3.0-1.0.pre.',
-    )
-    super.kind,
     super.supportedDevices,
+    super.allowedButtonsFilter,
   });
 
   @override
@@ -646,6 +631,7 @@
   PanGestureRecognizer({
     super.debugOwner,
     super.supportedDevices,
+    super.allowedButtonsFilter,
   });
 
   @override
diff --git a/framework/lib/src/gestures/multidrag.dart b/framework/lib/src/gestures/multidrag.dart
index 197fcfb..19d61a0 100644
--- a/framework/lib/src/gestures/multidrag.dart
+++ b/framework/lib/src/gestures/multidrag.dart
@@ -35,8 +35,7 @@
   ///
   /// The [initialPosition] argument must not be null.
   MultiDragPointerState(this.initialPosition, this.kind, this.gestureSettings)
-    : assert(initialPosition != null),
-      _velocityTracker = VelocityTracker.withKind(kind);
+    : _velocityTracker = VelocityTracker.withKind(kind);
 
   /// Device specific gesture configuration that should be preferred over
   /// framework constants.
@@ -133,7 +132,6 @@
   void _startDrag(Drag client) {
     assert(_arenaEntry != null);
     assert(_client == null);
-    assert(client != null);
     assert(pendingDelta != null);
     _client = client;
     final DragUpdateDetails details = DragUpdateDetails(
@@ -217,14 +215,13 @@
   /// {@macro flutter.gestures.GestureRecognizer.supportedDevices}
   MultiDragGestureRecognizer({
     required super.debugOwner,
-    @Deprecated(
-      'Migrate to supportedDevices. '
-      'This feature was deprecated after v2.3.0-1.0.pre.',
-    )
-    super.kind,
     super.supportedDevices,
+    super.allowedButtonsFilter = _defaultButtonAcceptBehavior,
   });
 
+  // Accept the input if, and only if, [kPrimaryButton] is pressed.
+  static bool _defaultButtonAcceptBehavior(int buttons) => buttons == kPrimaryButton;
+
   /// Called when this class recognizes the start of a drag gesture.
   ///
   /// The remaining notifications for this drag gesture are delivered to the
@@ -236,8 +233,6 @@
   @override
   void addAllowedPointer(PointerDownEvent event) {
     assert(_pointers != null);
-    assert(event.pointer != null);
-    assert(event.position != null);
     assert(!_pointers!.containsKey(event.pointer));
     final MultiDragPointerState state = createNewPointerState(event);
     _pointers![event.pointer] = state;
@@ -253,9 +248,6 @@
 
   void _handleEvent(PointerEvent event) {
     assert(_pointers != null);
-    assert(event.pointer != null);
-    assert(event.timeStamp != null);
-    assert(event.position != null);
     assert(_pointers!.containsKey(event.pointer));
     final MultiDragPointerState state = _pointers![event.pointer]!;
     if (event is PointerMoveEvent) {
@@ -292,7 +284,6 @@
   Drag? _startDrag(Offset initialPosition, int pointer) {
     assert(_pointers != null);
     final MultiDragPointerState state = _pointers![pointer]!;
-    assert(state != null);
     assert(state._pendingDelta != null);
     Drag? drag;
     if (onStart != null) {
@@ -311,7 +302,6 @@
     assert(_pointers != null);
     if (_pointers!.containsKey(pointer)) {
       final MultiDragPointerState state = _pointers![pointer]!;
-      assert(state != null);
       state.rejected();
       _removeState(pointer);
     } // else we already preemptively forgot about it (e.g. we got an up event)
@@ -376,12 +366,8 @@
   /// {@macro flutter.gestures.GestureRecognizer.supportedDevices}
   ImmediateMultiDragGestureRecognizer({
     super.debugOwner,
-    @Deprecated(
-      'Migrate to supportedDevices. '
-      'This feature was deprecated after v2.3.0-1.0.pre.',
-    )
-    super.kind,
     super.supportedDevices,
+    super.allowedButtonsFilter,
   });
 
   @override
@@ -433,12 +419,8 @@
   /// {@macro flutter.gestures.GestureRecognizer.supportedDevices}
   HorizontalMultiDragGestureRecognizer({
     super.debugOwner,
-    @Deprecated(
-      'Migrate to supportedDevices. '
-      'This feature was deprecated after v2.3.0-1.0.pre.',
-    )
-    super.kind,
     super.supportedDevices,
+    super.allowedButtonsFilter,
   });
 
   @override
@@ -490,12 +472,8 @@
   /// {@macro flutter.gestures.GestureRecognizer.supportedDevices}
   VerticalMultiDragGestureRecognizer({
     super.debugOwner,
-    @Deprecated(
-      'Migrate to supportedDevices. '
-      'This feature was deprecated after v2.3.0-1.0.pre.',
-    )
-    super.kind,
     super.supportedDevices,
+    super.allowedButtonsFilter,
   });
 
   @override
@@ -508,8 +486,7 @@
 }
 
 class _DelayedPointerState extends MultiDragPointerState {
-  _DelayedPointerState(super.initialPosition, Duration delay, super.kind, super.deviceGestureSettings)
-      : assert(delay != null) {
+  _DelayedPointerState(super.initialPosition, Duration delay, super.kind, super.deviceGestureSettings) {
     _timer = Timer(delay, _delayPassed);
   }
 
@@ -600,13 +577,9 @@
   DelayedMultiDragGestureRecognizer({
     this.delay = kLongPressTimeout,
     super.debugOwner,
-    @Deprecated(
-      'Migrate to supportedDevices. '
-      'This feature was deprecated after v2.3.0-1.0.pre.',
-    )
-    super.kind,
     super.supportedDevices,
-  }) : assert(delay != null);
+    super.allowedButtonsFilter,
+  });
 
   /// The amount of time the pointer must remain in the same place for the drag
   /// to be recognized.
diff --git a/framework/lib/src/gestures/multitap.dart b/framework/lib/src/gestures/multitap.dart
index 426e00b..b4d6c84 100644
--- a/framework/lib/src/gestures/multitap.dart
+++ b/framework/lib/src/gestures/multitap.dart
@@ -43,8 +43,7 @@
 /// CountdownZoned tracks whether the specified duration has elapsed since
 /// creation, honoring [Zone].
 class _CountdownZoned {
-  _CountdownZoned({ required Duration duration })
-       : assert(duration != null) {
+  _CountdownZoned({ required Duration duration }) {
     Timer(duration, _onTimeout);
   }
 
@@ -65,10 +64,7 @@
     required this.entry,
     required Duration doubleTapMinTime,
     required this.gestureSettings,
-  }) : assert(doubleTapMinTime != null),
-       assert(event != null),
-       assert(event.buttons != null),
-       pointer = event.pointer,
+  }) : pointer = event.pointer,
        _initialGlobalPosition = event.position,
        initialButtons = event.buttons,
        _doubleTapMinTimeCountdown = _CountdownZoned(duration: doubleTapMinTime);
@@ -113,8 +109,8 @@
 /// Recognizes when the user has tapped the screen at the same location twice in
 /// quick succession.
 ///
-/// [DoubleTapGestureRecognizer] competes on pointer events of [kPrimaryButton]
-/// only when it has a non-null callback. If it has no callbacks, it is a no-op.
+/// [DoubleTapGestureRecognizer] competes on pointer events when it
+/// has a non-null callback. If it has no callbacks, it is a no-op.
 ///
 class DoubleTapGestureRecognizer extends GestureRecognizer {
   /// Create a gesture recognizer for double taps.
@@ -122,14 +118,14 @@
   /// {@macro flutter.gestures.GestureRecognizer.supportedDevices}
   DoubleTapGestureRecognizer({
     super.debugOwner,
-    @Deprecated(
-      'Migrate to supportedDevices. '
-      'This feature was deprecated after v2.3.0-1.0.pre.',
-    )
-    super.kind,
     super.supportedDevices,
+    super.allowedButtonsFilter = _defaultButtonAcceptBehavior,
   });
 
+  // The default value for [allowedButtonsFilter].
+  // Accept the input if, and only if, [kPrimaryButton] is pressed.
+  static bool _defaultButtonAcceptBehavior(int buttons) => buttons == kPrimaryButton;
+
   // Implementation notes:
   //
   // The double tap recognizer can be in one of four states. There's no
@@ -165,7 +161,7 @@
   ///
   /// See also:
   ///
-  ///  * [kPrimaryButton], the button this callback responds to.
+  ///  * [allowedButtonsFilter], which decides which button will be allowed.
   ///  * [TapDownDetails], which is passed as an argument to this callback.
   ///  * [GestureDetector.onDoubleTapDown], which exposes this callback.
   GestureTapDownCallback? onDoubleTapDown;
@@ -178,7 +174,7 @@
   ///
   /// See also:
   ///
-  ///  * [kPrimaryButton], the button this callback responds to.
+  ///  * [allowedButtonsFilter], which decides which button will be allowed.
   ///  * [GestureDetector.onDoubleTap], which exposes this callback.
   GestureDoubleTapCallback? onDoubleTap;
 
@@ -192,7 +188,7 @@
   ///
   /// See also:
   ///
-  ///  * [kPrimaryButton], the button this callback responds to.
+  ///  * [allowedButtonsFilter], which decides which button will be allowed.
   ///  * [GestureDetector.onDoubleTapCancel], which exposes this callback.
   GestureTapCancelCallback? onDoubleTapCancel;
 
@@ -203,19 +199,19 @@
   @override
   bool isPointerAllowed(PointerDownEvent event) {
     if (_firstTap == null) {
-      switch (event.buttons) {
-        case kPrimaryButton:
-          if (onDoubleTapDown == null &&
-              onDoubleTap == null &&
-              onDoubleTapCancel == null) {
-            return false;
-          }
-          break;
-        default:
-          return false;
+      if (onDoubleTapDown == null &&
+          onDoubleTap == null &&
+          onDoubleTapCancel == null) {
+        return false;
       }
     }
-    return super.isPointerAllowed(event);
+
+    // If second tap is not allowed, reset the state.
+    final bool isPointerAllowed = super.isPointerAllowed(event);
+    if (isPointerAllowed == false) {
+      _reset();
+    }
+    return isPointerAllowed;
   }
 
   @override
@@ -367,7 +363,6 @@
   }
 
   void _checkUp(int buttons) {
-    assert(buttons == kPrimaryButton);
     if (onDoubleTap != null) {
       invokeCallback<void>('onDoubleTap', onDoubleTap!);
     }
@@ -486,12 +481,8 @@
   MultiTapGestureRecognizer({
     this.longTapDelay = Duration.zero,
     super.debugOwner,
-    @Deprecated(
-      'Migrate to supportedDevices. '
-      'This feature was deprecated after v2.3.0-1.0.pre.',
-    )
-    super.kind,
     super.supportedDevices,
+    super.allowedButtonsFilter,
   });
 
   /// A pointer that might cause a tap has contacted the screen at a particular
@@ -679,8 +670,7 @@
   /// The `count` argument must be greater than zero.
   SerialTapCancelDetails({
     this.count = 1,
-  }) : assert(count != null),
-       assert(count > 0);
+  }) : assert(count > 0);
 
   /// The number of consecutive taps that were in progress when the gesture was
   /// interrupted.
@@ -813,6 +803,7 @@
   SerialTapGestureRecognizer({
     super.debugOwner,
     super.supportedDevices,
+    super.allowedButtonsFilter,
   });
 
   /// A pointer has contacted the screen at a particular location, which might
diff --git a/framework/lib/src/gestures/pointer_signal_resolver.dart b/framework/lib/src/gestures/pointer_signal_resolver.dart
index 6cf84e0..6ffcf76 100644
--- a/framework/lib/src/gestures/pointer_signal_resolver.dart
+++ b/framework/lib/src/gestures/pointer_signal_resolver.dart
@@ -64,8 +64,6 @@
   /// See the documentation for the [PointerSignalResolver] class on when and
   /// how this method should be used.
   void register(PointerSignalEvent event, PointerSignalResolvedCallback callback) {
-    assert(event != null);
-    assert(callback != null);
     assert(_currentEvent == null || _isSameEvent(_currentEvent!, event));
     if (_firstRegisteredCallback != null) {
       return;
diff --git a/framework/lib/src/gestures/recognizer.dart b/framework/lib/src/gestures/recognizer.dart
index 243c86a..0a30fbf 100644
--- a/framework/lib/src/gestures/recognizer.dart
+++ b/framework/lib/src/gestures/recognizer.dart
@@ -48,6 +48,11 @@
   start,
 }
 
+/// Signature for `allowedButtonsFilter` in [GestureRecognizer].
+/// Used to filter the input buttons of incoming pointer events.
+/// The parameter `buttons` comes from [PointerEvent.buttons].
+typedef AllowedButtonsFilter = bool Function(int buttons);
+
 /// The base class that all gesture recognizers inherit from.
 ///
 /// Provides a basic API that can be used by classes that work with
@@ -73,14 +78,10 @@
   /// {@endtemplate}
   GestureRecognizer({
     this.debugOwner,
-    @Deprecated(
-      'Migrate to supportedDevices. '
-      'This feature was deprecated after v2.3.0-1.0.pre.',
-    )
-    PointerDeviceKind? kind,
     Set<PointerDeviceKind>? supportedDevices,
-  }) : assert(kind == null || supportedDevices == null),
-       _supportedDevices = kind == null ? supportedDevices : <PointerDeviceKind>{ kind };
+    AllowedButtonsFilter? allowedButtonsFilter,
+  }) : _supportedDevices = supportedDevices,
+       _allowedButtonsFilter = allowedButtonsFilter ?? _defaultButtonAcceptBehavior;
 
   /// The recognizer's owner.
   ///
@@ -98,6 +99,29 @@
   /// tracked and recognized.
   final Set<PointerDeviceKind>? _supportedDevices;
 
+  /// {@template flutter.gestures.multidrag._allowedButtonsFilter}
+  /// Called when interaction starts. This limits the dragging behavior
+  /// for custom clicks (such as scroll click). Its parameter comes
+  /// from [PointerEvent.buttons].
+  ///
+  /// Due to how [kPrimaryButton], [kSecondaryButton], etc., use integers,
+  /// bitwise operations can help filter how buttons are pressed.
+  /// For example, if someone simultaneously presses the primary and secondary
+  /// buttons, the default behavior will return false. The following code
+  /// accepts any button press with primary:
+  /// `(int buttons) => buttons & kPrimaryButton != 0`.
+  ///
+  /// When value is `(int buttons) => false`, allow no interactions.
+  /// When value is `(int buttons) => true`, allow all interactions.
+  ///
+  /// Defaults to all buttons.
+  /// {@endtemplate}
+  final AllowedButtonsFilter _allowedButtonsFilter;
+
+  // The default value for [allowedButtonsFilter].
+  // Accept any input.
+  static bool _defaultButtonAcceptBehavior(int buttons) => true;
+
   /// Holds a mapping between pointer IDs and the kind of devices they are
   /// coming from.
   final Map<int, PointerDeviceKind> _pointerToKind = <int, PointerDeviceKind>{};
@@ -185,9 +209,9 @@
   /// Checks whether or not a pointer is allowed to be tracked by this recognizer.
   @protected
   bool isPointerAllowed(PointerDownEvent event) {
-    // Currently, it only checks for device kind. But in the future we could check
-    // for other things e.g. mouse button.
-    return _supportedDevices == null || _supportedDevices!.contains(event.kind);
+    return (_supportedDevices == null ||
+            _supportedDevices!.contains(event.kind)) &&
+        _allowedButtonsFilter(event.buttons);
   }
 
   /// Handles a pointer pan/zoom being added that's not allowed by this recognizer.
@@ -237,7 +261,6 @@
   @protected
   @pragma('vm:notify-debugger-on-exception')
   T? invokeCallback<T>(String name, RecognizerCallback<T> callback, { String Function()? debugReport }) {
-    assert(callback != null);
     T? result;
     try {
       assert(() {
@@ -292,12 +315,8 @@
   /// {@macro flutter.gestures.GestureRecognizer.supportedDevices}
   OneSequenceGestureRecognizer({
     super.debugOwner,
-    @Deprecated(
-      'Migrate to supportedDevices. '
-      'This feature was deprecated after v2.3.0-1.0.pre.',
-    )
-    super.kind,
     super.supportedDevices,
+    super.allowedButtonsFilter,
   });
 
   final Map<int, GestureArenaEntry> _entries = <int, GestureArenaEntry>{};
@@ -427,7 +446,8 @@
   void startTrackingPointer(int pointer, [Matrix4? transform]) {
     GestureBinding.instance.pointerRouter.addRoute(pointer, handleEvent, transform);
     _trackedPointers.add(pointer);
-    assert(!_entries.containsValue(pointer));
+    // TODO(goderbauer): Enable assert after recognizers properly clean up their defunct `_entries`, see https://github.com/flutter/flutter/issues/117356.
+    // assert(!_entries.containsKey(pointer));
     _entries[pointer] = _addPointerToArena(pointer);
   }
 
@@ -504,12 +524,8 @@
     this.preAcceptSlopTolerance = kTouchSlop,
     this.postAcceptSlopTolerance = kTouchSlop,
     super.debugOwner,
-    @Deprecated(
-      'Migrate to supportedDevices. '
-      'This feature was deprecated after v2.3.0-1.0.pre.',
-    )
-    super.kind,
     super.supportedDevices,
+    super.allowedButtonsFilter,
   }) : assert(
          preAcceptSlopTolerance == null || preAcceptSlopTolerance >= 0,
          'The preAcceptSlopTolerance must be positive or null',
diff --git a/framework/lib/src/gestures/scale.dart b/framework/lib/src/gestures/scale.dart
index 8ee9c51..8d7e0ab 100644
--- a/framework/lib/src/gestures/scale.dart
+++ b/framework/lib/src/gestures/scale.dart
@@ -15,6 +15,18 @@
 export 'recognizer.dart' show DragStartBehavior;
 export 'velocity_tracker.dart' show Velocity;
 
+/// The default conversion factor when treating mouse scrolling as scaling.
+///
+/// The value was arbitrarily chosen to feel natural for most mousewheels on
+/// all supported platforms.
+const double kDefaultMouseScrollToScaleFactor = 200;
+
+/// The default conversion factor when treating trackpad scrolling as scaling.
+///
+/// This factor matches the default [kDefaultMouseScrollToScaleFactor] of 200 to
+/// feel natural for most trackpads, and the convention that scrolling up means
+/// zooming in.
+const Offset kDefaultTrackpadScrollToScaleFactor = Offset(0, -1/kDefaultMouseScrollToScaleFactor);
 
 /// The possible states of a [ScaleGestureRecognizer].
 enum _ScaleState {
@@ -36,17 +48,49 @@
 }
 
 class _PointerPanZoomData {
-  _PointerPanZoomData({
-    required this.focalPoint,
-    required this.scale,
-    required this.rotation
-  });
-  Offset focalPoint;
-  double scale;
-  double rotation;
+  _PointerPanZoomData.fromStartEvent(
+    this.parent,
+    PointerPanZoomStartEvent event
+  ) : _position = event.position,
+      _pan = Offset.zero,
+      _scale = 1,
+      _rotation = 0;
+
+  _PointerPanZoomData.fromUpdateEvent(
+    this.parent,
+    PointerPanZoomUpdateEvent event
+  ) : _position = event.position,
+      _pan = event.pan,
+      _scale = event.scale,
+      _rotation = event.rotation;
+
+  final ScaleGestureRecognizer parent;
+  final Offset _position;
+  final Offset _pan;
+  final double _scale;
+  final double _rotation;
+
+  Offset get focalPoint {
+    if (parent.trackpadScrollCausesScale) {
+      return _position;
+    }
+    return _position + _pan;
+  }
+
+  double get scale {
+    if (parent.trackpadScrollCausesScale) {
+      return _scale * math.exp(
+        (_pan.dx * parent.trackpadScrollToScaleFactor.dx) +
+        (_pan.dy * parent.trackpadScrollToScaleFactor.dy)
+      );
+    }
+    return _scale;
+  }
+
+  double get rotation => _rotation;
 
   @override
-  String toString() => '_PointerPanZoomData(focalPoint: $focalPoint, scale: $scale, angle: $rotation)';
+  String toString() => '_PointerPanZoomData(parent: $parent, _position: $_position, _pan: $_pan, _scale: $_scale, _rotation: $_rotation)';
 }
 
 /// Details for [GestureScaleStartCallback].
@@ -54,8 +98,11 @@
   /// Creates details for [GestureScaleStartCallback].
   ///
   /// The [focalPoint] argument must not be null.
-  ScaleStartDetails({ this.focalPoint = Offset.zero, Offset? localFocalPoint, this.pointerCount = 0 })
-    : assert(focalPoint != null), localFocalPoint = localFocalPoint ?? focalPoint;
+  ScaleStartDetails({
+    this.focalPoint = Offset.zero,
+    Offset? localFocalPoint,
+    this.pointerCount = 0,
+  }) : localFocalPoint = localFocalPoint ?? focalPoint;
 
   /// The initial focal point of the pointers in contact with the screen.
   ///
@@ -104,12 +151,9 @@
     this.rotation = 0.0,
     this.pointerCount = 0,
     this.focalPointDelta = Offset.zero,
-  }) : assert(focalPoint != null),
-       assert(focalPointDelta != null),
-       assert(scale != null && scale >= 0.0),
-       assert(horizontalScale != null && horizontalScale >= 0.0),
-       assert(verticalScale != null && verticalScale >= 0.0),
-       assert(rotation != null),
+  }) : assert(scale >= 0.0),
+       assert(horizontalScale >= 0.0),
+       assert(verticalScale >= 0.0),
        localFocalPoint = localFocalPoint ?? focalPoint;
 
   /// The amount the gesture's focal point has moved in the coordinate space of
@@ -201,12 +245,14 @@
   /// Creates details for [GestureScaleEndCallback].
   ///
   /// The [velocity] argument must not be null.
-  ScaleEndDetails({ this.velocity = Velocity.zero, this.pointerCount = 0 })
-    : assert(velocity != null);
+  ScaleEndDetails({ this.velocity = Velocity.zero, this.scaleVelocity = 0, this.pointerCount = 0 });
 
   /// The velocity of the last pointer to be lifted off of the screen.
   final Velocity velocity;
 
+  /// The final velocity of the scale factor reported by the gesture.
+  final double scaleVelocity;
+
   /// The number of pointers being tracked by the gesture recognizer.
   ///
   /// Typically this is the number of fingers being used to pan the widget using the gesture
@@ -214,7 +260,7 @@
   final int pointerCount;
 
   @override
-  String toString() => 'ScaleEndDetails(velocity: $velocity, pointerCount: $pointerCount)';
+  String toString() => 'ScaleEndDetails(velocity: $velocity, scaleVelocity: $scaleVelocity, pointerCount: $pointerCount)';
 }
 
 /// Signature for when the pointers in contact with the screen have established
@@ -229,7 +275,6 @@
 typedef GestureScaleEndCallback = void Function(ScaleEndDetails details);
 
 bool _isFlingGesture(Velocity velocity) {
-  assert(velocity != null);
   final double speedSquared = velocity.pixelsPerSecond.distanceSquared;
   return speedSquared > kMinFlingVelocity * kMinFlingVelocity;
 }
@@ -249,9 +294,7 @@
     this.pointerStartId = 0,
     this.pointerEndLocation = Offset.zero,
     this.pointerEndId = 1,
-  }) : assert(pointerStartLocation != null && pointerEndLocation != null),
-       assert(pointerStartId != null && pointerEndId != null),
-       assert(pointerStartId != pointerEndId);
+  }) : assert(pointerStartId != pointerEndId);
 
   // The location and the id of the pointer that marks the start of the line.
   final Offset pointerStartLocation;
@@ -268,23 +311,22 @@
 ///
 /// [ScaleGestureRecognizer] tracks the pointers in contact with the screen and
 /// calculates their focal point, indicated scale, and rotation. When a focal
-/// pointer is established, the recognizer calls [onStart]. As the focal point,
-/// scale, rotation change, the recognizer calls [onUpdate]. When the pointers
-/// are no longer in contact with the screen, the recognizer calls [onEnd].
+/// point is established, the recognizer calls [onStart]. As the focal point,
+/// scale, and rotation change, the recognizer calls [onUpdate]. When the
+/// pointers are no longer in contact with the screen, the recognizer calls
+/// [onEnd].
 class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
   /// Create a gesture recognizer for interactions intended for scaling content.
   ///
   /// {@macro flutter.gestures.GestureRecognizer.supportedDevices}
   ScaleGestureRecognizer({
     super.debugOwner,
-    @Deprecated(
-      'Migrate to supportedDevices. '
-      'This feature was deprecated after v2.3.0-1.0.pre.',
-    )
-    super.kind,
     super.supportedDevices,
+    super.allowedButtonsFilter,
     this.dragStartBehavior = DragStartBehavior.down,
-  }) : assert(dragStartBehavior != null);
+    this.trackpadScrollCausesScale = false,
+    this.trackpadScrollToScaleFactor = kDefaultTrackpadScrollToScaleFactor,
+  });
 
   /// Determines what point is used as the starting point in all calculations
   /// involving this gesture.
@@ -331,6 +373,26 @@
 
   Matrix4? _lastTransform;
 
+  /// {@template flutter.gestures.scale.trackpadScrollCausesScale}
+  /// Whether scrolling up/down on a trackpad should cause scaling instead of
+  /// panning.
+  ///
+  /// Defaults to false.
+  /// {@endtemplate}
+  bool trackpadScrollCausesScale;
+
+  /// {@template flutter.gestures.scale.trackpadScrollToScaleFactor}
+  /// A factor to control the direction and magnitude of scale when converting
+  /// trackpad scrolling.
+  ///
+  /// Incoming trackpad pan offsets will be divided by this factor to get scale
+  /// values. Increasing this offset will reduce the amount of scaling caused by
+  /// a fixed amount of trackpad scrolling.
+  ///
+  /// Defaults to [kDefaultTrackpadScrollToScaleFactor].
+  /// {@endtemplate}
+  Offset trackpadScrollToScaleFactor;
+
   late Offset _initialFocalPoint;
   Offset? _currentFocalPoint;
   late double _initialSpan;
@@ -345,6 +407,7 @@
   final Map<int, Offset> _pointerLocations = <int, Offset>{};
   final List<int> _pointerQueue = <int>[]; // A queue to sort pointers in order of entrance
   final Map<int, VelocityTracker> _velocityTrackers = <int, VelocityTracker>{};
+  VelocityTracker? _scaleVelocityTracker;
   late Offset _delta;
   final Map<int, _PointerPanZoomData> _pointerPanZooms = <int, _PointerPanZoomData>{};
   double _initialPanZoomScaleFactor = 1;
@@ -465,23 +528,16 @@
       _lastTransform = event.transform;
     } else if (event is PointerPanZoomStartEvent) {
       assert(_pointerPanZooms[event.pointer] == null);
-      _pointerPanZooms[event.pointer] = _PointerPanZoomData(
-        focalPoint: event.position,
-        scale: 1,
-        rotation: 0
-      );
+      _pointerPanZooms[event.pointer] = _PointerPanZoomData.fromStartEvent(this, event);
       didChangeConfiguration = true;
       shouldStartIfAccepted = true;
+      _lastTransform = event.transform;
     } else if (event is PointerPanZoomUpdateEvent) {
       assert(_pointerPanZooms[event.pointer] != null);
-      if (!event.synthesized) {
+      if (!event.synthesized && !trackpadScrollCausesScale) {
         _velocityTrackers[event.pointer]!.addPosition(event.timeStamp, event.pan);
       }
-      _pointerPanZooms[event.pointer] = _PointerPanZoomData(
-        focalPoint: event.position + event.pan,
-        scale: event.scale,
-        rotation: event.rotation
-      );
+      _pointerPanZooms[event.pointer] = _PointerPanZoomData.fromUpdateEvent(this, event);
       _lastTransform = event.transform;
       shouldStartIfAccepted = true;
     } else if (event is PointerPanZoomEndEvent) {
@@ -494,7 +550,7 @@
     _update();
 
     if (!didChangeConfiguration || _reconfigure(event.pointer)) {
-      _advanceStateMachine(shouldStartIfAccepted, event.kind);
+      _advanceStateMachine(shouldStartIfAccepted, event);
     }
     stopTrackingIfPointerNoLongerDown(event);
   }
@@ -606,18 +662,20 @@
           if (pixelsPerSecond.distanceSquared > kMaxFlingVelocity * kMaxFlingVelocity) {
             velocity = Velocity(pixelsPerSecond: (pixelsPerSecond / pixelsPerSecond.distance) * kMaxFlingVelocity);
           }
-          invokeCallback<void>('onEnd', () => onEnd!(ScaleEndDetails(velocity: velocity, pointerCount: _pointerCount)));
+          invokeCallback<void>('onEnd', () => onEnd!(ScaleEndDetails(velocity: velocity, scaleVelocity: _scaleVelocityTracker?.getVelocity().pixelsPerSecond.dx ?? -1, pointerCount: _pointerCount)));
         } else {
-          invokeCallback<void>('onEnd', () => onEnd!(ScaleEndDetails(pointerCount: _pointerCount)));
+          invokeCallback<void>('onEnd', () => onEnd!(ScaleEndDetails(scaleVelocity: _scaleVelocityTracker?.getVelocity().pixelsPerSecond.dx ?? -1, pointerCount: _pointerCount)));
         }
       }
       _state = _ScaleState.accepted;
+      _scaleVelocityTracker = VelocityTracker.withKind(PointerDeviceKind.touch); // arbitrary PointerDeviceKind
       return false;
     }
+    _scaleVelocityTracker = VelocityTracker.withKind(PointerDeviceKind.touch); // arbitrary PointerDeviceKind
     return true;
   }
 
-  void _advanceStateMachine(bool shouldStartIfAccepted, PointerDeviceKind pointerDeviceKind) {
+  void _advanceStateMachine(bool shouldStartIfAccepted, PointerEvent event) {
     if (_state == _ScaleState.ready) {
       _state = _ScaleState.possible;
     }
@@ -625,7 +683,7 @@
     if (_state == _ScaleState.possible) {
       final double spanDelta = (_currentSpan - _initialSpan).abs();
       final double focalPointDelta = (_currentFocalPoint! - _initialFocalPoint).distance;
-      if (spanDelta > computeScaleSlop(pointerDeviceKind) || focalPointDelta > computePanSlop(pointerDeviceKind, gestureSettings) || math.max(_scaleFactor / _pointerScaleFactor, _pointerScaleFactor / _scaleFactor) > 1.05) {
+      if (spanDelta > computeScaleSlop(event.kind) || focalPointDelta > computePanSlop(event.kind, gestureSettings) || math.max(_scaleFactor / _pointerScaleFactor, _pointerScaleFactor / _scaleFactor) > 1.05) {
         resolve(GestureDisposition.accepted);
       }
     } else if (_state.index >= _ScaleState.accepted.index) {
@@ -637,19 +695,22 @@
       _dispatchOnStartCallbackIfNeeded();
     }
 
-    if (_state == _ScaleState.started && onUpdate != null) {
-      invokeCallback<void>('onUpdate', () {
-        onUpdate!(ScaleUpdateDetails(
-          scale: _scaleFactor,
-          horizontalScale: _horizontalScaleFactor,
-          verticalScale: _verticalScaleFactor,
-          focalPoint: _currentFocalPoint!,
-          localFocalPoint: _localFocalPoint,
-          rotation: _computeRotationFactor(),
-          pointerCount: _pointerCount,
-          focalPointDelta: _delta,
-        ));
-      });
+    if (_state == _ScaleState.started) {
+      _scaleVelocityTracker?.addPosition(event.timeStamp, Offset(_scaleFactor, 0));
+      if (onUpdate != null) {
+        invokeCallback<void>('onUpdate', () {
+          onUpdate!(ScaleUpdateDetails(
+            scale: _scaleFactor,
+            horizontalScale: _horizontalScaleFactor,
+            verticalScale: _verticalScaleFactor,
+            focalPoint: _currentFocalPoint!,
+            localFocalPoint: _localFocalPoint,
+            rotation: _computeRotationFactor(),
+            pointerCount: _pointerCount,
+            focalPointDelta: _delta,
+          ));
+        });
+      }
     }
   }
 
diff --git a/framework/lib/src/gestures/tap.dart b/framework/lib/src/gestures/tap.dart
index b58dfff..efa3a05 100644
--- a/framework/lib/src/gestures/tap.dart
+++ b/framework/lib/src/gestures/tap.dart
@@ -32,8 +32,7 @@
     this.globalPosition = Offset.zero,
     Offset? localPosition,
     this.kind,
-  }) : assert(globalPosition != null),
-       localPosition = localPosition ?? globalPosition;
+  }) : localPosition = localPosition ?? globalPosition;
 
   /// The global position at which the pointer contacted the screen.
   final Offset globalPosition;
@@ -45,11 +44,13 @@
   final Offset localPosition;
 }
 
+/// {@template flutter.gestures.tap.GestureTapDownCallback}
 /// Signature for when a pointer that might cause a tap has contacted the
 /// screen.
 ///
 /// The position at which the pointer contacted the screen is available in the
 /// `details`.
+/// {@endtemplate}
 ///
 /// See also:
 ///
@@ -69,8 +70,7 @@
     required this.kind,
     this.globalPosition = Offset.zero,
     Offset? localPosition,
-  }) : assert(globalPosition != null),
-       localPosition = localPosition ?? globalPosition;
+  }) : localPosition = localPosition ?? globalPosition;
 
   /// The global position at which the pointer contacted the screen.
   final Offset globalPosition;
@@ -82,11 +82,13 @@
   final PointerDeviceKind kind;
 }
 
+/// {@template flutter.gestures.tap.GestureTapUpCallback}
 /// Signature for when a pointer that will trigger a tap has stopped contacting
 /// the screen.
 ///
 /// The position at which the pointer stopped contacting the screen is available
 /// in the `details`.
+/// {@endtemplate}
 ///
 /// See also:
 ///
@@ -145,7 +147,11 @@
   /// Creates a tap gesture recognizer.
   ///
   /// {@macro flutter.gestures.GestureRecognizer.supportedDevices}
-  BaseTapGestureRecognizer({ super.debugOwner, super.supportedDevices })
+  BaseTapGestureRecognizer({
+    super.debugOwner,
+    super.supportedDevices,
+    super.allowedButtonsFilter,
+  })
     : super(deadline: kPressTimeout);
 
   bool _sentTapDown = false;
@@ -198,7 +204,6 @@
 
   @override
   void addAllowedPointer(PointerDownEvent event) {
-    assert(event != null);
     if (state == GestureRecognizerState.ready) {
       // If there is no result in the previous gesture arena,
       // we ignore them and prepare to accept a new pointer.
@@ -216,7 +221,7 @@
     if (_down != null) {
       // This happens when this tap gesture has been rejected while the pointer
       // is down (i.e. due to movement), when another allowed pointer is added,
-      // in which case all pointers are simply ignored. The `_down` being null
+      // in which case all pointers are ignored. The `_down` being null
       // means that _reset() has been called, since it is always set at the
       // first allowed down event and will not be cleared except for reset(),
       super.addAllowedPointer(event);
@@ -350,6 +355,16 @@
 /// one non-null `onTertiaryTap*` callback. If it has no callbacks, it is a
 /// no-op.
 ///
+/// {@template flutter.gestures.tap.TapGestureRecognizer.allowedButtonsFilter}
+/// The [allowedButtonsFilter] argument only gives this recognizer the
+/// ability to limit the buttons it accepts. It does not provide the
+/// ability to recognize any buttons beyond the ones it already accepts:
+/// kPrimaryButton, kSecondaryButton or kTertiaryButton. Therefore, a
+/// combined value of `kPrimaryButton & kSecondaryButton` would be ignored,
+/// but `kPrimaryButton | kSecondaryButton` would be allowed, as long as
+/// only one of them is selected at a time.
+/// {@endtemplate}
+///
 /// See also:
 ///
 ///  * [GestureDetector.onTap], which uses this recognizer.
@@ -358,10 +373,16 @@
   /// Creates a tap gesture recognizer.
   ///
   /// {@macro flutter.gestures.GestureRecognizer.supportedDevices}
-  TapGestureRecognizer({ super.debugOwner, super.supportedDevices });
+  TapGestureRecognizer({
+    super.debugOwner,
+    super.supportedDevices,
+    super.allowedButtonsFilter,
+  });
 
+  /// {@template flutter.gestures.tap.TapGestureRecognizer.onTapDown}
   /// A pointer has contacted the screen at a particular location with a primary
   /// button, which might be the start of a tap.
+  /// {@endtemplate}
   ///
   /// This triggers after the down event, once a short timeout ([deadline]) has
   /// elapsed, or once the gestures has won the arena, whichever comes first.
@@ -378,8 +399,10 @@
   ///  * [GestureDetector.onTapDown], which exposes this callback.
   GestureTapDownCallback? onTapDown;
 
+  /// {@template flutter.gestures.tap.TapGestureRecognizer.onTapUp}
   /// A pointer has stopped contacting the screen at a particular location,
   /// which is recognized as a tap of a primary button.
+  /// {@endtemplate}
   ///
   /// This triggers on the up event, if the recognizer wins the arena with it
   /// or has previously won, immediately followed by [onTap].
@@ -411,8 +434,10 @@
   ///  * [GestureDetector.onTap], which exposes this callback.
   GestureTapCallback? onTap;
 
+  /// {@template flutter.gestures.tap.TapGestureRecognizer.onTapCancel}
   /// A pointer that previously triggered [onTapDown] will not end up causing
   /// a tap.
+  /// {@endtemplate}
   ///
   /// This triggers once the gesture loses the arena if [onTapDown] has
   /// previously been triggered.
@@ -428,8 +453,10 @@
   ///  * [GestureDetector.onTapCancel], which exposes this callback.
   GestureTapCancelCallback? onTapCancel;
 
+  /// {@template flutter.gestures.tap.TapGestureRecognizer.onSecondaryTap}
   /// A pointer has stopped contacting the screen, which is recognized as a tap
   /// of a secondary button.
+  /// {@endtemplate}
   ///
   /// This triggers on the up event, if the recognizer wins the arena with it or
   /// has previously won, immediately following [onSecondaryTapUp].
@@ -444,8 +471,10 @@
   ///  * [GestureDetector.onSecondaryTap], which exposes this callback.
   GestureTapCallback? onSecondaryTap;
 
+  /// {@template flutter.gestures.tap.TapGestureRecognizer.onSecondaryTapDown}
   /// A pointer has contacted the screen at a particular location with a
   /// secondary button, which might be the start of a secondary tap.
+  /// {@endtemplate}
   ///
   /// This triggers after the down event, once a short timeout ([deadline]) has
   /// elapsed, or once the gestures has won the arena, whichever comes first.
@@ -462,8 +491,10 @@
   ///  * [GestureDetector.onSecondaryTapDown], which exposes this callback.
   GestureTapDownCallback? onSecondaryTapDown;
 
+  /// {@template flutter.gestures.tap.TapGestureRecognizer.onSecondaryTapUp}
   /// A pointer has stopped contacting the screen at a particular location,
   /// which is recognized as a tap of a secondary button.
+  /// {@endtemplate}
   ///
   /// This triggers on the up event if the recognizer wins the arena with it
   /// or has previously won.
@@ -482,8 +513,10 @@
   ///  * [GestureDetector.onSecondaryTapUp], which exposes this callback.
   GestureTapUpCallback? onSecondaryTapUp;
 
+  /// {@template flutter.gestures.tap.TapGestureRecognizer.onSecondaryTapCancel}
   /// A pointer that previously triggered [onSecondaryTapDown] will not end up
   /// causing a tap.
+  /// {@endtemplate}
   ///
   /// This triggers once the gesture loses the arena if [onSecondaryTapDown]
   /// has previously been triggered.
diff --git a/framework/lib/src/gestures/velocity_tracker.dart b/framework/lib/src/gestures/velocity_tracker.dart
index 1e61fda..973e7cd 100644
--- a/framework/lib/src/gestures/velocity_tracker.dart
+++ b/framework/lib/src/gestures/velocity_tracker.dart
@@ -18,7 +18,7 @@
   /// The [pixelsPerSecond] argument must not be null.
   const Velocity({
     required this.pixelsPerSecond,
-  }) : assert(pixelsPerSecond != null);
+  });
 
   /// A velocity that isn't moving at all.
   static const Velocity zero = Velocity(pixelsPerSecond: Offset.zero);
@@ -50,8 +50,8 @@
   /// If the magnitude of this Velocity is within the specified bounds then
   /// just return this.
   Velocity clampMagnitude(double minValue, double maxValue) {
-    assert(minValue != null && minValue >= 0.0);
-    assert(maxValue != null && maxValue >= 0.0 && maxValue >= minValue);
+    assert(minValue >= 0.0);
+    assert(maxValue >= 0.0 && maxValue >= minValue);
     final double valueSquared = pixelsPerSecond.distanceSquared;
     if (valueSquared > maxValue * maxValue) {
       return Velocity(pixelsPerSecond: (pixelsPerSecond / pixelsPerSecond.distance) * maxValue);
@@ -97,10 +97,7 @@
     required this.confidence,
     required this.duration,
     required this.offset,
-  }) : assert(pixelsPerSecond != null),
-       assert(confidence != null),
-       assert(duration != null),
-       assert(offset != null);
+  });
 
   /// The number of pixels per second of velocity in the x and y directions.
   final Offset pixelsPerSecond;
@@ -124,9 +121,7 @@
 }
 
 class _PointAtTime {
-  const _PointAtTime(this.point, this.time)
-    : assert(point != null),
-      assert(time != null);
+  const _PointAtTime(this.point, this.time);
 
   final Duration time;
   final Offset point;
diff --git a/framework/lib/src/material/about.dart b/framework/lib/src/material/about.dart
index fd6b1bb..dea95b4 100644
--- a/framework/lib/src/material/about.dart
+++ b/framework/lib/src/material/about.dart
@@ -184,8 +184,6 @@
   RouteSettings? routeSettings,
   Offset? anchorPoint,
 }) {
-  assert(context != null);
-  assert(useRootNavigator != null);
   showDialog<void>(
     context: context,
     useRootNavigator: useRootNavigator,
@@ -230,8 +228,6 @@
   String? applicationLegalese,
   bool useRootNavigator = false,
 }) {
-  assert(context != null);
-  assert(useRootNavigator != null);
   Navigator.of(context, rootNavigator: useRootNavigator).push(MaterialPageRoute<void>(
     builder: (BuildContext context) => LicensePage(
       applicationName: applicationName,
@@ -486,8 +482,7 @@
     required this.version,
     this.icon,
     this.legalese,
-  })  : assert(name != null),
-        assert(version != null);
+  });
 
   final String name;
   final String version;
@@ -542,8 +537,7 @@
     required this.about,
     required this.isLateral,
     required this.selectedId,
-  })  : assert(about != null),
-        assert(isLateral != null);
+  });
 
   final Widget about;
   final bool isLateral;
@@ -571,6 +565,17 @@
           builder: (BuildContext context, BoxConstraints constraints) {
             switch (snapshot.connectionState) {
               case ConnectionState.done:
+                if (snapshot.hasError) {
+                  assert(() {
+                    FlutterError.reportError(FlutterErrorDetails(
+                      exception: snapshot.error!,
+                      stack: snapshot.stackTrace,
+                      context: ErrorDescription('while decoding the license file'),
+                    ));
+                    return true;
+                  }());
+                  return Center(child: Text(snapshot.error.toString()));
+                }
                 _initDefaultDetailPage(snapshot.data!, context);
                 return ValueListenableBuilder<int?>(
                   valueListenable: widget.selectedId,
@@ -745,7 +750,7 @@
   final List<LicenseEntry> licenseEntries;
 
   @override
-  bool operator ==(final dynamic other) {
+  bool operator ==(final Object other) {
     if (other is _DetailArguments) {
       return other.packageName == packageName;
     }
@@ -867,7 +872,8 @@
           title: _PackageLicensePageTitle(
             title,
             subtitle,
-            theme.appBarTheme.textTheme ?? theme.primaryTextTheme,
+            theme.primaryTextTheme,
+            theme.appBarTheme.titleTextStyle,
           ),
         ),
         body: Center(
@@ -899,7 +905,7 @@
             automaticallyImplyLeading: false,
             pinned: true,
             backgroundColor: theme.cardColor,
-            title: _PackageLicensePageTitle(title, subtitle, theme.textTheme),
+            title: _PackageLicensePageTitle(title, subtitle, theme.textTheme, theme.textTheme.titleLarge),
           ),
           SliverPadding(
             padding: padding,
@@ -929,21 +935,24 @@
     this.title,
     this.subtitle,
     this.theme,
+    this.titleTextStyle,
   );
 
   final String title;
   final String subtitle;
   final TextTheme theme;
+  final TextStyle? titleTextStyle;
 
   @override
   Widget build(BuildContext context) {
     final Color? color = Theme.of(context).appBarTheme.foregroundColor;
+    final TextStyle? effectiveTitleTextStyle = titleTextStyle ?? theme.titleLarge;
 
     return Column(
       mainAxisAlignment: MainAxisAlignment.center,
       crossAxisAlignment: CrossAxisAlignment.start,
       children: <Widget>[
-        Text(title, style: theme.titleLarge?.copyWith(color: color)),
+        Text(title, style: effectiveTitleTextStyle?.copyWith(color: color)),
         Text(subtitle, style: theme.titleSmall?.copyWith(color: color)),
       ],
     );
@@ -976,7 +985,7 @@
 const double _narrowGutterSize = 12.0;
 
 double _getGutterSize(BuildContext context) =>
-    MediaQuery.of(context).size.width >= _materialGutterThreshold ? _wideGutterSize : _narrowGutterSize;
+    MediaQuery.sizeOf(context).width >= _materialGutterThreshold ? _wideGutterSize : _narrowGutterSize;
 
 /// Signature for the builder callback used by [_MasterDetailFlow].
 typedef _MasterViewBuilder = Widget Function(BuildContext context, bool isLateralUI);
@@ -1033,14 +1042,11 @@
   const _MasterDetailFlow({
     required this.detailPageBuilder,
     required this.masterViewBuilder,
-    this.automaticallyImplyLeading = true,
+    this.automaticallyImplyLeading = true, // ignore: unused_element
     this.detailPageFABlessGutterWidth,
-    this.displayMode = _LayoutMode.auto,
+    this.displayMode = _LayoutMode.auto, // ignore: unused_element
     this.title,
-  })  : assert(masterViewBuilder != null),
-        assert(automaticallyImplyLeading != null),
-        assert(detailPageBuilder != null),
-        assert(displayMode != null);
+  });
 
   /// Builder for the master view for lateral navigation.
   ///
@@ -1301,8 +1307,7 @@
     this.title,
     required this.automaticallyImplyLeading,
     this.detailPageFABlessGutterWidth,
-  })  : assert(detailPageBuilder != null),
-        assert(masterViewBuilder != null);
+  });
 
   final _MasterViewBuilder masterViewBuilder;
 
@@ -1451,8 +1456,7 @@
   const _DetailView({
     required _DetailPageBuilder builder,
     Object? arguments,
-  })  : assert(builder != null),
-        _builder = builder,
+  })  : _builder = builder,
         _arguments = arguments;
 
   final _DetailPageBuilder _builder;
@@ -1463,7 +1467,7 @@
     if (_arguments == null) {
       return const SizedBox.shrink();
     }
-    final double screenHeight = MediaQuery.of(context).size.height;
+    final double screenHeight = MediaQuery.sizeOf(context).height;
     final double minHeight = (screenHeight - kToolbarHeight) / screenHeight;
 
     return DraggableScrollableSheet(
diff --git a/framework/lib/src/material/action_chip.dart b/framework/lib/src/material/action_chip.dart
index 7d3c17f..e3e30a1 100644
--- a/framework/lib/src/material/action_chip.dart
+++ b/framework/lib/src/material/action_chip.dart
@@ -20,7 +20,7 @@
 /// Action chips can be tapped to trigger an action or show progress and
 /// confirmation. For Material 3, a disabled state is supported for Action
 /// chips and is specified with [onPressed] being null. For previous versions
-/// of Material Design, it is recommended to remove the Action chip from the
+/// of Material Design, it is recommended to remove the Action chip from
 /// the interface entirely rather than display a disabled chip.
 ///
 /// Action chips are displayed after primary content, such as below a card or
@@ -86,10 +86,7 @@
     this.shadowColor,
     this.surfaceTintColor,
     this.iconTheme,
-  }) : assert(label != null),
-       assert(clipBehavior != null),
-       assert(autofocus != null),
-       assert(pressElevation == null || pressElevation >= 0.0),
+  }) : assert(pressElevation == null || pressElevation >= 0.0),
        assert(elevation == null || elevation >= 0.0);
 
   @override
@@ -178,7 +175,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _ActionChipDefaultsM3 extends ChipThemeData {
   const _ActionChipDefaultsM3(this.context, this.isEnabled)
@@ -239,7 +236,7 @@
   EdgeInsetsGeometry? get labelPadding => EdgeInsets.lerp(
     const EdgeInsets.symmetric(horizontal: 8.0),
     const EdgeInsets.symmetric(horizontal: 4.0),
-    clampDouble(MediaQuery.of(context).textScaleFactor - 1.0, 0.0, 1.0),
+    clampDouble(MediaQuery.textScaleFactorOf(context) - 1.0, 0.0, 1.0),
   )!;
 }
 
diff --git a/framework/lib/src/material/adaptive_text_selection_toolbar.dart b/framework/lib/src/material/adaptive_text_selection_toolbar.dart
index 5f9af12..5b94777 100644
--- a/framework/lib/src/material/adaptive_text_selection_toolbar.dart
+++ b/framework/lib/src/material/adaptive_text_selection_toolbar.dart
@@ -211,6 +211,8 @@
             return localizations.pasteButtonLabel;
           case ContextMenuButtonType.selectAll:
             return localizations.selectAllButtonLabel;
+          case ContextMenuButtonType.delete:
+            return localizations.deleteButtonTooltip.toUpperCase();
           case ContextMenuButtonType.custom:
             return '';
         }
@@ -218,7 +220,7 @@
   }
 
   /// Returns a List of Widgets generated by turning [buttonItems] into the
-  /// the default context menu buttons for the current platform.
+  /// default context menu buttons for the current platform.
   ///
   /// This is useful when building a text selection toolbar with the default
   /// button appearance for the given platform, but where the toolbar and/or the
diff --git a/framework/lib/src/material/animated_icons/animated_icons.dart b/framework/lib/src/material/animated_icons/animated_icons.dart
index a28f015..bc8ea27 100644
--- a/framework/lib/src/material/animated_icons/animated_icons.dart
+++ b/framework/lib/src/material/animated_icons/animated_icons.dart
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-part of material_animated_icons;
+// TODO(goderbauer): Clean up the part-of hack currently used for testing the private implementation.
+part of material_animated_icons; // ignore: use_string_in_part_of_directives
 
 // The code for drawing animated icons is kept in a private API, as we are not
 // yet ready for exposing a public API for (partial) vector graphics support.
@@ -38,8 +39,7 @@
     this.size,
     this.semanticLabel,
     this.textDirection,
-  }) : assert(progress != null),
-       assert(icon != null);
+  });
 
   /// The animation progress for the animated icon.
   ///
diff --git a/framework/lib/src/material/animated_icons/animated_icons_data.dart b/framework/lib/src/material/animated_icons/animated_icons_data.dart
index 242ba5a..6efca7d 100644
--- a/framework/lib/src/material/animated_icons/animated_icons_data.dart
+++ b/framework/lib/src/material/animated_icons/animated_icons_data.dart
@@ -8,7 +8,7 @@
 // while the _AnimatedIconData interface which used to deliver the icon data is
 // kept private.
 
-part of material_animated_icons;
+part of material_animated_icons; // ignore: use_string_in_part_of_directives
 
 /// Identifier for the supported Material Design animated icons.
 ///
diff --git a/framework/lib/src/material/animated_icons/data/add_event.g.dart b/framework/lib/src/material/animated_icons/data/add_event.g.dart
index 27305b8..88d4600 100644
--- a/framework/lib/src/material/animated_icons/data/add_event.g.dart
+++ b/framework/lib/src/material/animated_icons/data/add_event.g.dart
@@ -4,7 +4,7 @@
 
 // AUTOGENERATED FILE DO NOT EDIT!
 // This file was generated by vitool.
-part of material_animated_icons;
+part of material_animated_icons; // ignore: use_string_in_part_of_directives
 const _AnimatedIconData _$add_event = _AnimatedIconData(
   Size(48.0, 48.0),
   <_PathFrames>[
diff --git a/framework/lib/src/material/animated_icons/data/arrow_menu.g.dart b/framework/lib/src/material/animated_icons/data/arrow_menu.g.dart
index 2649d8c..549c870 100644
--- a/framework/lib/src/material/animated_icons/data/arrow_menu.g.dart
+++ b/framework/lib/src/material/animated_icons/data/arrow_menu.g.dart
@@ -4,7 +4,7 @@
 
 // AUTOGENERATED FILE DO NOT EDIT!
 // This file was generated by vitool.
-part of material_animated_icons;
+part of material_animated_icons; // ignore: use_string_in_part_of_directives
 const _AnimatedIconData _$arrow_menu = _AnimatedIconData(
   Size(48.0, 48.0),
   <_PathFrames>[
diff --git a/framework/lib/src/material/animated_icons/data/close_menu.g.dart b/framework/lib/src/material/animated_icons/data/close_menu.g.dart
index a0b86c0..311a745 100644
--- a/framework/lib/src/material/animated_icons/data/close_menu.g.dart
+++ b/framework/lib/src/material/animated_icons/data/close_menu.g.dart
@@ -4,7 +4,7 @@
 
 // AUTOGENERATED FILE DO NOT EDIT!
 // This file was generated by vitool.
-part of material_animated_icons;
+part of material_animated_icons; // ignore: use_string_in_part_of_directives
 const _AnimatedIconData _$close_menu = _AnimatedIconData(
   Size(48.0, 48.0),
   <_PathFrames>[
diff --git a/framework/lib/src/material/animated_icons/data/ellipsis_search.g.dart b/framework/lib/src/material/animated_icons/data/ellipsis_search.g.dart
index ef8802d..9f539c6 100644
--- a/framework/lib/src/material/animated_icons/data/ellipsis_search.g.dart
+++ b/framework/lib/src/material/animated_icons/data/ellipsis_search.g.dart
@@ -4,7 +4,7 @@
 
 // AUTOGENERATED FILE DO NOT EDIT!
 // This file was generated by vitool.
-part of material_animated_icons;
+part of material_animated_icons; // ignore: use_string_in_part_of_directives
 const _AnimatedIconData _$ellipsis_search = _AnimatedIconData(
   Size(96.0, 96.0),
   <_PathFrames>[
diff --git a/framework/lib/src/material/animated_icons/data/event_add.g.dart b/framework/lib/src/material/animated_icons/data/event_add.g.dart
index 8a012f2..1b64f89 100644
--- a/framework/lib/src/material/animated_icons/data/event_add.g.dart
+++ b/framework/lib/src/material/animated_icons/data/event_add.g.dart
@@ -4,7 +4,7 @@
 
 // AUTOGENERATED FILE DO NOT EDIT!
 // This file was generated by vitool.
-part of material_animated_icons;
+part of material_animated_icons; // ignore: use_string_in_part_of_directives
 const _AnimatedIconData _$event_add = _AnimatedIconData(
   Size(48.0, 48.0),
   <_PathFrames>[
diff --git a/framework/lib/src/material/animated_icons/data/home_menu.g.dart b/framework/lib/src/material/animated_icons/data/home_menu.g.dart
index 447a370..559c453 100644
--- a/framework/lib/src/material/animated_icons/data/home_menu.g.dart
+++ b/framework/lib/src/material/animated_icons/data/home_menu.g.dart
@@ -4,7 +4,7 @@
 
 // AUTOGENERATED FILE DO NOT EDIT!
 // This file was generated by vitool.
-part of material_animated_icons;
+part of material_animated_icons; // ignore: use_string_in_part_of_directives
 const _AnimatedIconData _$home_menu = _AnimatedIconData(
   Size(48.0, 48.0),
   <_PathFrames>[
diff --git a/framework/lib/src/material/animated_icons/data/list_view.g.dart b/framework/lib/src/material/animated_icons/data/list_view.g.dart
index 35814a0..25d544c 100644
--- a/framework/lib/src/material/animated_icons/data/list_view.g.dart
+++ b/framework/lib/src/material/animated_icons/data/list_view.g.dart
@@ -4,7 +4,7 @@
 
 // AUTOGENERATED FILE DO NOT EDIT!
 // This file was generated by vitool.
-part of material_animated_icons;
+part of material_animated_icons; // ignore: use_string_in_part_of_directives
 const _AnimatedIconData _$list_view = _AnimatedIconData(
   Size(48.0, 48.0),
   <_PathFrames>[
diff --git a/framework/lib/src/material/animated_icons/data/menu_arrow.g.dart b/framework/lib/src/material/animated_icons/data/menu_arrow.g.dart
index 78613e3..4717a93 100644
--- a/framework/lib/src/material/animated_icons/data/menu_arrow.g.dart
+++ b/framework/lib/src/material/animated_icons/data/menu_arrow.g.dart
@@ -4,7 +4,7 @@
 
 // AUTOGENERATED FILE DO NOT EDIT!
 // This file was generated by vitool.
-part of material_animated_icons;
+part of material_animated_icons; // ignore: use_string_in_part_of_directives
 const _AnimatedIconData _$menu_arrow = _AnimatedIconData(
   Size(48.0, 48.0),
   <_PathFrames>[
diff --git a/framework/lib/src/material/animated_icons/data/menu_close.g.dart b/framework/lib/src/material/animated_icons/data/menu_close.g.dart
index 43e194f..27d3408 100644
--- a/framework/lib/src/material/animated_icons/data/menu_close.g.dart
+++ b/framework/lib/src/material/animated_icons/data/menu_close.g.dart
@@ -4,7 +4,7 @@
 
 // AUTOGENERATED FILE DO NOT EDIT!
 // This file was generated by vitool.
-part of material_animated_icons;
+part of material_animated_icons; // ignore: use_string_in_part_of_directives
 const _AnimatedIconData _$menu_close = _AnimatedIconData(
   Size(48.0, 48.0),
   <_PathFrames>[
diff --git a/framework/lib/src/material/animated_icons/data/menu_home.g.dart b/framework/lib/src/material/animated_icons/data/menu_home.g.dart
index dfdcc79..53c3ec7 100644
--- a/framework/lib/src/material/animated_icons/data/menu_home.g.dart
+++ b/framework/lib/src/material/animated_icons/data/menu_home.g.dart
@@ -4,7 +4,7 @@
 
 // AUTOGENERATED FILE DO NOT EDIT!
 // This file was generated by vitool.
-part of material_animated_icons;
+part of material_animated_icons; // ignore: use_string_in_part_of_directives
 const _AnimatedIconData _$menu_home = _AnimatedIconData(
   Size(48.0, 48.0),
   <_PathFrames>[
diff --git a/framework/lib/src/material/animated_icons/data/pause_play.g.dart b/framework/lib/src/material/animated_icons/data/pause_play.g.dart
index b9d117e..2d9d926 100644
--- a/framework/lib/src/material/animated_icons/data/pause_play.g.dart
+++ b/framework/lib/src/material/animated_icons/data/pause_play.g.dart
@@ -4,7 +4,7 @@
 
 // AUTOGENERATED FILE DO NOT EDIT!
 // This file was generated by vitool.
-part of material_animated_icons;
+part of material_animated_icons; // ignore: use_string_in_part_of_directives
 const _AnimatedIconData _$pause_play = _AnimatedIconData(
   Size(48.0, 48.0),
   <_PathFrames>[
diff --git a/framework/lib/src/material/animated_icons/data/play_pause.g.dart b/framework/lib/src/material/animated_icons/data/play_pause.g.dart
index a850aa3..71fa193 100644
--- a/framework/lib/src/material/animated_icons/data/play_pause.g.dart
+++ b/framework/lib/src/material/animated_icons/data/play_pause.g.dart
@@ -4,7 +4,7 @@
 
 // AUTOGENERATED FILE DO NOT EDIT!
 // This file was generated by vitool.
-part of material_animated_icons;
+part of material_animated_icons; // ignore: use_string_in_part_of_directives
 const _AnimatedIconData _$play_pause = _AnimatedIconData(
   Size(48.0, 48.0),
   <_PathFrames>[
diff --git a/framework/lib/src/material/animated_icons/data/search_ellipsis.g.dart b/framework/lib/src/material/animated_icons/data/search_ellipsis.g.dart
index 93ae867..6760e2a 100644
--- a/framework/lib/src/material/animated_icons/data/search_ellipsis.g.dart
+++ b/framework/lib/src/material/animated_icons/data/search_ellipsis.g.dart
@@ -4,7 +4,7 @@
 
 // AUTOGENERATED FILE DO NOT EDIT!
 // This file was generated by vitool.
-part of material_animated_icons;
+part of material_animated_icons; // ignore: use_string_in_part_of_directives
 const _AnimatedIconData _$search_ellipsis = _AnimatedIconData(
   Size(96.0, 96.0),
   <_PathFrames>[
diff --git a/framework/lib/src/material/animated_icons/data/view_list.g.dart b/framework/lib/src/material/animated_icons/data/view_list.g.dart
index af9606b..65ec982 100644
--- a/framework/lib/src/material/animated_icons/data/view_list.g.dart
+++ b/framework/lib/src/material/animated_icons/data/view_list.g.dart
@@ -4,7 +4,7 @@
 
 // AUTOGENERATED FILE DO NOT EDIT!
 // This file was generated by vitool.
-part of material_animated_icons;
+part of material_animated_icons; // ignore: use_string_in_part_of_directives
 const _AnimatedIconData _$view_list = _AnimatedIconData(
   Size(48.0, 48.0),
   <_PathFrames>[
diff --git a/framework/lib/src/material/app.dart b/framework/lib/src/material/app.dart
index 1defb57..fb82772 100644
--- a/framework/lib/src/material/app.dart
+++ b/framework/lib/src/material/app.dart
@@ -241,17 +241,13 @@
     this.actions,
     this.restorationScopeId,
     this.scrollBehavior,
+    @Deprecated(
+      'Remove this parameter as it is now ignored. '
+      'MaterialApp never introduces its own MediaQuery; the View widget takes care of that. '
+      'This feature was deprecated after v3.7.0-29.0.pre.'
+    )
     this.useInheritedMediaQuery = false,
-  }) : assert(routes != null),
-       assert(navigatorObservers != null),
-       assert(title != null),
-       assert(debugShowMaterialGrid != null),
-       assert(showPerformanceOverlay != null),
-       assert(checkerboardRasterCacheImages != null),
-       assert(checkerboardOffscreenLayers != null),
-       assert(showSemanticsDebugger != null),
-       assert(debugShowCheckedModeBanner != null),
-       routeInformationProvider = null,
+  }) : routeInformationProvider = null,
        routeInformationParser = null,
        routerDelegate = null,
        backButtonDispatcher = null,
@@ -294,15 +290,13 @@
     this.actions,
     this.restorationScopeId,
     this.scrollBehavior,
+    @Deprecated(
+      'Remove this parameter as it is now ignored. '
+      'MaterialApp never introduces its own MediaQuery; the View widget takes care of that. '
+      'This feature was deprecated after v3.7.0-29.0.pre.'
+    )
     this.useInheritedMediaQuery = false,
   }) : assert(routerDelegate != null || routerConfig != null),
-       assert(title != null),
-       assert(debugShowMaterialGrid != null),
-       assert(showPerformanceOverlay != null),
-       assert(checkerboardRasterCacheImages != null),
-       assert(checkerboardOffscreenLayers != null),
-       assert(showSemanticsDebugger != null),
-       assert(debugShowCheckedModeBanner != null),
        navigatorObservers = null,
        navigatorKey = null,
        onGenerateRoute = null,
@@ -749,6 +743,11 @@
   final bool debugShowMaterialGrid;
 
   /// {@macro flutter.widgets.widgetsApp.useInheritedMediaQuery}
+  @Deprecated(
+    'This setting is now ignored. '
+    'MaterialApp never introduces its own MediaQuery; the View widget takes care of that. '
+    'This feature was deprecated after v3.7.0-29.0.pre.'
+  )
   final bool useInheritedMediaQuery;
 
   @override
@@ -999,7 +998,6 @@
         shortcuts: widget.shortcuts,
         actions: widget.actions,
         restorationScopeId: widget.restorationScopeId,
-        useInheritedMediaQuery: widget.useInheritedMediaQuery,
       );
     }
 
@@ -1035,7 +1033,6 @@
       shortcuts: widget.shortcuts,
       actions: widget.actions,
       restorationScopeId: widget.restorationScopeId,
-      useInheritedMediaQuery: widget.useInheritedMediaQuery,
     );
   }
 
diff --git a/framework/lib/src/material/app_bar.dart b/framework/lib/src/material/app_bar.dart
index cce53af..884b05f 100644
--- a/framework/lib/src/material/app_bar.dart
+++ b/framework/lib/src/material/app_bar.dart
@@ -11,12 +11,14 @@
 
 import 'app_bar_theme.dart';
 import 'back_button.dart';
+import 'button_style.dart';
 import 'color_scheme.dart';
 import 'colors.dart';
 import 'constants.dart';
 import 'debug.dart';
 import 'flexible_space_bar.dart';
 import 'icon_button.dart';
+import 'icon_button_theme.dart';
 import 'icons.dart';
 import 'material.dart';
 import 'material_localizations.dart';
@@ -127,7 +129,7 @@
 ///
 /// If the app bar's [actions] contains [TextButton]s, they will not
 /// be visible if their foreground (text) color is the same as the
-/// the app bar's background color.
+/// app bar's background color.
 ///
 /// The default app bar [backgroundColor] is the overall theme's
 /// [ColorScheme.primary] if the overall theme's brightness is
@@ -199,11 +201,6 @@
     this.brightness,
     this.iconTheme,
     this.actionsIconTheme,
-    @Deprecated(
-      'This property is no longer used, please use toolbarTextStyle and titleTextStyle instead. '
-      'This feature was deprecated after v2.4.0-0.0.pre.',
-    )
-    this.textTheme,
     this.primary = true,
     this.centerTitle,
     this.excludeHeaderSemantics = false,
@@ -220,12 +217,8 @@
     this.toolbarTextStyle,
     this.titleTextStyle,
     this.systemOverlayStyle,
-  }) : assert(automaticallyImplyLeading != null),
-       assert(elevation == null || elevation >= 0.0),
-       assert(notificationPredicate != null),
-       assert(primary != null),
-       assert(toolbarOpacity != null),
-       assert(bottomOpacity != null),
+    this.forceMaterialTransparency = false,
+  }) : assert(elevation == null || elevation >= 0.0),
        preferredSize = _PreferredAppBarSize(toolbarHeight, bottom?.preferredSize.height);
 
   /// Used by [Scaffold] to compute its [AppBar]'s overall height. The returned value is
@@ -593,7 +586,7 @@
   /// See also:
   ///
   ///  * [actionsIconTheme], which defines the appearance of icons in
-  ///    in the [actions] list.
+  ///    the [actions] list.
   final IconThemeData? iconTheme;
 
   /// {@template flutter.material.appbar.actionsIconTheme}
@@ -614,23 +607,6 @@
   ///  * [iconTheme], which defines the appearance of all of the toolbar icons.
   final IconThemeData? actionsIconTheme;
 
-  /// {@template flutter.material.appbar.textTheme}
-  /// This property is deprecated, please use [toolbarTextStyle] and
-  /// [titleTextStyle] instead.
-  ///
-  /// The typographic styles to use for text in the app bar. Typically this is
-  /// set along with [backgroundColor], [iconTheme].
-  ///
-  /// If this property is null, then [AppBarTheme.textTheme] of
-  /// [ThemeData.appBarTheme] is used. If that is also null, then
-  /// [ThemeData.primaryTextTheme] is used.
-  /// {@endtemplate}
-  @Deprecated(
-    'This property is no longer used, please use toolbarTextStyle and titleTextStyle instead. '
-    'This feature was deprecated after v2.4.0-0.0.pre.',
-  )
-  final TextTheme? textTheme;
-
   /// {@template flutter.material.appbar.primary}
   /// Whether this app bar is being displayed at the top of the screen.
   ///
@@ -717,7 +693,7 @@
   ///
   /// If true, preserves the original defaults for the [backgroundColor],
   /// [iconTheme], [actionsIconTheme] properties, and the original use of
-  /// the [textTheme] and [brightness] properties.
+  /// the [brightness] property.
   ///
   /// If this property is null, then [AppBarTheme.backwardsCompatibility] of
   /// [ThemeData.appBarTheme] is used. If that is also null, the default
@@ -748,7 +724,7 @@
   ///
   ///  * [titleTextStyle], which overrides the default text style for the [title].
   ///  * [DefaultTextStyle], which overrides the default text style for all of the
-  ///    the widgets in a subtree.
+  ///    widgets in a subtree.
   final TextStyle? toolbarTextStyle;
 
   /// {@template flutter.material.appbar.titleTextStyle}
@@ -766,7 +742,7 @@
   ///    [title], [leading], and [actions] widgets, also known as the
   ///    AppBar's "toolbar".
   ///  * [DefaultTextStyle], which overrides the default text style for all of the
-  ///    the widgets in a subtree.
+  ///    widgets in a subtree.
   final TextStyle? titleTextStyle;
 
   /// {@template flutter.material.appbar.systemOverlayStyle}
@@ -789,9 +765,23 @@
   ///  * [SystemChrome.setSystemUIOverlayStyle]
   final SystemUiOverlayStyle? systemOverlayStyle;
 
+  /// {@template flutter.material.appbar.forceMaterialTransparency}
+  /// Forces the AppBar's Material widget type to be [MaterialType.transparency]
+  /// (instead of Material's default type).
+  ///
+  /// This will remove the visual display of [backgroundColor] and [elevation],
+  /// and affect other characteristics of the AppBar's Material widget.
+  ///
+  /// Provided for cases where the app bar is to be transparent, and gestures
+  /// must pass through the app bar to widgets beneath the app bar (i.e. with
+  /// [Scaffold.extendBodyBehindAppBar] set to true).
+  ///
+  /// Defaults to false.
+  /// {@endtemplate}
+  final bool forceMaterialTransparency;
+
   bool _getEffectiveCenterTitle(ThemeData theme) {
     bool platformCenter() {
-      assert(theme.platform != null);
       switch (theme.platform) {
         case TargetPlatform.android:
         case TargetPlatform.fuchsia:
@@ -893,6 +883,7 @@
     assert(!widget.primary || debugCheckHasMediaQuery(context));
     assert(debugCheckHasMaterialLocalizations(context));
     final ThemeData theme = Theme.of(context);
+    final IconButtonThemeData iconButtonTheme = IconButtonTheme.of(context);
     final AppBarTheme appBarTheme = AppBarTheme.of(context);
     final AppBarTheme defaults = theme.useMaterial3 ? _AppBarDefaultsM3(context) : _AppBarDefaultsM2(context);
     final ScaffoldState? scaffold = Scaffold.maybeOf(context);
@@ -955,16 +946,16 @@
       ?? overallIconTheme;
 
     TextStyle? toolbarTextStyle = backwardsCompatibility
-      ? widget.textTheme?.bodyMedium
-        ?? appBarTheme.textTheme?.bodyMedium
+      ? widget.toolbarTextStyle
+        ?? appBarTheme.toolbarTextStyle
         ?? theme.primaryTextTheme.bodyMedium
       : widget.toolbarTextStyle
         ?? appBarTheme.toolbarTextStyle
         ?? defaults.toolbarTextStyle?.copyWith(color: foregroundColor);
 
     TextStyle? titleTextStyle = backwardsCompatibility
-      ? widget.textTheme?.titleLarge
-        ?? appBarTheme.textTheme?.titleLarge
+      ? widget.titleTextStyle
+        ?? appBarTheme.titleTextStyle
         ?? theme.primaryTextTheme.titleLarge
       : widget.titleTextStyle
         ?? appBarTheme.titleTextStyle
@@ -1003,13 +994,42 @@
       }
     }
     if (leading != null) {
-      // Based on the Material Design 3 specs, the leading IconButton should have
-      // a size of 48x48, and a highlight size of 40x40. Users can also put other
-      // type of widgets on leading with the original config.
       if (theme.useMaterial3) {
-        leading =  ConstrainedBox(
+        final IconButtonThemeData effectiveIconButtonTheme;
+
+        // This comparison is to check if there is a custom [overallIconTheme]. If true, it means that no
+        // custom [overallIconTheme] is provided, so [iconButtonTheme] is applied. Otherwise, we generate
+        // a new [IconButtonThemeData] based on the values from [overallIconTheme]. If [iconButtonTheme] only
+        // has null values, the default [overallIconTheme] will be applied below by [IconTheme.merge]
+        if (overallIconTheme == defaults.iconTheme) {
+          effectiveIconButtonTheme = iconButtonTheme;
+        } else {
+          // The [IconButton.styleFrom] method is used to generate a correct [overlayColor] based on the [foregroundColor].
+          final ButtonStyle leadingIconButtonStyle = IconButton.styleFrom(
+            foregroundColor: overallIconTheme.color,
+            iconSize: overallIconTheme.size,
+          );
+
+          effectiveIconButtonTheme = IconButtonThemeData(
+            style: iconButtonTheme.style?.copyWith(
+              foregroundColor: leadingIconButtonStyle.foregroundColor,
+              overlayColor: leadingIconButtonStyle.overlayColor,
+              iconSize: leadingIconButtonStyle.iconSize,
+            )
+          );
+        }
+
+        leading = IconButtonTheme(
+            data: effectiveIconButtonTheme,
+            child: leading is IconButton ? Center(child: leading) : leading,
+        );
+
+        // Based on the Material Design 3 specs, the leading IconButton should have
+        // a size of 48x48, and a highlight size of 40x40. Users can also put other
+        // type of widgets on leading with the original config.
+        leading = ConstrainedBox(
           constraints: BoxConstraints.tightFor(width: widget.leadingWidth ?? _kLeadingWidth),
-          child: leading is IconButton ? Center(child: leading) : leading,
+          child: leading,
         );
       } else {
         leading = ConstrainedBox(
@@ -1085,9 +1105,30 @@
 
     // Allow the trailing actions to have their own theme if necessary.
     if (actions != null) {
-      actions = IconTheme.merge(
-        data: actionsIconTheme,
-        child: actions,
+      final IconButtonThemeData effectiveActionsIconButtonTheme;
+      if (actionsIconTheme == defaults.actionsIconTheme) {
+        effectiveActionsIconButtonTheme = iconButtonTheme;
+      } else {
+        final ButtonStyle actionsIconButtonStyle = IconButton.styleFrom(
+          foregroundColor: actionsIconTheme.color,
+          iconSize: actionsIconTheme.size,
+        );
+
+        effectiveActionsIconButtonTheme = IconButtonThemeData(
+          style: iconButtonTheme.style?.copyWith(
+            foregroundColor: actionsIconButtonStyle.foregroundColor,
+            overlayColor: actionsIconButtonStyle.overlayColor,
+            iconSize: actionsIconButtonStyle.iconSize,
+          )
+        );
+      }
+
+      actions = IconButtonTheme(
+        data: effectiveActionsIconButtonTheme,
+        child: IconTheme.merge(
+          data: actionsIconTheme,
+          child: actions,
+        ),
       );
     }
 
@@ -1193,6 +1234,9 @@
         child: Material(
           color: backgroundColor,
           elevation: effectiveElevation,
+          type: widget.forceMaterialTransparency
+              ? MaterialType.transparency
+              : MaterialType.canvas,
           shadowColor: widget.shadowColor
             ?? appBarTheme.shadowColor
             ?? defaults.shadowColor,
@@ -1228,7 +1272,6 @@
     required this.brightness,
     required this.iconTheme,
     required this.actionsIconTheme,
-    required this.textTheme,
     required this.primary,
     required this.centerTitle,
     required this.excludeHeaderSemantics,
@@ -1249,11 +1292,8 @@
     required this.toolbarTextStyle,
     required this.titleTextStyle,
     required this.systemOverlayStyle,
+    required this.forceMaterialTransparency,
   }) : assert(primary || topPadding == 0.0),
-       assert(
-         !floating || (snapConfiguration == null && showOnScreenConfiguration == null) || vsync != null,
-         'vsync cannot be null when snapConfiguration or showOnScreenConfiguration is not null, and floating is true',
-       ),
        _bottomHeight = bottom?.preferredSize.height ?? 0.0;
 
   final Widget? leading;
@@ -1272,7 +1312,6 @@
   final Brightness? brightness;
   final IconThemeData? iconTheme;
   final IconThemeData? actionsIconTheme;
-  final TextTheme? textTheme;
   final bool primary;
   final bool? centerTitle;
   final bool excludeHeaderSemantics;
@@ -1290,6 +1329,7 @@
   final TextStyle? titleTextStyle;
   final SystemUiOverlayStyle? systemOverlayStyle;
   final double _bottomHeight;
+  final bool forceMaterialTransparency;
 
   @override
   double get minExtent => collapsedHeight;
@@ -1348,7 +1388,6 @@
         brightness: brightness,
         iconTheme: iconTheme,
         actionsIconTheme: actionsIconTheme,
-        textTheme: textTheme,
         primary: primary,
         centerTitle: centerTitle,
         excludeHeaderSemantics: excludeHeaderSemantics,
@@ -1362,6 +1401,7 @@
         toolbarTextStyle: toolbarTextStyle,
         titleTextStyle: titleTextStyle,
         systemOverlayStyle: systemOverlayStyle,
+        forceMaterialTransparency: forceMaterialTransparency,
       ),
     );
     return appBar;
@@ -1383,7 +1423,6 @@
         || brightness != oldDelegate.brightness
         || iconTheme != oldDelegate.iconTheme
         || actionsIconTheme != oldDelegate.actionsIconTheme
-        || textTheme != oldDelegate.textTheme
         || primary != oldDelegate.primary
         || centerTitle != oldDelegate.centerTitle
         || titleSpacing != oldDelegate.titleSpacing
@@ -1401,7 +1440,8 @@
         || backwardsCompatibility != oldDelegate.backwardsCompatibility
         || toolbarTextStyle != oldDelegate.toolbarTextStyle
         || titleTextStyle != oldDelegate.titleTextStyle
-        || systemOverlayStyle != oldDelegate.systemOverlayStyle;
+        || systemOverlayStyle != oldDelegate.systemOverlayStyle
+        || forceMaterialTransparency != oldDelegate.forceMaterialTransparency;
   }
 
   @override
@@ -1522,11 +1562,6 @@
     this.brightness,
     this.iconTheme,
     this.actionsIconTheme,
-    @Deprecated(
-      'This property is no longer used, please use toolbarTextStyle and titleTextStyle instead. '
-      'This feature was deprecated after v2.4.0-0.0.pre.',
-    )
-    this.textTheme,
     this.primary = true,
     this.centerTitle,
     this.excludeHeaderSemantics = false,
@@ -1550,15 +1585,8 @@
     this.toolbarTextStyle,
     this.titleTextStyle,
     this.systemOverlayStyle,
-  }) : assert(automaticallyImplyLeading != null),
-       assert(forceElevated != null),
-       assert(primary != null),
-       assert(floating != null),
-       assert(pinned != null),
-       assert(snap != null),
-       assert(stretch != null),
-       assert(toolbarHeight != null),
-       assert(floating || !snap, 'The "snap" argument only makes sense for floating app bars.'),
+    this.forceMaterialTransparency = false,
+  }) : assert(floating || !snap, 'The "snap" argument only makes sense for floating app bars.'),
        assert(stretchTriggerOffset > 0.0),
        assert(collapsedHeight == null || collapsedHeight >= toolbarHeight, 'The "collapsedHeight" argument has to be larger than or equal to [toolbarHeight].');
 
@@ -1628,6 +1656,7 @@
       actions: actions,
       flexibleSpace: flexibleSpace ?? _ScrollUnderFlexibleSpace(
         title: title,
+        foregroundColor: foregroundColor,
         variant: _ScrollUnderFlexibleVariant.medium,
         centerCollapsedTitle: centerTitle,
         primary: primary,
@@ -1729,6 +1758,7 @@
       actions: actions,
       flexibleSpace: flexibleSpace ?? _ScrollUnderFlexibleSpace(
         title: title,
+        foregroundColor: foregroundColor,
         variant: _ScrollUnderFlexibleVariant.large,
         centerCollapsedTitle: centerTitle,
         primary: primary,
@@ -1854,15 +1884,6 @@
   /// This property is used to configure an [AppBar].
   final IconThemeData? actionsIconTheme;
 
-  /// {@macro flutter.material.appbar.textTheme}
-  ///
-  /// This property is used to configure an [AppBar].
-  @Deprecated(
-    'This property is no longer used, please use toolbarTextStyle and titleTextStyle instead. '
-    'This feature was deprecated after v2.4.0-0.0.pre.',
-  )
-  final TextTheme? textTheme;
-
   /// {@macro flutter.material.appbar.primary}
   ///
   /// This property is used to configure an [AppBar].
@@ -2038,6 +2059,11 @@
   /// This property is used to configure an [AppBar].
   final SystemUiOverlayStyle? systemOverlayStyle;
 
+  /// {@macro flutter.material.appbar.forceMaterialTransparency}
+  ///
+  /// This property is used to configure an [AppBar].
+  final bool forceMaterialTransparency;
+
   @override
   State<SliverAppBar> createState() => _SliverAppBarState();
 }
@@ -2097,7 +2123,7 @@
   Widget build(BuildContext context) {
     assert(!widget.primary || debugCheckHasMediaQuery(context));
     final double bottomHeight = widget.bottom?.preferredSize.height ?? 0.0;
-    final double topPadding = widget.primary ? MediaQuery.of(context).padding.top : 0.0;
+    final double topPadding = widget.primary ? MediaQuery.paddingOf(context).top : 0.0;
     final double collapsedHeight = (widget.pinned && widget.floating && widget.bottom != null)
       ? (widget.collapsedHeight ?? 0.0) + bottomHeight + topPadding
       : (widget.collapsedHeight ?? widget.toolbarHeight) + bottomHeight + topPadding;
@@ -2126,7 +2152,6 @@
           brightness: widget.brightness,
           iconTheme: widget.iconTheme,
           actionsIconTheme: widget.actionsIconTheme,
-          textTheme: widget.textTheme,
           primary: widget.primary,
           centerTitle: widget.centerTitle,
           excludeHeaderSemantics: widget.excludeHeaderSemantics,
@@ -2146,6 +2171,7 @@
           toolbarTextStyle: widget.toolbarTextStyle,
           titleTextStyle: widget.titleTextStyle,
           systemOverlayStyle: widget.systemOverlayStyle,
+          forceMaterialTransparency: widget.forceMaterialTransparency,
         ),
       ),
     );
@@ -2156,7 +2182,7 @@
 // center it within its (NavigationToolbar) parent, and allow the
 // parent to constrain the title's actual height.
 class _AppBarTitleBox extends SingleChildRenderObjectWidget {
-  const _AppBarTitleBox({ required Widget super.child }) : assert(child != null);
+  const _AppBarTitleBox({ required Widget super.child });
 
   @override
   _RenderAppBarTitleBox createRenderObject(BuildContext context) {
@@ -2197,12 +2223,14 @@
 class _ScrollUnderFlexibleSpace extends StatelessWidget {
   const _ScrollUnderFlexibleSpace({
     this.title,
+    this.foregroundColor,
     required this.variant,
     this.centerCollapsedTitle,
     this.primary = true,
   });
 
   final Widget? title;
+  final Color? foregroundColor;
   final _ScrollUnderFlexibleVariant variant;
   final bool? centerCollapsedTitle;
   final bool primary;
@@ -2210,8 +2238,9 @@
   @override
   Widget build(BuildContext context) {
     late final ThemeData theme = Theme.of(context);
+    late final AppBarTheme appBarTheme = AppBarTheme.of(context);
     final FlexibleSpaceBarSettings settings = context.dependOnInheritedWidgetOfExactType<FlexibleSpaceBarSettings>()!;
-    final double topPadding = primary ? MediaQuery.of(context).viewPadding.top : 0;
+    final double topPadding = primary ? MediaQuery.viewPaddingOf(context).top : 0;
     final double collapsedHeight = settings.minExtent - topPadding;
     final double scrollUnderHeight = settings.maxExtent - settings.minExtent;
     final _ScrollUnderFlexibleConfig config;
@@ -2229,13 +2258,13 @@
     if (title != null) {
       collapsedTitle = config.collapsedTextStyle != null
         ? DefaultTextStyle(
-            style: config.collapsedTextStyle!,
+            style: config.collapsedTextStyle!.copyWith(color: foregroundColor ?? appBarTheme.foregroundColor),
             child: title!,
           )
         : title;
       expandedTitle = config.expandedTextStyle != null
         ? DefaultTextStyle(
-            style: config.expandedTextStyle!,
+            style: config.expandedTextStyle!.copyWith(color: foregroundColor ?? appBarTheme.foregroundColor),
             child: title!,
           )
         : title;
@@ -2244,7 +2273,6 @@
     late final bool centerTitle;
     {
       bool platformCenter() {
-        assert(theme.platform != null);
         switch (theme.platform) {
           case TargetPlatform.android:
           case TargetPlatform.fuchsia:
@@ -2256,9 +2284,7 @@
             return true;
         }
       }
-      centerTitle = centerCollapsedTitle
-        ?? theme.appBarTheme.centerTitle
-        ?? platformCenter();
+      centerTitle = centerCollapsedTitle ?? appBarTheme.centerTitle ?? platformCenter();
     }
 
     final bool isCollapsed = settings.isScrolledUnder ?? false;
@@ -2277,7 +2303,7 @@
                 alignment: centerTitle
                   ? Alignment.center
                   : AlignmentDirectional.centerStart,
-                child: collapsedTitle
+                child: collapsedTitle,
               ),
             ),
           ),
@@ -2346,7 +2372,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _AppBarDefaultsM3 extends AppBarTheme {
   _AppBarDefaultsM3(this.context)
diff --git a/framework/lib/src/material/app_bar_theme.dart b/framework/lib/src/material/app_bar_theme.dart
index bb4734c..0229bcd 100644
--- a/framework/lib/src/material/app_bar_theme.dart
+++ b/framework/lib/src/material/app_bar_theme.dart
@@ -8,7 +8,6 @@
 import 'package:flute/services.dart';
 import 'package:flute/widgets.dart';
 
-import 'text_theme.dart';
 import 'theme.dart';
 
 /// Overrides the default values of visual properties for descendant
@@ -43,11 +42,6 @@
     this.shape,
     this.iconTheme,
     this.actionsIconTheme,
-    @Deprecated(
-      'This property is no longer used, please use toolbarTextStyle and titleTextStyle instead. '
-      'This feature was deprecated after v2.4.0-0.0.pre.',
-    )
-    this.textTheme,
     this.centerTitle,
     this.titleSpacing,
     this.toolbarHeight,
@@ -161,24 +155,6 @@
   ///    [AppBar.foregroundColor] in all descendant [AppBar] widgets.
   final IconThemeData? actionsIconTheme;
 
-  /// This property is deprecated, please use [toolbarTextStyle] and
-  /// [titleTextStyle] instead.
-  ///
-  /// Overrides the default value of the obsolete [AppBar.textTheme]
-  /// property in all descendant [AppBar] widgets.
-  ///
-  /// See also:
-  ///
-  ///  * [toolbarTextStyle], which overrides the default value of
-  ///    [AppBar.toolbarTextStyle in all descendant [AppBar] widgets.
-  ///  * [titleTextStyle], which overrides the default value of
-  ///    [AppBar.titleTextStyle in all descendant [AppBar] widgets.
-  @Deprecated(
-    'This property is no longer used, please use toolbarTextStyle and titleTextStyle instead. '
-    'This feature was deprecated after v2.4.0-0.0.pre.',
-  )
-  final TextTheme? textTheme;
-
   /// Overrides the default value of [AppBar.centerTitle]
   /// property in all descendant [AppBar] widgets.
   final bool? centerTitle;
@@ -252,11 +228,6 @@
     Color? surfaceTintColor,
     ShapeBorder? shape,
     IconThemeData? iconTheme,
-    @Deprecated(
-      'This property is no longer used, please use toolbarTextStyle and titleTextStyle instead. '
-      'This feature was deprecated after v2.4.0-0.0.pre.',
-    )
-    TextTheme? textTheme,
     bool? centerTitle,
     double? titleSpacing,
     double? toolbarHeight,
@@ -284,7 +255,6 @@
       shape: shape ?? this.shape,
       iconTheme: iconTheme ?? this.iconTheme,
       actionsIconTheme: actionsIconTheme ?? this.actionsIconTheme,
-      textTheme: textTheme ?? this.textTheme,
       centerTitle: centerTitle ?? this.centerTitle,
       titleSpacing: titleSpacing ?? this.titleSpacing,
       toolbarHeight: toolbarHeight ?? this.toolbarHeight,
@@ -306,7 +276,6 @@
   ///
   /// {@macro dart.ui.shadow.lerp}
   static AppBarTheme lerp(AppBarTheme? a, AppBarTheme? b, double t) {
-    assert(t != null);
     return AppBarTheme(
       brightness: t < 0.5 ? a?.brightness : b?.brightness,
       backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
@@ -318,7 +287,6 @@
       shape: ShapeBorder.lerp(a?.shape, b?.shape, t),
       iconTheme: IconThemeData.lerp(a?.iconTheme, b?.iconTheme, t),
       actionsIconTheme: IconThemeData.lerp(a?.actionsIconTheme, b?.actionsIconTheme, t),
-      textTheme: TextTheme.lerp(a?.textTheme, b?.textTheme, t),
       centerTitle: t < 0.5 ? a?.centerTitle : b?.centerTitle,
       titleSpacing: lerpDouble(a?.titleSpacing, b?.titleSpacing, t),
       toolbarHeight: lerpDouble(a?.toolbarHeight, b?.toolbarHeight, t),
@@ -341,7 +309,6 @@
     shape,
     iconTheme,
     actionsIconTheme,
-    textTheme,
     centerTitle,
     titleSpacing,
     toolbarHeight,
@@ -370,7 +337,6 @@
         && other.shape == shape
         && other.iconTheme == iconTheme
         && other.actionsIconTheme == actionsIconTheme
-        && other.textTheme == textTheme
         && other.centerTitle == centerTitle
         && other.titleSpacing == titleSpacing
         && other.toolbarHeight == toolbarHeight
@@ -393,7 +359,6 @@
     properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
     properties.add(DiagnosticsProperty<IconThemeData>('iconTheme', iconTheme, defaultValue: null));
     properties.add(DiagnosticsProperty<IconThemeData>('actionsIconTheme', actionsIconTheme, defaultValue: null));
-    properties.add(DiagnosticsProperty<TextTheme>('textTheme', textTheme, defaultValue: null));
     properties.add(DiagnosticsProperty<bool>('centerTitle', centerTitle, defaultValue: null));
     properties.add(DiagnosticsProperty<double>('titleSpacing', titleSpacing, defaultValue: null));
     properties.add(DiagnosticsProperty<double>('toolbarHeight', toolbarHeight, defaultValue: null));
diff --git a/framework/lib/src/material/autocomplete.dart b/framework/lib/src/material/autocomplete.dart
index 50c7112..2e465cf 100644
--- a/framework/lib/src/material/autocomplete.dart
+++ b/framework/lib/src/material/autocomplete.dart
@@ -43,8 +43,7 @@
     this.optionsMaxHeight = 200.0,
     this.optionsViewBuilder,
     this.initialValue,
-  }) : assert(displayStringForOption != null),
-       assert(optionsBuilder != null);
+  });
 
   /// {@macro flutter.widgets.RawAutocomplete.displayStringForOption}
   final AutocompleteOptionToString<T> displayStringForOption;
diff --git a/framework/lib/src/material/back_button.dart b/framework/lib/src/material/back_button.dart
index 04cffca..3e88494 100644
--- a/framework/lib/src/material/back_button.dart
+++ b/framework/lib/src/material/back_button.dart
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'package:flute/foundation.dart';
 import 'package:flute/widgets.dart';
 
 import 'debug.dart';
@@ -27,22 +28,39 @@
   /// the current platform (as obtained from the [Theme]).
   const BackButtonIcon({ super.key });
 
-  /// Returns the appropriate "back" icon for the given `platform`.
-  static IconData _getIconData(TargetPlatform platform) {
-    switch (platform) {
+  @override
+  Widget build(BuildContext context) {
+    final String? semanticsLabel;
+    final IconData data;
+    switch (Theme.of(context).platform) {
       case TargetPlatform.android:
       case TargetPlatform.fuchsia:
       case TargetPlatform.linux:
       case TargetPlatform.windows:
-        return Icons.arrow_back;
+        data = Icons.arrow_back;
+        break;
       case TargetPlatform.iOS:
       case TargetPlatform.macOS:
-        return Icons.arrow_back_ios;
+        data = Icons.arrow_back_ios;
+        break;
     }
-  }
+    // This can't use the platform from Theme because it is the Android OS that
+    // expects the duplicated tooltip and label.
+    switch (defaultTargetPlatform) {
+      case TargetPlatform.android:
+        semanticsLabel = MaterialLocalizations.of(context).backButtonTooltip;
+        break;
+      case TargetPlatform.fuchsia:
+      case TargetPlatform.linux:
+      case TargetPlatform.windows:
+      case TargetPlatform.iOS:
+      case TargetPlatform.macOS:
+        semanticsLabel = null;
+        break;
+    }
 
-  @override
-  Widget build(BuildContext context) => Icon(_getIconData(Theme.of(context).platform));
+    return Icon(data, semanticLabel: semanticsLabel);
+  }
 }
 
 /// A Material Design back button.
@@ -149,8 +167,23 @@
   @override
   Widget build(BuildContext context) {
     assert(debugCheckHasMaterialLocalizations(context));
+    final String? semanticsLabel;
+    // This can't use the platform from Theme because it is the Android OS that
+    // expects the duplicated tooltip and label.
+    switch (defaultTargetPlatform) {
+      case TargetPlatform.android:
+        semanticsLabel = MaterialLocalizations.of(context).closeButtonTooltip;
+        break;
+      case TargetPlatform.fuchsia:
+      case TargetPlatform.linux:
+      case TargetPlatform.windows:
+      case TargetPlatform.iOS:
+      case TargetPlatform.macOS:
+        semanticsLabel = null;
+        break;
+    }
     return IconButton(
-      icon: const Icon(Icons.close),
+      icon: Icon(Icons.close, semanticLabel: semanticsLabel),
       color: color,
       tooltip: MaterialLocalizations.of(context).closeButtonTooltip,
       onPressed: () {
diff --git a/framework/lib/src/material/badge.dart b/framework/lib/src/material/badge.dart
index ffa202c..2d8d65d 100644
--- a/framework/lib/src/material/badge.dart
+++ b/framework/lib/src/material/badge.dart
@@ -193,7 +193,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _BadgeDefaultsM3 extends BadgeThemeData {
   _BadgeDefaultsM3(this.context) : super(
diff --git a/framework/lib/src/material/badge_theme.dart b/framework/lib/src/material/badge_theme.dart
index 29ee237..1b0298a 100644
--- a/framework/lib/src/material/badge_theme.dart
+++ b/framework/lib/src/material/badge_theme.dart
@@ -153,7 +153,7 @@
     super.key,
     required this.data,
     required super.child,
-  }) : assert(data != null);
+  });
 
   /// Specifies the default color and size overrides for descendant [Badge] widgets.
   final BadgeThemeData data;
diff --git a/framework/lib/src/material/banner.dart b/framework/lib/src/material/banner.dart
index 14617bb..45c19bf 100644
--- a/framework/lib/src/material/banner.dart
+++ b/framework/lib/src/material/banner.dart
@@ -106,15 +106,13 @@
     this.shadowColor,
     this.dividerColor,
     this.padding,
+    this.margin,
     this.leadingPadding,
     this.forceActionsBelow = false,
     this.overflowAlignment = OverflowBarAlignment.end,
     this.animation,
     this.onVisible,
-  }) : assert(elevation == null || elevation >= 0.0),
-       assert(content != null),
-       assert(actions != null),
-       assert(forceActionsBelow != null);
+  }) : assert(elevation == null || elevation >= 0.0);
 
   /// The content of the [MaterialBanner].
   ///
@@ -188,6 +186,12 @@
   /// `EdgeInsetsDirectional.only(start: 16.0, top: 2.0)`.
   final EdgeInsetsGeometry? padding;
 
+  /// Empty space to surround the [MaterialBanner].
+  ///
+  /// If the [margin] is null then this defaults to
+  /// 0 if the banner's [elevation] is 0, 10 otherwise.
+  final EdgeInsetsGeometry? margin;
+
   /// The amount of space by which to inset the [leading] widget.
   ///
   /// This defaults to `EdgeInsetsDirectional.only(end: 16.0)`.
@@ -240,6 +244,7 @@
       leading: leading,
       backgroundColor: backgroundColor,
       padding: padding,
+      margin: margin,
       leadingPadding: leadingPadding,
       forceActionsBelow: forceActionsBelow,
       overflowAlignment: overflowAlignment,
@@ -293,7 +298,7 @@
   @override
   Widget build(BuildContext context) {
     assert(debugCheckHasMediaQuery(context));
-    final MediaQueryData mediaQueryData = MediaQuery.of(context);
+    final bool accessibleNavigation = MediaQuery.accessibleNavigationOf(context);
 
     assert(widget.actions.isNotEmpty);
 
@@ -321,6 +326,7 @@
     );
 
     final double elevation = widget.elevation ?? bannerTheme.elevation ?? 0.0;
+    final EdgeInsetsGeometry margin = widget.margin ?? EdgeInsets.only(bottom: elevation > 0 ? 10.0 : 0.0);
     final Color backgroundColor = widget.backgroundColor
         ?? bannerTheme.backgroundColor
         ?? defaults.backgroundColor!;
@@ -337,7 +343,7 @@
         ?? defaults.contentTextStyle;
 
     Widget materialBanner = Container(
-      margin: EdgeInsets.only(bottom: elevation > 0 ? 10.0 : 0.0),
+      margin: margin,
       child: Material(
         elevation: elevation,
         color: backgroundColor,
@@ -399,7 +405,7 @@
       onDismiss: () {
         ScaffoldMessenger.of(context).removeCurrentMaterialBanner(reason: MaterialBannerClosedReason.dismiss);
       },
-      child: mediaQueryData.accessibleNavigation
+      child: accessibleNavigation
           ? materialBanner
           : SlideTransition(
         position: slideOutAnimation,
@@ -408,7 +414,7 @@
     );
 
     final Widget materialBannerTransition;
-    if (mediaQueryData.accessibleNavigation) {
+    if (accessibleNavigation) {
       materialBannerTransition = materialBanner;
     } else {
       materialBannerTransition = AnimatedBuilder(
@@ -453,7 +459,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _BannerDefaultsM3 extends MaterialBannerThemeData {
   const _BannerDefaultsM3(this.context)
diff --git a/framework/lib/src/material/banner_theme.dart b/framework/lib/src/material/banner_theme.dart
index d52edd6..0083340 100644
--- a/framework/lib/src/material/banner_theme.dart
+++ b/framework/lib/src/material/banner_theme.dart
@@ -101,7 +101,6 @@
   ///
   /// {@macro dart.ui.shadow.lerp}
   static MaterialBannerThemeData lerp(MaterialBannerThemeData? a, MaterialBannerThemeData? b, double t) {
-    assert(t != null);
     return MaterialBannerThemeData(
       backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
       surfaceTintColor: Color.lerp(a?.surfaceTintColor, b?.surfaceTintColor, t),
diff --git a/framework/lib/src/material/bottom_app_bar.dart b/framework/lib/src/material/bottom_app_bar.dart
index d37e99d..41e83cb 100644
--- a/framework/lib/src/material/bottom_app_bar.dart
+++ b/framework/lib/src/material/bottom_app_bar.dart
@@ -72,9 +72,7 @@
     this.padding,
     this.surfaceTintColor,
     this.height,
-  }) : assert(elevation == null || elevation >= 0.0),
-       assert(notchMargin != null),
-       assert(clipBehavior != null);
+  }) : assert(elevation == null || elevation >= 0.0);
 
   /// The widget below this widget in the tree.
   ///
@@ -196,10 +194,9 @@
           key: materialKey,
           type: isMaterial3 ? MaterialType.canvas : MaterialType.transparency,
           elevation: elevation,
+          color: isMaterial3 ? effectiveColor : null,
           surfaceTintColor: surfaceTintColor,
-          child: child == null
-            ? null
-            : SafeArea(child: child),
+          child: SafeArea(child: child),
         ),
       ),
     );
@@ -212,10 +209,7 @@
     required this.shape,
     required this.materialKey,
     required this.notchMargin,
-  }) : assert(geometry != null),
-       assert(shape != null),
-       assert(notchMargin != null),
-       super(reclip: geometry);
+  }) : super(reclip: geometry);
 
   final ValueListenable<ScaffoldGeometry> geometry;
   final NotchedShape shape;
@@ -275,7 +269,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _BottomAppBarDefaultsM3 extends BottomAppBarTheme {
   const _BottomAppBarDefaultsM3(this.context)
diff --git a/framework/lib/src/material/bottom_app_bar_theme.dart b/framework/lib/src/material/bottom_app_bar_theme.dart
index ff45376..e59c538 100644
--- a/framework/lib/src/material/bottom_app_bar_theme.dart
+++ b/framework/lib/src/material/bottom_app_bar_theme.dart
@@ -94,7 +94,6 @@
   ///
   /// {@macro dart.ui.shadow.lerp}
   static BottomAppBarTheme lerp(BottomAppBarTheme? a, BottomAppBarTheme? b, double t) {
-    assert(t != null);
     return BottomAppBarTheme(
       color: Color.lerp(a?.color, b?.color, t),
       elevation: lerpDouble(a?.elevation, b?.elevation, t),
diff --git a/framework/lib/src/material/bottom_navigation_bar.dart b/framework/lib/src/material/bottom_navigation_bar.dart
index 46990f9..8895478 100644
--- a/framework/lib/src/material/bottom_navigation_bar.dart
+++ b/framework/lib/src/material/bottom_navigation_bar.dart
@@ -199,21 +199,20 @@
     this.enableFeedback,
     this.landscapeLayout,
     this.useLegacyColorScheme = true,
-  }) : assert(items != null),
-       assert(items.length >= 2),
+  }) : assert(items.length >= 2),
        assert(
         items.every((BottomNavigationBarItem item) => item.label != null),
         'Every item must have a non-null label',
        ),
        assert(0 <= currentIndex && currentIndex < items.length),
        assert(elevation == null || elevation >= 0.0),
-       assert(iconSize != null && iconSize >= 0.0),
+       assert(iconSize >= 0.0),
        assert(
          selectedItemColor == null || fixedColor == null,
          'Either selectedItemColor or fixedColor can be specified, but not both',
        ),
-       assert(selectedFontSize != null && selectedFontSize >= 0.0),
-       assert(unselectedFontSize != null && unselectedFontSize >= 0.0),
+       assert(selectedFontSize >= 0.0),
+       assert(unselectedFontSize >= 0.0),
        selectedItemColor = selectedItemColor ?? fixedColor;
 
   /// Defines the appearance of the button items that are arrayed within the
@@ -421,13 +420,7 @@
     required this.mouseCursor,
     required this.enableFeedback,
     required this.layout,
-  }) : assert(type != null),
-       assert(item != null),
-       assert(animation != null),
-       assert(selected != null),
-       assert(selectedLabelStyle != null),
-       assert(unselectedLabelStyle != null),
-       assert(mouseCursor != null);
+  });
 
   final BottomNavigationBarType type;
   final BottomNavigationBarItem item;
@@ -607,8 +600,7 @@
 
   @override
   Widget build(BuildContext context) {
-    final MediaQueryData data = MediaQuery.of(context);
-    if (data.orientation == Orientation.landscape && layout == BottomNavigationBarLandscapeLayout.linear) {
+    if (MediaQuery.orientationOf(context) == Orientation.landscape && layout == BottomNavigationBarLandscapeLayout.linear) {
       return Align(
         heightFactor: 1,
         child: Row(
@@ -634,8 +626,7 @@
     required this.item,
     required this.selectedIconTheme,
     required this.unselectedIconTheme,
-  }) : assert(selected != null),
-       assert(item != null);
+  });
 
   final ColorTween colorTween;
   final Animation<double> animation;
@@ -678,13 +669,7 @@
     required this.unselectedLabelStyle,
     required this.showSelectedLabels,
     required this.showUnselectedLabels,
-  }) : assert(colorTween != null),
-       assert(animation != null),
-       assert(item != null),
-       assert(selectedLabelStyle != null),
-       assert(unselectedLabelStyle != null),
-       assert(showSelectedLabels != null),
-       assert(showUnselectedLabels != null);
+  });
 
   final ColorTween colorTween;
   final Animation<double> animation;
@@ -935,7 +920,6 @@
 
   List<Widget> _createTiles(BottomNavigationBarLandscapeLayout layout) {
     final MaterialLocalizations localizations = MaterialLocalizations.of(context);
-    assert(localizations != null);
 
     final ThemeData themeData = Theme.of(context);
     final BottomNavigationBarThemeData bottomTheme = BottomNavigationBarTheme.of(context);
@@ -1114,7 +1098,7 @@
     final BottomNavigationBarLandscapeLayout layout = widget.landscapeLayout
       ?? bottomTheme.landscapeLayout
       ?? BottomNavigationBarLandscapeLayout.spread;
-    final double additionalBottomPadding = MediaQuery.of(context).viewPadding.bottom;
+    final double additionalBottomPadding = MediaQuery.viewPaddingOf(context).bottom;
 
     Color? backgroundColor;
     switch (_effectiveType) {
@@ -1180,14 +1164,13 @@
 
   @override
   Widget build(BuildContext context) {
-    final MediaQueryData data = MediaQuery.of(context);
     Widget alignedChild = child;
-    if (data.orientation == Orientation.landscape && layout == BottomNavigationBarLandscapeLayout.centered) {
+    if (MediaQuery.orientationOf(context) == Orientation.landscape && layout == BottomNavigationBarLandscapeLayout.centered) {
       alignedChild = Align(
         alignment: Alignment.bottomCenter,
         heightFactor: 1,
         child: SizedBox(
-          width: data.size.height,
+          width: MediaQuery.sizeOf(context).height,
           child: child,
         ),
       );
@@ -1207,9 +1190,7 @@
     required this.index,
     required this.color,
     required TickerProvider vsync,
-  }) : assert(state != null),
-       assert(index != null),
-       assert(color != null) {
+  }) {
     controller = AnimationController(
       duration: kThemeAnimationDuration,
       vsync: vsync,
@@ -1252,8 +1233,7 @@
   _RadialPainter({
     required this.circles,
     required this.textDirection,
-  }) : assert(circles != null),
-       assert(textDirection != null);
+  });
 
   final List<_Circle> circles;
   final TextDirection textDirection;
diff --git a/framework/lib/src/material/bottom_navigation_bar_theme.dart b/framework/lib/src/material/bottom_navigation_bar_theme.dart
index e4e6ac9..7d150ef 100644
--- a/framework/lib/src/material/bottom_navigation_bar_theme.dart
+++ b/framework/lib/src/material/bottom_navigation_bar_theme.dart
@@ -174,7 +174,6 @@
   ///
   /// {@macro dart.ui.shadow.lerp}
   static BottomNavigationBarThemeData lerp(BottomNavigationBarThemeData? a, BottomNavigationBarThemeData? b, double t) {
-    assert(t != null);
     return BottomNavigationBarThemeData(
       backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
       elevation: lerpDouble(a?.elevation, b?.elevation, t),
@@ -280,7 +279,7 @@
     super.key,
     required this.data,
     required super.child,
-  }) : assert(data != null);
+  });
 
   /// The properties used for all descendant [BottomNavigationBar] widgets.
   final BottomNavigationBarThemeData data;
diff --git a/framework/lib/src/material/bottom_sheet.dart b/framework/lib/src/material/bottom_sheet.dart
index 1ba592f..887d7e2 100644
--- a/framework/lib/src/material/bottom_sheet.dart
+++ b/framework/lib/src/material/bottom_sheet.dart
@@ -5,6 +5,7 @@
 import 'package:engine/ui.dart' show lerpDouble;
 
 import 'package:flute/foundation.dart';
+import 'package:flute/rendering.dart';
 import 'package:flute/widgets.dart';
 
 import 'bottom_sheet_theme.dart';
@@ -83,10 +84,7 @@
     this.constraints,
     required this.onClosing,
     required this.builder,
-  }) : assert(enableDrag != null),
-       assert(onClosing != null),
-       assert(builder != null),
-       assert(elevation == null || elevation >= 0.0);
+  }) : assert(elevation == null || elevation >= 0.0);
 
   /// The animation controller that controls the bottom sheet's entrance and
   /// exit animations.
@@ -319,16 +317,130 @@
 
 // See scaffold.dart
 
+typedef _SizeChangeCallback<Size> = void Function(Size);
 
-// MODAL BOTTOM SHEETS
-class _ModalBottomSheetLayout extends SingleChildLayoutDelegate {
-  _ModalBottomSheetLayout(this.progress, this.isScrollControlled);
+class _BottomSheetLayoutWithSizeListener extends SingleChildRenderObjectWidget {
 
-  final double progress;
+  const _BottomSheetLayoutWithSizeListener({
+    required this.animationValue,
+    required this.isScrollControlled,
+    required this.onChildSizeChanged,
+    super.child,
+  });
+
+  final double animationValue;
   final bool isScrollControlled;
+  final _SizeChangeCallback<Size> onChildSizeChanged;
 
   @override
-  BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
+  _RenderBottomSheetLayoutWithSizeListener createRenderObject(BuildContext context) {
+    return _RenderBottomSheetLayoutWithSizeListener(
+      animationValue: animationValue,
+      isScrollControlled: isScrollControlled,
+      onChildSizeChanged: onChildSizeChanged,
+    );
+  }
+
+  @override
+  void updateRenderObject(BuildContext context, _RenderBottomSheetLayoutWithSizeListener renderObject) {
+    renderObject.onChildSizeChanged = onChildSizeChanged;
+    renderObject.animationValue = animationValue;
+    renderObject.isScrollControlled = isScrollControlled;
+  }
+}
+
+class _RenderBottomSheetLayoutWithSizeListener extends RenderShiftedBox {
+  _RenderBottomSheetLayoutWithSizeListener({
+    RenderBox? child,
+    required _SizeChangeCallback<Size> onChildSizeChanged,
+    required double animationValue,
+    required bool isScrollControlled,
+  }) : _animationValue = animationValue,
+       _isScrollControlled = isScrollControlled,
+       _onChildSizeChanged = onChildSizeChanged,
+       super(child);
+
+  Size _lastSize = Size.zero;
+
+  _SizeChangeCallback<Size> get onChildSizeChanged => _onChildSizeChanged;
+  _SizeChangeCallback<Size> _onChildSizeChanged;
+    set onChildSizeChanged(_SizeChangeCallback<Size> newCallback) {
+    if (_onChildSizeChanged == newCallback) {
+      return;
+    }
+
+    _onChildSizeChanged = newCallback;
+    markNeedsLayout();
+  }
+
+  double get animationValue => _animationValue;
+  double _animationValue;
+  set animationValue(double newValue) {
+    if (_animationValue == newValue) {
+      return;
+    }
+
+    _animationValue = newValue;
+    markNeedsLayout();
+  }
+
+  bool get isScrollControlled => _isScrollControlled;
+  bool _isScrollControlled;
+  set isScrollControlled(bool newValue) {
+    if (_isScrollControlled == newValue) {
+      return;
+    }
+
+    _isScrollControlled = newValue;
+    markNeedsLayout();
+  }
+
+  Size _getSize(BoxConstraints constraints) {
+    return constraints.constrain(constraints.biggest);
+  }
+
+  @override
+  double computeMinIntrinsicWidth(double height) {
+    final double width = _getSize(BoxConstraints.tightForFinite(height: height)).width;
+    if (width.isFinite) {
+      return width;
+    }
+    return 0.0;
+  }
+
+  @override
+  double computeMaxIntrinsicWidth(double height) {
+    final double width = _getSize(BoxConstraints.tightForFinite(height: height)).width;
+    if (width.isFinite) {
+      return width;
+    }
+    return 0.0;
+  }
+
+  @override
+  double computeMinIntrinsicHeight(double width) {
+    final double height = _getSize(BoxConstraints.tightForFinite(width: width)).height;
+    if (height.isFinite) {
+      return height;
+    }
+    return 0.0;
+  }
+
+  @override
+  double computeMaxIntrinsicHeight(double width) {
+    final double height = _getSize(BoxConstraints.tightForFinite(width: width)).height;
+    if (height.isFinite) {
+      return height;
+    }
+    return 0.0;
+  }
+
+  @override
+  Size computeDryLayout(BoxConstraints constraints) {
+    return _getSize(constraints);
+  }
+
+    BoxConstraints _getConstraintsForChild(BoxConstraints constraints) {
     return BoxConstraints(
       minWidth: constraints.maxWidth,
       maxWidth: constraints.maxWidth,
@@ -338,14 +450,26 @@
     );
   }
 
-  @override
-  Offset getPositionForChild(Size size, Size childSize) {
-    return Offset(0.0, size.height - childSize.height * progress);
+  Offset _getPositionForChild(Size size, Size childSize) {
+    return Offset(0.0, size.height - childSize.height * animationValue);
   }
 
   @override
-  bool shouldRelayout(_ModalBottomSheetLayout oldDelegate) {
-    return progress != oldDelegate.progress;
+  void performLayout() {
+    size = _getSize(constraints);
+    if (child != null) {
+      final BoxConstraints childConstraints = _getConstraintsForChild(constraints);
+      assert(childConstraints.debugAssertIsValid(isAppliedConstraint: true));
+      child!.layout(childConstraints, parentUsesSize: !childConstraints.isTight);
+      final BoxParentData childParentData = child!.parentData! as BoxParentData;
+      childParentData.offset = _getPositionForChild(size, childConstraints.isTight ? childConstraints.smallest : child!.size);
+      final Size childSize = childConstraints.isTight ? childConstraints.smallest : child!.size;
+
+      if (_lastSize != childSize) {
+        _lastSize = childSize;
+        _onChildSizeChanged.call(_lastSize);
+      }
+    }
   }
 }
 
@@ -360,8 +484,7 @@
     this.constraints,
     this.isScrollControlled = false,
     this.enableDrag = true,
-  }) : assert(isScrollControlled != null),
-       assert(enableDrag != null);
+  });
 
   final ModalBottomSheetRoute<T> route;
   final bool isScrollControlled;
@@ -392,6 +515,10 @@
     }
   }
 
+  EdgeInsets _getNewClipDetails(Size topLayerSize) {
+    return EdgeInsets.fromLTRB(0, 0, 0, topLayerSize.height);
+  }
+
   void handleDragStart(DragStartDetails details) {
     // Allow the bottom sheet to track the user's finger accurately.
     animationCurve = Curves.linear;
@@ -409,7 +536,6 @@
   Widget build(BuildContext context) {
     assert(debugCheckHasMediaQuery(context));
     assert(debugCheckHasMaterialLocalizations(context));
-    final MediaQueryData mediaQuery = MediaQuery.of(context);
     final MaterialLocalizations localizations = MaterialLocalizations.of(context);
     final String routeLabel = _getRouteLabel(localizations);
 
@@ -436,7 +562,7 @@
         // Disable the initial animation when accessible navigation is on so
         // that the semantics are added to the tree at the correct time.
         final double animationValue = animationCurve.transform(
-            mediaQuery.accessibleNavigation ? 1.0 : widget.route.animation!.value,
+            MediaQuery.accessibleNavigationOf(context) ? 1.0 : widget.route.animation!.value,
         );
         return Semantics(
           scopesRoute: true,
@@ -444,8 +570,14 @@
           label: routeLabel,
           explicitChildNodes: true,
           child: ClipRect(
-            child: CustomSingleChildLayout(
-              delegate: _ModalBottomSheetLayout(animationValue, widget.isScrollControlled),
+            child: _BottomSheetLayoutWithSizeListener(
+              onChildSizeChanged: (Size size) {
+                widget.route._didChangeBarrierSemanticsClip(
+                  _getNewClipDetails(size),
+                );
+              },
+              animationValue: animationValue,
+              isScrollControlled: widget.isScrollControlled,
               child: child,
             ),
           ),
@@ -517,6 +649,7 @@
     required this.builder,
     this.capturedThemes,
     this.barrierLabel,
+    this.barrierOnTapHint,
     this.backgroundColor,
     this.elevation,
     this.shape,
@@ -530,9 +663,7 @@
     this.transitionAnimationController,
     this.anchorPoint,
     this.useSafeArea = false,
-  }) : assert(isScrollControlled != null),
-       assert(isDismissible != null),
-       assert(enableDrag != null);
+  });
 
   /// A builder for the contents of the sheet.
   ///
@@ -647,6 +778,35 @@
   /// Default is false.
   final bool useSafeArea;
 
+  /// {@template flutter.material.ModalBottomSheetRoute.barrierOnTapHint}
+  /// 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
+  /// announcement of 'Double tap to activate'.
+  /// {@endtemplate}
+  ///
+  /// See also:
+  ///
+  ///  * [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;
+
+  final ValueNotifier<EdgeInsets> _clipDetailsNotifier = ValueNotifier<EdgeInsets>(EdgeInsets.zero);
+
+  /// Updates the details regarding how the [SemanticsNode.rect] (focus) of
+  /// the barrier for this [ModalBottomSheetRoute] should be clipped.
+  ///
+  /// returns true if the clipDetails did change and false otherwise.
+  bool _didChangeBarrierSemanticsClip(EdgeInsets newClipDetails) {
+    if (_clipDetailsNotifier.value == newClipDetails) {
+      return false;
+    }
+    _clipDetailsNotifier.value = newClipDetails;
+    return true;
+  }
+
   @override
   Duration get transitionDuration => _bottomSheetEnterDuration;
 
@@ -711,6 +871,35 @@
 
     return capturedThemes?.wrap(bottomSheet) ?? bottomSheet;
   }
+
+  @override
+  Widget buildModalBarrier() {
+    if (barrierColor.alpha != 0 && !offstage) { // changedInternalState is called if barrierColor or offstage updates
+      assert(barrierColor != barrierColor.withOpacity(0.0));
+      final Animation<Color?> 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,
+      );
+    }
+  }
 }
 
 // TODO(guidezpl): Look into making this public. A copy of this class is in
@@ -736,15 +925,14 @@
   const _BottomSheetSuspendedCurve(
     this.startingPoint, {
     this.curve = Curves.easeOutCubic,
-  }) : assert(startingPoint != null),
-       assert(curve != null);
+  });
 
   /// The progress value at which [curve] should begin.
-  ///
-  /// This defaults to [Curves.easeOutCubic].
   final double startingPoint;
 
   /// The curve to use when [startingPoint] is reached.
+  ///
+  /// This defaults to [Curves.easeOutCubic].
   final Curve curve;
 
   @override
@@ -835,21 +1023,17 @@
   AnimationController? transitionAnimationController,
   Offset? anchorPoint,
 }) {
-  assert(context != null);
-  assert(builder != null);
-  assert(isScrollControlled != null);
-  assert(useRootNavigator != null);
-  assert(isDismissible != null);
-  assert(enableDrag != null);
   assert(debugCheckHasMediaQuery(context));
   assert(debugCheckHasMaterialLocalizations(context));
 
   final NavigatorState navigator = Navigator.of(context, rootNavigator: useRootNavigator);
+  final MaterialLocalizations localizations = MaterialLocalizations.of(context);
   return navigator.push(ModalBottomSheetRoute<T>(
     builder: builder,
     capturedThemes: InheritedTheme.capture(from: context, to: navigator.context),
     isScrollControlled: isScrollControlled,
-    barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
+    barrierLabel: localizations.scrimLabel,
+    barrierOnTapHint: localizations.scrimOnTapHint(localizations.bottomSheetLabel),
     backgroundColor: backgroundColor,
     elevation: elevation,
     shape: shape,
@@ -920,8 +1104,6 @@
   bool? enableDrag,
   AnimationController? transitionAnimationController,
 }) {
-  assert(context != null);
-  assert(builder != null);
   assert(debugCheckHasScaffold(context));
 
   return Scaffold.of(context).showBottomSheet<T>(
@@ -945,7 +1127,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _BottomSheetDefaultsM3 extends BottomSheetThemeData {
    const _BottomSheetDefaultsM3(this.context)
diff --git a/framework/lib/src/material/bottom_sheet_theme.dart b/framework/lib/src/material/bottom_sheet_theme.dart
index 1c52523..c0ebc22 100644
--- a/framework/lib/src/material/bottom_sheet_theme.dart
+++ b/framework/lib/src/material/bottom_sheet_theme.dart
@@ -118,7 +118,6 @@
   ///
   /// {@macro dart.ui.shadow.lerp}
   static BottomSheetThemeData? lerp(BottomSheetThemeData? a, BottomSheetThemeData? b, double t) {
-    assert(t != null);
     if (a == null && b == null) {
       return null;
     }
diff --git a/framework/lib/src/material/button.dart b/framework/lib/src/material/button.dart
index 41b6ff0..3ee3642 100644
--- a/framework/lib/src/material/button.dart
+++ b/framework/lib/src/material/button.dart
@@ -74,17 +74,11 @@
     this.child,
     this.enableFeedback = true,
   }) : materialTapTargetSize = materialTapTargetSize ?? MaterialTapTargetSize.padded,
-       assert(shape != null),
-       assert(elevation != null && elevation >= 0.0),
-       assert(focusElevation != null && focusElevation >= 0.0),
-       assert(hoverElevation != null && hoverElevation >= 0.0),
-       assert(highlightElevation != null && highlightElevation >= 0.0),
-       assert(disabledElevation != null && disabledElevation >= 0.0),
-       assert(padding != null),
-       assert(constraints != null),
-       assert(animationDuration != null),
-       assert(clipBehavior != null),
-       assert(autofocus != null);
+       assert(elevation >= 0.0),
+       assert(focusElevation >= 0.0),
+       assert(hoverElevation >= 0.0),
+       assert(highlightElevation >= 0.0),
+       assert(disabledElevation >= 0.0);
 
   /// Called when the button is tapped or otherwise activated.
   ///
diff --git a/framework/lib/src/material/button_bar.dart b/framework/lib/src/material/button_bar.dart
index 4542083..069c285 100644
--- a/framework/lib/src/material/button_bar.dart
+++ b/framework/lib/src/material/button_bar.dart
@@ -233,7 +233,7 @@
 class _ButtonBarRow extends Flex {
   /// Creates a button bar that attempts to display in a row, but displays in
   /// a column if there is insufficient horizontal space.
-  _ButtonBarRow({
+  const _ButtonBarRow({
     required super.children,
     super.mainAxisSize,
     super.mainAxisAlignment,
@@ -300,8 +300,7 @@
     super.verticalDirection,
     super.textBaseline,
     this.overflowButtonSpacing,
-  }) : assert(textDirection != null),
-       assert(overflowButtonSpacing == null || overflowButtonSpacing >= 0);
+  }) : assert(overflowButtonSpacing == null || overflowButtonSpacing >= 0);
 
   bool _hasCheckedLayoutWidth = false;
   double? overflowButtonSpacing;
diff --git a/framework/lib/src/material/button_bar_theme.dart b/framework/lib/src/material/button_bar_theme.dart
index 2efbcdd..20df2ae 100644
--- a/framework/lib/src/material/button_bar_theme.dart
+++ b/framework/lib/src/material/button_bar_theme.dart
@@ -146,7 +146,6 @@
   ///
   /// {@macro dart.ui.shadow.lerp}
   static ButtonBarThemeData? lerp(ButtonBarThemeData? a, ButtonBarThemeData? b, double t) {
-    assert(t != null);
     if (a == null && b == null) {
       return null;
     }
@@ -240,7 +239,7 @@
     super.key,
     required this.data,
     required super.child,
-  }) : assert(data != null);
+  });
 
   /// The properties used for all descendant [ButtonBar] widgets.
   final ButtonBarThemeData data;
diff --git a/framework/lib/src/material/button_style.dart b/framework/lib/src/material/button_style.dart
index b15cba5..18cf679 100644
--- a/framework/lib/src/material/button_style.dart
+++ b/framework/lib/src/material/button_style.dart
@@ -492,7 +492,6 @@
 
   /// Linearly interpolate between two [ButtonStyle]s.
   static ButtonStyle? lerp(ButtonStyle? a, ButtonStyle? b, double t) {
-    assert (t != null);
     if (a == null && b == null) {
       return null;
     }
diff --git a/framework/lib/src/material/button_style_button.dart b/framework/lib/src/material/button_style_button.dart
index 0d975eb..eafdde4 100644
--- a/framework/lib/src/material/button_style_button.dart
+++ b/framework/lib/src/material/button_style_button.dart
@@ -43,8 +43,7 @@
     required this.clipBehavior,
     this.statesController,
     required this.child,
-  }) : assert(autofocus != null),
-       assert(clipBehavior != null);
+  });
 
   /// Called when the button is tapped or otherwise activated.
   ///
@@ -175,10 +174,6 @@
     EdgeInsetsGeometry geometry3x,
     double textScaleFactor,
   ) {
-    assert(geometry1x != null);
-    assert(geometry2x != null);
-    assert(geometry3x != null);
-    assert(textScaleFactor != null);
 
     if (textScaleFactor <= 1) {
       return geometry1x;
@@ -260,7 +255,6 @@
     final ButtonStyle? widgetStyle = widget.style;
     final ButtonStyle? themeStyle = widget.themeStyleOf(context);
     final ButtonStyle defaultStyle = widget.defaultStyleOf(context);
-    assert(defaultStyle != null);
 
     T? effectiveValue<T>(T? Function(ButtonStyle? style) getProperty) {
       final T? widgetValue  = getProperty(widgetStyle);
diff --git a/framework/lib/src/material/button_theme.dart b/framework/lib/src/material/button_theme.dart
index dae7eaf..7e38bf1 100644
--- a/framework/lib/src/material/button_theme.dart
+++ b/framework/lib/src/material/button_theme.dart
@@ -87,11 +87,8 @@
     ColorScheme? colorScheme,
     MaterialTapTargetSize? materialTapTargetSize,
     required super.child,
-  }) : assert(textTheme != null),
-       assert(minWidth != null && minWidth >= 0.0),
-       assert(height != null && height >= 0.0),
-       assert(alignedDropdown != null),
-       assert(layoutBehavior != null),
+  }) : assert(minWidth >= 0.0),
+       assert(height >= 0.0),
        data = ButtonThemeData(
          textTheme: textTheme,
          minWidth: minWidth,
@@ -117,7 +114,7 @@
     super.key,
     required this.data,
     required super.child,
-  }) : assert(data != null);
+  });
 
   /// Specifies the color and geometry of buttons.
   final ButtonThemeData data;
@@ -194,11 +191,8 @@
     Color? splashColor,
     this.colorScheme,
     MaterialTapTargetSize? materialTapTargetSize,
-  }) : assert(textTheme != null),
-       assert(minWidth != null && minWidth >= 0.0),
-       assert(height != null && height >= 0.0),
-       assert(alignedDropdown != null),
-       assert(layoutBehavior != null),
+  }) : assert(minWidth >= 0.0),
+       assert(height >= 0.0),
        _buttonColor = buttonColor,
        _disabledColor = disabledColor,
        _focusColor = focusColor,
@@ -235,7 +229,7 @@
   /// Defaults to [ButtonBarLayoutBehavior.padded].
   final ButtonBarLayoutBehavior layoutBehavior;
 
-  /// Simply a convenience that returns [minWidth] and [height] as a
+  /// Convenience that returns [minWidth] and [height] as a
   /// [BoxConstraints] object.
   BoxConstraints get constraints {
     return BoxConstraints(
@@ -382,13 +376,12 @@
   /// A set of thirteen colors that can be used to derive the button theme's
   /// colors.
   ///
-  /// This property was added much later than the theme's set of highly
-  /// specific colors, like [ThemeData.buttonColor], [ThemeData.highlightColor],
-  /// [ThemeData.splashColor] etc.
+  /// This property was added much later than the theme's set of highly specific
+  /// colors, like [ThemeData.highlightColor] and [ThemeData.splashColor] etc.
   ///
-  /// The colors for new button classes can be defined exclusively in terms
-  /// of [colorScheme]. When it's possible, the existing buttons will
-  /// (continue to) gradually migrate to it.
+  /// The colors for new button classes can be defined exclusively in terms of
+  /// [colorScheme]. When it's possible, the existing buttons will (continue to)
+  /// gradually migrate to it.
   final ColorScheme? colorScheme;
 
   // The minimum size of a button's tap target.
diff --git a/framework/lib/src/material/calendar_date_picker.dart b/framework/lib/src/material/calendar_date_picker.dart
index cfe617e..754fa2e 100644
--- a/framework/lib/src/material/calendar_date_picker.dart
+++ b/framework/lib/src/material/calendar_date_picker.dart
@@ -11,12 +11,14 @@
 
 import 'color_scheme.dart';
 import 'date.dart';
+import 'date_picker_theme.dart';
 import 'debug.dart';
 import 'divider.dart';
 import 'icon_button.dart';
 import 'icons.dart';
 import 'ink_well.dart';
 import 'material_localizations.dart';
+import 'material_state.dart';
 import 'text_theme.dart';
 import 'theme.dart';
 
@@ -93,15 +95,10 @@
     this.onDisplayedMonthChanged,
     this.initialCalendarMode = DatePickerMode.day,
     this.selectableDayPredicate,
-  }) : assert(initialDate != null),
-       assert(firstDate != null),
-       assert(lastDate != null),
-       initialDate = DateUtils.dateOnly(initialDate),
+  }) : initialDate = DateUtils.dateOnly(initialDate),
        firstDate = DateUtils.dateOnly(firstDate),
        lastDate = DateUtils.dateOnly(lastDate),
-       currentDate = DateUtils.dateOnly(currentDate ?? DateTime.now()),
-       assert(onDateChanged != null),
-       assert(initialCalendarMode != null) {
+       currentDate = DateUtils.dateOnly(currentDate ?? DateTime.now()) {
     assert(
       !this.lastDate.isBefore(this.firstDate),
       'lastDate ${this.lastDate} must be on or after firstDate ${this.firstDate}.',
@@ -188,8 +185,10 @@
     _textDirection = Directionality.of(context);
     if (!_announcedInitialDate) {
       _announcedInitialDate = true;
+      final bool isToday = DateUtils.isSameDay(widget.currentDate, _selectedDate);
+      final String semanticLabelSuffix = isToday ? ', ${_localizations.currentDateLabel}' : '';
       SemanticsService.announce(
-        _localizations.formatFullDate(_selectedDate),
+        '${_localizations.formatFullDate(_selectedDate)}$semanticLabelSuffix',
         _textDirection,
       );
     }
@@ -282,7 +281,7 @@
             firstDate: widget.firstDate,
             lastDate: widget.lastDate,
             initialDate: _currentDisplayedMonthDate,
-            selectedDate: _selectedDate,
+            selectedDate: _currentDisplayedMonthDate,
             onChanged: _handleYearChanged,
           ),
         );
@@ -440,12 +439,7 @@
     required this.onChanged,
     required this.onDisplayedMonthChanged,
     this.selectableDayPredicate,
-  }) : assert(selectedDate != null),
-       assert(currentDate != null),
-       assert(onChanged != null),
-       assert(firstDate != null),
-       assert(lastDate != null),
-       assert(!firstDate.isAfter(lastDate)),
+  }) : assert(!firstDate.isAfter(lastDate)),
        assert(!selectedDate.isBefore(firstDate)),
        assert(!selectedDate.isAfter(lastDate));
 
@@ -827,13 +821,7 @@
     required this.selectedDate,
     required this.onChanged,
     this.selectableDayPredicate,
-  }) : assert(currentDate != null),
-       assert(displayedMonth != null),
-       assert(firstDate != null),
-       assert(lastDate != null),
-       assert(selectedDate != null),
-       assert(onChanged != null),
-       assert(!firstDate.isAfter(lastDate)),
+  }) : assert(!firstDate.isAfter(lastDate)),
        assert(!selectedDate.isBefore(firstDate)),
        assert(!selectedDate.isAfter(lastDate));
 
@@ -934,18 +922,11 @@
 
   @override
   Widget build(BuildContext context) {
-    final ColorScheme colorScheme = Theme.of(context).colorScheme;
     final MaterialLocalizations localizations = MaterialLocalizations.of(context);
-    final TextTheme textTheme = Theme.of(context).textTheme;
-    final TextStyle? headerStyle = textTheme.bodySmall?.apply(
-      color: colorScheme.onSurface.withOpacity(0.60),
-    );
-    final TextStyle dayStyle = textTheme.bodySmall!;
-    final Color enabledDayColor = colorScheme.onSurface.withOpacity(0.87);
-    final Color disabledDayColor = colorScheme.onSurface.withOpacity(0.38);
-    final Color selectedDayColor = colorScheme.onPrimary;
-    final Color selectedDayBackground = colorScheme.primary;
-    final Color todayColor = colorScheme.primary;
+    final DatePickerThemeData datePickerTheme = DatePickerTheme.of(context);
+    final DatePickerThemeData defaults = DatePickerTheme.defaults(context);
+    final TextStyle? weekdayStyle = datePickerTheme.weekdayStyle ?? defaults.weekdayStyle;
+    final TextStyle? dayStyle = datePickerTheme.dayStyle ?? defaults.dayStyle;
 
     final int year = widget.displayedMonth.year;
     final int month = widget.displayedMonth.month;
@@ -953,7 +934,19 @@
     final int daysInMonth = DateUtils.getDaysInMonth(year, month);
     final int dayOffset = DateUtils.firstDayOffset(year, month, localizations);
 
-    final List<Widget> dayItems = _dayHeaders(headerStyle, localizations);
+    T? effectiveValue<T>(T? Function(DatePickerThemeData? theme) getProperty) {
+      return getProperty(datePickerTheme) ?? getProperty(defaults);
+    }
+
+    T? resolve<T>(MaterialStateProperty<T>? Function(DatePickerThemeData? theme) getProperty, Set<MaterialState> states) {
+      return effectiveValue(
+        (DatePickerThemeData? theme) {
+          return getProperty(theme)?.resolve(states);
+        },
+      );
+    }
+
+    final List<Widget> dayItems = _dayHeaders(weekdayStyle, localizations);
     // 1-based day of month, e.g. 1-31 for January, and 1-29 for February on
     // a leap year.
     int day = -dayOffset;
@@ -963,42 +956,42 @@
         dayItems.add(Container());
       } else {
         final DateTime dayToBuild = DateTime(year, month, day);
-        final bool isDisabled = dayToBuild.isAfter(widget.lastDate) ||
-            dayToBuild.isBefore(widget.firstDate) ||
-            (widget.selectableDayPredicate != null && !widget.selectableDayPredicate!(dayToBuild));
+        final bool isDisabled =
+          dayToBuild.isAfter(widget.lastDate) ||
+          dayToBuild.isBefore(widget.firstDate) ||
+          (widget.selectableDayPredicate != null && !widget.selectableDayPredicate!(dayToBuild));
         final bool isSelectedDay = DateUtils.isSameDay(widget.selectedDate, dayToBuild);
         final bool isToday = DateUtils.isSameDay(widget.currentDate, dayToBuild);
+        final String semanticLabelSuffix = isToday ? ', ${localizations.currentDateLabel}' : '';
 
-        BoxDecoration? decoration;
-        Color dayColor = enabledDayColor;
-        if (isSelectedDay) {
-          // The selected day gets a circle background highlight, and a
-          // contrasting text color.
-          dayColor = selectedDayColor;
-          decoration = BoxDecoration(
-            color: selectedDayBackground,
-            shape: BoxShape.circle,
-          );
-        } else if (isToday) {
-          // The current day gets a different text color (if enabled) and a circle stroke
-          // border.
-          if (isDisabled) {
-            dayColor = disabledDayColor;
-          } else {
-            dayColor = todayColor;
-          }
-          decoration = BoxDecoration(
-            border: Border.all(color: dayColor),
-            shape: BoxShape.circle,
-          );
-        } else if (isDisabled) {
-          dayColor = disabledDayColor;
-        }
+        final Set<MaterialState> states = <MaterialState>{
+          if (isDisabled) MaterialState.disabled,
+          if (isSelectedDay) MaterialState.selected,
+        };
+
+        final Color? dayForegroundColor = resolve<Color?>((DatePickerThemeData? theme) => isToday ? theme?.todayForegroundColor : theme?.dayForegroundColor, states);
+        final Color? dayBackgroundColor = resolve<Color?>((DatePickerThemeData? theme) => isToday ? theme?.todayBackgroundColor : theme?.dayBackgroundColor, states);
+        final MaterialStateProperty<Color?> dayOverlayColor = MaterialStateProperty.resolveWith<Color?>(
+          (Set<MaterialState> states) => effectiveValue((DatePickerThemeData? theme) => theme?.dayOverlayColor?.resolve(states)),
+        );
+        final BoxDecoration decoration = isToday
+          ? BoxDecoration(
+              color: dayBackgroundColor,
+              border: Border.fromBorderSide(
+                (datePickerTheme.todayBorder ?? defaults.todayBorder!)
+                  .copyWith(color: dayForegroundColor)
+              ),
+              shape: BoxShape.circle,
+            )
+          : BoxDecoration(
+              color: dayBackgroundColor,
+              shape: BoxShape.circle,
+            );
 
         Widget dayWidget = Container(
           decoration: decoration,
           child: Center(
-            child: Text(localizations.formatDecimal(day), style: dayStyle.apply(color: dayColor)),
+            child: Text(localizations.formatDecimal(day), style: dayStyle?.apply(color: dayForegroundColor)),
           ),
         );
 
@@ -1011,7 +1004,8 @@
             focusNode: _dayFocusNodes[day - 1],
             onTap: () => widget.onChanged(dayToBuild),
             radius: _dayPickerRowHeight / 2 + 4,
-            splashColor: selectedDayBackground.withOpacity(0.38),
+            statesController: MaterialStatesController(states),
+            overlayColor: dayOverlayColor,
             child: Semantics(
               // We want the day of month to be spoken first irrespective of the
               // locale-specific preferences or TextDirection. This is because
@@ -1019,7 +1013,7 @@
               // day of month before the rest of the date, as they are looking
               // for the day of month. To do that we prepend day of month to the
               // formatted full date.
-              label: '${localizations.formatDecimal(day)}, ${localizations.formatFullDate(dayToBuild)}',
+              label: '${localizations.formatDecimal(day)}, ${localizations.formatFullDate(dayToBuild)}$semanticLabelSuffix',
               selected: isSelectedDay,
               excludeSemantics: true,
               child: dayWidget,
@@ -1101,11 +1095,7 @@
     required this.selectedDate,
     required this.onChanged,
     this.dragStartBehavior = DragStartBehavior.start,
-  }) : assert(firstDate != null),
-       assert(lastDate != null),
-       assert(selectedDate != null),
-       assert(onChanged != null),
-       assert(!firstDate.isAfter(lastDate)),
+  }) : assert(!firstDate.isAfter(lastDate)),
        currentDate = DateUtils.dateOnly(currentDate ?? DateTime.now()),
        initialDate = DateUtils.dateOnly(initialDate ?? selectedDate);
 
@@ -1167,8 +1157,20 @@
   }
 
   Widget _buildYearItem(BuildContext context, int index) {
-    final ColorScheme colorScheme = Theme.of(context).colorScheme;
-    final TextTheme textTheme = Theme.of(context).textTheme;
+    final DatePickerThemeData datePickerTheme = DatePickerTheme.of(context);
+    final DatePickerThemeData defaults = DatePickerTheme.defaults(context);
+
+    T? effectiveValue<T>(T? Function(DatePickerThemeData? theme) getProperty) {
+      return getProperty(datePickerTheme) ?? getProperty(defaults);
+    }
+
+    T? resolve<T>(MaterialStateProperty<T>? Function(DatePickerThemeData? theme) getProperty, Set<MaterialState> states) {
+      return effectiveValue(
+        (DatePickerThemeData? theme) {
+          return getProperty(theme)?.resolve(states);
+        },
+      );
+    }
 
     // Backfill the _YearPicker with disabled years if necessary.
     final int offset = _itemCount < minYears ? (minYears - _itemCount) ~/ 2 : 0;
@@ -1179,33 +1181,32 @@
     const double decorationHeight = 36.0;
     const double decorationWidth = 72.0;
 
-    final Color textColor;
-    if (isSelected) {
-      textColor = colorScheme.onPrimary;
-    } else if (isDisabled) {
-      textColor = colorScheme.onSurface.withOpacity(0.38);
-    } else if (isCurrentYear) {
-      textColor = colorScheme.primary;
-    } else {
-      textColor = colorScheme.onSurface.withOpacity(0.87);
-    }
-    final TextStyle? itemStyle = textTheme.bodyLarge?.apply(color: textColor);
+    final Set<MaterialState> states = <MaterialState>{
+      if (isDisabled) MaterialState.disabled,
+      if (isSelected) MaterialState.selected,
+    };
 
-    BoxDecoration? decoration;
-    if (isSelected) {
-      decoration = BoxDecoration(
-        color: colorScheme.primary,
-        borderRadius: BorderRadius.circular(decorationHeight / 2),
+    final Color? textColor = resolve<Color?>((DatePickerThemeData? theme) => isCurrentYear ? theme?.todayForegroundColor : theme?.yearForegroundColor, states);
+    final Color? background = resolve<Color?>((DatePickerThemeData? theme) => isCurrentYear ? theme?.todayBackgroundColor : theme?.yearBackgroundColor, states);
+    final MaterialStateProperty<Color?> overlayColor =
+      MaterialStateProperty.resolveWith<Color?>((Set<MaterialState> states) =>
+        effectiveValue((DatePickerThemeData? theme) => theme?.dayOverlayColor?.resolve(states)),
       );
-    } else if (isCurrentYear && !isDisabled) {
-      decoration = BoxDecoration(
-        border: Border.all(
-          color: colorScheme.primary,
-        ),
-        borderRadius: BorderRadius.circular(decorationHeight / 2),
-      );
-    }
 
+    BoxBorder? border;
+    if (isCurrentYear) {
+      final BorderSide? todayBorder = datePickerTheme.todayBorder ?? defaults.todayBorder;
+      if (todayBorder != null) {
+        border = Border.fromBorderSide(todayBorder.copyWith(color: textColor));
+      }
+    }
+    final BoxDecoration decoration = BoxDecoration(
+      border: border,
+      color: background,
+      borderRadius: BorderRadius.circular(decorationHeight / 2),
+    );
+
+    final TextStyle? itemStyle = (datePickerTheme.yearStyle ?? defaults.yearStyle)?.apply(color: textColor);
     Widget yearItem = Center(
       child: Container(
         decoration: decoration,
@@ -1229,6 +1230,8 @@
       yearItem = InkWell(
         key: ValueKey<int>(year),
         onTap: () => widget.onChanged(DateTime(year, widget.initialDate.month)),
+        statesController: MaterialStatesController(states),
+        overlayColor: overlayColor,
         child: yearItem,
       );
     }
diff --git a/framework/lib/src/material/card.dart b/framework/lib/src/material/card.dart
index 00ef5a7..998f4e4 100644
--- a/framework/lib/src/material/card.dart
+++ b/framework/lib/src/material/card.dart
@@ -71,15 +71,15 @@
     this.clipBehavior,
     this.child,
     this.semanticContainer = true,
-  }) : assert(elevation == null || elevation >= 0.0),
-       assert(borderOnForeground != null);
+  }) : assert(elevation == null || elevation >= 0.0);
 
   /// The card's background color.
   ///
   /// Defines the card's [Material.color].
   ///
-  /// If this property is null then [CardTheme.color] of [ThemeData.cardTheme]
-  /// is used. If that's null then [ThemeData.cardColor] is used.
+  /// If this property is null then the ambient [CardTheme.color] is used. If that is null,
+  /// and [ThemeData.useMaterial3] is true, then [ColorScheme.surface] of
+  /// [ThemeData.colorScheme] is used. Otherwise, [ThemeData.cardColor] is used.
   final Color? color;
 
   /// The color to paint the shadow below the card.
@@ -214,7 +214,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _CardDefaultsM3 extends CardTheme {
   const _CardDefaultsM3(this.context)
diff --git a/framework/lib/src/material/card_theme.dart b/framework/lib/src/material/card_theme.dart
index aa6f80e..db849ee 100644
--- a/framework/lib/src/material/card_theme.dart
+++ b/framework/lib/src/material/card_theme.dart
@@ -114,7 +114,6 @@
   ///
   /// {@macro dart.ui.shadow.lerp}
   static CardTheme lerp(CardTheme? a, CardTheme? b, double t) {
-    assert(t != null);
     return CardTheme(
       clipBehavior: t < 0.5 ? a?.clipBehavior : b?.clipBehavior,
       color: Color.lerp(a?.color, b?.color, t),
diff --git a/framework/lib/src/material/checkbox.dart b/framework/lib/src/material/checkbox.dart
index 3f83fec..d4e8346 100644
--- a/framework/lib/src/material/checkbox.dart
+++ b/framework/lib/src/material/checkbox.dart
@@ -34,7 +34,7 @@
 ///
 /// {@tool dartpad}
 /// This example shows how you can override the default theme of
-/// of a [Checkbox] with a [MaterialStateProperty].
+/// a [Checkbox] with a [MaterialStateProperty].
 /// In this example, the checkbox's color will be `Colors.blue` when the [Checkbox]
 /// is being pressed, hovered, or focused. Otherwise, the checkbox's color will
 /// be `Colors.red`.
@@ -88,9 +88,7 @@
     this.shape,
     this.side,
     this.isError = false,
-  }) : assert(tristate != null),
-       assert(tristate || value != null),
-       assert(autofocus != null);
+  }) : assert(tristate || value != null);
 
   /// Whether this checkbox is checked.
   ///
@@ -321,6 +319,7 @@
   ///  * [MaterialState.hovered].
   ///  * [MaterialState.focused].
   ///  * [MaterialState.disabled].
+  ///  * [MaterialState.error].
   ///
   /// If this property is not a [MaterialStateBorderSide] and it is
   /// non-null, then it is only rendered when the checkbox's value is
@@ -396,7 +395,8 @@
 
   BorderSide? _resolveSide(BorderSide? side) {
     if (side is MaterialStateBorderSide) {
-      return MaterialStateProperty.resolveAs<BorderSide?>(side, states);
+      final Set<MaterialState> sideStates = widget.isError ? (states..add(MaterialState.error)) : states;
+      return MaterialStateProperty.resolveAs<BorderSide?>(side, sideStates);
     }
     if (!states.contains(MaterialState.selected)) {
       return side;
@@ -764,7 +764,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _CheckboxDefaultsM3 extends CheckboxThemeData {
   _CheckboxDefaultsM3(BuildContext context)
diff --git a/framework/lib/src/material/checkbox_list_tile.dart b/framework/lib/src/material/checkbox_list_tile.dart
index 8040099..97f25c7 100644
--- a/framework/lib/src/material/checkbox_list_tile.dart
+++ b/framework/lib/src/material/checkbox_list_tile.dart
@@ -50,7 +50,7 @@
 ///
 /// {@tool snippet}
 /// ```dart
-/// Container(
+/// ColoredBox(
 ///   color: Colors.green,
 ///   child: Material(
 ///     child: CheckboxListTile(
@@ -85,6 +85,13 @@
 /// ** See code in examples/api/lib/material/checkbox_list_tile/checkbox_list_tile.0.dart **
 /// {@end-tool}
 ///
+/// {@tool dartpad}
+/// This sample demonstrates how [CheckboxListTile] positions the checkbox widget
+/// relative to the text in different configurations.
+///
+/// ** See code in examples/api/lib/material/checkbox_list_tile/checkbox_list_tile.1.dart **
+/// {@end-tool}
+///
 /// ## Semantics in CheckboxListTile
 ///
 /// Since the entirety of the CheckboxListTile is interactive, it should represent
@@ -109,7 +116,7 @@
 /// LinkedLabelCheckbox, that includes an interactive [RichText] widget that
 /// handles tap gestures.
 ///
-/// ** See code in examples/api/lib/material/checkbox_list_tile/checkbox_list_tile.1.dart **
+/// ** See code in examples/api/lib/material/checkbox_list_tile/custom_labeled_checkbox.0.dart **
 /// {@end-tool}
 ///
 /// ## CheckboxListTile isn't exactly what I want
@@ -125,7 +132,7 @@
 /// Here is an example of a custom LabeledCheckbox widget, but you can easily
 /// make your own configurable widget.
 ///
-/// ** See code in examples/api/lib/material/checkbox_list_tile/checkbox_list_tile.2.dart **
+/// ** See code in examples/api/lib/material/checkbox_list_tile/custom_labeled_checkbox.1.dart **
 /// {@end-tool}
 ///
 /// See also:
@@ -178,13 +185,8 @@
     this.focusNode,
     this.onFocusChange,
     this.enableFeedback,
-  }) : assert(tristate != null),
-       assert(tristate || value != null),
-       assert(isThreeLine != null),
-       assert(!isThreeLine || subtitle != null),
-       assert(selected != null),
-       assert(controlAffinity != null),
-       assert(autofocus != null);
+  }) : assert(tristate || value != null),
+       assert(!isThreeLine || subtitle != null);
 
   /// Whether this checkbox is checked.
   final bool? value;
@@ -219,7 +221,7 @@
 
   /// The color to use when this checkbox is checked.
   ///
-  /// Defaults to accent color of the current [Theme].
+  /// Defaults to [ColorScheme.secondary] of the current [Theme].
   final Color? activeColor;
 
   /// The color to use for the check icon when this checkbox is checked.
diff --git a/framework/lib/src/material/checkbox_theme.dart b/framework/lib/src/material/checkbox_theme.dart
index 807cd5f..7d99ecd 100644
--- a/framework/lib/src/material/checkbox_theme.dart
+++ b/framework/lib/src/material/checkbox_theme.dart
@@ -192,10 +192,10 @@
 
   // Special case because BorderSide.lerp() doesn't support null arguments
   static BorderSide? _lerpSides(BorderSide? a, BorderSide? b, double t) {
-    if (a == null && b == null) {
+    if (a == null || b == null) {
       return null;
     }
-    return BorderSide.lerp(a!, b!, t);
+    return BorderSide.lerp(a, b, t);
   }
 }
 
diff --git a/framework/lib/src/material/chip.dart b/framework/lib/src/material/chip.dart
index 2d0907e..e6c40cf 100644
--- a/framework/lib/src/material/chip.dart
+++ b/framework/lib/src/material/chip.dart
@@ -593,10 +593,7 @@
       'This feature was deprecated after v2.10.0-0.3.pre.'
     )
     this.useDeleteButtonTooltip = true,
-  }) : assert(label != null),
-       assert(autofocus != null),
-       assert(clipBehavior != null),
-       assert(elevation == null || elevation >= 0.0);
+  }) : assert(elevation == null || elevation >= 0.0);
 
   @override
   final Widget? avatar;
@@ -766,12 +763,7 @@
       'This feature was deprecated after v2.10.0-0.3.pre.'
     )
     this.useDeleteButtonTooltip = true,
-  }) : assert(label != null),
-       assert(isEnabled != null),
-       assert(selected != null),
-       assert(clipBehavior != null),
-       assert(autofocus != null),
-       assert(pressElevation == null || pressElevation >= 0.0),
+  }) : assert(pressElevation == null || pressElevation >= 0.0),
        assert(elevation == null || elevation >= 0.0),
        deleteIcon = deleteIcon ?? _kDefaultDeleteIcon;
 
@@ -1158,7 +1150,7 @@
     final EdgeInsetsGeometry defaultLabelPadding = EdgeInsets.lerp(
       const EdgeInsets.symmetric(horizontal: 8.0),
       const EdgeInsets.symmetric(horizontal: 4.0),
-      clampDouble(MediaQuery.of(context).textScaleFactor - 1.0, 0.0, 1.0),
+      clampDouble(MediaQuery.textScaleFactorOf(context) - 1.0, 0.0, 1.0),
     )!;
 
     final ThemeData theme = Theme.of(context);
@@ -1381,7 +1373,7 @@
     required this.deleteDrawerAnimation,
     required this.enableAnimation,
     this.avatarBorder,
-  }) : assert(theme != null);
+  });
 
   final _ChipRenderTheme theme;
   final bool? value;
@@ -1518,9 +1510,7 @@
     required this.deleteDrawerAnimation,
     required this.enableAnimation,
     this.avatarBorder,
-  }) : assert(theme != null),
-       assert(textDirection != null),
-       _theme = theme,
+  }) : _theme = theme,
        _textDirection = textDirection {
     checkmarkAnimation.addListener(markNeedsPaint);
     avatarDrawerAnimation.addListener(markNeedsLayout);
@@ -1917,7 +1907,7 @@
   );
 
   Color get _disabledColor {
-    if (enableAnimation == null || enableAnimation.isCompleted) {
+    if (enableAnimation.isCompleted) {
       return Colors.white;
     }
     final ColorTween enableTween;
@@ -2196,7 +2186,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _ChipDefaultsM3 extends ChipThemeData {
   const _ChipDefaultsM3(this.context, this.isEnabled)
@@ -2257,7 +2247,7 @@
   EdgeInsetsGeometry? get labelPadding => EdgeInsets.lerp(
     const EdgeInsets.symmetric(horizontal: 8.0),
     const EdgeInsets.symmetric(horizontal: 4.0),
-    clampDouble(MediaQuery.of(context).textScaleFactor - 1.0, 0.0, 1.0),
+    clampDouble(MediaQuery.textScaleFactorOf(context) - 1.0, 0.0, 1.0),
   )!;
 }
 
diff --git a/framework/lib/src/material/chip_theme.dart b/framework/lib/src/material/chip_theme.dart
index 3583fc4..63e65bc 100644
--- a/framework/lib/src/material/chip_theme.dart
+++ b/framework/lib/src/material/chip_theme.dart
@@ -47,8 +47,7 @@
     super.key,
     required this.data,
     required super.child,
-  }) : assert(child != null),
-       assert(data != null);
+  });
 
   /// Specifies the color, shape, and text style values for descendant chip
   /// widgets.
@@ -225,8 +224,6 @@
   }) {
     assert(primaryColor != null || brightness != null, 'One of primaryColor or brightness must be specified');
     assert(primaryColor == null || brightness == null, 'Only one of primaryColor or brightness may be specified');
-    assert(secondaryColor != null);
-    assert(labelStyle != null);
 
     if (primaryColor != null) {
       brightness = ThemeData.estimateBrightnessForColor(primaryColor);
@@ -486,7 +483,6 @@
   ///
   /// {@macro dart.ui.shadow.lerp}
   static ChipThemeData? lerp(ChipThemeData? a, ChipThemeData? b, double t) {
-    assert(t != null);
     if (a == null && b == null) {
       return null;
     }
diff --git a/framework/lib/src/material/choice_chip.dart b/framework/lib/src/material/choice_chip.dart
index aaf6965..9bd44bd 100644
--- a/framework/lib/src/material/choice_chip.dart
+++ b/framework/lib/src/material/choice_chip.dart
@@ -83,11 +83,7 @@
     this.iconTheme,
     this.selectedShadowColor,
     this.avatarBorder = const CircleBorder(),
-  }) : assert(selected != null),
-       assert(label != null),
-       assert(clipBehavior != null),
-       assert(autofocus != null),
-       assert(pressElevation == null || pressElevation >= 0.0),
+  }) : assert(pressElevation == null || pressElevation >= 0.0),
        assert(elevation == null || elevation >= 0.0);
 
   @override
@@ -191,7 +187,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _ChoiceChipDefaultsM3 extends ChipThemeData {
   const _ChoiceChipDefaultsM3(this.context, this.isEnabled, this.isSelected)
@@ -212,7 +208,7 @@
   Color? get backgroundColor => null;
 
   @override
-  Color? get shadowColor => Theme.of(context).colorScheme.shadow;
+  Color? get shadowColor => Colors.transparent;
 
   @override
   Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;
@@ -259,7 +255,7 @@
   EdgeInsetsGeometry? get labelPadding => EdgeInsets.lerp(
     const EdgeInsets.symmetric(horizontal: 8.0),
     const EdgeInsets.symmetric(horizontal: 4.0),
-    clampDouble(MediaQuery.of(context).textScaleFactor - 1.0, 0.0, 1.0),
+    clampDouble(MediaQuery.textScaleFactorOf(context) - 1.0, 0.0, 1.0),
   )!;
 }
 
diff --git a/framework/lib/src/material/color_scheme.dart b/framework/lib/src/material/color_scheme.dart
index 68e8f2e..2e55a26 100644
--- a/framework/lib/src/material/color_scheme.dart
+++ b/framework/lib/src/material/color_scheme.dart
@@ -9,9 +9,11 @@
 import 'colors.dart';
 import 'theme_data.dart';
 
+/// {@template flutter.material.color_scheme.ColorScheme}
 /// A set of 30 colors based on the
 /// [Material spec](https://m3.material.io/styles/color/the-color-system/color-roles)
 /// that can be used to configure the color properties of most components.
+/// {@endtemplate}
 ///
 /// The main accent color groups in the scheme are [primary], [secondary],
 /// and [tertiary].
@@ -117,18 +119,7 @@
       'This feature was deprecated after v2.6.0-0.0.pre.'
     )
     Color? secondaryVariant,
-  }) : assert(brightness != null),
-       assert(primary != null),
-       assert(onPrimary != null),
-       assert(secondary != null),
-       assert(onSecondary != null),
-       assert(error != null),
-       assert(onError != null),
-       assert(background != null),
-       assert(onBackground != null),
-       assert(surface != null),
-       assert(onSurface != null),
-       _primaryContainer = primaryContainer,
+  }) : _primaryContainer = primaryContainer,
        _onPrimaryContainer = onPrimaryContainer,
        _secondaryContainer = secondaryContainer,
        _onSecondaryContainer = onSecondaryContainer,
@@ -295,18 +286,7 @@
       'This feature was deprecated after v2.6.0-0.0.pre.'
     )
     Color? secondaryVariant = const Color(0xff018786),
-  }) : assert(brightness != null),
-       assert(primary != null),
-       assert(onPrimary != null),
-       assert(secondary != null),
-       assert(onSecondary != null),
-       assert(error != null),
-       assert(onError != null),
-       assert(background != null),
-       assert(onBackground != null),
-       assert(surface != null),
-       assert(onSurface != null),
-       _primaryContainer = primaryContainer,
+  }) : _primaryContainer = primaryContainer,
        _onPrimaryContainer = onPrimaryContainer,
        _secondaryContainer = secondaryContainer,
        _onSecondaryContainer = onSecondaryContainer,
@@ -373,18 +353,7 @@
       'This feature was deprecated after v2.6.0-0.0.pre.'
     )
     Color? secondaryVariant = const Color(0xff03dac6),
-  }) : assert(brightness != null),
-       assert(primary != null),
-       assert(onPrimary != null),
-       assert(secondary != null),
-       assert(onSecondary != null),
-       assert(error != null),
-       assert(onError != null),
-       assert(background != null),
-       assert(onBackground != null),
-       assert(surface != null),
-       assert(onSurface != null),
-       _primaryContainer = primaryContainer,
+  }) : _primaryContainer = primaryContainer,
        _onPrimaryContainer = onPrimaryContainer,
        _secondaryContainer = secondaryContainer,
        _onSecondaryContainer = onSecondaryContainer,
@@ -451,18 +420,7 @@
       'This feature was deprecated after v2.6.0-0.0.pre.'
     )
     Color? secondaryVariant = const Color(0xff018786),
-  }) : assert(brightness != null),
-       assert(primary != null),
-       assert(onPrimary != null),
-       assert(secondary != null),
-       assert(onSecondary != null),
-       assert(error != null),
-       assert(onError != null),
-       assert(background != null),
-       assert(onBackground != null),
-       assert(surface != null),
-       assert(onSurface != null),
-       _primaryContainer = primaryContainer,
+  }) : _primaryContainer = primaryContainer,
        _onPrimaryContainer = onPrimaryContainer,
        _secondaryContainer = secondaryContainer,
        _onSecondaryContainer = onSecondaryContainer,
@@ -529,18 +487,7 @@
       'This feature was deprecated after v2.6.0-0.0.pre.'
     )
     Color? secondaryVariant = const Color(0xff66fff9),
-  }) : assert(brightness != null),
-       assert(primary != null),
-       assert(onPrimary != null),
-       assert(secondary != null),
-       assert(onSecondary != null),
-       assert(error != null),
-       assert(onError != null),
-       assert(background != null),
-       assert(onBackground != null),
-       assert(surface != null),
-       assert(onSurface != null),
-       _primaryContainer = primaryContainer,
+  }) : _primaryContainer = primaryContainer,
        _onPrimaryContainer = onPrimaryContainer,
        _secondaryContainer = secondaryContainer,
        _onSecondaryContainer = onSecondaryContainer,
@@ -576,8 +523,6 @@
     Color? errorColor,
     Brightness brightness = Brightness.light,
   }) {
-    assert(primarySwatch != null);
-    assert(brightness != null);
 
     final bool isDark = brightness == Brightness.dark;
     final bool primaryIsDark = _brightnessFor(primarySwatch) == Brightness.dark;
diff --git a/framework/lib/src/material/data_table.dart b/framework/lib/src/material/data_table.dart
index c790a70..ba4f434 100644
--- a/framework/lib/src/material/data_table.dart
+++ b/framework/lib/src/material/data_table.dart
@@ -44,7 +44,7 @@
     this.tooltip,
     this.numeric = false,
     this.onSort,
-  }) : assert(label != null);
+  });
 
   /// The column heading.
   ///
@@ -107,7 +107,7 @@
     this.onLongPress,
     this.color,
     required this.cells,
-  }) : assert(cells != null);
+  });
 
   /// Creates the configuration for a row of a [DataTable], deriving
   /// the key from a row index.
@@ -120,8 +120,7 @@
     this.onLongPress,
     this.color,
     required this.cells,
-  }) : assert(cells != null),
-       key = ValueKey<int?>(index);
+  }) : key = ValueKey<int?>(index);
 
   /// A [Key] that uniquely identifies this row. This is used to
   /// ensure that if a row is added or removed, any stateful widgets
@@ -234,7 +233,7 @@
     this.onTapDown,
     this.onDoubleTap,
     this.onTapCancel,
-  }) : assert(child != null);
+  });
 
   /// A cell that has no content and has zero width and height.
   static const DataCell empty = DataCell(SizedBox.shrink());
@@ -407,15 +406,10 @@
     this.checkboxHorizontalMargin,
     this.border,
     this.clipBehavior = Clip.none,
-  }) : assert(columns != null),
-       assert(columns.isNotEmpty),
+  }) : assert(columns.isNotEmpty),
        assert(sortColumnIndex == null || (sortColumnIndex >= 0 && sortColumnIndex < columns.length)),
-       assert(sortAscending != null),
-       assert(showCheckboxColumn != null),
-       assert(rows != null),
        assert(!rows.any((DataRow row) => row.cells.length != columns.length)),
        assert(dividerThickness == null || dividerThickness >= 0),
-       assert(clipBehavior != null),
        _onlyTextColumn = _initOnlyTextColumn(columns);
 
   /// The configuration and labels for the columns in the table.
@@ -973,7 +967,7 @@
     int displayColumnIndex = 0;
     if (displayCheckboxColumn) {
       tableColumns[0] = FixedColumnWidth(effectiveCheckboxHorizontalMarginStart + Checkbox.width + effectiveCheckboxHorizontalMarginEnd);
-      tableRows[0].children![0] = _buildCheckbox(
+      tableRows[0].children[0] = _buildCheckbox(
         context: context,
         checked: someChecked ? null : allChecked,
         onRowTap: null,
@@ -983,7 +977,7 @@
       );
       rowIndex = 1;
       for (final DataRow row in rows) {
-        tableRows[rowIndex].children![0] = _buildCheckbox(
+        tableRows[rowIndex].children[0] = _buildCheckbox(
           context: context,
           checked: row.selected,
           onRowTap: row.onSelectChanged == null ? null : () => row.onSelectChanged?.call(!row.selected),
@@ -1026,7 +1020,7 @@
       } else {
         tableColumns[displayColumnIndex] = const IntrinsicColumnWidth();
       }
-      tableRows[0].children![displayColumnIndex] = _buildHeadingCell(
+      tableRows[0].children[displayColumnIndex] = _buildHeadingCell(
         context: context,
         padding: padding,
         label: column.label,
@@ -1040,7 +1034,7 @@
       rowIndex = 1;
       for (final DataRow row in rows) {
         final DataCell cell = row.cells[dataColumnIndex];
-        tableRows[rowIndex].children![displayColumnIndex] = _buildDataCell(
+        tableRows[rowIndex].children[displayColumnIndex] = _buildDataCell(
           context: context,
           padding: padding,
           label: cell.child,
diff --git a/framework/lib/src/material/data_table_theme.dart b/framework/lib/src/material/data_table_theme.dart
index 5f8d741..1ff4b55 100644
--- a/framework/lib/src/material/data_table_theme.dart
+++ b/framework/lib/src/material/data_table_theme.dart
@@ -122,7 +122,6 @@
   ///
   /// {@macro dart.ui.shadow.lerp}
   static DataTableThemeData lerp(DataTableThemeData a, DataTableThemeData b, double t) {
-    assert(t != null);
     return DataTableThemeData(
       decoration: Decoration.lerp(a.decoration, b.decoration, t),
       dataRowColor: MaterialStateProperty.lerp<Color?>(a.dataRowColor, b.dataRowColor, t, Color.lerp),
@@ -214,7 +213,7 @@
     super.key,
     required this.data,
     required super.child,
-  }) : assert(data != null);
+  });
 
   /// The properties used for all descendant [DataTable] widgets.
   final DataTableThemeData data;
diff --git a/framework/lib/src/material/date.dart b/framework/lib/src/material/date.dart
index a06c921..5186c48 100644
--- a/framework/lib/src/material/date.dart
+++ b/framework/lib/src/material/date.dart
@@ -212,9 +212,7 @@
   DateTimeRange({
     required this.start,
     required this.end,
-  }) : assert(start != null),
-       assert(end != null),
-       assert(!start.isAfter(end));
+  }) : assert(!start.isAfter(end));
 
   /// The start of the range of dates.
   final DateTime start;
diff --git a/framework/lib/src/material/date_picker.dart b/framework/lib/src/material/date_picker.dart
index 553979f..e9e0c90 100644
--- a/framework/lib/src/material/date_picker.dart
+++ b/framework/lib/src/material/date_picker.dart
@@ -4,16 +4,18 @@
 
 import 'dart:math' as math;
 
-import 'package:flute/gestures.dart' show DragStartBehavior;
 import 'package:flute/rendering.dart';
 import 'package:flute/services.dart';
 import 'package:flute/widgets.dart';
 
 import 'app_bar.dart';
 import 'back_button.dart';
+import 'button_style.dart';
 import 'calendar_date_picker.dart';
 import 'color_scheme.dart';
+import 'colors.dart';
 import 'date.dart';
+import 'date_picker_theme.dart';
 import 'debug.dart';
 import 'dialog.dart';
 import 'dialog_theme.dart';
@@ -26,15 +28,20 @@
 import 'input_decorator.dart';
 import 'material.dart';
 import 'material_localizations.dart';
+import 'material_state.dart';
 import 'scaffold.dart';
 import 'text_button.dart';
 import 'text_field.dart';
 import 'text_theme.dart';
 import 'theme.dart';
 
-const Size _calendarPortraitDialogSize = Size(330.0, 518.0);
+// The M3 sizes are coming from the tokens, but are hand coded,
+// as the current token DB does not contain landscape versions.
+const Size _calendarPortraitDialogSizeM2 = Size(330.0, 518.0);
+const Size _calendarPortraitDialogSizeM3 = Size(328.0, 512.0);
 const Size _calendarLandscapeDialogSize = Size(496.0, 346.0);
-const Size _inputPortraitDialogSize = Size(330.0, 270.0);
+const Size _inputPortraitDialogSizeM2 = Size(330.0, 270.0);
+const Size _inputPortraitDialogSizeM3 = Size(328.0, 270.0);
 const Size _inputLandscapeDialogSize = Size(496, 160.0);
 const Size _inputRangeLandscapeDialogSize = Size(496, 164.0);
 const Duration _dialogSizeAnimationDuration = Duration(milliseconds: 200);
@@ -158,10 +165,6 @@
   TextInputType? keyboardType,
   Offset? anchorPoint,
 }) async {
-  assert(context != null);
-  assert(initialDate != null);
-  assert(firstDate != null);
-  assert(lastDate != null);
   initialDate = DateUtils.dateOnly(initialDate);
   firstDate = DateUtils.dateOnly(firstDate);
   lastDate = DateUtils.dateOnly(lastDate);
@@ -181,9 +184,6 @@
     selectableDayPredicate == null || selectableDayPredicate(initialDate),
     'Provided initialDate $initialDate must satisfy provided selectableDayPredicate.',
   );
-  assert(initialEntryMode != null);
-  assert(useRootNavigator != null);
-  assert(initialDatePickerMode != null);
   assert(debugCheckHasMaterialLocalizations(context));
 
   Widget dialog = DatePickerDialog(
@@ -259,15 +259,10 @@
     this.fieldLabelText,
     this.keyboardType,
     this.restorationId,
-  }) : assert(initialDate != null),
-       assert(firstDate != null),
-       assert(lastDate != null),
-       initialDate = DateUtils.dateOnly(initialDate),
+  }) : initialDate = DateUtils.dateOnly(initialDate),
        firstDate = DateUtils.dateOnly(firstDate),
        lastDate = DateUtils.dateOnly(lastDate),
-       currentDate = DateUtils.dateOnly(currentDate ?? DateTime.now()),
-       assert(initialEntryMode != null),
-       assert(initialCalendarMode != null) {
+       currentDate = DateUtils.dateOnly(currentDate ?? DateTime.now()) {
     assert(
       !this.lastDate.isBefore(this.firstDate),
       'lastDate ${this.lastDate} must be on or after firstDate ${this.firstDate}.',
@@ -425,13 +420,15 @@
   }
 
   Size _dialogSize(BuildContext context) {
-    final Orientation orientation = MediaQuery.of(context).orientation;
+    final bool useMaterial3 = Theme.of(context).useMaterial3;
+    final Orientation orientation = MediaQuery.orientationOf(context);
+
     switch (_entryMode.value) {
       case DatePickerEntryMode.calendar:
       case DatePickerEntryMode.calendarOnly:
         switch (orientation) {
           case Orientation.portrait:
-            return _calendarPortraitDialogSize;
+            return useMaterial3 ? _calendarPortraitDialogSizeM3 : _calendarPortraitDialogSizeM2;
           case Orientation.landscape:
             return _calendarLandscapeDialogSize;
         }
@@ -439,7 +436,7 @@
       case DatePickerEntryMode.inputOnly:
         switch (orientation) {
           case Orientation.portrait:
-            return _inputPortraitDialogSize;
+            return useMaterial3 ? _inputPortraitDialogSizeM3 : _inputPortraitDialogSizeM2;
           case Orientation.landscape:
             return _inputLandscapeDialogSize;
         }
@@ -454,21 +451,28 @@
   @override
   Widget build(BuildContext context) {
     final ThemeData theme = Theme.of(context);
-    final ColorScheme colorScheme = theme.colorScheme;
+    final bool useMaterial3 = theme.useMaterial3;
     final MaterialLocalizations localizations = MaterialLocalizations.of(context);
-    final Orientation orientation = MediaQuery.of(context).orientation;
+    final Orientation orientation = MediaQuery.orientationOf(context);
+    final DatePickerThemeData datePickerTheme = DatePickerTheme.of(context);
+    final DatePickerThemeData defaults = DatePickerTheme.defaults(context);
     final TextTheme textTheme = theme.textTheme;
+
     // Constrain the textScaleFactor to the largest supported value to prevent
     // layout issues.
-    final double textScaleFactor = math.min(MediaQuery.of(context).textScaleFactor, 1.3);
+    final double textScaleFactor = math.min(MediaQuery.textScaleFactorOf(context), 1.3);
+    final Color? headerForegroundColor = datePickerTheme.headerForegroundColor ?? defaults.headerForegroundColor;
+    final TextStyle? headlineStyle = useMaterial3
+      ? (datePickerTheme.headerHeadlineStyle ?? defaults.headerHeadlineStyle)?.copyWith(
+          color: headerForegroundColor,
+        )
+      // Material2 has support for landscape and the current M3 spec doesn't
+      // address this layout, so handling it seperately here.
+      : (orientation == Orientation.landscape
+        ? textTheme.headlineSmall?.copyWith(color: headerForegroundColor)
+        : textTheme.headlineMedium?.copyWith(color: headerForegroundColor));
 
     final String dateText = localizations.formatMediumDate(_selectedDate.value);
-    final Color onPrimarySurface = colorScheme.brightness == Brightness.light
-      ? colorScheme.onPrimary
-      : colorScheme.onSurface;
-    final TextStyle? dateStyle = orientation == Orientation.landscape
-      ? textTheme.headlineSmall?.copyWith(color: onPrimarySurface)
-      : textTheme.headlineMedium?.copyWith(color: onPrimarySurface);
 
     final Widget actions = Container(
       alignment: AlignmentDirectional.centerEnd,
@@ -480,7 +484,7 @@
           TextButton(
             onPressed: _handleCancel,
             child: Text(widget.cancelText ?? (
-              theme.useMaterial3
+              useMaterial3
                 ? localizations.cancelButtonLabel
                 : localizations.cancelButtonLabel.toUpperCase()
             )),
@@ -546,8 +550,8 @@
       case DatePickerEntryMode.calendar:
         picker = calendarDatePicker();
         entryModeButton = IconButton(
-          icon: const Icon(Icons.edit),
-          color: onPrimarySurface,
+          icon:  Icon(useMaterial3 ? Icons.edit_outlined : Icons.edit),
+          color: headerForegroundColor,
           tooltip: localizations.inputDateModeButtonLabel,
           onPressed: _handleEntryModeToggle,
         );
@@ -562,7 +566,7 @@
         picker = inputDatePicker();
         entryModeButton = IconButton(
           icon: const Icon(Icons.calendar_today),
-          color: onPrimarySurface,
+          color: headerForegroundColor,
           tooltip: localizations.calendarModeButtonLabel,
           onPressed: _handleEntryModeToggle,
         );
@@ -576,19 +580,29 @@
 
     final Widget header = _DatePickerHeader(
       helpText: widget.helpText ?? (
-        Theme.of(context).useMaterial3
+        useMaterial3
           ? localizations.datePickerHelpText
           : localizations.datePickerHelpText.toUpperCase()
       ),
       titleText: dateText,
-      titleStyle: dateStyle,
+      titleStyle: headlineStyle,
       orientation: orientation,
       isShort: orientation == Orientation.landscape,
       entryModeButton: entryModeButton,
     );
 
     final Size dialogSize = _dialogSize(context) * textScaleFactor;
+    final DialogTheme dialogTheme = theme.dialogTheme;
     return Dialog(
+      backgroundColor: datePickerTheme.backgroundColor ?? defaults.backgroundColor,
+      elevation: useMaterial3
+        ? datePickerTheme.elevation ?? defaults.elevation!
+        : datePickerTheme.elevation ?? dialogTheme.elevation ?? 24,
+      shadowColor: datePickerTheme.shadowColor ?? defaults.shadowColor,
+      surfaceTintColor: datePickerTheme.surfaceTintColor ?? defaults.surfaceTintColor,
+      shape: useMaterial3
+        ? datePickerTheme.shape ?? defaults.shape
+        : datePickerTheme.shape ?? dialogTheme.shape ?? defaults.shape,
       insetPadding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 24.0),
       clipBehavior: Clip.antiAlias,
       child: AnimatedContainer(
@@ -608,6 +622,7 @@
                   crossAxisAlignment: CrossAxisAlignment.stretch,
                   children: <Widget>[
                     header,
+                    if (useMaterial3) const Divider(),
                     Expanded(child: picker),
                     actions,
                   ],
@@ -618,6 +633,7 @@
                   crossAxisAlignment: CrossAxisAlignment.stretch,
                   children: <Widget>[
                     header,
+                    if (useMaterial3) const VerticalDivider(),
                     Flexible(
                       child: Column(
                         mainAxisSize: MainAxisSize.min,
@@ -712,9 +728,7 @@
     required this.orientation,
     this.isShort = false,
     this.entryModeButton,
-  }) : assert(helpText != null),
-       assert(orientation != null),
-       assert(isShort != null);
+  });
 
   static const double _datePickerHeaderLandscapeWidth = 152.0;
   static const double _datePickerHeaderPortraitHeight = 120.0;
@@ -751,17 +765,12 @@
 
   @override
   Widget build(BuildContext context) {
-    final ThemeData theme = Theme.of(context);
-    final ColorScheme colorScheme = theme.colorScheme;
-    final TextTheme textTheme = theme.textTheme;
-
-    // The header should use the primary color in light themes and surface color in dark
-    final bool isDark = colorScheme.brightness == Brightness.dark;
-    final Color primarySurfaceColor = isDark ? colorScheme.surface : colorScheme.primary;
-    final Color onPrimarySurfaceColor = isDark ? colorScheme.onSurface : colorScheme.onPrimary;
-
-    final TextStyle? helpStyle = textTheme.labelSmall?.copyWith(
-      color: onPrimarySurfaceColor,
+    final DatePickerThemeData themeData = DatePickerTheme.of(context);
+    final DatePickerThemeData defaults = DatePickerTheme.defaults(context);
+    final Color? backgroundColor = themeData.headerBackgroundColor ?? defaults.headerBackgroundColor;
+    final Color? foregroundColor = themeData.headerForegroundColor ?? defaults.headerForegroundColor;
+    final TextStyle? helpStyle = (themeData.headerHelpStyle ?? defaults.headerHelpStyle)?.copyWith(
+      color: foregroundColor,
     );
 
     final Text help = Text(
@@ -783,7 +792,7 @@
         return SizedBox(
           height: _datePickerHeaderPortraitHeight,
           child: Material(
-            color: primarySurfaceColor,
+            color: backgroundColor,
             child: Padding(
               padding: const EdgeInsetsDirectional.only(
                 start: 24,
@@ -811,7 +820,7 @@
         return SizedBox(
           width: _datePickerHeaderLandscapeWidth,
           child: Material(
-            color: primarySurfaceColor,
+            color: backgroundColor,
             child: Column(
               crossAxisAlignment: CrossAxisAlignment.start,
               children: <Widget>[
@@ -963,19 +972,12 @@
   TransitionBuilder? builder,
   Offset? anchorPoint,
 }) async {
-  assert(context != null);
-  assert(
-    initialDateRange == null || (initialDateRange.start != null && initialDateRange.end != null),
-    'initialDateRange must be null or have non-null start and end dates.',
-  );
   assert(
     initialDateRange == null || !initialDateRange.start.isAfter(initialDateRange.end),
     "initialDateRange's start date must not be after it's end date.",
   );
   initialDateRange = initialDateRange == null ? null : DateUtils.datesOnly(initialDateRange);
-  assert(firstDate != null);
   firstDate = DateUtils.dateOnly(firstDate);
-  assert(lastDate != null);
   lastDate = DateUtils.dateOnly(lastDate);
   assert(
     !lastDate.isBefore(firstDate),
@@ -998,8 +1000,6 @@
     "initialDateRange's end date must be on or before lastDate $lastDate.",
   );
   currentDate = DateUtils.dateOnly(currentDate ?? DateTime.now());
-  assert(initialEntryMode != null);
-  assert(useRootNavigator != null);
   assert(debugCheckHasMaterialLocalizations(context));
 
   Widget dialog = DateRangePickerDialog(
@@ -1316,19 +1316,20 @@
 
   @override
   Widget build(BuildContext context) {
-    final MediaQueryData mediaQuery = MediaQuery.of(context);
-    final Orientation orientation = mediaQuery.orientation;
-    final double textScaleFactor = math.min(mediaQuery.textScaleFactor, 1.3);
+    final ThemeData theme = Theme.of(context);
+    final bool useMaterial3 = theme.useMaterial3;
+    final Orientation orientation = MediaQuery.orientationOf(context);
+    final double textScaleFactor = math.min(MediaQuery.textScaleFactorOf(context), 1.3);
     final MaterialLocalizations localizations = MaterialLocalizations.of(context);
-    final ColorScheme colors = Theme.of(context).colorScheme;
-    final Color onPrimarySurface = colors.brightness == Brightness.light
-      ? colors.onPrimary
-      : colors.onSurface;
+    final DatePickerThemeData datePickerTheme = DatePickerTheme.of(context);
+    final DatePickerThemeData defaults =  DatePickerTheme.defaults(context);
 
     final Widget contents;
     final Size size;
-    ShapeBorder? shape;
-    final double elevation;
+    final double? elevation;
+    final Color? shadowColor;
+    final Color? surfaceTintColor;
+    final ShapeBorder? shape;
     final EdgeInsets insetPadding;
     final bool showEntryModeButton =
       _entryMode.value == DatePickerEntryMode.calendar ||
@@ -1349,28 +1350,29 @@
           onCancel: _handleCancel,
           entryModeButton: showEntryModeButton
             ? IconButton(
-                icon: const Icon(Icons.edit),
+                icon: Icon(useMaterial3 ? Icons.edit_outlined : Icons.edit),
                 padding: EdgeInsets.zero,
-                color: onPrimarySurface,
                 tooltip: localizations.inputDateModeButtonLabel,
                 onPressed: _handleEntryModeToggle,
               )
             : null,
           confirmText: widget.saveText ?? (
-            Theme.of(context).useMaterial3
+            useMaterial3
               ? localizations.saveButtonLabel
               : localizations.saveButtonLabel.toUpperCase()
           ),
           helpText: widget.helpText ?? (
-            Theme.of(context).useMaterial3
+            useMaterial3
               ? localizations.dateRangePickerHelpText
               : localizations.dateRangePickerHelpText.toUpperCase()
             ),
         );
-        size = mediaQuery.size;
+        size = MediaQuery.sizeOf(context);
         insetPadding = EdgeInsets.zero;
-        shape = const RoundedRectangleBorder();
-        elevation = 0;
+        elevation = datePickerTheme.rangePickerElevation ?? defaults.rangePickerElevation!;
+        shadowColor = datePickerTheme.rangePickerShadowColor ?? defaults.rangePickerShadowColor!;
+        surfaceTintColor = datePickerTheme.rangePickerSurfaceTintColor ?? defaults.rangePickerSurfaceTintColor!;
+        shape = datePickerTheme.rangePickerShape ?? defaults.rangePickerShape;
         break;
 
       case DatePickerEntryMode.input:
@@ -1416,35 +1418,46 @@
             ? IconButton(
                 icon: const Icon(Icons.calendar_today),
                 padding: EdgeInsets.zero,
-                color: onPrimarySurface,
                 tooltip: localizations.calendarModeButtonLabel,
                 onPressed: _handleEntryModeToggle,
               )
             : null,
           confirmText: widget.confirmText ?? localizations.okButtonLabel,
           cancelText: widget.cancelText ?? (
-            Theme.of(context).useMaterial3
+            useMaterial3
               ? localizations.cancelButtonLabel
               : localizations.cancelButtonLabel.toUpperCase()
           ),
           helpText: widget.helpText ?? (
-            Theme.of(context).useMaterial3
+            useMaterial3
               ? localizations.dateRangePickerHelpText
               : localizations.dateRangePickerHelpText.toUpperCase()
           ),
         );
-        final DialogTheme dialogTheme = Theme.of(context).dialogTheme;
-        size = orientation == Orientation.portrait ? _inputPortraitDialogSize : _inputRangeLandscapeDialogSize;
+        final DialogTheme dialogTheme = theme.dialogTheme;
+        size = orientation == Orientation.portrait
+          ? (useMaterial3 ? _inputPortraitDialogSizeM3 : _inputPortraitDialogSizeM2)
+          : _inputRangeLandscapeDialogSize;
+        elevation = useMaterial3
+          ? datePickerTheme.elevation ?? defaults.elevation!
+          : datePickerTheme.elevation ?? dialogTheme.elevation ?? 24;
+        shadowColor = datePickerTheme.shadowColor ?? defaults.shadowColor;
+        surfaceTintColor = datePickerTheme.surfaceTintColor ?? defaults.surfaceTintColor;
+        shape = useMaterial3
+          ? datePickerTheme.shape ?? defaults.shape
+          : datePickerTheme.shape ?? dialogTheme.shape ?? defaults.shape;
+
         insetPadding = const EdgeInsets.symmetric(horizontal: 16.0, vertical: 24.0);
-        shape = dialogTheme.shape;
-        elevation = dialogTheme.elevation ?? 24;
         break;
     }
 
     return Dialog(
       insetPadding: insetPadding,
-      shape: shape,
+      backgroundColor: datePickerTheme.backgroundColor ?? defaults.backgroundColor,
       elevation: elevation,
+      shadowColor: shadowColor,
+      surfaceTintColor: surfaceTintColor,
+      shape: shape,
       clipBehavior: Clip.antiAlias,
       child: AnimatedContainer(
         width: size.width,
@@ -1497,26 +1510,29 @@
   @override
   Widget build(BuildContext context) {
     final ThemeData theme = Theme.of(context);
-    final ColorScheme colorScheme = theme.colorScheme;
+    final bool useMaterial3 = theme.useMaterial3;
     final MaterialLocalizations localizations = MaterialLocalizations.of(context);
-    final Orientation orientation = MediaQuery.of(context).orientation;
-    final TextTheme textTheme = theme.textTheme;
-    final Color headerForeground = colorScheme.brightness == Brightness.light
-        ? colorScheme.onPrimary
-        : colorScheme.onSurface;
-    final Color headerDisabledForeground = headerForeground.withOpacity(0.38);
+    final Orientation orientation = MediaQuery.orientationOf(context);
+    final DatePickerThemeData themeData = DatePickerTheme.of(context);
+    final DatePickerThemeData defaults = DatePickerTheme.defaults(context);
+    final Color? dialogBackground = themeData.rangePickerBackgroundColor ?? defaults.rangePickerBackgroundColor;
+    final Color? headerForeground = themeData.rangePickerHeaderForegroundColor ?? defaults.rangePickerHeaderForegroundColor;
+    final Color? headerDisabledForeground = headerForeground?.withOpacity(0.38);
+    final TextStyle? headlineStyle = themeData.rangePickerHeaderHeadlineStyle ?? defaults.rangePickerHeaderHeadlineStyle;
+    final TextStyle? headlineHelpStyle = (themeData.rangePickerHeaderHelpStyle ?? defaults.rangePickerHeaderHelpStyle)?.apply(color: headerForeground);
     final String startDateText = _formatRangeStartDate(localizations, selectedStartDate, selectedEndDate);
     final String endDateText = _formatRangeEndDate(localizations, selectedStartDate, selectedEndDate, DateTime.now());
-    final TextStyle? headlineStyle = textTheme.headlineSmall;
     final TextStyle? startDateStyle = headlineStyle?.apply(
         color: selectedStartDate != null ? headerForeground : headerDisabledForeground,
     );
     final TextStyle? endDateStyle = headlineStyle?.apply(
         color: selectedEndDate != null ? headerForeground : headerDisabledForeground,
     );
-    final TextStyle saveButtonStyle = textTheme.labelLarge!.apply(
-        color: onConfirm != null ? headerForeground : headerDisabledForeground,
+    final ButtonStyle buttonStyle = TextButton.styleFrom(
+      foregroundColor: headerForeground,
+      disabledForegroundColor: headerDisabledForeground
     );
+    final IconThemeData iconTheme = IconThemeData(color: headerForeground);
 
     return SafeArea(
       top: false,
@@ -1524,6 +1540,11 @@
       right: false,
       child: Scaffold(
         appBar: AppBar(
+          iconTheme: iconTheme,
+          actionsIconTheme: iconTheme,
+          elevation: useMaterial3 ? 0 : null,
+          scrolledUnderElevation: useMaterial3 ? 0 : null,
+          backgroundColor: useMaterial3 ? Colors.transparent : null,
           leading: CloseButton(
             onPressed: onCancel,
           ),
@@ -1531,15 +1552,16 @@
             if (orientation == Orientation.landscape && entryModeButton != null)
               entryModeButton!,
             TextButton(
+              style: buttonStyle,
               onPressed: onConfirm,
-              child: Text(confirmText, style: saveButtonStyle),
+              child: Text(confirmText),
             ),
             const SizedBox(width: 8),
           ],
           bottom: PreferredSize(
             preferredSize: const Size(double.infinity, 64),
             child: Row(children: <Widget>[
-              SizedBox(width: MediaQuery.of(context).size.width < 360 ? 42 : 72),
+              SizedBox(width: MediaQuery.sizeOf(context).width < 360 ? 42 : 72),
               Expanded(
                 child: Semantics(
                   label: '$helpText $startDateText to $endDateText',
@@ -1547,12 +1569,7 @@
                   child: Column(
                     crossAxisAlignment: CrossAxisAlignment.start,
                     children: <Widget>[
-                      Text(
-                        helpText,
-                        style: textTheme.labelSmall!.apply(
-                          color: headerForeground,
-                        ),
-                      ),
+                      Text(helpText, style: headlineHelpStyle),
                       const SizedBox(height: 8),
                       Row(
                         children: <Widget>[
@@ -1582,11 +1599,15 @@
               if (orientation == Orientation.portrait && entryModeButton != null)
                 Padding(
                   padding: const EdgeInsets.symmetric(horizontal: 8.0),
-                  child: entryModeButton,
+                  child: IconTheme(
+                    data: iconTheme,
+                    child: entryModeButton!,
+                  ),
                 ),
             ]),
           ),
         ),
+        backgroundColor: dialogBackground,
         body: _CalendarDateRangePicker(
           initialStartDate: selectedStartDate,
           initialEndDate: selectedEndDate,
@@ -1625,8 +1646,6 @@
     required this.onEndDateChanged,
   }) : initialStartDate = initialStartDate != null ? DateUtils.dateOnly(initialStartDate) : null,
        initialEndDate = initialEndDate != null ? DateUtils.dateOnly(initialEndDate) : null,
-       assert(firstDate != null),
-       assert(lastDate != null),
        firstDate = DateUtils.dateOnly(firstDate),
        lastDate = DateUtils.dateOnly(lastDate),
        currentDate = DateUtils.dateOnly(currentDate ?? DateTime.now()) {
@@ -2017,7 +2036,7 @@
 
     return Container(
       constraints: BoxConstraints(
-        maxWidth: MediaQuery.of(context).orientation == Orientation.landscape
+        maxWidth: MediaQuery.orientationOf(context) == Orientation.landscape
           ? _maxCalendarWidthLandscape
           : _maxCalendarWidthPortrait,
         maxHeight: _monthItemRowHeight,
@@ -2066,10 +2085,9 @@
     required this.dayChildWidth,
     required this.edgeChildWidth,
     required this.reverseCrossAxis,
-  }) : assert(crossAxisCount != null && crossAxisCount > 0),
-       assert(dayChildWidth != null && dayChildWidth >= 0),
-       assert(edgeChildWidth != null && edgeChildWidth >= 0),
-       assert(reverseCrossAxis != null);
+  }) : assert(crossAxisCount > 0),
+       assert(dayChildWidth >= 0),
+       assert(edgeChildWidth >= 0);
 
   /// The number of children in the cross axis.
   final int crossAxisCount;
@@ -2160,19 +2178,12 @@
     required this.firstDate,
     required this.lastDate,
     required this.displayedMonth,
-    this.dragStartBehavior = DragStartBehavior.start,
-  }) : assert(firstDate != null),
-       assert(lastDate != null),
-       assert(!firstDate.isAfter(lastDate)),
+  }) : assert(!firstDate.isAfter(lastDate)),
        assert(selectedDateStart == null || !selectedDateStart.isBefore(firstDate)),
        assert(selectedDateEnd == null || !selectedDateEnd.isBefore(firstDate)),
        assert(selectedDateStart == null || !selectedDateStart.isAfter(lastDate)),
        assert(selectedDateEnd == null || !selectedDateEnd.isAfter(lastDate)),
-       assert(selectedDateStart == null || selectedDateEnd == null || !selectedDateStart.isAfter(selectedDateEnd)),
-       assert(currentDate != null),
-       assert(onChanged != null),
-       assert(displayedMonth != null),
-       assert(dragStartBehavior != null);
+       assert(selectedDateStart == null || selectedDateEnd == null || !selectedDateStart.isAfter(selectedDateEnd));
 
   /// The currently selected start date.
   ///
@@ -2199,25 +2210,6 @@
   /// The month whose days are displayed by this picker.
   final DateTime displayedMonth;
 
-  /// Determines the way that drag start behavior is handled.
-  ///
-  /// If set to [DragStartBehavior.start], the drag gesture used to scroll a
-  /// date picker wheel will begin at the position where the drag gesture won
-  /// the arena. If set to [DragStartBehavior.down] it will begin at the position
-  /// where a down event is first detected.
-  ///
-  /// In general, setting this to [DragStartBehavior.start] will make drag
-  /// animation smoother and setting it to [DragStartBehavior.down] will make
-  /// drag behavior feel slightly more reactive.
-  ///
-  /// By default, the drag start behavior is [DragStartBehavior.start].
-  ///
-  /// See also:
-  ///
-  ///  * [DragGestureRecognizer.dragStartBehavior], which gives an example for
-  ///    the different behaviors.
-  final DragStartBehavior dragStartBehavior;
-
   @override
   _MonthItemState createState() => _MonthItemState();
 }
@@ -2255,7 +2247,8 @@
   }
 
   Color _highlightColor(BuildContext context) {
-    return Theme.of(context).colorScheme.primary.withOpacity(0.12);
+    return DatePickerTheme.of(context).rangeSelectionBackgroundColor
+      ?? DatePickerTheme.defaults(context).rangeSelectionBackgroundColor!;
   }
 
   void _dayFocusChanged(bool focused) {
@@ -2286,6 +2279,8 @@
     final ColorScheme colorScheme = theme.colorScheme;
     final TextTheme textTheme = theme.textTheme;
     final MaterialLocalizations localizations = MaterialLocalizations.of(context);
+    final DatePickerThemeData datePickerTheme = DatePickerTheme.of(context);
+    final DatePickerThemeData defaults = DatePickerTheme.defaults(context);
     final TextDirection textDirection = Directionality.of(context);
     final Color highlightColor = _highlightColor(context);
     final int day = dayToBuild.day;
@@ -2302,14 +2297,42 @@
       dayToBuild.isAfter(widget.selectedDateStart!) &&
       dayToBuild.isBefore(widget.selectedDateEnd!);
 
+    T? effectiveValue<T>(T? Function(DatePickerThemeData? theme) getProperty) {
+      return getProperty(datePickerTheme) ?? getProperty(defaults);
+    }
+
+    T? resolve<T>(MaterialStateProperty<T>? Function(DatePickerThemeData? theme) getProperty, Set<MaterialState> states) {
+      return effectiveValue(
+        (DatePickerThemeData? theme) {
+          return getProperty(theme)?.resolve(states);
+        },
+      );
+    }
+
+    final Set<MaterialState> states = <MaterialState>{
+      if (isDisabled) MaterialState.disabled,
+      if (isSelectedDayStart || isSelectedDayEnd) MaterialState.selected,
+    };
+
+    final Color? dayForegroundColor = resolve<Color?>((DatePickerThemeData? theme) => theme?.dayForegroundColor, states);
+    final Color? dayBackgroundColor = resolve<Color?>((DatePickerThemeData? theme) => theme?.dayBackgroundColor, states);
+    final MaterialStateProperty<Color?> dayOverlayColor = MaterialStateProperty.resolveWith<Color?>(
+      (Set<MaterialState> states) => effectiveValue(
+        (DatePickerThemeData? theme) =>
+          isInRange
+            ? theme?.rangeSelectionOverlayColor?.resolve(states)
+             : theme?.dayOverlayColor?.resolve(states),
+      )
+    );
+
     _HighlightPainter? highlightPainter;
 
     if (isSelectedDayStart || isSelectedDayEnd) {
       // The selected start and end dates gets a circle background
       // highlight, and a contrasting text color.
-      itemStyle = textTheme.bodyMedium?.apply(color: colorScheme.onPrimary);
+      itemStyle = textTheme.bodyMedium?.apply(color: dayForegroundColor);
       decoration = BoxDecoration(
-        color: colorScheme.primary,
+        color: dayBackgroundColor,
         shape: BoxShape.circle,
       );
 
@@ -2348,7 +2371,8 @@
     // day of month before the rest of the date, as they are looking
     // for the day of month. To do that we prepend day of month to the
     // formatted full date.
-    String semanticLabel = '${localizations.formatDecimal(day)}, ${localizations.formatFullDate(dayToBuild)}';
+    final String semanticLabelSuffix = DateUtils.isSameDay(widget.currentDate, dayToBuild) ? ', ${localizations.currentDateLabel}' : '';
+    String semanticLabel = '${localizations.formatDecimal(day)}, ${localizations.formatFullDate(dayToBuild)}$semanticLabelSuffix';
     if (isSelectedDayStart) {
       semanticLabel = localizations.dateRangeStartDateSemanticLabel(semanticLabel);
     } else if (isSelectedDayEnd) {
@@ -2380,7 +2404,8 @@
         focusNode: _dayFocusNodes[day - 1],
         onTap: () => widget.onChanged(dayToBuild),
         radius: _monthItemRowHeight / 2 + 4,
-        splashColor: colorScheme.primary.withOpacity(0.38),
+        statesController: MaterialStatesController(states),
+        overlayColor: dayOverlayColor,
         onFocusChange: _dayFocusChanged,
         child: dayWidget,
       );
@@ -2403,8 +2428,7 @@
     final int daysInMonth = DateUtils.getDaysInMonth(year, month);
     final int dayOffset = DateUtils.firstDayOffset(year, month, localizations);
     final int weeks = ((daysInMonth + dayOffset) / DateTime.daysPerWeek).ceil();
-    final double gridHeight =
-        weeks * _monthItemRowHeight + (weeks - 1) * _monthItemSpaceBetweenRows;
+    final double gridHeight = weeks * _monthItemRowHeight + (weeks - 1) * _monthItemSpaceBetweenRows;
     final List<Widget> dayItems = <Widget>[];
 
     for (int i = 0; true; i += 1) {
@@ -2468,7 +2492,7 @@
       paddedDayItems.addAll(weekList);
     }
 
-    final double maxWidth = MediaQuery.of(context).orientation == Orientation.landscape
+    final double maxWidth = MediaQuery.orientationOf(context) == Orientation.landscape
       ? _maxCalendarWidthLandscape
       : _maxCalendarWidthPortrait;
     return Column(
@@ -2619,18 +2643,17 @@
 
   @override
   Widget build(BuildContext context) {
-    final ThemeData theme = Theme.of(context);
-    final ColorScheme colorScheme = theme.colorScheme;
+    final bool useMaterial3 = Theme.of(context).useMaterial3;
     final MaterialLocalizations localizations = MaterialLocalizations.of(context);
-    final Orientation orientation = MediaQuery.of(context).orientation;
-    final TextTheme textTheme = theme.textTheme;
+    final Orientation orientation = MediaQuery.orientationOf(context);
+    final DatePickerThemeData datePickerTheme = DatePickerTheme.of(context);
+    final DatePickerThemeData defaults = DatePickerTheme.defaults(context);
 
-    final Color onPrimarySurfaceColor = colorScheme.brightness == Brightness.light
-        ? colorScheme.onPrimary
-        : colorScheme.onSurface;
-    final TextStyle? dateStyle = orientation == Orientation.landscape
-        ? textTheme.headlineSmall?.apply(color: onPrimarySurfaceColor)
-        : textTheme.headlineMedium?.apply(color: onPrimarySurfaceColor);
+    final Color? headerForegroundColor = datePickerTheme.headerForegroundColor ?? defaults.headerForegroundColor;
+    final TextStyle? headlineStyle = (datePickerTheme.headerHeadlineStyle ?? defaults.headerHeadlineStyle)?.copyWith(
+      color: headerForegroundColor,
+    );
+
     final String dateText = _formatDateRange(context, selectedStartDate, selectedEndDate, currentDate!);
     final String semanticDateText = selectedStartDate != null && selectedEndDate != null
         ? '${localizations.formatMediumDate(selectedStartDate!)} – ${localizations.formatMediumDate(selectedEndDate!)}'
@@ -2638,13 +2661,13 @@
 
     final Widget header = _DatePickerHeader(
       helpText: helpText ?? (
-        Theme.of(context).useMaterial3
+        useMaterial3
           ? localizations.dateRangePickerHelpText
           : localizations.dateRangePickerHelpText.toUpperCase()
       ),
       titleText: dateText,
       titleSemanticsLabel: semanticDateText,
-      titleStyle: dateStyle,
+      titleStyle: headlineStyle,
       orientation: orientation,
       isShort: orientation == Orientation.landscape,
       entryModeButton: entryModeButton,
@@ -2660,7 +2683,7 @@
           TextButton(
             onPressed: onCancel,
             child: Text(cancelText ?? (
-              theme.useMaterial3
+              useMaterial3
                 ? localizations.cancelButtonLabel
                 : localizations.cancelButtonLabel.toUpperCase()
             )),
@@ -2732,14 +2755,8 @@
     this.autovalidate = false,
   }) : initialStartDate = initialStartDate == null ? null : DateUtils.dateOnly(initialStartDate),
        initialEndDate = initialEndDate == null ? null : DateUtils.dateOnly(initialEndDate),
-       assert(firstDate != null),
        firstDate = DateUtils.dateOnly(firstDate),
-       assert(lastDate != null),
-       lastDate = DateUtils.dateOnly(lastDate),
-       assert(firstDate != null),
-       assert(lastDate != null),
-       assert(autofocus != null),
-       assert(autovalidate != null);
+       lastDate = DateUtils.dateOnly(lastDate);
 
   /// The [DateTime] that represents the start of the initial date range selection.
   final DateTime? initialStartDate;
@@ -2915,8 +2932,13 @@
 
   @override
   Widget build(BuildContext context) {
+    final ThemeData theme = Theme.of(context);
+    final bool useMaterial3 = theme.useMaterial3;
     final MaterialLocalizations localizations = MaterialLocalizations.of(context);
-    final InputDecorationTheme inputTheme = Theme.of(context).inputDecorationTheme;
+    final InputDecorationTheme inputTheme = theme.inputDecorationTheme;
+    final InputBorder inputBorder = inputTheme.border
+      ?? (useMaterial3 ? const OutlineInputBorder() : const UnderlineInputBorder());
+
     return Row(
       crossAxisAlignment: CrossAxisAlignment.start,
       children: <Widget>[
@@ -2924,7 +2946,7 @@
           child: TextField(
             controller: _startController,
             decoration: InputDecoration(
-              border: inputTheme.border ?? const UnderlineInputBorder(),
+              border: inputBorder,
               filled: inputTheme.filled,
               hintText: widget.fieldStartHintText ?? localizations.dateHelpText,
               labelText: widget.fieldStartLabelText ?? localizations.dateRangeStartLabel,
@@ -2940,7 +2962,7 @@
           child: TextField(
             controller: _endController,
             decoration: InputDecoration(
-              border: inputTheme.border ?? const UnderlineInputBorder(),
+              border: inputBorder,
               filled: inputTheme.filled,
               hintText: widget.fieldEndHintText ?? localizations.dateHelpText,
               labelText: widget.fieldEndLabelText ?? localizations.dateRangeEndLabel,
diff --git a/framework/lib/src/material/date_picker_theme.dart b/framework/lib/src/material/date_picker_theme.dart
new file mode 100644
index 0000000..c9a394f
--- /dev/null
+++ b/framework/lib/src/material/date_picker_theme.dart
@@ -0,0 +1,975 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:engine/ui.dart' show lerpDouble;
+
+import 'package:flute/foundation.dart';
+import 'package:flute/widgets.dart';
+
+import 'color_scheme.dart';
+import 'colors.dart';
+import 'material_state.dart';
+import 'text_theme.dart';
+import 'theme.dart';
+
+// Examples can assume:
+// late BuildContext context;
+
+/// Overrides the default values of visual properties for descendant
+/// [DatePickerDialog] widgets.
+///
+/// Descendant widgets obtain the current [DatePickerThemeData] object with
+/// [DatePickerTheme.of]. Instances of [DatePickerTheme] can
+/// be customized with [DatePickerThemeData.copyWith].
+///
+/// Typically a [DatePickerTheme] is specified as part of the overall
+/// [Theme] with [ThemeData.datePickerTheme].
+///
+/// All [DatePickerThemeData] properties are null by default. When null,
+/// the [DatePickerDialog] computes its own default values, typically based on
+/// the overall theme's [ThemeData.colorScheme], [ThemeData.textTheme], and
+/// [ThemeData.iconTheme].
+@immutable
+class DatePickerThemeData with Diagnosticable {
+  /// Creates a [DatePickerThemeData] that can be used to override default properties
+  /// in a [DatePickerTheme] widget.
+  const DatePickerThemeData({
+    this.backgroundColor,
+    this.elevation,
+    this.shadowColor,
+    this.surfaceTintColor,
+    this.shape,
+    this.headerBackgroundColor,
+    this.headerForegroundColor,
+    this.headerHeadlineStyle,
+    this.headerHelpStyle,
+    this.weekdayStyle,
+    this.dayStyle,
+    this.dayForegroundColor,
+    this.dayBackgroundColor,
+    this.dayOverlayColor,
+    this.todayForegroundColor,
+    this.todayBackgroundColor,
+    this.todayBorder,
+    this.yearStyle,
+    this.yearForegroundColor,
+    this.yearBackgroundColor,
+    this.yearOverlayColor,
+    this.rangePickerBackgroundColor,
+    this.rangePickerElevation,
+    this.rangePickerShadowColor,
+    this.rangePickerSurfaceTintColor,
+    this.rangePickerShape,
+    this.rangePickerHeaderBackgroundColor,
+    this.rangePickerHeaderForegroundColor,
+    this.rangePickerHeaderHeadlineStyle,
+    this.rangePickerHeaderHelpStyle,
+    this.rangeSelectionBackgroundColor,
+    this.rangeSelectionOverlayColor,
+  });
+
+  /// Overrides the default value of [Dialog.backgroundColor].
+  final Color? backgroundColor;
+
+  /// Overrides the default value of [Dialog.elevation].
+  ///
+  /// See also:
+  ///   [Material.elevation], which explains how elevation is related to a component's shadow.
+  final double? elevation;
+
+  /// Overrides the default value of [Dialog.shadowColor].
+  ///
+  /// See also:
+  ///   [Material.shadowColor], which explains how the shadow is rendered.
+  final Color? shadowColor;
+
+  /// Overrides the default value of [Dialog.surfaceTintColor].
+  ///
+  /// See also:
+  ///   [Material.surfaceTintColor], which explains how this color is related to
+  ///   [elevation] and [backgroundColor].
+  final Color? surfaceTintColor;
+
+  /// Overrides the default value of [Dialog.shape].
+  ///
+  /// If [elevation] is greater than zero then a shadow is shown and the shadow's
+  /// shape mirrors the shape of the dialog.
+  final ShapeBorder? shape;
+
+  /// Overrides the header's default background fill color.
+  ///
+  /// The dialog's header displays the currently selected date.
+  final Color? headerBackgroundColor;
+
+  /// Overrides the header's default color used for text labels and icons.
+  ///
+  /// The dialog's header displays the currently selected date.
+  ///
+  /// This is used instead of the [TextStyle.color] property of [headerHeadlineStyle]
+  /// and [headerHelpStyle].
+  final Color? headerForegroundColor;
+
+  /// Overrides the header's default headline text style.
+  ///
+  /// The dialog's header displays the currently selected date.
+  ///
+  /// The [TextStyle.color] of the [headerHeadlineStyle] is not used,
+  /// [headerForegroundColor] is used instead.
+  final TextStyle? headerHeadlineStyle;
+
+  /// Overrides the header's default help text style.
+  ///
+  /// The help text (also referred to as "supporting text" in the Material
+  /// spec) is usually a prompt to the user at the top of the header
+  /// (i.e. 'Select date').
+  ///
+  /// The [TextStyle.color] of the [headerHelpStyle] is not used,
+  /// [headerForegroundColor] is used instead.
+  ///
+  /// See also:
+  ///   [DatePickerDialog.helpText], which specifies the help text.
+  final TextStyle? headerHelpStyle;
+
+  /// Overrides the default text style used for the row of weekday
+  /// labels at the top of the date picker grid.
+  final TextStyle? weekdayStyle;
+
+  /// Overrides the default text style used for each individual day
+  /// label in the grid of the date picker.
+  ///
+  /// The [TextStyle.color] of the [dayStyle] is not used,
+  /// [dayForegroundColor] is used instead.
+  final TextStyle? dayStyle;
+
+  /// Overrides the default color used to paint the day labels in the
+  /// grid of the date picker.
+  ///
+  /// This will be used instead of the color provided in [dayStyle].
+  final MaterialStateProperty<Color?>? dayForegroundColor;
+
+  /// Overrides the default color used to paint the background of the
+  /// day labels in the grid of the date picker.
+  final MaterialStateProperty<Color?>? dayBackgroundColor;
+
+  /// Overriddes the default highlight color that's typically used to
+  /// indicate that a day in the grid is focused, hovered, or pressed.
+  final MaterialStateProperty<Color?>? dayOverlayColor;
+
+  /// Overrides the default color used to paint the
+  /// [DatePickerDialog.currentDate] label in the grid of the dialog's
+  /// [CalendarDatePicker] and the corresponding year in the dialog's
+  /// [YearPicker].
+  ///
+  /// This will be used instead of the [TextStyle.color] provided in [dayStyle].
+  final MaterialStateProperty<Color?>? todayForegroundColor;
+
+  /// Overrides the default color used to paint the background of the
+  /// [DatePickerDialog.currentDate] label in the grid of the date picker.
+  final MaterialStateProperty<Color?>? todayBackgroundColor;
+
+  /// Overrides the border used to paint the
+  /// [DatePickerDialog.currentDate] label in the grid of the date
+  /// picker.
+  ///
+  /// The border side's [BorderSide.color] is not used,
+  /// [todayForegroundColor] is used instead.
+  final BorderSide? todayBorder;
+
+  /// Overrides the default text style used to paint each of the year
+  /// entries in the year selector of the date picker.
+  ///
+  /// The [TextStyle.color] of the [yearStyle] is not used,
+  /// [yearForegroundColor] is used instead.
+  final TextStyle? yearStyle;
+
+  /// Overrides the default color used to paint the year labels in the year
+  /// selector of the date picker.
+  ///
+  /// This will be used instead of the color provided in [yearStyle].
+  final MaterialStateProperty<Color?>? yearForegroundColor;
+
+  /// Overrides the default color used to paint the background of the
+  /// year labels in the year selector of the of the date picker.
+  final MaterialStateProperty<Color?>? yearBackgroundColor;
+
+  /// Overrides the default highlight color that's typically used to
+  /// indicate that a year in the year selector is focused, hovered,
+  /// or pressed.
+  final MaterialStateProperty<Color?>? yearOverlayColor;
+
+  /// Overrides the default [Scaffold.backgroundColor] for
+  /// [DateRangePickerDialog].
+  final Color? rangePickerBackgroundColor;
+
+  /// Overrides the default elevation of the full screen
+  /// [DateRangePickerDialog].
+  ///
+  /// See also:
+  ///   [Material.elevation], which explains how elevation is related to a component's shadow.
+  final double? rangePickerElevation;
+
+  /// Overrides the color of the shadow painted below a full screen
+  /// [DateRangePickerDialog].
+  ///
+  /// See also:
+  ///   [Material.shadowColor], which explains how the shadow is rendered.
+  final Color? rangePickerShadowColor;
+
+  /// Overrides the default color of the surface tint overlay applied
+  /// to the [backgroundColor] of a full screen
+  /// [DateRangePickerDialog]'s to indicate elevation.
+  ///
+  /// See also:
+  ///   [Material.surfaceTintColor], which explains how this color is related to
+  ///   [elevation].
+  final Color? rangePickerSurfaceTintColor;
+
+  /// Overrides the default overall shape of a full screen
+  /// [DateRangePickerDialog].
+  ///
+  /// If [elevation] is greater than zero then a shadow is shown and the shadow's
+  /// shape mirrors the shape of the dialog.
+  ///
+  ///   [Material.surfaceTintColor], which explains how this color is related to
+  ///   [elevation].
+  final ShapeBorder? rangePickerShape;
+
+  /// Overrides the default background fill color for [DateRangePickerDialog].
+  ///
+  /// The dialog's header displays the currently selected date range.
+  final Color? rangePickerHeaderBackgroundColor;
+
+  /// Overrides the default color used for text labels and icons in
+  /// the header of a full screen [DateRangePickerDialog]
+  ///
+  /// The dialog's header displays the currently selected date range.
+  ///
+  /// This is used instead of any colors provided by
+  /// [rangePickerHeaderHeadlineStyle] or [rangePickerHeaderHelpStyle].
+  final Color? rangePickerHeaderForegroundColor;
+
+  /// Overrides the default text style used for the headline text in
+  /// the header of a full screen [DateRangePickerDialog].
+  ///
+  /// The dialog's header displays the currently selected date range.
+  ///
+  /// The [TextStyle.color] of [rangePickerHeaderHeadlineStyle] is not used,
+  /// [rangePickerHeaderForegroundColor] is used instead.
+  final TextStyle? rangePickerHeaderHeadlineStyle;
+
+  /// Overrides the default text style used for the help text of the
+  /// header of a full screen [DateRangePickerDialog].
+  ///
+  /// The help text (also referred to as "supporting text" in the Material
+  /// spec) is usually a prompt to the user at the top of the header
+  /// (i.e. 'Select date').
+  ///
+  /// The [TextStyle.color] of the [rangePickerHeaderHelpStyle] is not used,
+  /// [rangePickerHeaderForegroundColor] is used instead.
+  ///
+  /// See also:
+  ///   [DateRangePickerDialog.helpText], which specifies the help text.
+  final TextStyle? rangePickerHeaderHelpStyle;
+
+  /// Overrides the default background color used to paint days
+  /// selected between the start and end dates in a
+  /// [DateRangePickerDialog].
+  final Color? rangeSelectionBackgroundColor;
+
+  /// Overrides the default highlight color that's typically used to
+  /// indicate that a date in the selected range of a
+  /// [DateRangePickerDialog] is focused, hovered, or pressed.
+  final MaterialStateProperty<Color?>? rangeSelectionOverlayColor;
+
+  /// Creates a copy of this object with the given fields replaced with the
+  /// new values.
+  DatePickerThemeData copyWith({
+    Color? backgroundColor,
+    double? elevation,
+    Color? shadowColor,
+    Color? surfaceTintColor,
+    ShapeBorder? shape,
+    Color? headerBackgroundColor,
+    Color? headerForegroundColor,
+    TextStyle? headerHeadlineStyle,
+    TextStyle? headerHelpStyle,
+    TextStyle? weekdayStyle,
+    TextStyle? dayStyle,
+    MaterialStateProperty<Color?>? dayForegroundColor,
+    MaterialStateProperty<Color?>? dayBackgroundColor,
+    MaterialStateProperty<Color?>? dayOverlayColor,
+    MaterialStateProperty<Color?>? todayForegroundColor,
+    MaterialStateProperty<Color?>? todayBackgroundColor,
+    BorderSide? todayBorder,
+    TextStyle? yearStyle,
+    MaterialStateProperty<Color?>? yearForegroundColor,
+    MaterialStateProperty<Color?>? yearBackgroundColor,
+    MaterialStateProperty<Color?>? yearOverlayColor,
+    Color? rangePickerBackgroundColor,
+    double? rangePickerElevation,
+    Color? rangePickerShadowColor,
+    Color? rangePickerSurfaceTintColor,
+    ShapeBorder? rangePickerShape,
+    Color? rangePickerHeaderBackgroundColor,
+    Color? rangePickerHeaderForegroundColor,
+    TextStyle? rangePickerHeaderHeadlineStyle,
+    TextStyle? rangePickerHeaderHelpStyle,
+    Color? rangeSelectionBackgroundColor,
+    MaterialStateProperty<Color?>? rangeSelectionOverlayColor,
+  }) {
+    return DatePickerThemeData(
+      backgroundColor: backgroundColor ?? this.backgroundColor,
+      elevation: elevation ?? this.elevation,
+      shadowColor: shadowColor ?? this.shadowColor,
+      surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
+      shape: shape ?? this.shape,
+      headerBackgroundColor: headerBackgroundColor ?? this.headerBackgroundColor,
+      headerForegroundColor: headerForegroundColor ?? this.headerForegroundColor,
+      headerHeadlineStyle: headerHeadlineStyle ?? this.headerHeadlineStyle,
+      headerHelpStyle: headerHelpStyle ?? this.headerHelpStyle,
+      weekdayStyle: weekdayStyle ?? this.weekdayStyle,
+      dayStyle: dayStyle ?? this.dayStyle,
+      dayForegroundColor: dayForegroundColor ?? this.dayForegroundColor,
+      dayBackgroundColor: dayBackgroundColor ?? this.dayBackgroundColor,
+      dayOverlayColor: dayOverlayColor ?? this.dayOverlayColor,
+      todayForegroundColor: todayForegroundColor ?? this.todayForegroundColor,
+      todayBackgroundColor: todayBackgroundColor ?? this.todayBackgroundColor,
+      todayBorder: todayBorder ?? this.todayBorder,
+      yearStyle: yearStyle ?? this.yearStyle,
+      yearForegroundColor: yearForegroundColor ?? this.yearForegroundColor,
+      yearBackgroundColor: yearBackgroundColor ?? this.yearBackgroundColor,
+      yearOverlayColor: yearOverlayColor ?? this.yearOverlayColor,
+      rangePickerBackgroundColor: rangePickerBackgroundColor ?? this.rangePickerBackgroundColor,
+      rangePickerElevation: rangePickerElevation ?? this.rangePickerElevation,
+      rangePickerShadowColor: rangePickerShadowColor ?? this.rangePickerShadowColor,
+      rangePickerSurfaceTintColor: rangePickerSurfaceTintColor ?? this.rangePickerSurfaceTintColor,
+      rangePickerShape: rangePickerShape ?? this.rangePickerShape,
+      rangePickerHeaderBackgroundColor: rangePickerHeaderBackgroundColor ?? this.rangePickerHeaderBackgroundColor,
+      rangePickerHeaderForegroundColor: rangePickerHeaderForegroundColor ?? this.rangePickerHeaderForegroundColor,
+      rangePickerHeaderHeadlineStyle: rangePickerHeaderHeadlineStyle ?? this.rangePickerHeaderHeadlineStyle,
+      rangePickerHeaderHelpStyle: rangePickerHeaderHelpStyle ?? this.rangePickerHeaderHelpStyle,
+      rangeSelectionBackgroundColor: rangeSelectionBackgroundColor ?? this.rangeSelectionBackgroundColor,
+      rangeSelectionOverlayColor: rangeSelectionOverlayColor ?? this.rangeSelectionOverlayColor,
+    );
+  }
+
+  /// Linearly interpolates between two [DatePickerThemeData].
+  static DatePickerThemeData lerp(DatePickerThemeData? a, DatePickerThemeData? b, double t) {
+    return DatePickerThemeData(
+      backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
+      elevation: lerpDouble(a?.elevation, b?.elevation, t),
+      shadowColor: Color.lerp(a?.shadowColor, b?.shadowColor, t),
+      surfaceTintColor: Color.lerp(a?.surfaceTintColor, b?.surfaceTintColor, t),
+      shape: ShapeBorder.lerp(a?.shape, b?.shape, t),
+      headerBackgroundColor: Color.lerp(a?.headerBackgroundColor, b?.headerBackgroundColor, t),
+      headerForegroundColor: Color.lerp(a?.headerForegroundColor, b?.headerForegroundColor, t),
+      headerHeadlineStyle: TextStyle.lerp(a?.headerHeadlineStyle, b?.headerHeadlineStyle, t),
+      headerHelpStyle: TextStyle.lerp(a?.headerHelpStyle, b?.headerHelpStyle, t),
+      weekdayStyle: TextStyle.lerp(a?.weekdayStyle, b?.weekdayStyle, t),
+      dayStyle: TextStyle.lerp(a?.dayStyle, b?.dayStyle, t),
+      dayForegroundColor: MaterialStateProperty.lerp<Color?>(a?.dayForegroundColor, b?.dayForegroundColor, t, Color.lerp),
+      dayBackgroundColor: MaterialStateProperty.lerp<Color?>(a?.dayBackgroundColor, b?.dayBackgroundColor, t, Color.lerp),
+      dayOverlayColor: MaterialStateProperty.lerp<Color?>(a?.dayOverlayColor, b?.dayOverlayColor, t, Color.lerp),
+      todayForegroundColor: MaterialStateProperty.lerp<Color?>(a?.todayForegroundColor, b?.todayForegroundColor, t, Color.lerp),
+      todayBackgroundColor: MaterialStateProperty.lerp<Color?>(a?.todayBackgroundColor, b?.todayBackgroundColor, t, Color.lerp),
+      todayBorder: _lerpBorderSide(a?.todayBorder, b?.todayBorder, t),
+      yearStyle: TextStyle.lerp(a?.yearStyle, b?.yearStyle, t),
+      yearForegroundColor: MaterialStateProperty.lerp<Color?>(a?.yearForegroundColor, b?.yearForegroundColor, t, Color.lerp),
+      yearBackgroundColor: MaterialStateProperty.lerp<Color?>(a?.yearBackgroundColor, b?.yearBackgroundColor, t, Color.lerp),
+      yearOverlayColor: MaterialStateProperty.lerp<Color?>(a?.yearOverlayColor, b?.yearOverlayColor, t, Color.lerp),
+      rangePickerBackgroundColor: Color.lerp(a?.rangePickerBackgroundColor, b?.rangePickerBackgroundColor, t),
+      rangePickerElevation: lerpDouble(a?.rangePickerElevation, b?.rangePickerElevation, t),
+      rangePickerShadowColor: Color.lerp(a?.rangePickerShadowColor, b?.rangePickerShadowColor, t),
+      rangePickerSurfaceTintColor: Color.lerp(a?.rangePickerSurfaceTintColor, b?.rangePickerSurfaceTintColor, t),
+      rangePickerShape: ShapeBorder.lerp(a?.rangePickerShape, b?.rangePickerShape, t),
+      rangePickerHeaderBackgroundColor: Color.lerp(a?.rangePickerHeaderBackgroundColor, b?.rangePickerHeaderBackgroundColor, t),
+      rangePickerHeaderForegroundColor: Color.lerp(a?.rangePickerHeaderForegroundColor, b?.rangePickerHeaderForegroundColor, t),
+      rangePickerHeaderHeadlineStyle: TextStyle.lerp(a?.rangePickerHeaderHeadlineStyle, b?.rangePickerHeaderHeadlineStyle, t),
+      rangePickerHeaderHelpStyle: TextStyle.lerp(a?.rangePickerHeaderHelpStyle, b?.rangePickerHeaderHelpStyle, t),
+      rangeSelectionBackgroundColor: Color.lerp(a?.rangeSelectionBackgroundColor, b?.rangeSelectionBackgroundColor, t),
+      rangeSelectionOverlayColor: MaterialStateProperty.lerp<Color?>(a?.rangeSelectionOverlayColor, b?.rangeSelectionOverlayColor, t, Color.lerp),
+    );
+  }
+
+  static BorderSide? _lerpBorderSide(BorderSide? a, BorderSide? b, double t) {
+    if (a == null && b == null) {
+      return null;
+    }
+    if (a == null) {
+      return BorderSide.lerp(BorderSide(width: 0, color: b!.color.withAlpha(0)), b, t);
+    }
+    return BorderSide.lerp(a, BorderSide(width: 0, color: a.color.withAlpha(0)), t);
+  }
+
+  @override
+  int get hashCode => Object.hashAll(<Object?>[
+    backgroundColor,
+    elevation,
+    shadowColor,
+    surfaceTintColor,
+    shape,
+    headerBackgroundColor,
+    headerForegroundColor,
+    headerHeadlineStyle,
+    headerHelpStyle,
+    weekdayStyle,
+    dayStyle,
+    dayForegroundColor,
+    dayBackgroundColor,
+    dayOverlayColor,
+    todayForegroundColor,
+    todayBackgroundColor,
+    todayBorder,
+    yearStyle,
+    yearForegroundColor,
+    yearBackgroundColor,
+    yearOverlayColor,
+    rangePickerBackgroundColor,
+    rangePickerElevation,
+    rangePickerShadowColor,
+    rangePickerSurfaceTintColor,
+    rangePickerShape,
+    rangePickerHeaderBackgroundColor,
+    rangePickerHeaderForegroundColor,
+    rangePickerHeaderHeadlineStyle,
+    rangePickerHeaderHelpStyle,
+    rangeSelectionBackgroundColor,
+    rangeSelectionOverlayColor,
+  ]);
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) {
+      return true;
+    }
+    return other is DatePickerThemeData
+      && other.backgroundColor == backgroundColor
+      && other.elevation == elevation
+      && other.shadowColor == shadowColor
+      && other.surfaceTintColor == surfaceTintColor
+      && other.shape == shape
+      && other.headerBackgroundColor == headerBackgroundColor
+      && other.headerForegroundColor == headerForegroundColor
+      && other.headerHeadlineStyle == headerHeadlineStyle
+      && other.headerHelpStyle == headerHelpStyle
+      && other.weekdayStyle == weekdayStyle
+      && other.dayStyle == dayStyle
+      && other.dayForegroundColor == dayForegroundColor
+      && other.dayBackgroundColor == dayBackgroundColor
+      && other.dayOverlayColor == dayOverlayColor
+      && other.todayForegroundColor == todayForegroundColor
+      && other.todayBackgroundColor == todayBackgroundColor
+      && other.todayBorder == todayBorder
+      && other.yearStyle == yearStyle
+      && other.yearForegroundColor == yearForegroundColor
+      && other.yearBackgroundColor == yearBackgroundColor
+      && other.yearOverlayColor == yearOverlayColor
+      && other.rangePickerBackgroundColor == rangePickerBackgroundColor
+      && other.rangePickerElevation == rangePickerElevation
+      && other.rangePickerShadowColor == rangePickerShadowColor
+      && other.rangePickerSurfaceTintColor == rangePickerSurfaceTintColor
+      && other.rangePickerShape == rangePickerShape
+      && other.rangePickerHeaderBackgroundColor == rangePickerHeaderBackgroundColor
+      && other.rangePickerHeaderForegroundColor == rangePickerHeaderForegroundColor
+      && other.rangePickerHeaderHeadlineStyle == rangePickerHeaderHeadlineStyle
+      && other.rangePickerHeaderHelpStyle == rangePickerHeaderHelpStyle
+      && other.rangeSelectionBackgroundColor == rangeSelectionBackgroundColor
+      && other.rangeSelectionOverlayColor == rangeSelectionOverlayColor;
+  }
+
+  @override
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+    super.debugFillProperties(properties);
+    properties.add(ColorProperty('backgroundColor', backgroundColor, defaultValue: null));
+    properties.add(DoubleProperty('elevation', elevation, defaultValue: null));
+    properties.add(ColorProperty('shadowColor', shadowColor, defaultValue: null));
+    properties.add(ColorProperty('surfaceTintColor', surfaceTintColor, defaultValue: null));
+    properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
+    properties.add(ColorProperty('headerBackgroundColor', headerBackgroundColor, defaultValue: null));
+    properties.add(ColorProperty('headerForegroundColor', headerForegroundColor, defaultValue: null));
+    properties.add(DiagnosticsProperty<TextStyle>('headerHeadlineStyle', headerHeadlineStyle, defaultValue: null));
+    properties.add(DiagnosticsProperty<TextStyle>('headerHelpStyle', headerHelpStyle, defaultValue: null));
+    properties.add(DiagnosticsProperty<TextStyle>('weekDayStyle', weekdayStyle, defaultValue: null));
+    properties.add(DiagnosticsProperty<TextStyle>('dayStyle', dayStyle, defaultValue: null));
+    properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('dayForegroundColor', dayForegroundColor, defaultValue: null));
+    properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('dayBackgroundColor', dayBackgroundColor, defaultValue: null));
+    properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('dayOverlayColor', dayOverlayColor, defaultValue: null));
+    properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('todayForegroundColor', todayForegroundColor, defaultValue: null));
+    properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('todayBackgroundColor', todayBackgroundColor, defaultValue: null));
+    properties.add(DiagnosticsProperty<BorderSide?>('todayBorder', todayBorder, defaultValue: null));
+    properties.add(DiagnosticsProperty<TextStyle>('yearStyle', yearStyle, defaultValue: null));
+    properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('yearForegroundColor', yearForegroundColor, defaultValue: null));
+    properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('yearBackgroundColor', yearBackgroundColor, defaultValue: null));
+    properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('yearOverlayColor', yearOverlayColor, defaultValue: null));
+    properties.add(ColorProperty('rangePickerBackgroundColor', rangePickerBackgroundColor, defaultValue: null));
+    properties.add(DoubleProperty('rangePickerElevation', rangePickerElevation, defaultValue: null));
+    properties.add(ColorProperty('rangePickerShadowColor', rangePickerShadowColor, defaultValue: null));
+    properties.add(ColorProperty('rangePickerSurfaceTintColor', rangePickerSurfaceTintColor, defaultValue: null));
+    properties.add(DiagnosticsProperty<ShapeBorder>('rangePickerShape', rangePickerShape, defaultValue: null));
+    properties.add(ColorProperty('rangePickerHeaderBackgroundColor', rangePickerHeaderBackgroundColor, defaultValue: null));
+    properties.add(ColorProperty('rangePickerHeaderForegroundColor', rangePickerHeaderForegroundColor, defaultValue: null));
+    properties.add(DiagnosticsProperty<TextStyle>('rangePickerHeaderHeadlineStyle', rangePickerHeaderHeadlineStyle, defaultValue: null));
+    properties.add(DiagnosticsProperty<TextStyle>('rangePickerHeaderHelpStyle', rangePickerHeaderHelpStyle, defaultValue: null));
+    properties.add(ColorProperty('rangeSelectionBackgroundColor', rangeSelectionBackgroundColor, defaultValue: null));
+    properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('rangeSelectionOverlayColor', rangeSelectionOverlayColor, defaultValue: null));
+  }
+}
+
+/// An inherited widget that defines the visual properties for
+/// [DatePickerDialog]s in this widget's subtree.
+///
+/// Values specified here are used for [DatePickerDialog] properties that are not
+/// given an explicit non-null value.
+class DatePickerTheme extends InheritedTheme {
+  /// Creates a [DatePickerTheme] that controls visual parameters for
+  /// descendent [DatePickerDialog]s.
+  const DatePickerTheme({
+    super.key,
+    required this.data,
+    required super.child,
+  });
+
+  /// Specifies the visual properties used by descendant [DatePickerDialog]
+  /// widgets.
+  final DatePickerThemeData data;
+
+  /// The [data] from the closest instance of this class that encloses the given
+  /// context.
+  ///
+  /// If there is no [DatePickerTheme] in scope, this will return
+  /// [ThemeData.datePickerTheme] from the ambient [Theme].
+  ///
+  /// Typical usage is as follows:
+  ///
+  /// ```dart
+  /// DatePickerThemeData theme = DatePickerTheme.of(context);
+  /// ```
+  ///
+  /// See also:
+  ///
+  ///  * [maybeOf], which returns null if it doesn't find a
+  ///    [DatePickerTheme] ancestor.
+  ///  * [defaults], which will return the default properties used when no
+  ///    other [DatePickerTheme] has been provided.
+  static DatePickerThemeData of(BuildContext context) {
+    return maybeOf(context) ?? Theme.of(context).datePickerTheme;
+  }
+
+  /// The data from the closest instance of this class that encloses the given
+  /// context, if any.
+  ///
+  /// Use this function if you want to allow situations where no
+  /// [DatePickerTheme] is in scope. Prefer using [DatePickerTheme.of]
+  /// in situations where a [DatePickerThemeData] is expected to be
+  /// non-null.
+  ///
+  /// If there is no [DatePickerTheme] in scope, then this function will
+  /// return null.
+  ///
+  /// Typical usage is as follows:
+  ///
+  /// ```dart
+  /// DatePickerThemeData? theme = DatePickerTheme.maybeOf(context);
+  /// if (theme == null) {
+  ///   // Do something else instead.
+  /// }
+  /// ```
+  ///
+  /// See also:
+  ///
+  ///  * [of], which will return [ThemeData.datePickerTheme] if it doesn't
+  ///    find a [DatePickerTheme] ancestor, instead of returning null.
+  ///  * [defaults], which will return the default properties used when no
+  ///    other [DatePickerTheme] has been provided.
+  static DatePickerThemeData? maybeOf(BuildContext context) {
+    return context.dependOnInheritedWidgetOfExactType<DatePickerTheme>()?.data;
+  }
+
+  /// A DatePickerThemeData used as the default properties for date pickers.
+  ///
+  /// This is only used for properties not already specified in the ambient
+  /// [DatePickerTheme.of].
+  ///
+  /// See also:
+  ///
+  ///  * [of], which will return [ThemeData.datePickerTheme] if it doesn't
+  ///    find a [DatePickerTheme] ancestor, instead of returning null.
+  ///  * [maybeOf], which returns null if it doesn't find a
+  ///    [DatePickerTheme] ancestor.
+  static DatePickerThemeData defaults(BuildContext context) {
+    return Theme.of(context).useMaterial3
+      ? _DatePickerDefaultsM3(context)
+      : _DatePickerDefaultsM2(context);
+  }
+
+  @override
+  Widget wrap(BuildContext context, Widget child) {
+    return DatePickerTheme(data: data, child: child);
+  }
+
+  @override
+  bool updateShouldNotify(DatePickerTheme oldWidget) => data != oldWidget.data;
+}
+
+// Hand coded defaults based on Material Design 2.
+class _DatePickerDefaultsM2 extends DatePickerThemeData {
+  _DatePickerDefaultsM2(this.context)
+    : super(
+        elevation: 24.0,
+        shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))),
+        rangePickerElevation: 0.0,
+        rangePickerShape: const RoundedRectangleBorder(),
+      );
+
+  final BuildContext context;
+  late final ThemeData _theme = Theme.of(context);
+  late final ColorScheme _colors = _theme.colorScheme;
+  late final TextTheme _textTheme = _theme.textTheme;
+  late final bool _isDark = _colors.brightness == Brightness.dark;
+
+  @override
+  Color? get headerBackgroundColor => _isDark ? _colors.surface : _colors.primary;
+
+  @override
+  Color? get headerForegroundColor => _isDark ? _colors.onSurface : _colors.onPrimary;
+
+  @override
+  TextStyle? get headerHeadlineStyle => _textTheme.headlineSmall;
+
+  @override
+  TextStyle? get headerHelpStyle => _textTheme.labelSmall;
+
+  @override
+  TextStyle? get weekdayStyle => _textTheme.bodySmall?.apply(
+    color: _colors.onSurface.withOpacity(0.60),
+  );
+
+  @override
+  TextStyle? get dayStyle => _textTheme.bodySmall;
+
+  @override
+  MaterialStateProperty<Color?>? get dayForegroundColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.selected)) {
+        return _colors.onPrimary;
+      } else if (states.contains(MaterialState.disabled)) {
+        return _colors.onSurface.withOpacity(0.38);
+      }
+      return _colors.onSurface;
+    });
+
+  @override
+  MaterialStateProperty<Color?>? get dayBackgroundColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.selected)) {
+        return _colors.primary;
+      }
+      return null;
+    });
+
+  @override
+  MaterialStateProperty<Color?>? get dayOverlayColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.selected)) {
+        if (states.contains(MaterialState.hovered)) {
+          return _colors.onPrimary.withOpacity(0.08);
+        }
+        if (states.contains(MaterialState.focused)) {
+          return _colors.onPrimary.withOpacity(0.12);
+        }
+        if (states.contains(MaterialState.pressed)) {
+          return _colors.onPrimary.withOpacity(0.38);
+        }
+      } else {
+        if (states.contains(MaterialState.hovered)) {
+          return _colors.onSurfaceVariant.withOpacity(0.08);
+        }
+        if (states.contains(MaterialState.focused)) {
+          return _colors.onSurfaceVariant.withOpacity(0.12);
+        }
+        if (states.contains(MaterialState.pressed)) {
+          return _colors.onSurfaceVariant.withOpacity(0.12);
+        }
+      }
+      return null;
+    });
+
+  @override
+  MaterialStateProperty<Color?>? get todayForegroundColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.selected)) {
+        return _colors.onPrimary;
+      } else if (states.contains(MaterialState.disabled)) {
+        return _colors.onSurface.withOpacity(0.38);
+      }
+      return _colors.primary;
+    });
+
+  @override
+  MaterialStateProperty<Color?>? get todayBackgroundColor => dayBackgroundColor;
+
+  @override
+  BorderSide? get todayBorder => BorderSide(color: _colors.primary);
+
+  @override
+  TextStyle? get yearStyle => _textTheme.bodyLarge;
+
+  @override
+  Color? get rangePickerBackgroundColor => _colors.surface;
+
+  @override
+  Color? get rangePickerShadowColor => Colors.transparent;
+
+  @override
+  Color? get rangePickerSurfaceTintColor => Colors.transparent;
+
+  @override
+  Color? get rangePickerHeaderBackgroundColor => _isDark ? _colors.surface : _colors.primary;
+
+  @override
+  Color? get rangePickerHeaderForegroundColor => _isDark ? _colors.onSurface : _colors.onPrimary;
+
+  @override
+  TextStyle? get rangePickerHeaderHeadlineStyle => _textTheme.headlineSmall;
+
+  @override
+  TextStyle? get rangePickerHeaderHelpStyle => _textTheme.labelSmall;
+
+  @override
+  Color? get rangeSelectionBackgroundColor => _colors.primary.withOpacity(0.12);
+
+  @override
+  MaterialStateProperty<Color?>? get rangeSelectionOverlayColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.selected)) {
+        if (states.contains(MaterialState.hovered)) {
+          return _colors.onPrimary.withOpacity(0.08);
+        }
+        if (states.contains(MaterialState.focused)) {
+          return _colors.onPrimary.withOpacity(0.12);
+        }
+        if (states.contains(MaterialState.pressed)) {
+          return _colors.onPrimary.withOpacity(0.38);
+        }
+      } else {
+        if (states.contains(MaterialState.hovered)) {
+          return _colors.onSurfaceVariant.withOpacity(0.08);
+        }
+        if (states.contains(MaterialState.focused)) {
+          return _colors.onSurfaceVariant.withOpacity(0.12);
+        }
+        if (states.contains(MaterialState.pressed)) {
+          return _colors.onSurfaceVariant.withOpacity(0.12);
+        }
+      }
+      return null;
+    });
+}
+
+// BEGIN GENERATED TOKEN PROPERTIES - DatePicker
+
+// Do not edit by hand. The code between the "BEGIN GENERATED" and
+// "END GENERATED" comments are generated from data in the Material
+// Design token database by the script:
+//   dev/tools/gen_defaults/bin/gen_defaults.dart.
+
+// Token database version: v0_158
+
+class _DatePickerDefaultsM3 extends DatePickerThemeData {
+  _DatePickerDefaultsM3(this.context)
+    : super(
+        elevation: 6.0,
+        shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(28.0))),
+        rangePickerElevation: 0.0,
+        rangePickerShape: const RoundedRectangleBorder(),
+      );
+
+  final BuildContext context;
+  late final ThemeData _theme = Theme.of(context);
+  late final ColorScheme _colors = _theme.colorScheme;
+  late final TextTheme _textTheme = _theme.textTheme;
+
+  @override
+  Color? get backgroundColor => _colors.surface;
+
+  @override
+  Color? get shadowColor => Colors.transparent;
+
+  @override
+  Color? get surfaceTintColor => _colors.surfaceTint;
+
+  @override
+  Color? get headerBackgroundColor => Colors.transparent;
+
+  @override
+  Color? get headerForegroundColor => _colors.onSurfaceVariant;
+
+  @override
+  TextStyle? get headerHeadlineStyle => _textTheme.headlineLarge;
+
+  @override
+  TextStyle? get headerHelpStyle => _textTheme.labelLarge;
+
+  @override
+  TextStyle? get weekdayStyle => _textTheme.bodyLarge?.apply(
+    color: _colors.onSurface,
+  );
+
+  @override
+  TextStyle? get dayStyle => _textTheme.bodyLarge;
+
+  @override
+  MaterialStateProperty<Color?>? get dayForegroundColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.selected)) {
+        return _colors.onPrimary;
+      } else if (states.contains(MaterialState.disabled)) {
+        return _colors.onSurface.withOpacity(0.38);
+      }
+      return _colors.onSurface;
+    });
+
+  @override
+  MaterialStateProperty<Color?>? get dayBackgroundColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.selected)) {
+        return _colors.primary;
+      }
+      return null;
+    });
+
+  @override
+  MaterialStateProperty<Color?>? get dayOverlayColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.selected)) {
+        if (states.contains(MaterialState.hovered)) {
+          return _colors.onPrimary.withOpacity(0.08);
+        }
+        if (states.contains(MaterialState.focused)) {
+          return _colors.onPrimary.withOpacity(0.12);
+        }
+        if (states.contains(MaterialState.pressed)) {
+          return _colors.onPrimary.withOpacity(0.12);
+        }
+      } else {
+        if (states.contains(MaterialState.hovered)) {
+          return _colors.onSurfaceVariant.withOpacity(0.08);
+        }
+        if (states.contains(MaterialState.focused)) {
+          return _colors.onSurfaceVariant.withOpacity(0.12);
+        }
+        if (states.contains(MaterialState.pressed)) {
+          return _colors.onSurfaceVariant.withOpacity(0.12);
+        }
+      }
+      return null;
+    });
+
+  @override
+  MaterialStateProperty<Color?>? get todayForegroundColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.selected)) {
+        return _colors.onPrimary;
+      } else if (states.contains(MaterialState.disabled)) {
+        return _colors.primary.withOpacity(0.38);
+      }
+      return _colors.primary;
+    });
+
+  @override
+  MaterialStateProperty<Color?>? get todayBackgroundColor => dayBackgroundColor;
+
+  @override
+  BorderSide? get todayBorder => BorderSide(color: _colors.primary);
+
+  @override
+  TextStyle? get yearStyle => _textTheme.bodyLarge;
+
+  @override
+  MaterialStateProperty<Color?>? get yearForegroundColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.selected)) {
+        return _colors.onPrimary;
+      } else if (states.contains(MaterialState.disabled)) {
+        return _colors.onSurfaceVariant.withOpacity(0.38);
+      }
+      return _colors.onSurfaceVariant;
+    });
+
+  @override
+  MaterialStateProperty<Color?>? get yearBackgroundColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.selected)) {
+        return _colors.primary;
+      }
+      return null;
+    });
+
+  @override
+  MaterialStateProperty<Color?>? get yearOverlayColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.selected)) {
+        if (states.contains(MaterialState.hovered)) {
+          return _colors.onPrimary.withOpacity(0.08);
+        }
+        if (states.contains(MaterialState.focused)) {
+          return _colors.onPrimary.withOpacity(0.12);
+        }
+        if (states.contains(MaterialState.pressed)) {
+          return _colors.onPrimary.withOpacity(0.12);
+        }
+      } else {
+        if (states.contains(MaterialState.hovered)) {
+          return _colors.onSurfaceVariant.withOpacity(0.08);
+        }
+        if (states.contains(MaterialState.focused)) {
+          return _colors.onSurfaceVariant.withOpacity(0.12);
+        }
+        if (states.contains(MaterialState.pressed)) {
+          return _colors.onSurfaceVariant.withOpacity(0.12);
+        }
+      }
+      return null;
+    });
+
+    @override
+    Color? get rangePickerShadowColor => Colors.transparent;
+
+    @override
+    Color? get rangePickerSurfaceTintColor => Colors.transparent;
+
+    @override
+    Color? get rangeSelectionBackgroundColor => _colors.primaryContainer;
+
+  @override
+  MaterialStateProperty<Color?>? get rangeSelectionOverlayColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.hovered)) {
+        return null;
+      }
+      if (states.contains(MaterialState.focused)) {
+        return null;
+      }
+      if (states.contains(MaterialState.pressed)) {
+        return null;
+      }
+      return null;
+    });
+
+  @override
+  Color? get rangePickerHeaderBackgroundColor => Colors.transparent;
+
+  @override
+  Color? get rangePickerHeaderForegroundColor => _colors.onSurfaceVariant;
+
+  @override
+  TextStyle? get rangePickerHeaderHeadlineStyle => _textTheme.titleLarge;
+
+  @override
+  TextStyle? get rangePickerHeaderHelpStyle => _textTheme.titleSmall;
+
+
+}
+
+// END GENERATED TOKEN PROPERTIES - DatePicker
diff --git a/framework/lib/src/material/debug.dart b/framework/lib/src/material/debug.dart
index 260ab95..7f212ef 100644
--- a/framework/lib/src/material/debug.dart
+++ b/framework/lib/src/material/debug.dart
@@ -11,7 +11,8 @@
 // Examples can assume:
 // late BuildContext context;
 
-/// Asserts that the given context has a [Material] ancestor.
+/// Asserts that the given context has a [Material] ancestor within the closest
+/// [LookupBoundary].
 ///
 /// Used by many Material Design widgets to make sure that they are
 /// only used in contexts where they can print ink onto some material.
@@ -32,12 +33,17 @@
 /// Does nothing if asserts are disabled. Always returns true.
 bool debugCheckHasMaterial(BuildContext context) {
   assert(() {
-    if (context.widget is! Material && context.findAncestorWidgetOfExactType<Material>() == null) {
+    if (LookupBoundary.findAncestorWidgetOfExactType<Material>(context) == null) {
+      final bool hiddenByBoundary = LookupBoundary.debugIsHidingAncestorWidgetOfExactType<Material>(context);
       throw FlutterError.fromParts(<DiagnosticsNode>[
-        ErrorSummary('No Material widget found.'),
+        ErrorSummary('No Material widget found${hiddenByBoundary ? ' within the closest LookupBoundary' : ''}.'),
+        if (hiddenByBoundary)
+          ErrorDescription(
+            'There is an ancestor Material widget, but it is hidden by a LookupBoundary.'
+          ),
         ErrorDescription(
           '${context.widget.runtimeType} widgets require a Material '
-          'widget ancestor.\n'
+          'widget ancestor within the closest LookupBoundary.\n'
           'In Material Design, most widgets are conceptually "printed" on '
           "a sheet of material. In Flutter's material library, that "
           'material is represented by the Material widget. It is the '
diff --git a/framework/lib/src/material/desktop_text_selection.dart b/framework/lib/src/material/desktop_text_selection.dart
index 3b59c24..5de5c8e 100644
--- a/framework/lib/src/material/desktop_text_selection.dart
+++ b/framework/lib/src/material/desktop_text_selection.dart
@@ -177,12 +177,11 @@
       return const SizedBox.shrink();
     }
 
-    final MediaQueryData mediaQuery = MediaQuery.of(context);
-
+    final EdgeInsets mediaQueryPadding = MediaQuery.paddingOf(context);
     final Offset midpointAnchor = Offset(
       clampDouble(widget.selectionMidpoint.dx - widget.globalEditableRegion.left,
-        mediaQuery.padding.left,
-        mediaQuery.size.width - mediaQuery.padding.right,
+        mediaQueryPadding.left,
+        MediaQuery.sizeOf(context).width - mediaQueryPadding.right,
       ),
       widget.selectionMidpoint.dy - widget.globalEditableRegion.top,
     );
diff --git a/framework/lib/src/material/desktop_text_selection_toolbar.dart b/framework/lib/src/material/desktop_text_selection_toolbar.dart
index 8bdf670..adb41ea 100644
--- a/framework/lib/src/material/desktop_text_selection_toolbar.dart
+++ b/framework/lib/src/material/desktop_text_selection_toolbar.dart
@@ -64,9 +64,8 @@
   @override
   Widget build(BuildContext context) {
     assert(debugCheckHasMediaQuery(context));
-    final MediaQueryData mediaQuery = MediaQuery.of(context);
 
-    final double paddingAbove = mediaQuery.padding.top + _kToolbarScreenPadding;
+    final double paddingAbove = MediaQuery.paddingOf(context).top + _kToolbarScreenPadding;
     final Offset localAdjustment = Offset(_kToolbarScreenPadding, paddingAbove);
 
     return Padding(
diff --git a/framework/lib/src/material/dialog.dart b/framework/lib/src/material/dialog.dart
index ce4a864..414e8d7 100644
--- a/framework/lib/src/material/dialog.dart
+++ b/framework/lib/src/material/dialog.dart
@@ -60,8 +60,7 @@
     this.shape,
     this.alignment,
     this.child,
-  }) : assert(clipBehavior != null),
-       assert(elevation == null || elevation >= 0.0),
+  }) : assert(elevation == null || elevation >= 0.0),
        _fullscreen = false;
 
   /// Creates a fullscreen dialog.
@@ -217,7 +216,7 @@
   Widget build(BuildContext context) {
     final ThemeData theme = Theme.of(context);
     final DialogTheme dialogTheme = DialogTheme.of(context);
-    final EdgeInsets effectivePadding = MediaQuery.of(context).viewInsets + (insetPadding ?? EdgeInsets.zero);
+    final EdgeInsets effectivePadding = MediaQuery.viewInsetsOf(context) + (insetPadding ?? EdgeInsets.zero);
     final DialogTheme defaults = theme.useMaterial3
       ? (_fullscreen ? _DialogFullscreenDefaultsM3(context) : _DialogDefaultsM3(context))
       : _DialogDefaultsM2(context);
@@ -303,9 +302,9 @@
 ///     builder: (BuildContext context) {
 ///       return AlertDialog(
 ///         title: const Text('AlertDialog Title'),
-///         content: SingleChildScrollView(
+///         content: const SingleChildScrollView(
 ///           child: ListBody(
-///             children: const <Widget>[
+///             children: <Widget>[
 ///               Text('This is a demo alert dialog.'),
 ///               Text('Would you like to approve of this message?'),
 ///             ],
@@ -385,7 +384,7 @@
     this.shape,
     this.alignment,
     this.scrollable = false,
-  }) : assert(clipBehavior != null);
+  });
 
   /// An optional icon to display at the top of the dialog.
   ///
@@ -642,7 +641,7 @@
 
     // The paddingScaleFactor is used to adjust the padding of Dialog's
     // children.
-    final double paddingScaleFactor = _paddingScaleFactor(MediaQuery.of(context).textScaleFactor);
+    final double paddingScaleFactor = _paddingScaleFactor(MediaQuery.textScaleFactorOf(context));
     final TextDirection? textDirection = Directionality.maybeOf(context);
 
     Widget? iconWidget;
@@ -973,8 +972,7 @@
     this.clipBehavior = Clip.none,
     this.shape,
     this.alignment,
-  }) : assert(titlePadding != null),
-       assert(contentPadding != null);
+  });
 
   /// The (optional) title of the dialog is displayed in a large font at the top
   /// of the dialog.
@@ -1075,7 +1073,7 @@
 
     // The paddingScaleFactor is used to adjust the padding of Dialog
     // children.
-    final double paddingScaleFactor = _paddingScaleFactor(MediaQuery.of(context).textScaleFactor);
+    final double paddingScaleFactor = _paddingScaleFactor(MediaQuery.textScaleFactorOf(context));
     final TextDirection? textDirection = Directionality.maybeOf(context);
 
     Widget? titleWidget;
@@ -1238,8 +1236,11 @@
 ///
 /// {@macro flutter.widgets.RestorationManager}
 ///
-/// The `traversalEdgeBehavior` argument controls the transfer of focus
-/// beyond the first and the last items of the dialog route.
+/// If not null, `traversalEdgeBehavior` argument specifies the transfer of
+/// focus beyond the first and the last items of the dialog route. By default,
+/// uses [TraversalEdgeBehavior.closedLoop], because it's typical for dialogs
+/// to allow users to cycle through widgets inside it without leaving the
+/// dialog.
 ///
 /// ** See code in examples/api/lib/material/dialog/show_dialog.2.dart **
 /// {@end-tool}
@@ -1268,10 +1269,6 @@
   Offset? anchorPoint,
   TraversalEdgeBehavior? traversalEdgeBehavior,
 }) {
-  assert(builder != null);
-  assert(barrierDismissible != null);
-  assert(useSafeArea != null);
-  assert(useRootNavigator != null);
   assert(_debugIsActive(context));
   assert(debugCheckHasMaterialLocalizations(context));
 
@@ -1293,7 +1290,7 @@
     settings: routeSettings,
     themes: themes,
     anchorPoint: anchorPoint,
-    traversalEdgeBehavior: traversalEdgeBehavior,
+    traversalEdgeBehavior: traversalEdgeBehavior ?? TraversalEdgeBehavior.closedLoop,
   ));
 }
 
@@ -1373,8 +1370,7 @@
     super.settings,
     super.anchorPoint,
     super.traversalEdgeBehavior,
-  }) : assert(barrierDismissible != null),
-       super(
+  }) : super(
          pageBuilder: (BuildContext buildContext, Animation<double> animation, Animation<double> secondaryAnimation) {
            final Widget pageChild = Builder(builder: builder);
            Widget dialog = themes?.wrap(pageChild) ?? pageChild;
@@ -1437,7 +1433,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _DialogDefaultsM3 extends DialogTheme {
   _DialogDefaultsM3(this.context)
@@ -1482,7 +1478,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _DialogFullscreenDefaultsM3 extends DialogTheme {
   const _DialogFullscreenDefaultsM3(this.context);
diff --git a/framework/lib/src/material/dialog_theme.dart b/framework/lib/src/material/dialog_theme.dart
index 5896d87..c39da59 100644
--- a/framework/lib/src/material/dialog_theme.dart
+++ b/framework/lib/src/material/dialog_theme.dart
@@ -111,7 +111,6 @@
   ///
   /// {@macro dart.ui.shadow.lerp}
   static DialogTheme lerp(DialogTheme? a, DialogTheme? b, double t) {
-    assert(t != null);
     return DialogTheme(
       backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
       elevation: lerpDouble(a?.elevation, b?.elevation, t),
diff --git a/framework/lib/src/material/divider.dart b/framework/lib/src/material/divider.dart
index d40d117..5ddf599 100644
--- a/framework/lib/src/material/divider.dart
+++ b/framework/lib/src/material/divider.dart
@@ -328,7 +328,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _DividerDefaultsM3 extends DividerThemeData {
   const _DividerDefaultsM3(this.context) : super(
diff --git a/framework/lib/src/material/divider_theme.dart b/framework/lib/src/material/divider_theme.dart
index c7926ed..79d631d 100644
--- a/framework/lib/src/material/divider_theme.dart
+++ b/framework/lib/src/material/divider_theme.dart
@@ -87,7 +87,6 @@
   ///
   /// {@macro dart.ui.shadow.lerp}
   static DividerThemeData lerp(DividerThemeData? a, DividerThemeData? b, double t) {
-    assert(t != null);
     return DividerThemeData(
       color: Color.lerp(a?.color, b?.color, t),
       space: lerpDouble(a?.space, b?.space, t),
@@ -144,7 +143,7 @@
     super.key,
     required this.data,
     required super.child,
-  }) : assert(data != null);
+  });
 
   /// The properties for descendant [Divider]s, [VerticalDivider]s, dividers
   /// between [ListTile]s, and dividers between rows in [DataTable]s.
diff --git a/framework/lib/src/material/drawer.dart b/framework/lib/src/material/drawer.dart
index c0943f1..8bca807 100644
--- a/framework/lib/src/material/drawer.dart
+++ b/framework/lib/src/material/drawer.dart
@@ -115,7 +115,7 @@
 /// {@end-tool}
 ///
 /// An open drawer may be closed with a swipe to close gesture, pressing the
-/// the escape key, by tapping the scrim, or by calling pop route function such as
+/// escape key, by tapping the scrim, or by calling pop route function such as
 /// [Navigator.pop]. For example a drawer item might close the drawer when tapped:
 ///
 /// ```dart
@@ -325,10 +325,7 @@
     this.scrimColor,
     this.edgeDragWidth,
     this.enableOpenDragGesture = true,
-  }) : assert(child != null),
-       assert(dragStartBehavior != null),
-       assert(alignment != null),
-       super(key: key);
+  }) : super(key: key);
 
   /// The widget below this widget in the tree.
   ///
@@ -382,11 +379,11 @@
   /// drawer.
   ///
   /// By default, the value used is 20.0 added to the padding edge of
-  /// `MediaQuery.of(context).padding` that corresponds to [alignment].
+  /// `MediaQuery.paddingOf(context)` that corresponds to [alignment].
   /// This ensures that the drag area for notched devices is not obscured. For
   /// example, if [alignment] is set to [DrawerAlignment.start] and
   /// `TextDirection.of(context)` is set to [TextDirection.ltr],
-  /// 20.0 will be added to `MediaQuery.of(context).padding.left`.
+  /// 20.0 will be added to `MediaQuery.paddingOf(context).left`.
   final double? edgeDragWidth;
 
   /// Whether or not the drawer is opened or closed.
@@ -659,7 +656,6 @@
   }
 
   AlignmentDirectional get _drawerOuterAlignment {
-    assert(widget.alignment != null);
     switch (widget.alignment) {
       case DrawerAlignment.start:
         return AlignmentDirectional.centerStart;
@@ -669,7 +665,6 @@
   }
 
   AlignmentDirectional get _drawerInnerAlignment {
-    assert(widget.alignment != null);
     switch (widget.alignment) {
       case DrawerAlignment.start:
         return AlignmentDirectional.centerEnd;
@@ -680,7 +675,6 @@
 
   Widget _buildDrawer(BuildContext context) {
     final bool drawerIsStart = widget.alignment == DrawerAlignment.start;
-    final EdgeInsets padding = MediaQuery.of(context).padding;
     final TextDirection textDirection = Directionality.of(context);
     final bool isDesktop;
     switch (Theme.of(context).platform) {
@@ -698,6 +692,7 @@
 
     double? dragAreaWidth = widget.edgeDragWidth;
     if (widget.edgeDragWidth == null) {
+      final EdgeInsets padding = MediaQuery.paddingOf(context);
       switch (textDirection) {
         case TextDirection.ltr:
           dragAreaWidth = _kEdgeDragWidth +
@@ -741,7 +736,6 @@
           platformHasBackButton = false;
           break;
       }
-      assert(platformHasBackButton != null);
 
       final Widget child = _DrawerControllerScope(
         controller: widget,
@@ -827,13 +821,14 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _DrawerDefaultsM3 extends DrawerThemeData {
-  const _DrawerDefaultsM3(this.context)
+  _DrawerDefaultsM3(this.context)
       : super(elevation: 1.0);
 
   final BuildContext context;
+  late final TextDirection direction = Directionality.of(context);
 
   @override
   Color? get backgroundColor => Theme.of(context).colorScheme.surface;
@@ -844,18 +839,22 @@
   @override
   Color? get shadowColor => Colors.transparent;
 
-  // This don't appear to be tokens for this value, but it is
-  // shown in the spec.
+  // There isn't currently a token for this value, but it is shown in the spec,
+  // so hard coding here for now.
   @override
-  ShapeBorder? get shape => const RoundedRectangleBorder(
-    borderRadius: BorderRadius.horizontal(right: Radius.circular(16.0)),
+  ShapeBorder? get shape => RoundedRectangleBorder(
+    borderRadius: const BorderRadiusDirectional.horizontal(
+      end: Radius.circular(16.0),
+    ).resolve(direction),
   );
 
-  // This don't appear to be tokens for this value, but it is
-  // shown in the spec.
+  // There isn't currently a token for this value, but it is shown in the spec,
+  // so hard coding here for now.
   @override
-  ShapeBorder? get endShape => const RoundedRectangleBorder(
-    borderRadius: BorderRadius.horizontal(left: Radius.circular(16.0)),
+  ShapeBorder? get endShape => RoundedRectangleBorder(
+    borderRadius: const BorderRadiusDirectional.horizontal(
+      start: Radius.circular(16.0),
+    ).resolve(direction),
   );
 }
 
diff --git a/framework/lib/src/material/drawer_header.dart b/framework/lib/src/material/drawer_header.dart
index 639a36f..287ae5e 100644
--- a/framework/lib/src/material/drawer_header.dart
+++ b/framework/lib/src/material/drawer_header.dart
@@ -76,7 +76,7 @@
     assert(debugCheckHasMaterial(context));
     assert(debugCheckHasMediaQuery(context));
     final ThemeData theme = Theme.of(context);
-    final double statusBarHeight = MediaQuery.of(context).padding.top;
+    final double statusBarHeight = MediaQuery.paddingOf(context).top;
     return Container(
       height: statusBarHeight + _kDrawerHeaderHeight,
       margin: margin,
diff --git a/framework/lib/src/material/drawer_theme.dart b/framework/lib/src/material/drawer_theme.dart
index 26e2048..6986893 100644
--- a/framework/lib/src/material/drawer_theme.dart
+++ b/framework/lib/src/material/drawer_theme.dart
@@ -99,7 +99,6 @@
   ///
   /// {@macro dart.ui.shadow.lerp}
   static DrawerThemeData? lerp(DrawerThemeData? a, DrawerThemeData? b, double t) {
-    assert(t != null);
     if (a == null && b == null) {
       return null;
     }
@@ -174,7 +173,7 @@
     super.key,
     required this.data,
     required super.child,
-  }) : assert(data != null);
+  });
 
   /// Specifies the background color, scrim color, elevation, and shape for
   /// descendant [Drawer] widgets.
diff --git a/framework/lib/src/material/dropdown.dart b/framework/lib/src/material/dropdown.dart
index f357fc9..4286f51 100644
--- a/framework/lib/src/material/dropdown.dart
+++ b/framework/lib/src/material/dropdown.dart
@@ -434,8 +434,7 @@
     this.menuMaxHeight,
     required this.enableFeedback,
     this.borderRadius,
-  }) : assert(style != null),
-       itemHeights = List<double>.filled(items.length, itemHeight ?? kMinInteractiveDimension);
+  }) : itemHeights = List<double>.filled(items.length, itemHeight ?? kMinInteractiveDimension);
 
   final List<_MenuItem<T>> items;
   final EdgeInsetsGeometry padding;
@@ -664,7 +663,7 @@
     super.key,
     required this.onLayout,
     required this.item,
-  }) : assert(onLayout != null), super(child: item);
+  }) : super(child: item);
 
   final ValueChanged<Size> onLayout;
   final DropdownMenuItem<T>? item;
@@ -681,7 +680,7 @@
 }
 
 class _RenderMenuItem extends RenderProxyBox {
-  _RenderMenuItem(this.onLayout, [RenderBox? child]) : assert(onLayout != null), super(child);
+  _RenderMenuItem(this.onLayout, [RenderBox? child]) : super(child);
 
   ValueChanged<Size> onLayout;
 
@@ -703,7 +702,7 @@
     super.key,
     this.alignment = AlignmentDirectional.centerStart,
     required this.child,
-  }) : assert(child != null);
+  });
 
   /// The widget below this widget in the tree.
   ///
@@ -747,7 +746,7 @@
     this.enabled = true,
     super.alignment,
     required super.child,
-  }) : assert(child != null);
+  });
 
   /// Called when the dropdown menu item is tapped.
   final VoidCallback? onTap;
@@ -775,7 +774,7 @@
   const DropdownButtonHideUnderline({
     super.key,
     required super.child,
-  }) : assert(child != null);
+  });
 
   /// Returns whether the underline of [DropdownButton] widgets should
   /// be hidden.
@@ -898,11 +897,6 @@
                 'Either zero or 2 or more [DropdownMenuItem]s were detected '
                 'with the same value',
               ),
-       assert(elevation != null),
-       assert(iconSize != null),
-       assert(isDense != null),
-       assert(isExpanded != null),
-       assert(autofocus != null),
        assert(itemHeight == null || itemHeight >=  kMinInteractiveDimension),
        _inputDecoration = null,
        _isEmpty = false,
@@ -947,14 +941,7 @@
                 'Either zero or 2 or more [DropdownMenuItem]s were detected '
                 'with the same value',
               ),
-       assert(elevation != null),
-       assert(iconSize != null),
-       assert(isDense != null),
-       assert(isExpanded != null),
-       assert(autofocus != null),
        assert(itemHeight == null || itemHeight >=  kMinInteractiveDimension),
-       assert(isEmpty != null),
-       assert(isFocused != null),
        _inputDecoration = inputDecoration,
        _isEmpty = isEmpty,
        _isFocused = isFocused;
@@ -1333,7 +1320,7 @@
   // Similarly, we don't reduce the height of the button so much that its icon
   // would be clipped.
   double get _denseButtonHeight {
-    final double textScaleFactor = MediaQuery.of(context).textScaleFactor;
+    final double textScaleFactor = MediaQuery.textScaleFactorOf(context);
     final double fontSize = _textStyle!.fontSize ?? Theme.of(context).textTheme.titleMedium!.fontSize!;
     final double scaledFontSize = textScaleFactor * fontSize;
     return math.max(scaledFontSize, math.max(widget.iconSize, _kDenseButtonHeight));
@@ -1369,11 +1356,11 @@
   bool get _enabled => widget.items != null && widget.items!.isNotEmpty && widget.onChanged != null;
 
   Orientation _getOrientation(BuildContext context) {
-    Orientation? result = MediaQuery.maybeOf(context)?.orientation;
+    Orientation? result = MediaQuery.maybeOrientationOf(context);
     if (result == null) {
-      // If there's no MediaQuery, then use the window aspect to determine
+      // If there's no MediaQuery, then use the view aspect to determine
       // orientation.
-      final Size size = WidgetsBinding.instance.window.physicalSize;
+      final Size size = View.of(context).physicalSize;
       result = size.width > size.height ? Orientation.landscape : Orientation.portrait;
     }
     return result;
@@ -1530,7 +1517,7 @@
 /// This is a convenience widget that wraps a [DropdownButton] widget in a
 /// [FormField].
 ///
-/// A [Form] ancestor is not required. The [Form] simply makes it easier to
+/// A [Form] ancestor is not required. The [Form] allows one to
 /// save, reset, or validate multiple fields at once. To use without a [Form],
 /// pass a [GlobalKey] to the constructor and use [GlobalKey.currentState] to
 /// save or reset the form field.
@@ -1590,12 +1577,7 @@
                 'Either zero or 2 or more [DropdownMenuItem]s were detected '
                 'with the same value',
               ),
-       assert(elevation != null),
-       assert(iconSize != null),
-       assert(isDense != null),
-       assert(isExpanded != null),
        assert(itemHeight == null || itemHeight >= kMinInteractiveDimension),
-       assert(autofocus != null),
        decoration = decoration ?? InputDecoration(focusColor: focusColor),
        super(
          initialValue: value,
diff --git a/framework/lib/src/material/dropdown_menu.dart b/framework/lib/src/material/dropdown_menu.dart
index c301b79..a4d5ab9 100644
--- a/framework/lib/src/material/dropdown_menu.dart
+++ b/framework/lib/src/material/dropdown_menu.dart
@@ -135,6 +135,7 @@
     this.controller,
     this.initialSelection,
     this.onSelected,
+    this.requestFocusOnTap,
     required this.dropdownMenuEntries,
   });
 
@@ -228,6 +229,19 @@
   /// Defaults to null. If null, only the text field is updated.
   final ValueChanged<T?>? onSelected;
 
+  /// Determine if the dropdown button requests focus and the on-screen virtual
+  /// keyboard is shown in response to a touch event.
+  ///
+  /// By default, on mobile platforms, tapping on the text field and opening
+  /// the menu will not cause a focus request and the virtual keyboard will not
+  /// appear. The default behavior for desktop platforms is for the dropdown to
+  /// take the focus.
+  ///
+  /// Defaults to null. Setting this field to true or false, rather than allowing
+  /// the implementation to choose based on the platform, can be useful for
+  /// applications that want to override the default behavior.
+  final bool? requestFocusOnTap;
+
   /// Descriptions of the menu items in the [DropdownMenu].
   ///
   /// This is a required parameter. It is recommended that at least one [DropdownMenuEntry]
@@ -242,7 +256,6 @@
 class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
   final GlobalKey _anchorKey = GlobalKey();
   final GlobalKey _leadingKey = GlobalKey();
-  final FocusNode _textFocusNode = FocusNode();
   final MenuController _controller = MenuController();
   late final TextEditingController _textEditingController;
   late bool _enableFilter;
@@ -288,6 +301,23 @@
     }
   }
 
+  bool canRequestFocus() {
+    if (widget.requestFocusOnTap != null) {
+      return widget.requestFocusOnTap!;
+    }
+
+    switch (Theme.of(context).platform) {
+      case TargetPlatform.iOS:
+      case TargetPlatform.android:
+      case TargetPlatform.fuchsia:
+        return false;
+      case TargetPlatform.macOS:
+      case TargetPlatform.linux:
+      case TargetPlatform.windows:
+        return true;
+    }
+  }
+
   void refreshLeadingPadding() {
     WidgetsBinding.instance.addPostFrameCallback((_) {
       setState(() {
@@ -428,7 +458,6 @@
 
   @override
   void dispose() {
-    _textEditingController.dispose();
     super.dispose();
   }
 
@@ -489,13 +518,12 @@
           builder: (BuildContext context, MenuController controller, Widget? child) {
             assert(_initialMenu != null);
             final Widget trailingButton = Padding(
-              padding: const EdgeInsets.symmetric(horizontal: 4.0),
+              padding: const EdgeInsets.all(4.0),
               child: IconButton(
                 isSelected: controller.isOpen,
                 icon: widget.trailingIcon ?? const Icon(Icons.arrow_drop_down),
                 selectedIcon: widget.selectedTrailingIcon ?? const Icon(Icons.arrow_drop_up),
                 onPressed: () {
-                  _textFocusNode.requestFocus();
                   handlePressed(controller);
                 },
               ),
@@ -511,7 +539,9 @@
               width: widget.width,
               children: <Widget>[
                 TextField(
-                  focusNode: _textFocusNode,
+                  canRequestFocus: canRequestFocus(),
+                  enableInteractiveSelection: canRequestFocus(),
+                  textAlignVertical: TextAlignVertical.center,
                   style: effectiveTextStyle,
                   controller: _textEditingController,
                   onEditingComplete: () {
@@ -575,7 +605,7 @@
 }
 
 class _DropdownMenuBody extends MultiChildRenderObjectWidget {
-  _DropdownMenuBody({
+  const _DropdownMenuBody({
     super.key,
     super.children,
     this.width,
diff --git a/framework/lib/src/material/dropdown_menu_theme.dart b/framework/lib/src/material/dropdown_menu_theme.dart
index 3027be3..7d891c8 100644
--- a/framework/lib/src/material/dropdown_menu_theme.dart
+++ b/framework/lib/src/material/dropdown_menu_theme.dart
@@ -112,7 +112,7 @@
     super.key,
     required this.data,
     required super.child,
-  }) : assert(data != null);
+  });
 
   /// Specifies the visual properties used by descendant [DropdownMenu]
   /// widgets.
@@ -162,7 +162,6 @@
   ///  * [of], which will return [ThemeData.dropdownMenuTheme] if it doesn't
   ///    find a [DropdownMenuTheme] ancestor, instead of returning null.
   static DropdownMenuThemeData? maybeOf(BuildContext context) {
-    assert(context != null);
     return context.dependOnInheritedWidgetOfExactType<DropdownMenuTheme>()?.data;
   }
 
diff --git a/framework/lib/src/material/elevated_button.dart b/framework/lib/src/material/elevated_button.dart
index 4fdd820..2ba8c92 100644
--- a/framework/lib/src/material/elevated_button.dart
+++ b/framework/lib/src/material/elevated_button.dart
@@ -252,7 +252,7 @@
   /// each state, and "others" means all other states.
   ///
   /// The `textScaleFactor` is the value of
-  /// `MediaQuery.of(context).textScaleFactor` and the names of the
+  /// `MediaQuery.textScaleFactorOf(context)` and the names of the
   /// EdgeInsets constructors and `EdgeInsetsGeometry.lerp` have been
   /// abbreviated for readability.
   ///
@@ -394,7 +394,7 @@
     const EdgeInsets.symmetric(horizontal: 16),
     const EdgeInsets.symmetric(horizontal: 8),
     const EdgeInsets.symmetric(horizontal: 4),
-    MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
+    MediaQuery.textScaleFactorOf(context),
   );
 }
 
@@ -486,9 +486,7 @@
     super.statesController,
     required Widget icon,
     required Widget label,
-  }) : assert(icon != null),
-       assert(label != null),
-       super(
+  }) : super(
          autofocus: autofocus ?? false,
          clipBehavior: clipBehavior ?? Clip.none,
          child: _ElevatedButtonWithIconChild(icon: icon, label: label),
@@ -500,7 +498,7 @@
       const EdgeInsetsDirectional.fromSTEB(12, 0, 16, 0),
       const EdgeInsets.symmetric(horizontal: 8),
       const EdgeInsetsDirectional.fromSTEB(8, 0, 4, 0),
-      MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
+      MediaQuery.textScaleFactorOf(context),
     );
     return super.defaultStyleOf(context).copyWith(
       padding: MaterialStatePropertyAll<EdgeInsetsGeometry>(scaledPadding),
@@ -516,7 +514,7 @@
 
   @override
   Widget build(BuildContext context) {
-    final double scale = MediaQuery.maybeOf(context)?.textScaleFactor ?? 1;
+    final double scale = MediaQuery.textScaleFactorOf(context);
     final double gap = scale <= 1 ? 8 : lerpDouble(8, 4, math.min(scale - 1, 1))!;
     return Row(
       mainAxisSize: MainAxisSize.min,
@@ -532,7 +530,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _ElevatedButtonDefaultsM3 extends ButtonStyle {
   _ElevatedButtonDefaultsM3(this.context)
diff --git a/framework/lib/src/material/elevated_button_theme.dart b/framework/lib/src/material/elevated_button_theme.dart
index 629ae7e..bc59beb 100644
--- a/framework/lib/src/material/elevated_button_theme.dart
+++ b/framework/lib/src/material/elevated_button_theme.dart
@@ -49,7 +49,6 @@
 
   /// Linearly interpolate between two elevated button themes.
   static ElevatedButtonThemeData? lerp(ElevatedButtonThemeData? a, ElevatedButtonThemeData? b, double t) {
-    assert (t != null);
     if (a == null && b == null) {
       return null;
     }
@@ -98,7 +97,7 @@
     super.key,
     required this.data,
     required super.child,
-  }) : assert(data != null);
+  });
 
   /// The configuration of this theme.
   final ElevatedButtonThemeData data;
diff --git a/framework/lib/src/material/elevation_overlay.dart b/framework/lib/src/material/elevation_overlay.dart
index f989e60..21312dd 100644
--- a/framework/lib/src/material/elevation_overlay.dart
+++ b/framework/lib/src/material/elevation_overlay.dart
@@ -160,7 +160,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 // Surface tint opacities based on elevations according to the
 // Material Design 3 specification:
diff --git a/framework/lib/src/material/expand_icon.dart b/framework/lib/src/material/expand_icon.dart
index 48b3ee5..3581d75 100644
--- a/framework/lib/src/material/expand_icon.dart
+++ b/framework/lib/src/material/expand_icon.dart
@@ -39,9 +39,7 @@
     this.color,
     this.disabledColor,
     this.expandedColor,
-  }) : assert(isExpanded != null),
-       assert(size != null),
-       assert(padding != null);
+  });
 
   /// Whether the icon is in an expanded state.
   ///
@@ -66,7 +64,7 @@
   /// This property must not be null. It defaults to 8.0 padding on all sides.
   final EdgeInsetsGeometry padding;
 
-
+  /// {@template flutter.material.ExpandIcon.color}
   /// The color of the icon.
   ///
   /// Defaults to [Colors.black54] when the theme's
@@ -74,6 +72,7 @@
   /// [Colors.white60] when it is [Brightness.dark]. This adheres to the
   /// Material Design specifications for [icons](https://material.io/design/iconography/system-icons.html#color)
   /// and for [dark theme](https://material.io/design/color/dark-theme.html#ui-application)
+  /// {@endtemplate}
   final Color? color;
 
   /// The color of the icon when it is disabled,
diff --git a/framework/lib/src/material/expansion_panel.dart b/framework/lib/src/material/expansion_panel.dart
index 051f395..f318c6b 100644
--- a/framework/lib/src/material/expansion_panel.dart
+++ b/framework/lib/src/material/expansion_panel.dart
@@ -16,6 +16,7 @@
 const EdgeInsets _kPanelHeaderExpandedDefaultPadding = EdgeInsets.symmetric(
     vertical: 64.0 - _kPanelHeaderCollapsedHeight,
 );
+const EdgeInsets _kExpandIconPadding = EdgeInsets.all(12.0);
 
 class _SaltedKey<S, V> extends LocalKey {
   const _SaltedKey(this.salt, this.value);
@@ -81,10 +82,7 @@
     this.isExpanded = false,
     this.canTapOnHeader = false,
     this.backgroundColor,
-  }) : assert(headerBuilder != null),
-       assert(body != null),
-       assert(isExpanded != null),
-       assert(canTapOnHeader != null);
+  });
 
   /// The widget builder that builds the expansion panels' header.
   final ExpansionPanelHeaderBuilder headerBuilder;
@@ -131,7 +129,7 @@
     required super.body,
     super.canTapOnHeader,
     super.backgroundColor,
-  }) : assert(value != null);
+  });
 
   /// The value that uniquely identifies a radio panel so that the currently
   /// selected radio panel can be identified.
@@ -168,9 +166,8 @@
     this.expandedHeaderPadding = _kPanelHeaderExpandedDefaultPadding,
     this.dividerColor,
     this.elevation = 2,
-  }) : assert(children != null),
-       assert(animationDuration != null),
-       _allowOnlyOnePanelOpen = false,
+    this.expandIconColor,
+  }) : _allowOnlyOnePanelOpen = false,
        initialOpenPanelValue = null;
 
   /// Creates a radio expansion panel list widget.
@@ -195,9 +192,8 @@
     this.expandedHeaderPadding = _kPanelHeaderExpandedDefaultPadding,
     this.dividerColor,
     this.elevation = 2,
-  }) : assert(children != null),
-       assert(animationDuration != null),
-       _allowOnlyOnePanelOpen = true;
+    this.expandIconColor,
+  }) : _allowOnlyOnePanelOpen = true;
 
   /// The children of the expansion panel list. They are laid out in a similar
   /// fashion to [ListBody].
@@ -207,14 +203,14 @@
   /// is pressed. The arguments passed to the callback are the index of the
   /// pressed panel and whether the panel is currently expanded or not.
   ///
-  /// If ExpansionPanelList.radio is used, the callback may be called a
+  /// If [ExpansionPanelList.radio] is used, the callback may be called a
   /// second time if a different panel was previously open. The arguments
   /// passed to the second callback are the index of the panel that will close
   /// and false, marking that it will be closed.
   ///
-  /// For ExpansionPanelList, the callback needs to setState when it's notified
+  /// For [ExpansionPanelList], the callback needs to setState when it's notified
   /// about the closing/opening panel. On the other hand, the callback for
-  /// ExpansionPanelList.radio is simply meant to inform the parent widget of
+  /// [ExpansionPanelList.radio] is intended to inform the parent widget of
   /// changes, as the radio panels' open/close states are managed internally.
   ///
   /// This callback is useful in order to keep track of the expanded/collapsed
@@ -249,6 +245,9 @@
   /// By default, the value of elevation is 2.
   final double elevation;
 
+  /// {@macro flutter.material.ExpandIcon.color}
+  final Color? expandIconColor;
+
   @override
   State<StatefulWidget> createState() => _ExpansionPanelListState();
 }
@@ -356,8 +355,9 @@
       Widget expandIconContainer = Container(
         margin: const EdgeInsetsDirectional.only(end: 8.0),
         child: ExpandIcon(
+          color: widget.expandIconColor,
           isExpanded: _isChildExpanded(index),
-          padding: const EdgeInsets.all(16.0),
+          padding: _kExpandIconPadding,
           onPressed: !child.canTapOnHeader
               ? (bool isExpanded) => _handlePressed(isExpanded, index)
               : null,
diff --git a/framework/lib/src/material/expansion_tile.dart b/framework/lib/src/material/expansion_tile.dart
index fefc032..855b9ce 100644
--- a/framework/lib/src/material/expansion_tile.dart
+++ b/framework/lib/src/material/expansion_tile.dart
@@ -34,7 +34,8 @@
 /// to the [leading] and [trailing] properties of [ExpansionTile].
 ///
 /// {@tool dartpad}
-/// This example demonstrates different configurations of ExpansionTile.
+/// This example demonstrates how the [ExpansionTile] icon's location and appearance
+/// can be customized.
 ///
 /// ** See code in examples/api/lib/material/expansion_tile/expansion_tile.0.dart **
 /// {@end-tool}
@@ -73,9 +74,7 @@
     this.collapsedShape,
     this.clipBehavior,
     this.controlAffinity,
-  }) : assert(initiallyExpanded != null),
-       assert(maintainState != null),
-       assert(
+  }) : assert(
        expandedCrossAxisAlignment != CrossAxisAlignment.baseline,
        'CrossAxisAlignment.baseline is not supported since the expanded children '
            'are aligned in a column, not a row. Try to use another constant.',
@@ -218,7 +217,7 @@
   /// Used to override to the [ListTileThemeData.iconColor].
   ///
   /// If this property is null then [ExpansionTileThemeData.iconColor] is used. If that
-  /// is also null then the value of [ListTileThemeData.iconColor] is used.
+  /// is also null then the value of [ColorScheme.primary] is used.
   ///
   /// See also:
   ///
@@ -229,6 +228,15 @@
   /// The icon color of tile's expansion arrow icon when the sublist is collapsed.
   ///
   /// Used to override to the [ListTileThemeData.iconColor].
+  ///
+  /// If this property is null then [ExpansionTileThemeData.collapsedIconColor] is used. If that
+  /// is also null and [ThemeData.useMaterial3] is true, [ColorScheme.onSurface] is used. Otherwise,
+  /// defaults to [ThemeData.unselectedWidgetColor] color.
+  ///
+  /// See also:
+  ///
+  /// * [ExpansionTileTheme.of], which returns the nearest [ExpansionTileTheme]'s
+  ///   [ExpansionTileThemeData].
   final Color? collapsedIconColor;
 
 
@@ -237,7 +245,8 @@
   /// Used to override to the [ListTileThemeData.textColor].
   ///
   /// If this property is null then [ExpansionTileThemeData.textColor] is used. If that
-  /// is also null then the value of [ListTileThemeData.textColor] is used.
+  /// is also null then and [ThemeData.useMaterial3] is true, color of the [TextTheme.bodyLarge]
+  /// will be used for the [title] and [subtitle]. Otherwise, defaults to [ColorScheme.primary] color.
   ///
   /// See also:
   ///
@@ -249,8 +258,10 @@
   ///
   /// Used to override to the [ListTileThemeData.textColor].
   ///
-  /// If this property is null then [ExpansionTileThemeData.collapsedTextColor] is used. If that
-  /// is also null then the value of [ListTileThemeData.textColor] is used.
+  /// If this property is null then [ExpansionTileThemeData.collapsedTextColor] is used.
+  /// If that is also null and [ThemeData.useMaterial3] is true, color of the
+  /// [TextTheme.bodyLarge] will be used for the [title] and [subtitle]. Otherwise,
+  /// defaults to color of the [TextTheme.titleMedium].
   ///
   /// See also:
   ///
@@ -443,7 +454,9 @@
   void didChangeDependencies() {
     final ThemeData theme = Theme.of(context);
     final ExpansionTileThemeData expansionTileTheme = ExpansionTileTheme.of(context);
-    final ColorScheme colorScheme = theme.colorScheme;
+    final ExpansionTileThemeData defaults = theme.useMaterial3
+      ? _ExpansionTileDefaultsM3(context)
+      : _ExpansionTileDefaultsM2(context);
     _borderTween
       ..begin = widget.collapsedShape
         ?? expansionTileTheme.collapsedShape
@@ -460,13 +473,13 @@
     _headerColorTween
       ..begin = widget.collapsedTextColor
         ?? expansionTileTheme.collapsedTextColor
-        ?? theme.textTheme.titleMedium!.color
-      ..end = widget.textColor ?? expansionTileTheme.textColor ?? colorScheme.primary;
+        ?? defaults.collapsedTextColor
+      ..end = widget.textColor ?? expansionTileTheme.textColor ?? defaults.textColor;
     _iconColorTween
       ..begin = widget.collapsedIconColor
         ?? expansionTileTheme.collapsedIconColor
-        ?? theme.unselectedWidgetColor
-      ..end = widget.iconColor ?? expansionTileTheme.iconColor ?? colorScheme.primary;
+        ?? defaults.collapsedIconColor
+      ..end = widget.iconColor ?? expansionTileTheme.iconColor ?? defaults.iconColor;
     _backgroundColorTween
       ..begin = widget.collapsedBackgroundColor ?? expansionTileTheme.collapsedBackgroundColor
       ..end = widget.backgroundColor ?? expansionTileTheme.backgroundColor;
@@ -500,3 +513,54 @@
     );
   }
 }
+
+class _ExpansionTileDefaultsM2 extends ExpansionTileThemeData {
+  _ExpansionTileDefaultsM2(this.context);
+
+  final BuildContext context;
+  late final ThemeData _theme = Theme.of(context);
+  late final ColorScheme _colorScheme = _theme.colorScheme;
+
+  @override
+  Color? get textColor => _colorScheme.primary;
+
+  @override
+  Color? get iconColor => _colorScheme.primary;
+
+  @override
+  Color? get collapsedTextColor => _theme.textTheme.titleMedium!.color;
+
+  @override
+  Color? get collapsedIconColor => _theme.unselectedWidgetColor;
+}
+
+// BEGIN GENERATED TOKEN PROPERTIES - ExpansionTile
+
+// Do not edit by hand. The code between the "BEGIN GENERATED" and
+// "END GENERATED" comments are generated from data in the Material
+// Design token database by the script:
+//   dev/tools/gen_defaults/bin/gen_defaults.dart.
+
+// Token database version: v0_152
+
+class _ExpansionTileDefaultsM3 extends ExpansionTileThemeData {
+  _ExpansionTileDefaultsM3(this.context);
+
+  final BuildContext context;
+  late final ThemeData _theme = Theme.of(context);
+  late final ColorScheme _colors = _theme.colorScheme;
+
+  @override
+  Color? get textColor => Theme.of(context).textTheme.bodyLarge!.color;
+
+  @override
+  Color? get iconColor => _colors.primary;
+
+  @override
+  Color? get collapsedTextColor => Theme.of(context).textTheme.bodyLarge!.color;
+
+  @override
+  Color? get collapsedIconColor => _colors.onSurface;
+}
+
+// END GENERATED TOKEN PROPERTIES - ExpansionTile
diff --git a/framework/lib/src/material/expansion_tile_theme.dart b/framework/lib/src/material/expansion_tile_theme.dart
index 08dec3a..8d62465 100644
--- a/framework/lib/src/material/expansion_tile_theme.dart
+++ b/framework/lib/src/material/expansion_tile_theme.dart
@@ -124,7 +124,6 @@
 
   /// Linearly interpolate between ExpansionTileThemeData objects.
   static ExpansionTileThemeData? lerp(ExpansionTileThemeData? a, ExpansionTileThemeData? b, double t) {
-    assert (t != null);
     if (a == null && b == null) {
       return null;
     }
@@ -217,8 +216,7 @@
     super.key,
     required this.data,
     required super.child,
-  }) : assert(child != null),
-       assert(data != null);
+  });
 
   /// Specifies color, alignment, and text style values for
   /// descendant [ExpansionTile] widgets.
diff --git a/framework/lib/src/material/filled_button.dart b/framework/lib/src/material/filled_button.dart
index 15b0854..a7f52b6 100644
--- a/framework/lib/src/material/filled_button.dart
+++ b/framework/lib/src/material/filled_button.dart
@@ -288,7 +288,7 @@
   /// each state, and "others" means all other states.
   ///
   /// The `textScaleFactor` is the value of
-  /// `MediaQuery.of(context).textScaleFactor` and the names of the
+  /// `MediaQuery.textScaleFactorOf(context)` and the names of the
   /// EdgeInsets constructors and `EdgeInsetsGeometry.lerp` have been
   /// abbreviated for readability.
   ///
@@ -368,7 +368,7 @@
     const EdgeInsets.symmetric(horizontal: 16),
     const EdgeInsets.symmetric(horizontal: 8),
     const EdgeInsets.symmetric(horizontal: 4),
-    MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
+    MediaQuery.textScaleFactorOf(context),
   );
 }
 
@@ -436,9 +436,7 @@
     super.statesController,
     required Widget icon,
     required Widget label,
-  }) : assert(icon != null),
-       assert(label != null),
-       super(
+  }) : super(
          autofocus: autofocus ?? false,
          clipBehavior: clipBehavior ?? Clip.none,
          child: _FilledButtonWithIconChild(icon: icon, label: label)
@@ -457,9 +455,7 @@
     super.statesController,
     required Widget icon,
     required Widget label,
-  }) : assert(icon != null),
-       assert(label != null),
-       super.tonal(
+  }) : super.tonal(
          autofocus: autofocus ?? false,
          clipBehavior: clipBehavior ?? Clip.none,
          child: _FilledButtonWithIconChild(icon: icon, label: label)
@@ -471,7 +467,7 @@
       const EdgeInsetsDirectional.fromSTEB(12, 0, 16, 0),
       const EdgeInsets.symmetric(horizontal: 8),
       const EdgeInsetsDirectional.fromSTEB(8, 0, 4, 0),
-      MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
+      MediaQuery.textScaleFactorOf(context),
     );
     return super.defaultStyleOf(context).copyWith(
       padding: MaterialStatePropertyAll<EdgeInsetsGeometry>(scaledPadding),
@@ -487,7 +483,7 @@
 
   @override
   Widget build(BuildContext context) {
-    final double scale = MediaQuery.maybeOf(context)?.textScaleFactor ?? 1;
+    final double scale = MediaQuery.textScaleFactorOf(context);
     // Adjust the gap based on the text scale factor. Start at 8, and lerp
     // to 4 based on how large the text is.
     final double gap = scale <= 1 ? 8 : lerpDouble(8, 4, math.min(scale - 1, 1))!;
@@ -505,7 +501,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _FilledButtonDefaultsM3 extends ButtonStyle {
   _FilledButtonDefaultsM3(this.context)
@@ -629,7 +625,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _FilledTonalButtonDefaultsM3 extends ButtonStyle {
   _FilledTonalButtonDefaultsM3(this.context)
diff --git a/framework/lib/src/material/filled_button_theme.dart b/framework/lib/src/material/filled_button_theme.dart
index 1a2187b..8e3a4d3 100644
--- a/framework/lib/src/material/filled_button_theme.dart
+++ b/framework/lib/src/material/filled_button_theme.dart
@@ -49,7 +49,6 @@
 
   /// Linearly interpolate between two filled button themes.
   static FilledButtonThemeData? lerp(FilledButtonThemeData? a, FilledButtonThemeData? b, double t) {
-    assert (t != null);
     if (a == null && b == null) {
       return null;
     }
@@ -98,7 +97,7 @@
     super.key,
     required this.data,
     required super.child,
-  }) : assert(data != null);
+  });
 
   /// The configuration of this theme.
   final FilledButtonThemeData data;
diff --git a/framework/lib/src/material/filter_chip.dart b/framework/lib/src/material/filter_chip.dart
index 61da51c..cf8c62f 100644
--- a/framework/lib/src/material/filter_chip.dart
+++ b/framework/lib/src/material/filter_chip.dart
@@ -88,11 +88,7 @@
     this.showCheckmark,
     this.checkmarkColor,
     this.avatarBorder = const CircleBorder(),
-  }) : assert(selected != null),
-       assert(label != null),
-       assert(clipBehavior != null),
-       assert(autofocus != null),
-       assert(pressElevation == null || pressElevation >= 0.0),
+  }) : assert(pressElevation == null || pressElevation >= 0.0),
        assert(elevation == null || elevation >= 0.0);
 
   @override
@@ -199,7 +195,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _FilterChipDefaultsM3 extends ChipThemeData {
   const _FilterChipDefaultsM3(this.context, this.isEnabled, this.isSelected)
@@ -220,7 +216,7 @@
   Color? get backgroundColor => null;
 
   @override
-  Color? get shadowColor => Theme.of(context).colorScheme.shadow;
+  Color? get shadowColor => Colors.transparent;
 
   @override
   Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;
@@ -267,7 +263,7 @@
   EdgeInsetsGeometry? get labelPadding => EdgeInsets.lerp(
     const EdgeInsets.symmetric(horizontal: 8.0),
     const EdgeInsets.symmetric(horizontal: 4.0),
-    clampDouble(MediaQuery.of(context).textScaleFactor - 1.0, 0.0, 1.0),
+    clampDouble(MediaQuery.textScaleFactorOf(context) - 1.0, 0.0, 1.0),
   )!;
 }
 
diff --git a/framework/lib/src/material/flexible_space_bar.dart b/framework/lib/src/material/flexible_space_bar.dart
index e2aa07d..c1f6890 100644
--- a/framework/lib/src/material/flexible_space_bar.dart
+++ b/framework/lib/src/material/flexible_space_bar.dart
@@ -84,8 +84,7 @@
     this.collapseMode = CollapseMode.parallax,
     this.stretchModes = const <StretchMode>[StretchMode.zoomBackground],
     this.expandedTitleScale = 1.5,
-  }) : assert(collapseMode != null),
-       assert(expandedTitleScale >= 1);
+  }) : assert(expandedTitleScale >= 1);
 
   /// The primary contents of the flexible space bar when expanded.
   ///
@@ -117,7 +116,7 @@
   /// bottom-left or its center.
   ///
   /// Typically this property is used to adjust how far the title is
-  /// is inset from the bottom-left and it is specified along with
+  /// inset from the bottom-left and it is specified along with
   /// [centerTitle] false.
   ///
   /// By default the value of this property is
@@ -159,7 +158,6 @@
     required double currentExtent,
     required Widget child,
   }) {
-    assert(currentExtent != null);
     return FlexibleSpaceBarSettings(
       toolbarOpacity: toolbarOpacity ?? 1.0,
       minExtent: minExtent ?? currentExtent,
@@ -179,7 +177,6 @@
     if (widget.centerTitle != null) {
       return widget.centerTitle!;
     }
-    assert(theme.platform != null);
     switch (theme.platform) {
       case TargetPlatform.android:
       case TargetPlatform.fuchsia:
@@ -197,7 +194,6 @@
       return Alignment.bottomCenter;
     }
     final TextDirection textDirection = Directionality.of(context);
-    assert(textDirection != null);
     switch (textDirection) {
       case TextDirection.rtl:
         return Alignment.bottomRight;
@@ -223,10 +219,6 @@
     return LayoutBuilder(
       builder: (BuildContext context, BoxConstraints constraints) {
         final FlexibleSpaceBarSettings settings = context.dependOnInheritedWidgetOfExactType<FlexibleSpaceBarSettings>()!;
-        assert(
-          settings != null,
-          'A FlexibleSpaceBar must be wrapped in the widget returned by FlexibleSpaceBar.createSettings().',
-        );
 
         final List<Widget> children = <Widget>[];
 
@@ -388,10 +380,9 @@
     required this.currentExtent,
     required super.child,
     this.isScrolledUnder,
-  }) : assert(toolbarOpacity != null),
-       assert(minExtent != null && minExtent >= 0),
-       assert(maxExtent != null && maxExtent >= 0),
-       assert(currentExtent != null && currentExtent >= 0),
+  }) : assert(minExtent >= 0),
+       assert(maxExtent >= 0),
+       assert(currentExtent >= 0),
        assert(toolbarOpacity >= 0.0),
        assert(minExtent <= maxExtent),
        assert(minExtent <= currentExtent),
diff --git a/framework/lib/src/material/floating_action_button.dart b/framework/lib/src/material/floating_action_button.dart
index cea314f..a8d8823 100644
--- a/framework/lib/src/material/floating_action_button.dart
+++ b/framework/lib/src/material/floating_action_button.dart
@@ -127,10 +127,6 @@
        assert(hoverElevation == null || hoverElevation >= 0.0),
        assert(highlightElevation == null || highlightElevation >= 0.0),
        assert(disabledElevation == null || disabledElevation >= 0.0),
-       assert(mini != null),
-       assert(clipBehavior != null),
-       assert(isExtended != null),
-       assert(autofocus != null),
        _floatingActionButtonType = mini ? _FloatingActionButtonType.small : _FloatingActionButtonType.regular,
        _extendedLabel = null,
        extendedIconLabelSpacing = null,
@@ -174,8 +170,6 @@
        assert(hoverElevation == null || hoverElevation >= 0.0),
        assert(highlightElevation == null || highlightElevation >= 0.0),
        assert(disabledElevation == null || disabledElevation >= 0.0),
-       assert(clipBehavior != null),
-       assert(autofocus != null),
        _floatingActionButtonType = _FloatingActionButtonType.small,
        mini = true,
        isExtended = false,
@@ -221,8 +215,6 @@
        assert(hoverElevation == null || hoverElevation >= 0.0),
        assert(highlightElevation == null || highlightElevation >= 0.0),
        assert(disabledElevation == null || disabledElevation >= 0.0),
-       assert(clipBehavior != null),
-       assert(autofocus != null),
        _floatingActionButtonType = _FloatingActionButtonType.large,
        mini = false,
        isExtended = false,
@@ -273,9 +265,6 @@
        assert(hoverElevation == null || hoverElevation >= 0.0),
        assert(highlightElevation == null || highlightElevation >= 0.0),
        assert(disabledElevation == null || disabledElevation >= 0.0),
-       assert(isExtended != null),
-       assert(clipBehavior != null),
-       assert(autofocus != null),
        mini = false,
        _floatingActionButtonType = _FloatingActionButtonType.extended,
        child = icon,
@@ -804,7 +793,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _FABDefaultsM3 extends FloatingActionButtonThemeData {
   _FABDefaultsM3(this.context, this.type, this.hasChild)
diff --git a/framework/lib/src/material/floating_action_button_location.dart b/framework/lib/src/material/floating_action_button_location.dart
index 1f6f034..29fea42 100644
--- a/framework/lib/src/material/floating_action_button_location.dart
+++ b/framework/lib/src/material/floating_action_button_location.dart
@@ -652,7 +652,6 @@
   /// Calculates x-offset for start-aligned [FloatingActionButtonLocation]s.
   @override
   double getOffsetX(ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment) {
-    assert(scaffoldGeometry.textDirection != null);
     switch (scaffoldGeometry.textDirection) {
       case TextDirection.rtl:
         return StandardFabLocation._rightOffsetX(scaffoldGeometry, adjustment);
@@ -676,7 +675,6 @@
   /// Calculates x-offset for end-aligned [FloatingActionButtonLocation]s.
   @override
   double getOffsetX(ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment) {
-    assert(scaffoldGeometry.textDirection != null);
     switch (scaffoldGeometry.textDirection) {
       case TextDirection.rtl:
         return StandardFabLocation._leftOffsetX(scaffoldGeometry, adjustment);
diff --git a/framework/lib/src/material/floating_action_button_theme.dart b/framework/lib/src/material/floating_action_button_theme.dart
index d8495b8..1c744d5 100644
--- a/framework/lib/src/material/floating_action_button_theme.dart
+++ b/framework/lib/src/material/floating_action_button_theme.dart
@@ -193,7 +193,6 @@
   ///
   /// {@macro dart.ui.shadow.lerp}
   static FloatingActionButtonThemeData? lerp(FloatingActionButtonThemeData? a, FloatingActionButtonThemeData? b, double t) {
-    assert(t != null);
     if (a == null && b == null) {
       return null;
     }
diff --git a/framework/lib/src/material/flutter_logo.dart b/framework/lib/src/material/flutter_logo.dart
index 6abc740..2def362 100644
--- a/framework/lib/src/material/flutter_logo.dart
+++ b/framework/lib/src/material/flutter_logo.dart
@@ -28,10 +28,7 @@
     this.style = FlutterLogoStyle.markOnly,
     this.duration = const Duration(milliseconds: 750),
     this.curve = Curves.fastOutSlowIn,
-  }) : assert(textColor != null),
-       assert(style != null),
-       assert(duration != null),
-       assert(curve != null);
+  });
 
   /// The size of the logo in logical pixels.
   ///
diff --git a/framework/lib/src/material/grid_tile.dart b/framework/lib/src/material/grid_tile.dart
index e2560b7..01d5169 100644
--- a/framework/lib/src/material/grid_tile.dart
+++ b/framework/lib/src/material/grid_tile.dart
@@ -25,7 +25,7 @@
     this.header,
     this.footer,
     required this.child,
-  }) : assert(child != null);
+  });
 
   /// The widget to show over the top of this grid tile.
   ///
diff --git a/framework/lib/src/material/icon_button.dart b/framework/lib/src/material/icon_button.dart
index 6020d4e..21f541b 100644
--- a/framework/lib/src/material/icon_button.dart
+++ b/framework/lib/src/material/icon_button.dart
@@ -198,9 +198,7 @@
     this.isSelected,
     this.selectedIcon,
     required this.icon,
-  }) : assert(splashRadius == null || splashRadius > 0),
-       assert(autofocus != null),
-       assert(icon != null);
+  }) : assert(splashRadius == null || splashRadius > 0);
 
   /// The size of the icon inside the button.
   ///
@@ -962,7 +960,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _IconButtonDefaultsM3 extends ButtonStyle {
   _IconButtonDefaultsM3(this.context)
@@ -1011,7 +1009,7 @@
         return _colors.onSurfaceVariant.withOpacity(0.08);
       }
       if (states.contains(MaterialState.focused)) {
-        return _colors.onSurfaceVariant.withOpacity(0.08);
+        return _colors.onSurfaceVariant.withOpacity(0.12);
       }
       if (states.contains(MaterialState.pressed)) {
         return _colors.onSurfaceVariant.withOpacity(0.12);
diff --git a/framework/lib/src/material/icon_button_theme.dart b/framework/lib/src/material/icon_button_theme.dart
index 71010c2..1f5261d 100644
--- a/framework/lib/src/material/icon_button_theme.dart
+++ b/framework/lib/src/material/icon_button_theme.dart
@@ -49,7 +49,6 @@
 
   /// Linearly interpolate between two icon button themes.
   static IconButtonThemeData? lerp(IconButtonThemeData? a, IconButtonThemeData? b, double t) {
-    assert (t != null);
     if (a == null && b == null) {
       return null;
     }
@@ -96,7 +95,7 @@
     super.key,
     required this.data,
     required super.child,
-  }) : assert(data != null);
+  });
 
   /// The configuration of this theme.
   final IconButtonThemeData data;
diff --git a/framework/lib/src/material/icons.dart b/framework/lib/src/material/icons.dart
index 2da17ac..70e4f81 100644
--- a/framework/lib/src/material/icons.dart
+++ b/framework/lib/src/material/icons.dart
@@ -119,9 +119,9 @@
 /// ![The following code snippet would generate a row of icons consisting of a pink heart, a green musical note, and a blue umbrella, each progressively bigger than the last.](https://flutter.github.io/assets-for-api-docs/assets/widgets/icon.png)
 ///
 /// ```dart
-/// Row(
+/// const Row(
 ///   mainAxisAlignment: MainAxisAlignment.spaceAround,
-///   children: const <Widget>[
+///   children: <Widget>[
 ///     Icon(
 ///       Icons.favorite,
 ///       color: Colors.pink,
@@ -149,6 +149,7 @@
 ///  * [IconButton]
 ///  * <https://material.io/resources/icons>
 ///  * [AnimatedIcons], for the list of available animated Material Icons.
+@staticIconProvider
 class Icons {
   // This class is not meant to be instantiated or extended; this constructor
   // prevents instantiation and extension.
diff --git a/framework/lib/src/material/ink_decoration.dart b/framework/lib/src/material/ink_decoration.dart
index 8a95a83..3d5dd9d 100644
--- a/framework/lib/src/material/ink_decoration.dart
+++ b/framework/lib/src/material/ink_decoration.dart
@@ -193,10 +193,6 @@
     this.height,
     this.child,
   }) : assert(padding == null || padding.isNonNegative),
-       assert(image != null),
-       assert(alignment != null),
-       assert(repeat != null),
-       assert(matchTextDirection != null),
        decoration = BoxDecoration(
          image: DecorationImage(
            image: image,
@@ -241,10 +237,10 @@
   final double? height;
 
   EdgeInsetsGeometry get _paddingIncludingDecoration {
-    if (decoration == null || decoration!.padding == null) {
+    if (decoration == null) {
       return padding ?? EdgeInsets.zero;
     }
-    final EdgeInsetsGeometry decorationPadding = decoration!.padding!;
+    final EdgeInsetsGeometry decorationPadding = decoration!.padding;
     if (padding == null) {
       return decorationPadding;
     }
@@ -337,8 +333,7 @@
     required super.controller,
     required super.referenceBox,
     super.onRemoved,
-  }) : assert(configuration != null),
-       _configuration = configuration {
+  }) : _configuration = configuration {
     this.decoration = decoration;
     controller.addInkFeature(this);
   }
@@ -369,7 +364,6 @@
   ImageConfiguration get configuration => _configuration;
   ImageConfiguration _configuration;
   set configuration(ImageConfiguration value) {
-    assert(value != null);
     if (value == _configuration) {
       return;
     }
diff --git a/framework/lib/src/material/ink_highlight.dart b/framework/lib/src/material/ink_highlight.dart
index 10d6b31..a2f14ac 100644
--- a/framework/lib/src/material/ink_highlight.dart
+++ b/framework/lib/src/material/ink_highlight.dart
@@ -48,11 +48,7 @@
     RectCallback? rectCallback,
     super.onRemoved,
     Duration fadeDuration = _kDefaultHighlightFadeDuration,
-  }) : assert(color != null),
-       assert(shape != null),
-       assert(textDirection != null),
-       assert(fadeDuration != null),
-       _shape = shape,
+  }) : _shape = shape,
        _radius = radius,
        _borderRadius = borderRadius ?? BorderRadius.zero,
        _customBorder = customBorder,
@@ -109,7 +105,6 @@
   }
 
   void _paintHighlight(Canvas canvas, Rect rect, Paint paint) {
-    assert(_shape != null);
     canvas.save();
     if (_customBorder != null) {
       canvas.clipPath(_customBorder!.getOuterPath(rect, textDirection: _textDirection));
diff --git a/framework/lib/src/material/ink_ripple.dart b/framework/lib/src/material/ink_ripple.dart
index 009df09..8a2fe57 100644
--- a/framework/lib/src/material/ink_ripple.dart
+++ b/framework/lib/src/material/ink_ripple.dart
@@ -119,17 +119,13 @@
     ShapeBorder? customBorder,
     double? radius,
     super.onRemoved,
-  }) : assert(color != null),
-       assert(position != null),
-       assert(textDirection != null),
-       _position = position,
+  }) : _position = position,
        _borderRadius = borderRadius ?? BorderRadius.zero,
        _customBorder = customBorder,
        _textDirection = textDirection,
        _targetRadius = radius ?? _getTargetRadius(referenceBox, containedInkWell, rectCallback, position),
        _clipCallback = _getClipCallback(referenceBox, containedInkWell, rectCallback),
        super(controller: controller, color: color) {
-    assert(_borderRadius != null);
 
     // Immediately begin fading-in the initial splash.
     _fadeInController = AnimationController(duration: _kFadeInDuration, vsync: controller.vsync)
@@ -232,10 +228,14 @@
   void paintFeature(Canvas canvas, Matrix4 transform) {
     final int alpha = _fadeInController.isAnimating ? _fadeIn.value : _fadeOut.value;
     final Paint paint = Paint()..color = color.withAlpha(alpha);
+    Rect? rect;
+    if (_clipCallback != null) {
+       rect = _clipCallback!();
+    }
     // Splash moves to the center of the reference box.
     final Offset center = Offset.lerp(
       _position,
-      referenceBox.size.center(Offset.zero),
+      rect != null ? rect.center : referenceBox.size.center(Offset.zero),
       Curves.ease.transform(_radiusController.value),
     )!;
     paintInkCircle(
diff --git a/framework/lib/src/material/ink_splash.dart b/framework/lib/src/material/ink_splash.dart
index 66e98c5..805e519 100644
--- a/framework/lib/src/material/ink_splash.dart
+++ b/framework/lib/src/material/ink_splash.dart
@@ -125,8 +125,7 @@
     ShapeBorder? customBorder,
     double? radius,
     super.onRemoved,
-  }) : assert(textDirection != null),
-       _position = position,
+  }) : _position = position,
        _borderRadius = borderRadius ?? BorderRadius.zero,
        _customBorder = customBorder,
        _targetRadius = radius ?? _getTargetRadius(referenceBox, containedInkWell, rectCallback, position!),
@@ -134,7 +133,6 @@
        _repositionToReferenceBox = !containedInkWell,
        _textDirection = textDirection,
        super(controller: controller, color: color) {
-    assert(_borderRadius != null);
     _radiusController = AnimationController(duration: _kUnconfirmedSplashDuration, vsync: controller.vsync)
       ..addListener(controller.markNeedsPaint)
       ..forward();
diff --git a/framework/lib/src/material/ink_well.dart b/framework/lib/src/material/ink_well.dart
index 3e264af..018de53 100644
--- a/framework/lib/src/material/ink_well.dart
+++ b/framework/lib/src/material/ink_well.dart
@@ -42,9 +42,7 @@
     required super.referenceBox,
     required Color color,
     super.onRemoved,
-  }) : assert(controller != null),
-       assert(referenceBox != null),
-       _color = color;
+  }) : _color = color;
 
   /// Called when the user input that triggered this feature's appearance was confirmed.
   ///
@@ -111,12 +109,6 @@
     BorderRadius borderRadius = BorderRadius.zero,
     RectCallback? clipCallback,
   }) {
-    assert(canvas != null);
-    assert(transform != null);
-    assert(paint != null);
-    assert(center != null);
-    assert(radius != null);
-    assert(borderRadius != null);
 
     final Offset? originOffset = MatrixUtils.getAsTranslation(transform);
     canvas.save();
@@ -323,12 +315,7 @@
     this.onFocusChange,
     this.autofocus = false,
     this.statesController,
-  }) : assert(containedInkWell != null),
-       assert(highlightShape != null),
-       assert(enableFeedback != null),
-       assert(excludeFromSemantics != null),
-       assert(autofocus != null),
-       assert(canRequestFocus != null);
+  });
 
   /// The widget below this widget in the tree.
   ///
@@ -688,12 +675,7 @@
     this.getRectCallback,
     required this.debugCheckContext,
     this.statesController,
-  }) : assert(containedInkWell != null),
-       assert(highlightShape != null),
-       assert(enableFeedback != null),
-       assert(excludeFromSemantics != null),
-       assert(autofocus != null),
-       assert(canRequestFocus != null);
+  });
 
   final Widget? child;
   final GestureTapCallback? onTap;
@@ -781,7 +763,6 @@
 
   @override
   void markChildInkResponsePressed(_ParentInkResponseState childState, bool value) {
-    assert(childState != null);
     final bool lastAnyPressed = _anyChildInkResponsePressed;
     if (value) {
       _activeChildren.add(childState);
@@ -842,14 +823,14 @@
         widget.radius != oldWidget.radius ||
         widget.borderRadius != oldWidget.borderRadius ||
         widget.highlightShape != oldWidget.highlightShape) {
-      final InkHighlight? hoverHighLight = _highlights[_HighlightType.hover];
-      if (hoverHighLight != null) {
-        hoverHighLight.dispose();
+      final InkHighlight? hoverHighlight = _highlights[_HighlightType.hover];
+      if (hoverHighlight != null) {
+        hoverHighlight.dispose();
         updateHighlight(_HighlightType.hover, value: _hovering, callOnHover: false);
       }
-      final InkHighlight? focusHighLight = _highlights[_HighlightType.focus];
-      if (focusHighLight != null) {
-        focusHighLight.dispose();
+      final InkHighlight? focusHighlight = _highlights[_HighlightType.focus];
+      if (focusHighlight != null) {
+        focusHighlight.dispose();
         // Do not call updateFocusHighlights() here because it is called below
       }
     }
@@ -857,6 +838,13 @@
       statesController.update(MaterialState.disabled, !enabled);
       if (!enabled) {
         statesController.update(MaterialState.pressed, false);
+        // Remove the existing hover highlight immediately when enabled is false.
+        // Do not rely on updateHighlight or InkHighlight.deactivate to not break
+        // the expected lifecycle which is updating _hovering when the mouse exit.
+        // Manually updating _hovering here or calling InkHighlight.deactivate
+        // will lead to onHover not being called or call when it is not allowed.
+        final InkHighlight? hoverHighlight = _highlights[_HighlightType.hover];
+        hoverHighlight?.dispose();
       }
       // Don't call widget.onHover because many widgets, including the button
       // widgets, apply setState to an ancestor context from onHover.
@@ -937,7 +925,7 @@
         _highlights[type] = InkHighlight(
           controller: Material.of(context),
           referenceBox: referenceBox,
-          color: resolvedOverlayColor,
+          color: enabled ? resolvedOverlayColor : resolvedOverlayColor.withAlpha(0),
           shape: widget.highlightShape,
           radius: widget.radius,
           borderRadius: widget.borderRadius,
@@ -1018,7 +1006,7 @@
   }
 
   bool get _shouldShowFocus {
-    final NavigationMode mode = MediaQuery.maybeOf(context)?.navigationMode ?? NavigationMode.traditional;
+    final NavigationMode mode = MediaQuery.maybeNavigationModeOf(context) ?? NavigationMode.traditional;
     switch (mode) {
       case NavigationMode.traditional:
         return enabled && _hasFocus;
@@ -1166,7 +1154,7 @@
   }
 
   bool get _canRequestFocus {
-    final NavigationMode mode = MediaQuery.maybeOf(context)?.navigationMode ?? NavigationMode.traditional;
+    final NavigationMode mode = MediaQuery.maybeNavigationModeOf(context) ?? NavigationMode.traditional;
     switch (mode) {
       case NavigationMode.traditional:
         return enabled && widget.canRequestFocus;
diff --git a/framework/lib/src/material/input_border.dart b/framework/lib/src/material/input_border.dart
index a18cfd2..b1952eb 100644
--- a/framework/lib/src/material/input_border.dart
+++ b/framework/lib/src/material/input_border.dart
@@ -37,7 +37,7 @@
   /// [InputDecorator.isFocused].
   const InputBorder({
     this.borderSide = BorderSide.none,
-  }) : assert(borderSide != null);
+  });
 
   /// No input border.
   ///
@@ -157,7 +157,7 @@
       topLeft: Radius.circular(4.0),
       topRight: Radius.circular(4.0),
     ),
-  }) : assert(borderRadius != null);
+  });
 
   /// The radii of the border's rounded rectangle corners.
   ///
@@ -259,12 +259,13 @@
     if (other.runtimeType != runtimeType) {
       return false;
     }
-    return other is InputBorder
-        && other.borderSide == borderSide;
+    return other is UnderlineInputBorder
+        && other.borderSide == borderSide
+        && other.borderRadius == borderRadius;
   }
 
   @override
-  int get hashCode => borderSide.hashCode;
+  int get hashCode => Object.hash(borderSide, borderRadius);
 }
 
 /// Draws a rounded rectangle around an [InputDecorator]'s container.
@@ -307,8 +308,7 @@
     super.borderSide = const BorderSide(),
     this.borderRadius = const BorderRadius.all(Radius.circular(4.0)),
     this.gapPadding = 4.0,
-  }) : assert(borderRadius != null),
-       assert(gapPadding != null && gapPadding >= 0.0);
+  }) : assert(gapPadding >= 0.0);
 
   // The label text's gap can extend into the corners (even both the top left
   // and the top right corner). To avoid the more complicated problem of finding
@@ -515,7 +515,6 @@
     double gapPercentage = 0.0,
     TextDirection? textDirection,
   }) {
-    assert(gapExtent != null);
     assert(gapPercentage >= 0.0 && gapPercentage <= 1.0);
     assert(_cornersAreCircular(borderRadius));
 
diff --git a/framework/lib/src/material/input_chip.dart b/framework/lib/src/material/input_chip.dart
index c2d483c..ac5c40d 100644
--- a/framework/lib/src/material/input_chip.dart
+++ b/framework/lib/src/material/input_chip.dart
@@ -114,12 +114,7 @@
       'This feature was deprecated after v2.10.0-0.3.pre.'
     )
     this.useDeleteButtonTooltip = true,
-  }) : assert(selected != null),
-       assert(isEnabled != null),
-       assert(label != null),
-       assert(clipBehavior != null),
-       assert(autofocus != null),
-       assert(pressElevation == null || pressElevation >= 0.0),
+  }) : assert(pressElevation == null || pressElevation >= 0.0),
        assert(elevation == null || elevation >= 0.0);
 
   @override
@@ -249,7 +244,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _InputChipDefaultsM3 extends ChipThemeData {
   const _InputChipDefaultsM3(this.context, this.isEnabled)
@@ -310,7 +305,7 @@
   EdgeInsetsGeometry? get labelPadding => EdgeInsets.lerp(
     const EdgeInsets.symmetric(horizontal: 8.0),
     const EdgeInsets.symmetric(horizontal: 4.0),
-    clampDouble(MediaQuery.of(context).textScaleFactor - 1.0, 0.0, 1.0),
+    clampDouble(MediaQuery.textScaleFactorOf(context) - 1.0, 0.0, 1.0),
   )!;
 }
 
diff --git a/framework/lib/src/material/input_date_picker_form_field.dart b/framework/lib/src/material/input_date_picker_form_field.dart
index 7b6ac92..63acaff 100644
--- a/framework/lib/src/material/input_date_picker_form_field.dart
+++ b/framework/lib/src/material/input_date_picker_form_field.dart
@@ -58,10 +58,7 @@
     this.fieldLabelText,
     this.keyboardType,
     this.autofocus = false,
-  }) : assert(firstDate != null),
-       assert(lastDate != null),
-       assert(autofocus != null),
-       initialDate = initialDate != null ? DateUtils.dateOnly(initialDate) : null,
+  }) : initialDate = initialDate != null ? DateUtils.dateOnly(initialDate) : null,
        firstDate = DateUtils.dateOnly(firstDate),
        lastDate = DateUtils.dateOnly(lastDate) {
     assert(
@@ -237,11 +234,16 @@
 
   @override
   Widget build(BuildContext context) {
+    final ThemeData theme = Theme.of(context);
+    final bool useMaterial3 = theme.useMaterial3;
     final MaterialLocalizations localizations = MaterialLocalizations.of(context);
-    final InputDecorationTheme inputTheme = Theme.of(context).inputDecorationTheme;
+    final InputDecorationTheme inputTheme = theme.inputDecorationTheme;
+    final InputBorder inputBorder = inputTheme.border
+      ?? (useMaterial3 ? const OutlineInputBorder() : const UnderlineInputBorder());
+
     return TextFormField(
       decoration: InputDecoration(
-        border: inputTheme.border ?? const UnderlineInputBorder(),
+        border: inputBorder,
         filled: inputTheme.filled,
         hintText: widget.fieldHintText ?? localizations.dateHelpText,
         labelText: widget.fieldLabelText ?? localizations.dateInputLabel,
diff --git a/framework/lib/src/material/input_decorator.dart b/framework/lib/src/material/input_decorator.dart
index 708283d..7b2b408 100644
--- a/framework/lib/src/material/input_decorator.dart
+++ b/framework/lib/src/material/input_decorator.dart
@@ -12,6 +12,8 @@
 import 'color_scheme.dart';
 import 'colors.dart';
 import 'constants.dart';
+import 'icon_button.dart';
+import 'icon_button_theme.dart';
 import 'input_border.dart';
 import 'material.dart';
 import 'material_state.dart';
@@ -22,7 +24,9 @@
 // Examples can assume:
 // late Widget _myIcon;
 
-const Duration _kTransitionDuration = Duration(milliseconds: 200);
+// The duration value extracted from:
+// https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/textfield/TextInputLayout.java
+const Duration _kTransitionDuration = Duration(milliseconds: 167);
 const Curve _kTransitionCurve = Curves.fastOutSlowIn;
 const double _kFinalLabelScale = 0.75;
 
@@ -152,9 +156,7 @@
     required this.fillColor,
     required this.hoverColor,
     required this.isHovering,
-  }) : assert(border != null),
-       assert(gap != null),
-       assert(fillColor != null);
+  });
 
   final InputBorder border;
   final _InputBorderGap gap;
@@ -192,6 +194,7 @@
     _borderAnimation = CurvedAnimation(
       parent: _controller,
       curve: _kTransitionCurve,
+      reverseCurve: _kTransitionCurve.flipped,
     );
     _border = _InputBorderTween(
       begin: widget.border,
@@ -505,8 +508,7 @@
 ///    behave.
 @immutable
 class FloatingLabelAlignment {
-  const FloatingLabelAlignment._(this._x) : assert(_x != null),
-       assert(_x >= -1.0 && _x <= 1.0);
+  const FloatingLabelAlignment._(this._x) : assert(_x >= -1.0 && _x <= 1.0);
 
   // -1 denotes start, 0 denotes center, and 1 denotes end.
   final double _x;
@@ -589,11 +591,7 @@
     this.helperError,
     this.counter,
     this.container,
-  }) : assert(contentPadding != null),
-       assert(isCollapsed != null),
-       assert(floatingLabelHeight != null),
-       assert(floatingLabelProgress != null),
-       assert(floatingLabelAlignment != null);
+  });
 
   final EdgeInsetsGeometry contentPadding;
   final bool isCollapsed;
@@ -705,11 +703,7 @@
     required bool expands,
     required bool material3,
     TextAlignVertical? textAlignVertical,
-  }) : assert(decoration != null),
-       assert(textDirection != null),
-       assert(textBaseline != null),
-       assert(expands != null),
-       _decoration = decoration,
+  }) : _decoration = decoration,
        _textDirection = textDirection,
        _textBaseline = textBaseline,
        _textAlignVertical = textAlignVertical,
@@ -763,7 +757,6 @@
   _Decoration get decoration => _decoration;
   _Decoration _decoration;
   set decoration(_Decoration value) {
-    assert(value != null);
     if (_decoration == value) {
       return;
     }
@@ -774,7 +767,6 @@
   TextDirection get textDirection => _textDirection;
   TextDirection _textDirection;
   set textDirection(TextDirection value) {
-    assert(value != null);
     if (_textDirection == value) {
       return;
     }
@@ -785,7 +777,6 @@
   TextBaseline get textBaseline => _textBaseline;
   TextBaseline _textBaseline;
   set textBaseline(TextBaseline value) {
-    assert(value != null);
     if (_textBaseline == value) {
       return;
     }
@@ -814,7 +805,6 @@
   bool get isFocused => _isFocused;
   bool _isFocused;
   set isFocused(bool value) {
-    assert(value != null);
     if (_isFocused == value) {
       return;
     }
@@ -825,7 +815,6 @@
   bool get expands => _expands;
   bool _expands = false;
   set expands(bool value) {
-    assert(value != null);
     if (_expands == value) {
       return;
     }
@@ -978,12 +967,12 @@
       0.0,
       constraints.maxWidth - (
         _boxSize(icon).width
-        + contentPadding.left
+        + (prefixIcon != null ? 0 : (textDirection == TextDirection.ltr ? contentPadding.left : contentPadding.right))
         + _boxSize(prefixIcon).width
         + _boxSize(prefix).width
         + _boxSize(suffix).width
         + _boxSize(suffixIcon).width
-        + contentPadding.right),
+        + (suffixIcon != null ? 0 : (textDirection == TextDirection.ltr ? contentPadding.right : contentPadding.left))),
     );
     // Increase the available width for the label when it is scaled down.
     final double invertedLabelScale = lerpDouble(1.00, 1 / _kFinalLabelScale, decoration.floatingLabelProgress)!;
@@ -1326,6 +1315,35 @@
     return Size.zero;
   }
 
+  ChildSemanticsConfigurationsResult _childSemanticsConfigurationDelegate(List<SemanticsConfiguration> childConfigs) {
+    final ChildSemanticsConfigurationsResultBuilder builder = ChildSemanticsConfigurationsResultBuilder();
+    List<SemanticsConfiguration>? prefixMergeGroup;
+    List<SemanticsConfiguration>? suffixMergeGroup;
+    for (final SemanticsConfiguration childConfig in childConfigs) {
+      if (childConfig.tagsChildrenWith(_InputDecoratorState._kPrefixSemanticsTag)) {
+        prefixMergeGroup ??= <SemanticsConfiguration>[];
+        prefixMergeGroup.add(childConfig);
+      } else if (childConfig.tagsChildrenWith(_InputDecoratorState._kSuffixSemanticsTag)) {
+        suffixMergeGroup ??= <SemanticsConfiguration>[];
+        suffixMergeGroup.add(childConfig);
+      } else {
+        builder.markAsMergeUp(childConfig);
+      }
+    }
+    if (prefixMergeGroup != null) {
+      builder.markAsSiblingMergeGroup(prefixMergeGroup);
+    }
+    if (suffixMergeGroup != null) {
+      builder.markAsSiblingMergeGroup(suffixMergeGroup);
+    }
+    return builder.build();
+  }
+
+  @override
+  void describeSemanticsConfiguration(SemanticsConfiguration config) {
+    config.childConfigurationsDelegate = _childSemanticsConfigurationDelegate;
+  }
+
   @override
   void performLayout() {
     final BoxConstraints constraints = this.constraints;
@@ -1542,7 +1560,7 @@
       final double t = decoration.floatingLabelProgress;
       // The center of the outline border label ends up a little below the
       // center of the top border line.
-      final bool isOutlineBorder = decoration.border != null && decoration.border.isOutline;
+      final bool isOutlineBorder = decoration.border.isOutline;
       // Temporary opt-in fix for https://github.com/flutter/flutter/issues/54028
       // Center the scaled label relative to the border.
       final double floatingY = isOutlineBorder ? (-labelHeight * _kFinalLabelScale) / 2.0 + borderWeight / 2.0 : contentPadding.top;
@@ -1600,7 +1618,6 @@
 
   @override
   bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
-    assert(position != null);
     for (final RenderBox child in children) {
       // The label must be handled specially since we've transformed it.
       final Offset offset = _boxParentData(child).offset;
@@ -1639,10 +1656,7 @@
     required this.textBaseline,
     required this.isFocused,
     required this.expands,
-  }) : assert(decoration != null),
-       assert(textDirection != null),
-       assert(textBaseline != null),
-       assert(expands != null);
+  });
 
   final _Decoration decoration;
   final TextDirection textDirection;
@@ -1713,12 +1727,16 @@
     this.text,
     this.style,
     this.child,
+    this.semanticsSortKey,
+    required this.semanticsTag,
   });
 
   final bool labelIsFloating;
   final String? text;
   final TextStyle? style;
   final Widget? child;
+  final SemanticsSortKey? semanticsSortKey;
+  final SemanticsTag semanticsTag;
 
   @override
   Widget build(BuildContext context) {
@@ -1728,7 +1746,11 @@
         duration: _kTransitionDuration,
         curve: _kTransitionCurve,
         opacity: labelIsFloating ? 1.0 : 0.0,
-        child: child ?? (text == null ? null : Text(text!, style: style)),
+        child: Semantics(
+          sortKey: semanticsSortKey,
+          tagForChildren: semanticsTag,
+          child: child ?? (text == null ? null : Text(text!, style: style)),
+        ),
       ),
     );
   }
@@ -1773,11 +1795,7 @@
     this.expands = false,
     this.isEmpty = false,
     this.child,
-  }) : assert(decoration != null),
-       assert(isFocused != null),
-       assert(isHovering != null),
-       assert(expands != null),
-       assert(isEmpty != null);
+  });
 
   /// The text and styles to use when decorating the child.
   ///
@@ -1896,9 +1914,15 @@
 }
 
 class _InputDecoratorState extends State<InputDecorator> with TickerProviderStateMixin {
-  late AnimationController _floatingLabelController;
-  late AnimationController _shakingLabelController;
+  late final AnimationController _floatingLabelController;
+  late final Animation<double> _floatingLabelAnimation;
+  late final AnimationController _shakingLabelController;
   final _InputBorderGap _borderGap = _InputBorderGap();
+  static const OrdinalSortKey _kPrefixSemanticsSortOrder = OrdinalSortKey(0);
+  static const OrdinalSortKey _kInputSemanticsSortOrder = OrdinalSortKey(1);
+  static const OrdinalSortKey _kSuffixSemanticsSortOrder = OrdinalSortKey(2);
+  static const SemanticsTag _kPrefixSemanticsTag = SemanticsTag('_InputDecoratorState.prefix');
+  static const SemanticsTag _kSuffixSemanticsTag = SemanticsTag('_InputDecoratorState.suffix');
 
   @override
   void initState() {
@@ -1914,6 +1938,11 @@
       value: labelIsInitiallyFloating ? 1.0 : 0.0,
     );
     _floatingLabelController.addListener(_handleChange);
+    _floatingLabelAnimation = CurvedAnimation(
+      parent: _floatingLabelController,
+      curve: _kTransitionCurve,
+      reverseCurve: _kTransitionCurve.flipped,
+    );
 
     _shakingLabelController = AnimationController(
       duration: _kTransitionDuration,
@@ -2166,7 +2195,6 @@
       opacity: (isEmpty && !_hasInlineLabel) ? 1.0 : 0.0,
       duration: _kTransitionDuration,
       curve: _kTransitionCurve,
-      alwaysIncludeSemantics: isEmpty || (decoration.labelText == null && decoration.label == null),
       child: Text(
         hintText,
         style: hintStyle,
@@ -2191,7 +2219,7 @@
     final Widget container = _BorderContainer(
       border: border,
       gap: _borderGap,
-      gapAnimation: _floatingLabelController.view,
+      gapAnimation: _floatingLabelAnimation,
       fillColor: _getFillColor(themeData, defaults),
       hoverColor: _getHoverColor(themeData),
       isHovering: isHovering,
@@ -2218,22 +2246,42 @@
       ),
     );
 
-    final Widget? prefix = decoration.prefix == null && decoration.prefixText == null ? null :
-      _AffixText(
-        labelIsFloating: widget._labelShouldWithdraw,
-        text: decoration.prefixText,
-        style: MaterialStateProperty.resolveAs(decoration.prefixStyle, materialState) ?? hintStyle,
-        child: decoration.prefix,
-      );
+    final bool hasPrefix = decoration.prefix != null || decoration.prefixText != null;
+    final bool hasSuffix = decoration.suffix != null || decoration.suffixText != null;
 
-    final Widget? suffix = decoration.suffix == null && decoration.suffixText == null ? null :
-      _AffixText(
-        labelIsFloating: widget._labelShouldWithdraw,
-        text: decoration.suffixText,
-        style: MaterialStateProperty.resolveAs(decoration.suffixStyle, materialState) ?? hintStyle,
-        child: decoration.suffix,
-      );
+    Widget? input = widget.child;
+    // If at least two out of the three are visible, it needs semantics sort
+    // order.
+    final bool needsSemanticsSortOrder = widget._labelShouldWithdraw && (input != null ? (hasPrefix || hasSuffix) : (hasPrefix && hasSuffix));
 
+    final Widget? prefix = hasPrefix
+      ? _AffixText(
+          labelIsFloating: widget._labelShouldWithdraw,
+          text: decoration.prefixText,
+          style: MaterialStateProperty.resolveAs(decoration.prefixStyle, materialState) ?? hintStyle,
+          semanticsSortKey: needsSemanticsSortOrder ? _kPrefixSemanticsSortOrder : null,
+          semanticsTag: _kPrefixSemanticsTag,
+          child: decoration.prefix,
+        )
+      : null;
+
+    final Widget? suffix = hasSuffix
+      ? _AffixText(
+          labelIsFloating: widget._labelShouldWithdraw,
+          text: decoration.suffixText,
+          style: MaterialStateProperty.resolveAs(decoration.suffixStyle, materialState) ?? hintStyle,
+          semanticsSortKey: needsSemanticsSortOrder ? _kSuffixSemanticsSortOrder : null,
+          semanticsTag: _kSuffixSemanticsTag,
+          child: decoration.suffix,
+        )
+      : null;
+
+    if (input != null && needsSemanticsSortOrder) {
+      input = Semantics(
+        sortKey: _kInputSemanticsSortOrder,
+        child: input,
+      );
+    }
 
     final bool decorationIsDense = decoration.isDense ?? false;
     final double iconSize = decorationIsDense ? 18.0 : 24.0;
@@ -2261,18 +2309,28 @@
           cursor: SystemMouseCursors.basic,
           child: ConstrainedBox(
             constraints: decoration.prefixIconConstraints ??
-                themeData.visualDensity.effectiveConstraints(
-                  const BoxConstraints(
-                    minWidth: kMinInteractiveDimension,
-                    minHeight: kMinInteractiveDimension,
-                  ),
+              themeData.visualDensity.effectiveConstraints(
+                const BoxConstraints(
+                  minWidth: kMinInteractiveDimension,
+                  minHeight: kMinInteractiveDimension,
                 ),
+              ),
             child: IconTheme.merge(
               data: IconThemeData(
                 color: _getPrefixIconColor(themeData, defaults),
                 size: iconSize,
               ),
-              child: decoration.prefixIcon!,
+              child: IconButtonTheme(
+                data: IconButtonThemeData(
+                style: IconButton.styleFrom(
+                  foregroundColor: _getPrefixIconColor(themeData, defaults),
+                  iconSize: iconSize,
+                  ),
+                ),
+                child: Semantics(
+                  child: decoration.prefixIcon,
+                ),
+              ),
             ),
           ),
         ),
@@ -2286,22 +2344,32 @@
           cursor: SystemMouseCursors.basic,
           child: ConstrainedBox(
             constraints: decoration.suffixIconConstraints ??
-                themeData.visualDensity.effectiveConstraints(
-                  const BoxConstraints(
-                    minWidth: kMinInteractiveDimension,
-                    minHeight: kMinInteractiveDimension,
+              themeData.visualDensity.effectiveConstraints(
+                const BoxConstraints(
+                  minWidth: kMinInteractiveDimension,
+                  minHeight: kMinInteractiveDimension,
+                ),
+              ),
+              child: IconTheme.merge(
+                data: IconThemeData(
+                  color: _getSuffixIconColor(themeData, defaults),
+                  size: iconSize,
+                ),
+                child: IconButtonTheme(
+                  data: IconButtonThemeData(
+                  style: IconButton.styleFrom(
+                    foregroundColor: _getSuffixIconColor(themeData, defaults),
+                    iconSize: iconSize,
+                    ),
+                  ),
+                  child: Semantics(
+                    child: decoration.suffixIcon,
                   ),
                 ),
-            child: IconTheme.merge(
-              data: IconThemeData(
-                color: _getSuffixIconColor(themeData, defaults),
-                size: iconSize,
               ),
-              child: decoration.suffixIcon!,
             ),
           ),
-        ),
-      );
+        );
 
     final Widget helperError = _HelperError(
       textAlign: textAlign,
@@ -2367,14 +2435,14 @@
         isCollapsed: decoration.isCollapsed,
         floatingLabelHeight: floatingLabelHeight,
         floatingLabelAlignment: decoration.floatingLabelAlignment!,
-        floatingLabelProgress: _floatingLabelController.value,
+        floatingLabelProgress: _floatingLabelAnimation.value,
         border: border,
         borderGap: _borderGap,
         alignLabelWithHint: decoration.alignLabelWithHint ?? false,
         isDense: decoration.isDense,
         visualDensity: themeData.visualDensity,
         icon: icon,
-        input: widget.child,
+        input: input,
         label: label,
         hint: hint,
         prefix: prefix,
@@ -2542,8 +2610,7 @@
     this.semanticCounterText,
     this.alignLabelWithHint,
     this.constraints,
-  }) : assert(enabled != null),
-       assert(!(label != null && labelText != null), 'Declaring both label and labelText is not supported.'),
+  }) : assert(!(label != null && labelText != null), 'Declaring both label and labelText is not supported.'),
        assert(!(prefix != null && prefixText != null), 'Declaring both prefix and prefixText is not supported.'),
        assert(!(suffix != null && suffixText != null), 'Declaring both suffix and suffixText is not supported.');
 
@@ -2564,8 +2631,7 @@
     this.hoverColor,
     this.border = InputBorder.none,
     this.enabled = true,
-  }) : assert(enabled != null),
-       icon = null,
+  }) : icon = null,
        iconColor = null,
        label = null,
        labelText = null,
@@ -3780,11 +3846,7 @@
     this.border,
     this.alignLabelWithHint = false,
     this.constraints,
-  }) : assert(isDense != null),
-       assert(isCollapsed != null),
-       assert(floatingLabelAlignment != null),
-       assert(filled != null),
-       assert(alignLabelWithHint != null);
+  });
 
   /// {@macro flutter.material.inputDecoration.labelStyle}
   final TextStyle? labelStyle;
@@ -4480,7 +4542,7 @@
 // Design token database by the script:
 //   dev/tools/gen_defaults/bin/gen_defaults.dart.
 
-// Token database version: v0_143
+// Token database version: v0_158
 
 class _InputDecoratorDefaultsM3 extends InputDecorationTheme {
    _InputDecoratorDefaultsM3(this.context)
@@ -4580,7 +4642,7 @@
 
   @override
   TextStyle? get labelStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
-    final TextStyle textStyle= _textTheme.bodyLarge ?? const TextStyle();
+    final TextStyle textStyle = _textTheme.bodyLarge ?? const TextStyle();
     if(states.contains(MaterialState.error)) {
       if (states.contains(MaterialState.focused)) {
         return textStyle.copyWith(color:_colors.error);
@@ -4604,7 +4666,7 @@
 
   @override
   TextStyle? get floatingLabelStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
-    final TextStyle textStyle= _textTheme.bodyLarge ?? const TextStyle();
+    final TextStyle textStyle = _textTheme.bodyLarge ?? const TextStyle();
     if(states.contains(MaterialState.error)) {
       if (states.contains(MaterialState.focused)) {
         return textStyle.copyWith(color:_colors.error);
@@ -4628,7 +4690,7 @@
 
   @override
   TextStyle? get helperStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
-    final TextStyle textStyle= _textTheme.bodySmall ?? const TextStyle();
+    final TextStyle textStyle = _textTheme.bodySmall ?? const TextStyle();
     if (states.contains(MaterialState.disabled)) {
       return textStyle.copyWith(color:_colors.onSurface.withOpacity(0.38));
     }
@@ -4637,7 +4699,7 @@
 
   @override
   TextStyle? get errorStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
-    final TextStyle textStyle= _textTheme.bodySmall ?? const TextStyle();
+    final TextStyle textStyle = _textTheme.bodySmall ?? const TextStyle();
     return textStyle.copyWith(color:_colors.error);
   });
 }
diff --git a/framework/lib/src/material/list_tile.dart b/framework/lib/src/material/list_tile.dart
index d485f5f..c8af8a0 100644
--- a/framework/lib/src/material/list_tile.dart
+++ b/framework/lib/src/material/list_tile.dart
@@ -7,14 +7,18 @@
 import 'package:flute/rendering.dart';
 import 'package:flute/widgets.dart';
 
+import 'color_scheme.dart';
 import 'colors.dart';
 import 'constants.dart';
 import 'debug.dart';
 import 'divider.dart';
+import 'icon_button.dart';
+import 'icon_button_theme.dart';
 import 'ink_decoration.dart';
 import 'ink_well.dart';
 import 'list_tile_theme.dart';
 import 'material_state.dart';
+import 'text_theme.dart';
 import 'theme.dart';
 import 'theme_data.dart';
 
@@ -99,9 +103,9 @@
 ///
 /// {@tool snippet}
 /// ```dart
-/// Container(
+/// const ColoredBox(
 ///   color: Colors.green,
-///   child: const Material(
+///   child: Material(
 ///     child: ListTile(
 ///       title: Text('ListTile with red background'),
 ///       tileColor: Colors.red,
@@ -137,15 +141,29 @@
 /// ** See code in examples/api/lib/material/list_tile/list_tile.1.dart **
 /// {@end-tool}
 ///
-/// {@tool snippet}
+/// {@tool dartpad}
+/// This sample shows the creation of a [ListTile] using [ThemeData.useMaterial3] flag,
+/// as described in: https://m3.material.io/components/lists/overview.
 ///
+/// ** See code in examples/api/lib/material/list_tile/list_tile.2.dart **
+/// {@end-tool}
+///
+/// {@tool dartpad}
+/// This sample shows [ListTile]'s [textColor] and [iconColor] can use
+/// [MaterialStateColor] color to change the color of the text and icon
+/// when the [ListTile] is enabled, selected, or disabled.
+///
+/// ** See code in examples/api/lib/material/list_tile/list_tile.3.dart **
+/// {@end-tool}
+///
+/// {@tool snippet}
 /// To use a [ListTile] within a [Row], it needs to be wrapped in an
 /// [Expanded] widget. [ListTile] requires fixed width constraints,
 /// whereas a [Row] does not constrain its children.
 ///
 /// ```dart
-/// Row(
-///   children: const <Widget>[
+/// const Row(
+///   children: <Widget>[
 ///     Expanded(
 ///       child: ListTile(
 ///         leading: FlutterLogo(),
@@ -229,7 +247,7 @@
 ///
 /// ![Custom list item a](https://flutter.github.io/assets-for-api-docs/assets/widgets/custom_list_item_a.png)
 ///
-/// ** See code in examples/api/lib/material/list_tile/list_tile.4.dart **
+/// ** See code in examples/api/lib/material/list_tile/custom_list_item.0.dart **
 /// {@end-tool}
 ///
 /// {@tool dartpad}
@@ -239,7 +257,7 @@
 ///
 /// ![Custom list item b](https://flutter.github.io/assets-for-api-docs/assets/widgets/custom_list_item_b.png)
 ///
-/// ** See code in examples/api/lib/material/list_tile/list_tile.5.dart **
+/// ** See code in examples/api/lib/material/list_tile/custom_list_item.1.dart **
 /// {@end-tool}
 ///
 /// See also:
@@ -254,10 +272,10 @@
 ///  * [ListTile.divideTiles], a utility for inserting [Divider]s in between [ListTile]s.
 ///  * [CheckboxListTile], [RadioListTile], and [SwitchListTile], widgets
 ///    that combine [ListTile] with other controls.
-///  * <https://material.io/design/components/lists.html>
+///  * Material 3 [ListTile] specifications are referenced from <https://m3.material.io/components/lists/specs>
+///    and Material 2 [ListTile] specifications are referenced from <https://material.io/design/components/lists.html>
 ///  * Cookbook: [Use lists](https://flutter.dev/docs/cookbook/lists/basic-list)
 ///  * Cookbook: [Implement swipe to dismiss](https://flutter.dev/docs/cookbook/gestures/dismissible)
-// TODO(plg): Add link to m3 spec below m2 spec link when available
 class ListTile extends StatelessWidget {
   /// Creates a list tile.
   ///
@@ -278,6 +296,9 @@
     this.selectedColor,
     this.iconColor,
     this.textColor,
+    this.titleTextStyle,
+    this.subtitleTextStyle,
+    this.leadingAndTrailingTextStyle,
     this.contentPadding,
     this.enabled = true,
     this.onTap,
@@ -296,11 +317,7 @@
     this.horizontalTitleGap,
     this.minVerticalPadding,
     this.minLeadingWidth,
-  }) : assert(isThreeLine != null),
-       assert(enabled != null),
-       assert(selected != null),
-       assert(autofocus != null),
-       assert(!isThreeLine || subtitle != null);
+  }) : assert(!isThreeLine || subtitle != null);
 
   /// A widget to display before the title.
   ///
@@ -364,6 +381,8 @@
   /// If this property is null then its value is based on [ListTileTheme.dense].
   ///
   /// Dense list tiles default to a smaller height.
+  ///
+  /// It is not recommended to set [dense] to true when [ThemeData.useMaterial3] is true.
   final bool? dense;
 
   /// Defines how compact the list tile's layout will be.
@@ -402,7 +421,16 @@
 
   /// Defines the default color for [leading] and [trailing] icons.
   ///
-  /// If this property is null then [ListTileThemeData.iconColor] is used.
+  /// If this property is null and [selected] is false then [ListTileThemeData.iconColor]
+  /// is used. If that is also null and [ThemeData.useMaterial3] is true, [ColorScheme.onSurface]
+  /// is used, otherwise if [ThemeData.brightness] is [Brightness.light], [Colors.black54] is used,
+  /// and if [ThemeData.brightness] is [Brightness.dark], the value is null.
+  ///
+  /// If this property is null and [selected] is true then [ListTileThemeData.selectedColor]
+  /// is used. If that is also null then [ColorScheme.primary] is used.
+  ///
+  /// If this color is a [MaterialStateColor] it will be resolved against
+  /// [MaterialState.selected] and [MaterialState.disabled] states.
   ///
   /// See also:
   ///
@@ -410,10 +438,18 @@
   ///   [ListTileThemeData].
   final Color? iconColor;
 
-  /// Defines the default color for the [title] and [subtitle].
+  /// Defines the text color for the [title], [subtitle], [leading], and [trailing].
   ///
-  /// If this property is null then [ListTileThemeData.textColor] is used. If that
-  /// is also null then [ColorScheme.primary] is used.
+  /// If this property is null and [selected] is false then [ListTileThemeData.textColor]
+  /// is used. If that is also null then default text color is used for the [title], [subtitle]
+  /// [leading], and [trailing]. Except for [subtitle], if [ThemeData.useMaterial3] is false,
+  /// [TextTheme.bodySmall] is used.
+  ///
+  /// If this property is null and [selected] is true then [ListTileThemeData.selectedColor]
+  /// is used. If that is also null then [ColorScheme.primary] is used.
+  ///
+  /// If this color is a [MaterialStateColor] it will be resolved against
+  /// [MaterialState.selected] and [MaterialState.disabled] states.
   ///
   /// See also:
   ///
@@ -421,6 +457,28 @@
   ///   [ListTileThemeData].
   final Color? textColor;
 
+  /// The text style for ListTile's [title].
+  ///
+  /// If this property is null, then [ListTileThemeData.titleTextStyle] is used.
+  /// If that is also null and [ThemeData.useMaterial3] is true, [TextTheme.bodyLarge]
+  /// will be used. Otherwise, If ListTile style is [ListTileStyle.list],
+  /