Restore "Flutter gallery: updated Shrine demo" (#23878)

diff --git a/dev/automated_tests/pubspec.yaml b/dev/automated_tests/pubspec.yaml
index ea89315..1b0a2b2 100644
--- a/dev/automated_tests/pubspec.yaml
+++ b/dev/automated_tests/pubspec.yaml
@@ -10,7 +10,7 @@
   flutter_test:
     sdk: flutter
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -19,7 +19,7 @@
   convert: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -28,7 +28,7 @@
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -41,7 +41,7 @@
   plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -65,4 +65,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: e771
+# PUBSPEC CHECKSUM: 53cf
diff --git a/dev/benchmarks/complex_layout/pubspec.yaml b/dev/benchmarks/complex_layout/pubspec.yaml
index cc4578a..fd39dcc 100644
--- a/dev/benchmarks/complex_layout/pubspec.yaml
+++ b/dev/benchmarks/complex_layout/pubspec.yaml
@@ -40,11 +40,11 @@
   flutter_test:
     sdk: flutter
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -52,7 +52,7 @@
   http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -62,7 +62,7 @@
   package_resolver: 1.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -82,4 +82,4 @@
     - packages/flutter_gallery_assets/people/square/ali.png
     - packages/flutter_gallery_assets/places/india_chettinad_silk_maker.png
 
-# PUBSPEC CHECKSUM: d841
+# PUBSPEC CHECKSUM: 9f9f
diff --git a/dev/benchmarks/microbenchmarks/pubspec.yaml b/dev/benchmarks/microbenchmarks/pubspec.yaml
index 1fb2857..ca04aaa 100644
--- a/dev/benchmarks/microbenchmarks/pubspec.yaml
+++ b/dev/benchmarks/microbenchmarks/pubspec.yaml
@@ -14,7 +14,7 @@
   stocks:
     path: ../../../examples/stocks
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -24,7 +24,7 @@
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   dart_style: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -36,7 +36,7 @@
   isolate: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -49,7 +49,7 @@
   plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -73,4 +73,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: f9c7
+# PUBSPEC CHECKSUM: 3826
diff --git a/dev/bots/pubspec.yaml b/dev/bots/pubspec.yaml
index 378eee8..38fae6e 100644
--- a/dev/bots/pubspec.yaml
+++ b/dev/bots/pubspec.yaml
@@ -27,19 +27,19 @@
   test: 1.3.4
   mockito: 3.0.0
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   convert: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http_multi_server: 2.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -65,4 +65,4 @@
   web_socket_channel: 1.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   yaml: 2.1.15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
 
-# PUBSPEC CHECKSUM: 1cb4
+# PUBSPEC CHECKSUM: c16e
diff --git a/dev/devicelab/pubspec.yaml b/dev/devicelab/pubspec.yaml
index b6d156a..6a52050 100644
--- a/dev/devicelab/pubspec.yaml
+++ b/dev/devicelab/pubspec.yaml
@@ -38,10 +38,10 @@
   # See packages/flutter_test/pubspec.yaml for why we're pinning this version.
   test: 1.3.4
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -49,7 +49,7 @@
   http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -71,4 +71,4 @@
   watcher: 0.9.7+10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   yaml: 2.1.15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
 
-# PUBSPEC CHECKSUM: e39a
+# PUBSPEC CHECKSUM: 9154
diff --git a/dev/integration_tests/android_views/pubspec.yaml b/dev/integration_tests/android_views/pubspec.yaml
index 26af712..2ac0665 100644
--- a/dev/integration_tests/android_views/pubspec.yaml
+++ b/dev/integration_tests/android_views/pubspec.yaml
@@ -36,11 +36,11 @@
   flutter_goldens:
     sdk: flutter
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -48,7 +48,7 @@
   http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -60,7 +60,7 @@
   plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   process: 3.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -77,4 +77,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: 3b70
+# PUBSPEC CHECKSUM: 2fce
diff --git a/dev/integration_tests/ui/pubspec.yaml b/dev/integration_tests/ui/pubspec.yaml
index a50a5e7..bb557ca 100644
--- a/dev/integration_tests/ui/pubspec.yaml
+++ b/dev/integration_tests/ui/pubspec.yaml
@@ -40,10 +40,10 @@
     sdk: flutter
   test: 1.3.4
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -51,7 +51,7 @@
   http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -61,7 +61,7 @@
   package_resolver: 1.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -77,4 +77,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: d2cb
+# PUBSPEC CHECKSUM: fb2a
diff --git a/dev/manual_tests/pubspec.yaml b/dev/manual_tests/pubspec.yaml
index af8e42e..2cded97 100644
--- a/dev/manual_tests/pubspec.yaml
+++ b/dev/manual_tests/pubspec.yaml
@@ -19,7 +19,7 @@
 
   mockito: 3.0.0
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -27,7 +27,7 @@
   convert: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -36,7 +36,7 @@
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -48,7 +48,7 @@
   plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -70,4 +70,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: 70b4
+# PUBSPEC CHECKSUM: 1f13
diff --git a/dev/snippets/pubspec.yaml b/dev/snippets/pubspec.yaml
index 7d76fc3..920082d 100644
--- a/dev/snippets/pubspec.yaml
+++ b/dev/snippets/pubspec.yaml
@@ -18,17 +18,17 @@
   meta: 1.1.6
   platform: 2.2.0
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   charcode: 1.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   collection: 1.14.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   convert: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -98,4 +98,4 @@
   vm_service_client: 0.2.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   web_socket_channel: 1.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
 
-# PUBSPEC CHECKSUM: f478
+# PUBSPEC CHECKSUM: fc32
diff --git a/dev/tools/pubspec.yaml b/dev/tools/pubspec.yaml
index 55c1c61..292ee55 100644
--- a/dev/tools/pubspec.yaml
+++ b/dev/tools/pubspec.yaml
@@ -30,17 +30,17 @@
   test: 1.3.4
   mockito: 3.0.0
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http_multi_server: 2.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -66,4 +66,4 @@
   web_socket_channel: 1.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   yaml: 2.1.15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
 
-# PUBSPEC CHECKSUM: dee6
+# PUBSPEC CHECKSUM: 32a0
diff --git a/dev/tools/vitool/pubspec.yaml b/dev/tools/vitool/pubspec.yaml
index a0ac764..9066c0b 100644
--- a/dev/tools/vitool/pubspec.yaml
+++ b/dev/tools/vitool/pubspec.yaml
@@ -20,14 +20,14 @@
   flutter_test:
     sdk: flutter
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   charcode: 1.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   convert: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -36,7 +36,7 @@
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -49,7 +49,7 @@
   plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -69,4 +69,4 @@
   web_socket_channel: 1.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   yaml: 2.1.15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
 
-# PUBSPEC CHECKSUM: ec16
+# PUBSPEC CHECKSUM: c974
diff --git a/examples/catalog/pubspec.yaml b/examples/catalog/pubspec.yaml
index 5900975..454e64b 100644
--- a/examples/catalog/pubspec.yaml
+++ b/examples/catalog/pubspec.yaml
@@ -21,7 +21,7 @@
   flutter_driver:
     sdk: flutter
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -30,7 +30,7 @@
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   file: 5.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -40,7 +40,7 @@
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -51,7 +51,7 @@
   plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -73,4 +73,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: 27a2
+# PUBSPEC CHECKSUM: 3901
diff --git a/examples/flutter_gallery/lib/demo/shrine/app.dart b/examples/flutter_gallery/lib/demo/shrine/app.dart
new file mode 100644
index 0000000..e5eae3a
--- /dev/null
+++ b/examples/flutter_gallery/lib/demo/shrine/app.dart
@@ -0,0 +1,136 @@
+// Copyright 2018-present the Flutter authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'package:flutter/material.dart';
+
+import 'package:flutter_gallery/demo/shrine/backdrop.dart';
+import 'package:flutter_gallery/demo/shrine/category_menu_page.dart';
+import 'package:flutter_gallery/demo/shrine/colors.dart';
+import 'package:flutter_gallery/demo/shrine/expanding_bottom_sheet.dart';
+import 'package:flutter_gallery/demo/shrine/home.dart';
+import 'package:flutter_gallery/demo/shrine/login.dart';
+import 'package:flutter_gallery/demo/shrine/supplemental/cut_corners_border.dart';
+
+class ShrineApp extends StatefulWidget {
+  @override
+  _ShrineAppState createState() => _ShrineAppState();
+}
+
+class _ShrineAppState extends State<ShrineApp> with SingleTickerProviderStateMixin {
+  // Controller to coordinate both the opening/closing of backdrop and sliding
+  // of expanding bottom sheet
+  AnimationController _controller;
+
+  @override
+  void initState() {
+    super.initState();
+    _controller = AnimationController(
+      vsync: this,
+      duration: const Duration(milliseconds: 450),
+      value: 1.0,
+    );
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return MaterialApp(
+      title: 'Shrine',
+      home: HomePage(
+        backdrop: Backdrop(
+          frontLayer: const ProductPage(),
+          backLayer: CategoryMenuPage(onCategoryTap: () => _controller.forward()),
+          frontTitle: const Text('SHRINE'),
+          backTitle: const Text('MENU'),
+          controller: _controller,
+        ),
+        expandingBottomSheet: ExpandingBottomSheet(hideController: _controller),
+      ),
+      initialRoute: '/login',
+      onGenerateRoute: _getRoute,
+      theme: _kShrineTheme,
+    );
+  }
+}
+
+Route<dynamic> _getRoute(RouteSettings settings) {
+  if (settings.name != '/login') {
+    return null;
+  }
+
+  return MaterialPageRoute<void>(
+    settings: settings,
+    builder: (BuildContext context) => LoginPage(),
+    fullscreenDialog: true,
+  );
+}
+
+final ThemeData _kShrineTheme = _buildShrineTheme();
+
+IconThemeData _customIconTheme(IconThemeData original) {
+  return original.copyWith(color: kShrineBrown900);
+}
+
+ThemeData _buildShrineTheme() {
+  final ThemeData base = ThemeData.light();
+  return base.copyWith(
+    colorScheme: kShrineColorScheme,
+    accentColor: kShrineBrown900,
+    primaryColor: kShrinePink100,
+    buttonColor: kShrinePink100,
+    scaffoldBackgroundColor: kShrineBackgroundWhite,
+    cardColor: kShrineBackgroundWhite,
+    textSelectionColor: kShrinePink100,
+    errorColor: kShrineErrorRed,
+    buttonTheme: const ButtonThemeData(
+      colorScheme: kShrineColorScheme,
+      textTheme: ButtonTextTheme.normal,
+    ),
+    primaryIconTheme: _customIconTheme(base.iconTheme),
+    inputDecorationTheme: const InputDecorationTheme(border: CutCornersBorder()),
+    textTheme: _buildShrineTextTheme(base.textTheme),
+    primaryTextTheme: _buildShrineTextTheme(base.primaryTextTheme),
+    accentTextTheme: _buildShrineTextTheme(base.accentTextTheme),
+    iconTheme: _customIconTheme(base.iconTheme),
+  );
+}
+
+TextTheme _buildShrineTextTheme(TextTheme base) {
+  return base.copyWith(
+    headline: base.headline.copyWith(fontWeight: FontWeight.w500),
+    title: base.title.copyWith(fontSize: 18.0),
+    caption: base.caption.copyWith(fontWeight: FontWeight.w400, fontSize: 14.0),
+    body2: base.body2.copyWith(fontWeight: FontWeight.w500, fontSize: 16.0),
+    button: base.button.copyWith(fontWeight: FontWeight.w500, fontSize: 14.0),
+  ).apply(
+    fontFamily: 'Raleway',
+    displayColor: kShrineBrown900,
+    bodyColor: kShrineBrown900,
+  );
+}
+
+const ColorScheme kShrineColorScheme = ColorScheme(
+  primary: kShrinePink100,
+  primaryVariant: kShrineBrown900,
+  secondary: kShrinePink50,
+  secondaryVariant: kShrineBrown900,
+  surface: kShrineSurfaceWhite,
+  background: kShrineBackgroundWhite,
+  error: kShrineErrorRed,
+  onPrimary: kShrineBrown900,
+  onSecondary: kShrineBrown900,
+  onSurface: kShrineBrown900,
+  onBackground: kShrineBrown900,
+  onError: kShrineSurfaceWhite,
+  brightness: Brightness.light,
+);
diff --git a/examples/flutter_gallery/lib/demo/shrine/backdrop.dart b/examples/flutter_gallery/lib/demo/shrine/backdrop.dart
new file mode 100644
index 0000000..2e79fae
--- /dev/null
+++ b/examples/flutter_gallery/lib/demo/shrine/backdrop.dart
@@ -0,0 +1,330 @@
+// Copyright 2018-present the Flutter authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'package:flutter/material.dart';
+import 'package:meta/meta.dart';
+
+import 'package:flutter_gallery/demo/shrine/login.dart';
+
+const Cubic _kAccelerateCurve = Cubic(0.548, 0.0, 0.757, 0.464);
+const Cubic _kDecelerateCurve = Cubic(0.23, 0.94, 0.41, 1.0);
+const double _kPeakVelocityTime = 0.248210;
+const double _kPeakVelocityProgress = 0.379146;
+
+class _FrontLayer extends StatelessWidget {
+  const _FrontLayer({
+    Key key,
+    this.onTap,
+    this.child,
+  }) : super(key: key);
+
+  final VoidCallback onTap;
+  final Widget child;
+
+  @override
+  Widget build(BuildContext context) {
+    return Material(
+      elevation: 16.0,
+      shape: const BeveledRectangleBorder(
+        borderRadius: BorderRadius.only(topLeft: Radius.circular(46.0)),
+      ),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.stretch,
+        children: <Widget>[
+          GestureDetector(
+            behavior: HitTestBehavior.opaque,
+            onTap: onTap,
+            child: Container(
+              height: 40.0,
+              alignment: AlignmentDirectional.centerStart,
+            ),
+          ),
+          Expanded(
+            child: child,
+          ),
+        ],
+      ),
+    );
+  }
+}
+
+class _BackdropTitle extends AnimatedWidget {
+  const _BackdropTitle({
+    Key key,
+    Listenable listenable,
+    this.onPress,
+    @required this.frontTitle,
+    @required this.backTitle,
+  })  : assert(frontTitle != null),
+        assert(backTitle != null),
+        super(key: key, listenable: listenable);
+
+  final Function onPress;
+  final Widget frontTitle;
+  final Widget backTitle;
+
+  @override
+  Widget build(BuildContext context) {
+    final Animation<double> animation = CurvedAnimation(
+      parent: listenable,
+      curve: const Interval(0.0, 0.78),
+    );
+
+    return DefaultTextStyle(
+      style: Theme.of(context).primaryTextTheme.title,
+      softWrap: false,
+      overflow: TextOverflow.ellipsis,
+      child: Row(children: <Widget>[
+        // branded icon
+        SizedBox(
+          width: 72.0,
+          child: IconButton(
+            padding: const EdgeInsets.only(right: 8.0),
+            onPressed: onPress,
+            icon: Stack(children: <Widget>[
+              Opacity(
+                opacity: animation.value,
+                child: const ImageIcon(AssetImage('packages/shrine_images/slanted_menu.png')),
+              ),
+              FractionalTranslation(
+                translation: Tween<Offset>(
+                  begin: Offset.zero,
+                  end: const Offset(1.0, 0.0),
+                ).evaluate(animation),
+                child: const ImageIcon(AssetImage('packages/shrine_images/diamond.png')),
+              )
+            ]),
+          ),
+        ),
+        // Here, we do a custom cross fade between backTitle and frontTitle.
+        // This makes a smooth animation between the two texts.
+        Stack(
+          children: <Widget>[
+            Opacity(
+              opacity: CurvedAnimation(
+                parent: ReverseAnimation(animation),
+                curve: const Interval(0.5, 1.0),
+              ).value,
+              child: FractionalTranslation(
+                translation: Tween<Offset>(
+                  begin: Offset.zero,
+                  end: const Offset(0.5, 0.0),
+                ).evaluate(animation),
+                child: backTitle,
+              ),
+            ),
+            Opacity(
+              opacity: CurvedAnimation(
+                parent: animation,
+                curve: const Interval(0.5, 1.0),
+              ).value,
+              child: FractionalTranslation(
+                translation: Tween<Offset>(
+                  begin: const Offset(-0.25, 0.0),
+                  end: Offset.zero,
+                ).evaluate(animation),
+                child: frontTitle,
+              ),
+            ),
+          ],
+        )
+      ]),
+    );
+  }
+}
+
+/// Builds a Backdrop.
+///
+/// A Backdrop widget has two layers, front and back. The front layer is shown
+/// by default, and slides down to show the back layer, from which a user
+/// can make a selection. The user can also configure the titles for when the
+/// front or back layer is showing.
+class Backdrop extends StatefulWidget {
+  const Backdrop({
+    @required this.frontLayer,
+    @required this.backLayer,
+    @required this.frontTitle,
+    @required this.backTitle,
+    @required this.controller,
+  })  : assert(frontLayer != null),
+        assert(backLayer != null),
+        assert(frontTitle != null),
+        assert(backTitle != null),
+        assert(controller != null);
+
+  final Widget frontLayer;
+  final Widget backLayer;
+  final Widget frontTitle;
+  final Widget backTitle;
+  final AnimationController controller;
+
+  @override
+  _BackdropState createState() => _BackdropState();
+}
+
+class _BackdropState extends State<Backdrop> with SingleTickerProviderStateMixin {
+  final GlobalKey _backdropKey = GlobalKey(debugLabel: 'Backdrop');
+  AnimationController _controller;
+  Animation<RelativeRect> _layerAnimation;
+
+  @override
+  void initState() {
+    super.initState();
+    _controller = widget.controller;
+  }
+
+  @override
+  void dispose() {
+    _controller.dispose();
+    super.dispose();
+  }
+
+  bool get _frontLayerVisible {
+    final AnimationStatus status = _controller.status;
+    return status == AnimationStatus.completed || status == AnimationStatus.forward;
+  }
+
+  void _toggleBackdropLayerVisibility() {
+    // Call setState here to update layerAnimation if that's necessary
+    setState(() {
+      _frontLayerVisible ? _controller.reverse() : _controller.forward();
+    });
+  }
+
+  // _layerAnimation animates the front layer between open and close.
+  // _getLayerAnimation adjusts the values in the TweenSequence so the
+  // curve and timing are correct in both directions.
+  Animation<RelativeRect> _getLayerAnimation(Size layerSize, double layerTop) {
+    Curve firstCurve; // Curve for first TweenSequenceItem
+    Curve secondCurve; // Curve for second TweenSequenceItem
+    double firstWeight; // Weight of first TweenSequenceItem
+    double secondWeight; // Weight of second TweenSequenceItem
+    Animation<double> animation; // Animation on which TweenSequence runs
+
+    if (_frontLayerVisible) {
+      firstCurve = _kAccelerateCurve;
+      secondCurve = _kDecelerateCurve;
+      firstWeight = _kPeakVelocityTime;
+      secondWeight = 1.0 - _kPeakVelocityTime;
+      animation = CurvedAnimation(
+        parent: _controller.view,
+        curve: const Interval(0.0, 0.78),
+      );
+    } else {
+      // These values are only used when the controller runs from t=1.0 to t=0.0
+      firstCurve = _kDecelerateCurve.flipped;
+      secondCurve = _kAccelerateCurve.flipped;
+      firstWeight = 1.0 - _kPeakVelocityTime;
+      secondWeight = _kPeakVelocityTime;
+      animation = _controller.view;
+    }
+
+    return TweenSequence<RelativeRect>(
+      <TweenSequenceItem<RelativeRect>>[
+        TweenSequenceItem<RelativeRect>(
+          tween: RelativeRectTween(
+            begin: RelativeRect.fromLTRB(
+              0.0,
+              layerTop,
+              0.0,
+              layerTop - layerSize.height,
+            ),
+            end: RelativeRect.fromLTRB(
+              0.0,
+              layerTop * _kPeakVelocityProgress,
+              0.0,
+              (layerTop - layerSize.height) * _kPeakVelocityProgress,
+            ),
+          ).chain(CurveTween(curve: firstCurve)),
+          weight: firstWeight,
+        ),
+        TweenSequenceItem<RelativeRect>(
+          tween: RelativeRectTween(
+            begin: RelativeRect.fromLTRB(
+              0.0,
+              layerTop * _kPeakVelocityProgress,
+              0.0,
+              (layerTop - layerSize.height) * _kPeakVelocityProgress,
+            ),
+            end: RelativeRect.fill,
+          ).chain(CurveTween(curve: secondCurve)),
+          weight: secondWeight,
+        ),
+      ],
+    ).animate(animation);
+  }
+
+  Widget _buildStack(BuildContext context, BoxConstraints constraints) {
+    const double layerTitleHeight = 48.0;
+    final Size layerSize = constraints.biggest;
+    final double layerTop = layerSize.height - layerTitleHeight;
+
+    _layerAnimation = _getLayerAnimation(layerSize, layerTop);
+
+    return Stack(
+      key: _backdropKey,
+      children: <Widget>[
+        widget.backLayer,
+        PositionedTransition(
+          rect: _layerAnimation,
+          child: _FrontLayer(
+            onTap: _toggleBackdropLayerVisibility,
+            child: widget.frontLayer,
+          ),
+        ),
+      ],
+    );
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final AppBar appBar = AppBar(
+      brightness: Brightness.light,
+      elevation: 0.0,
+      titleSpacing: 0.0,
+      title: _BackdropTitle(
+        listenable: _controller.view,
+        onPress: _toggleBackdropLayerVisibility,
+        frontTitle: widget.frontTitle,
+        backTitle: widget.backTitle,
+      ),
+      actions: <Widget>[
+        IconButton(
+          icon: const Icon(Icons.search, semanticLabel: 'login'),
+          onPressed: () {
+            Navigator.push<void>(
+              context,
+              MaterialPageRoute<void>(builder: (BuildContext context) => LoginPage()),
+            );
+          },
+        ),
+        IconButton(
+          icon: const Icon(Icons.tune, semanticLabel: 'login'),
+          onPressed: () {
+            Navigator.push<void>(
+              context,
+              MaterialPageRoute<void>(builder: (BuildContext context) => LoginPage()),
+            );
+          },
+        ),
+      ],
+    );
+    return Scaffold(
+      appBar: appBar,
+      body: LayoutBuilder(
+        builder: _buildStack,
+      ),
+    );
+  }
+}
diff --git a/examples/flutter_gallery/lib/demo/shrine/category_menu_page.dart b/examples/flutter_gallery/lib/demo/shrine/category_menu_page.dart
new file mode 100644
index 0000000..1ac62d5
--- /dev/null
+++ b/examples/flutter_gallery/lib/demo/shrine/category_menu_page.dart
@@ -0,0 +1,85 @@
+// Copyright 2018-present the Flutter authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'package:flutter/material.dart';
+import 'package:scoped_model/scoped_model.dart';
+
+import 'package:flutter_gallery/demo/shrine/colors.dart';
+import 'package:flutter_gallery/demo/shrine/model/app_state_model.dart';
+import 'package:flutter_gallery/demo/shrine/model/product.dart';
+
+class CategoryMenuPage extends StatelessWidget {
+  const CategoryMenuPage({
+    Key key,
+    this.onCategoryTap,
+  }) : super(key: key);
+
+  final VoidCallback onCategoryTap;
+
+  Widget _buildCategory(Category category, BuildContext context) {
+    final String categoryString = category.toString().replaceAll('Category.', '').toUpperCase();
+    final ThemeData theme = Theme.of(context);
+    return ScopedModelDescendant<AppStateModel>(
+      builder: (BuildContext context, Widget child, AppStateModel model) =>
+          GestureDetector(
+            onTap: () {
+              model.setCategory(category);
+              if (onCategoryTap != null) {
+                onCategoryTap();
+              }
+            },
+            child: model.selectedCategory == category
+              ? Column(
+                  children: <Widget>[
+                    const SizedBox(height: 16.0),
+                    Text(
+                      categoryString,
+                      style: theme.textTheme.body2,
+                      textAlign: TextAlign.center,
+                    ),
+                    const SizedBox(height: 14.0),
+                    Container(
+                      width: 70.0,
+                      height: 2.0,
+                      color: kShrinePink400,
+                    ),
+                  ],
+                )
+              : Padding(
+                  padding: const EdgeInsets.symmetric(vertical: 16.0),
+                  child: Text(
+                    categoryString,
+                    style: theme.textTheme.body2.copyWith(
+                      color: kShrineBrown900.withAlpha(153)
+                    ),
+                    textAlign: TextAlign.center,
+                  ),
+                ),
+          ),
+    );
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Center(
+      child: Container(
+        padding: const EdgeInsets.only(top: 40.0),
+        color: kShrinePink100,
+        child: ListView(
+          children: Category.values.map((Category c) => _buildCategory(c, context)).toList(),
+        ),
+      ),
+    );
+  }
+}
diff --git a/examples/flutter_gallery/lib/demo/shrine/colors.dart b/examples/flutter_gallery/lib/demo/shrine/colors.dart
new file mode 100644
index 0000000..66a4728
--- /dev/null
+++ b/examples/flutter_gallery/lib/demo/shrine/colors.dart
@@ -0,0 +1,28 @@
+// Copyright 2018-present the Flutter authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'package:flutter/material.dart';
+
+const Color kShrinePink50 = Color(0xFFFEEAE6);
+const Color kShrinePink100 = Color(0xFFFEDBD0);
+const Color kShrinePink300 = Color(0xFFFBB8AC);
+const Color kShrinePink400 = Color(0xFFEAA4A4);
+
+const Color kShrineBrown900 = Color(0xFF442B2D);
+const Color kShrineBrown600 = Color(0xFF7D4F52);
+
+const Color kShrineErrorRed = Color(0xFFC5032B);
+
+const Color kShrineSurfaceWhite = Color(0xFFFFFBFA);
+const Color kShrineBackgroundWhite = Colors.white;
diff --git a/examples/flutter_gallery/lib/demo/shrine/expanding_bottom_sheet.dart b/examples/flutter_gallery/lib/demo/shrine/expanding_bottom_sheet.dart
new file mode 100644
index 0000000..b74d632
--- /dev/null
+++ b/examples/flutter_gallery/lib/demo/shrine/expanding_bottom_sheet.dart
@@ -0,0 +1,655 @@
+// Copyright 2018-present the Flutter authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'dart:async';
+
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:meta/meta.dart';
+import 'package:scoped_model/scoped_model.dart';
+
+import 'package:flutter_gallery/demo/shrine/colors.dart';
+import 'package:flutter_gallery/demo/shrine/model/app_state_model.dart';
+import 'package:flutter_gallery/demo/shrine/model/product.dart';
+import 'package:flutter_gallery/demo/shrine/shopping_cart.dart';
+
+// These curves define the emphasized easing curve.
+const Cubic _kAccelerateCurve = Cubic(0.548, 0.0, 0.757, 0.464);
+const Cubic _kDecelerateCurve = Cubic(0.23, 0.94, 0.41, 1.0);
+// The time at which the accelerate and decelerate curves switch off
+const double _kPeakVelocityTime = 0.248210;
+// Percent (as a decimal) of animation that should be completed at _peakVelocityTime
+const double _kPeakVelocityProgress = 0.379146;
+const double _kCartHeight = 56.0;
+// Radius of the shape on the top left of the sheet.
+const double _kCornerRadius = 24.0;
+// Width for just the cart icon and no thumbnails.
+const double _kWidthForCartIcon = 64.0;
+
+class ExpandingBottomSheet extends StatefulWidget {
+  const ExpandingBottomSheet({Key key, @required this.hideController})
+      : assert(hideController != null),
+        super(key: key);
+
+  final AnimationController hideController;
+
+  @override
+  _ExpandingBottomSheetState createState() => _ExpandingBottomSheetState();
+
+  static _ExpandingBottomSheetState of(BuildContext context, {bool isNullOk = false}) {
+    assert(isNullOk != null);
+    assert(context != null);
+    final _ExpandingBottomSheetState result = context.ancestorStateOfType(
+      const TypeMatcher<_ExpandingBottomSheetState>()
+    );
+    if (isNullOk || result != null) {
+      return result;
+    }
+    throw FlutterError(
+      'ExpandingBottomSheet.of() called with a context that does not contain a ExpandingBottomSheet.\n');
+  }
+}
+
+// Emphasized Easing is a motion curve that has an organic, exciting feeling.
+// It's very fast to begin with and then very slow to finish. Unlike standard
+// curves, like [Curves.fastOutSlowIn], it can't be expressed in a cubic bezier
+// curve formula. It's quintic, not cubic. But it _can_ be expressed as one
+// curve followed by another, which we do here.
+Animation<T> _getEmphasizedEasingAnimation<T>({
+  @required T begin,
+  @required T peak,
+  @required T end,
+  @required bool isForward,
+  @required Animation<double> parent}) {
+  Curve firstCurve;
+  Curve secondCurve;
+  double firstWeight;
+  double secondWeight;
+
+  if (isForward) {
+    firstCurve = _kAccelerateCurve;
+    secondCurve = _kDecelerateCurve;
+    firstWeight = _kPeakVelocityTime;
+    secondWeight = 1.0 - _kPeakVelocityTime;
+  } else {
+    firstCurve = _kDecelerateCurve.flipped;
+    secondCurve = _kAccelerateCurve.flipped;
+    firstWeight = 1.0 - _kPeakVelocityTime;
+    secondWeight = _kPeakVelocityTime;
+  }
+
+  return TweenSequence<T>(
+    <TweenSequenceItem<T>>[
+      TweenSequenceItem<T>(
+        weight: firstWeight,
+        tween: Tween<T>(
+          begin: begin,
+          end: peak,
+        ).chain(CurveTween(curve: firstCurve)),
+      ),
+      TweenSequenceItem<T>(
+        weight: secondWeight,
+        tween: Tween<T>(
+          begin: peak,
+          end: end,
+        ).chain(CurveTween(curve: secondCurve)),
+      ),
+    ],
+  ).animate(parent);
+}
+
+// Calculates the value where two double Animations should be joined. Used by
+// callers of _getEmphasisedEasing<double>().
+double _getPeakPoint({double begin, double end}) {
+  return begin + (end - begin) * _kPeakVelocityProgress;
+}
+
+class _ExpandingBottomSheetState extends State<ExpandingBottomSheet> with TickerProviderStateMixin {
+  final GlobalKey _expandingBottomSheetKey = GlobalKey(debugLabel: 'Expanding bottom sheet');
+
+  // The width of the Material, calculated by _widthFor() & based on the number
+  // of products in the cart. 64.0 is the width when there are 0 products
+  // (_kWidthForZeroProducts)
+  double _width = _kWidthForCartIcon;
+
+  // Controller for the opening and closing of the ExpandingBottomSheet
+  AnimationController _controller;
+
+  // Animations for the opening and closing of the ExpandingBottomSheet
+  Animation<double> _widthAnimation;
+  Animation<double> _heightAnimation;
+  Animation<double> _thumbnailOpacityAnimation;
+  Animation<double> _cartOpacityAnimation;
+  Animation<double> _shapeAnimation;
+  Animation<Offset> _slideAnimation;
+
+  @override
+  void initState() {
+    super.initState();
+    _controller = AnimationController(
+      duration: const Duration(milliseconds: 500),
+      vsync: this,
+    );
+  }
+
+  @override
+  void dispose() {
+    _controller.dispose();
+    super.dispose();
+  }
+
+  Animation<double> _getWidthAnimation(double screenWidth) {
+    if (_controller.status == AnimationStatus.forward) {
+      // Opening animation
+      return Tween<double>(begin: _width, end: screenWidth).animate(
+        CurvedAnimation(
+          parent: _controller.view,
+          curve: const Interval(0.0, 0.3, curve: Curves.fastOutSlowIn),
+        ),
+      );
+    } else {
+      // Closing animation
+      return _getEmphasizedEasingAnimation(
+        begin: _width,
+        peak: _getPeakPoint(begin: _width, end: screenWidth),
+        end: screenWidth,
+        isForward: false,
+        parent: CurvedAnimation(parent: _controller.view, curve: const Interval(0.0, 0.87)),
+      );
+    }
+  }
+
+  Animation<double> _getHeightAnimation(double screenHeight) {
+    if (_controller.status == AnimationStatus.forward) {
+      // Opening animation
+
+      return _getEmphasizedEasingAnimation(
+        begin: _kCartHeight,
+        peak: _kCartHeight + (screenHeight - _kCartHeight) * _kPeakVelocityProgress,
+        end: screenHeight,
+        isForward: true,
+        parent: _controller.view,
+      );
+    } else {
+      // Closing animation
+      return Tween<double>(
+        begin: _kCartHeight,
+        end: screenHeight,
+      ).animate(
+        CurvedAnimation(
+          parent: _controller.view,
+          curve: const Interval(0.434, 1.0, curve: Curves.linear), // not used
+          // only the reverseCurve will be used
+          reverseCurve: Interval(0.434, 1.0, curve: Curves.fastOutSlowIn.flipped),
+        ),
+      );
+    }
+  }
+
+  // Animation of the cut corner. It's cut when closed and not cut when open.
+  Animation<double> _getShapeAnimation() {
+    if (_controller.status == AnimationStatus.forward) {
+      return Tween<double>(begin: _kCornerRadius, end: 0.0).animate(
+        CurvedAnimation(
+          parent: _controller.view,
+          curve: const Interval(0.0, 0.3, curve: Curves.fastOutSlowIn),
+        ),
+      );
+    } else {
+      return _getEmphasizedEasingAnimation(
+        begin: _kCornerRadius,
+        peak: _getPeakPoint(begin: _kCornerRadius, end: 0.0),
+        end: 0.0,
+        isForward: false,
+        parent: _controller.view,
+      );
+    }
+  }
+
+  Animation<double> _getThumbnailOpacityAnimation() {
+    return Tween<double>(begin: 1.0, end: 0.0).animate(
+      CurvedAnimation(
+        parent: _controller.view,
+        curve: _controller.status == AnimationStatus.forward
+          ? const Interval(0.0, 0.3)
+          : const Interval(0.532, 0.766),
+      ),
+    );
+  }
+
+  Animation<double> _getCartOpacityAnimation() {
+    return CurvedAnimation(
+      parent: _controller.view,
+      curve: _controller.status == AnimationStatus.forward
+        ? const Interval(0.3, 0.6)
+        : const Interval(0.766, 1.0),
+    );
+  }
+
+  // Returns the correct width of the ExpandingBottomSheet based on the number of
+  // products in the cart.
+  double _widthFor(int numProducts) {
+    switch (numProducts) {
+      case 0:
+        return _kWidthForCartIcon;
+      case 1:
+        return 136.0;
+      case 2:
+        return 192.0;
+      case 3:
+        return 248.0;
+      default:
+        return 278.0;
+    }
+  }
+
+  // Returns true if the cart is open or opening and false otherwise.
+  bool get _isOpen {
+    final AnimationStatus status = _controller.status;
+    return status == AnimationStatus.completed || status == AnimationStatus.forward;
+  }
+
+  // Opens the ExpandingBottomSheet if it's closed, otherwise does nothing.
+  void open() {
+    if (!_isOpen) {
+      _controller.forward();
+    }
+  }
+
+  // Closes the ExpandingBottomSheet if it's open or opening, otherwise does nothing.
+  void close() {
+    if (_isOpen) {
+      _controller.reverse();
+    }
+  }
+
+  // Changes the padding between the start edge of the Material and the cart icon
+  // based on the number of products in the cart (padding increases when > 0
+  // products.)
+  EdgeInsetsDirectional _cartPaddingFor(int numProducts) {
+    return (numProducts == 0)
+      ? const EdgeInsetsDirectional.only(start: 20.0, end: 8.0)
+      : const EdgeInsetsDirectional.only(start: 32.0, end: 8.0);
+  }
+
+  bool get _cartIsVisible => _thumbnailOpacityAnimation.value == 0.0;
+
+  Widget _buildThumbnails(int numProducts) {
+    return ExcludeSemantics(
+      child: Opacity(
+        opacity: _thumbnailOpacityAnimation.value,
+        child: Column(
+          children: <Widget>[
+            Row(
+              children: <Widget>[
+                AnimatedPadding(
+                  padding: _cartPaddingFor(numProducts),
+                  child: const Icon(Icons.shopping_cart),
+                  duration: const Duration(milliseconds: 225),
+                ),
+                Container(
+                  // Accounts for the overflow number
+                  width: numProducts > 3 ? _width - 94.0 : _width - 64.0,
+                  height: _kCartHeight,
+                  padding: const EdgeInsets.symmetric(vertical: 8.0),
+                  child: ProductThumbnailRow(),
+                ),
+                ExtraProductsNumber(),
+              ],
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
+  Widget _buildShoppingCartPage() {
+    return Opacity(
+      opacity: _cartOpacityAnimation.value,
+      child: ShoppingCartPage(),
+    );
+  }
+
+  Widget _buildCart(BuildContext context, Widget child) {
+    // numProducts is the number of different products in the cart (does not
+    // include multiples of the same product).
+    final AppStateModel model = ScopedModel.of<AppStateModel>(context);
+    final int numProducts = model.productsInCart.keys.length;
+    final int totalCartQuantity = model.totalCartQuantity;
+    final Size screenSize = MediaQuery.of(context).size;
+    final double screenWidth = screenSize.width;
+    final double screenHeight = screenSize.height;
+
+    _width = _widthFor(numProducts);
+    _widthAnimation = _getWidthAnimation(screenWidth);
+    _heightAnimation = _getHeightAnimation(screenHeight);
+    _shapeAnimation = _getShapeAnimation();
+    _thumbnailOpacityAnimation = _getThumbnailOpacityAnimation();
+    _cartOpacityAnimation = _getCartOpacityAnimation();
+
+    return Semantics(
+      button: true,
+      value: 'Shopping cart, $totalCartQuantity items',
+      child: Container(
+        width: _widthAnimation.value,
+        height: _heightAnimation.value,
+        child: Material(
+          animationDuration: const Duration(milliseconds: 0),
+          shape: BeveledRectangleBorder(
+            borderRadius: BorderRadius.only(
+              topLeft: Radius.circular(_shapeAnimation.value),
+            ),
+          ),
+          elevation: 4.0,
+          color: kShrinePink50,
+          child: _cartIsVisible
+            ? _buildShoppingCartPage()
+            : _buildThumbnails(numProducts),
+        ),
+      ),
+    );
+  }
+
+  // Builder for the hide and reveal animation when the backdrop opens and closes
+  Widget _buildSlideAnimation(BuildContext context, Widget child) {
+    _slideAnimation = _getEmphasizedEasingAnimation(
+      begin: const Offset(1.0, 0.0),
+      peak: const Offset(_kPeakVelocityProgress, 0.0),
+      end: const Offset(0.0, 0.0),
+      isForward: widget.hideController.status == AnimationStatus.forward,
+      parent: widget.hideController,
+    );
+
+    return SlideTransition(
+      position: _slideAnimation,
+      child: child,
+    );
+  }
+
+  // Closes the cart if the cart is open, otherwise exits the app (this should
+  // only be relevant for Android).
+  Future<bool> _onWillPop() async {
+    if (!_isOpen) {
+      await SystemNavigator.pop();
+      return true;
+    }
+
+    close();
+    return true;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return AnimatedSize(
+      key: _expandingBottomSheetKey,
+      duration: const Duration(milliseconds: 225),
+      curve: Curves.easeInOut,
+      vsync: this,
+      alignment: FractionalOffset.topLeft,
+      child: WillPopScope(
+        onWillPop: _onWillPop,
+        child: AnimatedBuilder(
+          animation: widget.hideController,
+          builder: _buildSlideAnimation,
+          child: GestureDetector(
+            behavior: HitTestBehavior.opaque,
+            onTap: open,
+            child: ScopedModelDescendant<AppStateModel>(
+              builder: (BuildContext context, Widget child, AppStateModel model) {
+                return AnimatedBuilder(
+                  builder: _buildCart,
+                  animation: _controller,
+                );
+              },
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}
+
+class ProductThumbnailRow extends StatefulWidget {
+  @override
+  _ProductThumbnailRowState createState() => _ProductThumbnailRowState();
+}
+
+class _ProductThumbnailRowState extends State<ProductThumbnailRow> {
+  final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();
+
+  // _list represents what's currently on screen. If _internalList updates,
+  // it will need to be updated to match it.
+  _ListModel _list;
+
+  // _internalList represents the list as it is updated by the AppStateModel.
+  List<int> _internalList;
+
+  @override
+  void initState() {
+    super.initState();
+    _list = _ListModel(
+      listKey: _listKey,
+      initialItems: ScopedModel.of<AppStateModel>(context).productsInCart.keys.toList(),
+      removedItemBuilder: _buildRemovedThumbnail,
+    );
+    _internalList = List<int>.from(_list.list);
+  }
+
+  Product _productWithId(int productId) {
+    final AppStateModel model = ScopedModel.of<AppStateModel>(context);
+    final Product product = model.getProductById(productId);
+    assert(product != null);
+    return product;
+  }
+
+  Widget _buildRemovedThumbnail(int item, BuildContext context, Animation<double> animation) {
+    return ProductThumbnail(animation, animation, _productWithId(item));
+  }
+
+  Widget _buildThumbnail(BuildContext context, int index, Animation<double> animation) {
+    final Animation<double> thumbnailSize = Tween<double>(begin: 0.8, end: 1.0).animate(
+      CurvedAnimation(
+        curve: const Interval(0.33, 1.0, curve: Curves.easeIn),
+        parent: animation,
+      ),
+    );
+
+    final Animation<double> opacity = CurvedAnimation(
+      curve: const Interval(0.33, 1.0, curve: Curves.linear),
+      parent: animation,
+    );
+
+    return ProductThumbnail(thumbnailSize, opacity, _productWithId(_list[index]));
+  }
+
+  // If the lists are the same length, assume nothing has changed.
+  // If the internalList is shorter than the ListModel, an item has been removed.
+  // If the internalList is longer, then an item has been added.
+  void _updateLists() {
+    // Update _internalList based on the model
+    _internalList = ScopedModel.of<AppStateModel>(context).productsInCart.keys.toList();
+    final Set<int> internalSet = Set<int>.from(_internalList);
+    final Set<int> listSet = Set<int>.from(_list.list);
+
+    final Set<int> difference = internalSet.difference(listSet);
+    if (difference.isEmpty) {
+      return;
+    }
+
+    for (int product in difference) {
+      if (_internalList.length < _list.length) {
+        _list.remove(product);
+      } else if (_internalList.length > _list.length) {
+        _list.add(product);
+      }
+    }
+
+    while (_internalList.length != _list.length) {
+      int index = 0;
+      // Check bounds and that the list elements are the same
+      while (_internalList.isNotEmpty &&
+          _list.length > 0 &&
+          index < _internalList.length &&
+          index < _list.length &&
+          _internalList[index] == _list[index]) {
+        index++;
+      }
+    }
+  }
+
+  Widget _buildAnimatedList() {
+    return AnimatedList(
+      key: _listKey,
+      shrinkWrap: true,
+      itemBuilder: _buildThumbnail,
+      initialItemCount: _list.length,
+      scrollDirection: Axis.horizontal,
+      physics: const NeverScrollableScrollPhysics(), // Cart shouldn't scroll
+    );
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    _updateLists();
+    return ScopedModelDescendant<AppStateModel>(
+      builder: (BuildContext context, Widget child, AppStateModel model) => _buildAnimatedList(),
+    );
+  }
+}
+
+class ExtraProductsNumber extends StatelessWidget {
+  // Calculates the number to be displayed at the end of the row if there are
+  // more than three products in the cart. This calculates overflow products,
+  // including their duplicates (but not duplicates of products shown as
+  // thumbnails).
+  int _calculateOverflow(AppStateModel model) {
+    final Map<int, int> productMap = model.productsInCart;
+    // List created to be able to access products by index instead of ID.
+    // Order is guaranteed because productsInCart returns a LinkedHashMap.
+    final List<int> products = productMap.keys.toList();
+    int overflow = 0;
+    final int numProducts = products.length;
+    if (numProducts > 3) {
+      for (int i = 3; i < numProducts; i++) {
+        overflow += productMap[products[i]];
+      }
+    }
+    return overflow;
+  }
+
+  Widget _buildOverflow(AppStateModel model, BuildContext context) {
+    if (model.productsInCart.length <= 3)
+      return Container();
+
+    final int numOverflowProducts = _calculateOverflow(model);
+    // Maximum of 99 so padding doesn't get messy.
+    final int displayedOverflowProducts = numOverflowProducts <= 99 ? numOverflowProducts : 99;
+    return Container(
+      child: Text(
+        '+$displayedOverflowProducts',
+        style: Theme.of(context).primaryTextTheme.button,
+      ),
+    );
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return ScopedModelDescendant<AppStateModel>(
+      builder: (BuildContext builder, Widget child, AppStateModel model) => _buildOverflow(model, context),
+    );
+  }
+}
+
+class ProductThumbnail extends StatelessWidget {
+  const ProductThumbnail(this.animation, this.opacityAnimation, this.product);
+
+  final Animation<double> animation;
+  final Animation<double> opacityAnimation;
+  final Product product;
+
+  @override
+  Widget build(BuildContext context) {
+    return FadeTransition(
+      opacity: opacityAnimation,
+      child: ScaleTransition(
+        scale: animation,
+        child: Container(
+          width: 40.0,
+          height: 40.0,
+          decoration: BoxDecoration(
+            image: DecorationImage(
+              image: ExactAssetImage(
+                product.assetName, // asset name
+                package: product.assetPackage, // asset package
+              ),
+              fit: BoxFit.cover,
+            ),
+            borderRadius: const BorderRadius.all(Radius.circular(10.0)),
+          ),
+          margin: const EdgeInsets.only(left: 16.0),
+        ),
+      ),
+    );
+  }
+}
+
+// _ListModel manipulates an internal list and an AnimatedList
+class _ListModel {
+  _ListModel({
+    @required this.listKey,
+    @required this.removedItemBuilder,
+    Iterable<int> initialItems
+  }) : assert(listKey != null),
+       assert(removedItemBuilder != null),
+       _items = List<int>.from(initialItems ?? <int>[]);
+
+  final GlobalKey<AnimatedListState> listKey;
+  final dynamic removedItemBuilder;
+  final List<int> _items;
+
+  AnimatedListState get _animatedList => listKey.currentState;
+
+  void add(int product) {
+    _insert(_items.length, product);
+  }
+
+  void _insert(int index, int item) {
+    _items.insert(index, item);
+    _animatedList.insertItem(index, duration: const Duration(milliseconds: 225));
+  }
+
+  void remove(int product) {
+    final int index = _items.indexOf(product);
+    if (index >= 0) {
+      _removeAt(index);
+    }
+  }
+
+  void _removeAt(int index) {
+    final int removedItem = _items.removeAt(index);
+    if (removedItem != null) {
+      _animatedList.removeItem(index, (BuildContext context, Animation<double> animation) {
+        return removedItemBuilder(removedItem, context, animation);
+      });
+    }
+  }
+
+  int get length => _items.length;
+
+  int operator [](int index) => _items[index];
+
+  int indexOf(int item) => _items.indexOf(item);
+
+  List<int> get list => _items;
+}
diff --git a/examples/flutter_gallery/lib/demo/shrine/home.dart b/examples/flutter_gallery/lib/demo/shrine/home.dart
new file mode 100644
index 0000000..33131e2
--- /dev/null
+++ b/examples/flutter_gallery/lib/demo/shrine/home.dart
@@ -0,0 +1,57 @@
+// Copyright 2018-present the Flutter authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'package:flutter/material.dart';
+import 'package:scoped_model/scoped_model.dart';
+
+import 'package:flutter_gallery/demo/shrine/backdrop.dart';
+import 'package:flutter_gallery/demo/shrine/expanding_bottom_sheet.dart';
+import 'package:flutter_gallery/demo/shrine/model/app_state_model.dart';
+import 'package:flutter_gallery/demo/shrine/model/product.dart';
+import 'package:flutter_gallery/demo/shrine/supplemental/asymmetric_view.dart';
+
+class ProductPage extends StatelessWidget {
+  const ProductPage({this.category = Category.all});
+
+  final Category category;
+
+  @override
+  Widget build(BuildContext context) {
+    return ScopedModelDescendant<AppStateModel>(
+      builder: (BuildContext context, Widget child, AppStateModel model) {
+        return AsymmetricView(products: model.getProducts());
+    });
+  }
+}
+
+class HomePage extends StatelessWidget {
+  const HomePage({
+    this.expandingBottomSheet,
+    this.backdrop,
+    Key key,
+  }) : super(key: key);
+
+  final ExpandingBottomSheet expandingBottomSheet;
+  final Backdrop backdrop;
+
+  @override
+  Widget build(BuildContext context) {
+    return Stack(
+      children: <Widget>[
+        backdrop,
+        Align(child: expandingBottomSheet, alignment: Alignment.bottomRight)
+      ],
+    );
+  }
+}
diff --git a/examples/flutter_gallery/lib/demo/shrine/login.dart b/examples/flutter_gallery/lib/demo/shrine/login.dart
new file mode 100644
index 0000000..c400755
--- /dev/null
+++ b/examples/flutter_gallery/lib/demo/shrine/login.dart
@@ -0,0 +1,126 @@
+// Copyright 2018-present the Flutter authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'package:flutter/material.dart';
+
+import 'package:flutter_gallery/demo/shrine/colors.dart';
+
+class LoginPage extends StatefulWidget {
+  @override
+  _LoginPageState createState() => _LoginPageState();
+}
+
+class _LoginPageState extends State<LoginPage> {
+  final TextEditingController _usernameController = TextEditingController();
+  final TextEditingController _passwordController = TextEditingController();
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      body: SafeArea(
+        child: ListView(
+          padding: const EdgeInsets.symmetric(horizontal: 24.0),
+          children: <Widget>[
+            const SizedBox(height: 80.0),
+            Column(
+              children: <Widget>[
+                Image.asset('packages/shrine_images/diamond.png'),
+                const SizedBox(height: 16.0),
+                Text(
+                  'SHRINE',
+                  style: Theme.of(context).textTheme.headline,
+                ),
+              ],
+            ),
+            const SizedBox(height: 120.0),
+            PrimaryColorOverride(
+              color: kShrineBrown900,
+              child: TextField(
+                controller: _usernameController,
+                decoration: const InputDecoration(
+                  labelText: 'Username',
+                ),
+              ),
+            ),
+            const SizedBox(height: 12.0),
+            PrimaryColorOverride(
+              color: kShrineBrown900,
+              child: TextField(
+                controller: _passwordController,
+                decoration: const InputDecoration(
+                  labelText: 'Password',
+                ),
+              ),
+            ),
+            Wrap(
+              children: <Widget>[
+                ButtonBar(
+                  children: <Widget>[
+                    FlatButton(
+                      child: const Text('CANCEL'),
+                      shape: const BeveledRectangleBorder(
+                        borderRadius: BorderRadius.all(Radius.circular(7.0)),
+                      ),
+                      onPressed: () {
+                        _usernameController.clear();
+                        _passwordController.clear();
+                      },
+                    ),
+                    RaisedButton(
+                      child: const Text('NEXT'),
+                      elevation: 8.0,
+                      shape: const BeveledRectangleBorder(
+                        borderRadius: BorderRadius.all(Radius.circular(7.0)),
+                      ),
+                      onPressed: () {
+                        Navigator.pop(context);
+                      },
+                    ),
+                  ],
+                ),
+                Tooltip(
+                  message: 'Back',
+                  child: FlatButton(
+                    child: const Text('EXIT'),
+                    shape: const BeveledRectangleBorder(
+                      borderRadius: BorderRadius.all(Radius.circular(7.0)),
+                    ),
+                    onPressed: () {
+                      Navigator.of(context, rootNavigator: true).pop();
+                    },
+                  ),
+                ),
+              ],
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}
+
+class PrimaryColorOverride extends StatelessWidget {
+  const PrimaryColorOverride({Key key, this.color, this.child}) : super(key: key);
+
+  final Color color;
+  final Widget child;
+
+  @override
+  Widget build(BuildContext context) {
+    return Theme(
+      child: child,
+      data: Theme.of(context).copyWith(primaryColor: color),
+    );
+  }
+}
diff --git a/examples/flutter_gallery/lib/demo/shrine/model/app_state_model.dart b/examples/flutter_gallery/lib/demo/shrine/model/app_state_model.dart
new file mode 100644
index 0000000..9c98465
--- /dev/null
+++ b/examples/flutter_gallery/lib/demo/shrine/model/app_state_model.dart
@@ -0,0 +1,118 @@
+// Copyright 2018-present the Flutter authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'package:scoped_model/scoped_model.dart';
+
+import 'package:flutter_gallery/demo/shrine/model/product.dart';
+import 'package:flutter_gallery/demo/shrine/model/products_repository.dart';
+
+double _salesTaxRate = 0.06;
+double _shippingCostPerItem = 7.0;
+
+class AppStateModel extends Model {
+  // All the available products.
+  List<Product> _availableProducts;
+
+  // The currently selected category of products.
+  Category _selectedCategory = Category.all;
+
+  // The IDs and quantities of products currently in the cart.
+  final Map<int, int> _productsInCart = <int, int>{};
+
+  Map<int, int> get productsInCart => Map<int, int>.from(_productsInCart);
+
+  // Total number of items in the cart.
+  int get totalCartQuantity => _productsInCart.values.fold(0, (int v, int e) => v + e);
+
+  Category get selectedCategory => _selectedCategory;
+
+  // Totaled prices of the items in the cart.
+  double get subtotalCost {
+    return _productsInCart.keys
+      .map((int id) => _availableProducts[id].price * _productsInCart[id])
+      .fold(0.0, (double sum, int e) => sum + e);
+  }
+
+  // Total shipping cost for the items in the cart.
+  double get shippingCost {
+    return _shippingCostPerItem * _productsInCart.values.fold(0.0, (num sum, int e) => sum + e);
+  }
+
+  // Sales tax for the items in the cart
+  double get tax => subtotalCost * _salesTaxRate;
+
+  // Total cost to order everything in the cart.
+  double get totalCost => subtotalCost + shippingCost + tax;
+
+  // Returns a copy of the list of available products, filtered by category.
+  List<Product> getProducts() {
+    if (_availableProducts == null) {
+      return <Product>[];
+    }
+
+    if (_selectedCategory == Category.all) {
+      return List<Product>.from(_availableProducts);
+    } else {
+      return _availableProducts
+        .where((Product p) => p.category == _selectedCategory)
+        .toList();
+    }
+  }
+
+  // Adds a product to the cart.
+  void addProductToCart(int productId) {
+    if (!_productsInCart.containsKey(productId)) {
+      _productsInCart[productId] = 1;
+    } else {
+      _productsInCart[productId]++;
+    }
+
+    notifyListeners();
+  }
+
+  // Removes an item from the cart.
+  void removeItemFromCart(int productId) {
+    if (_productsInCart.containsKey(productId)) {
+      if (_productsInCart[productId] == 1) {
+        _productsInCart.remove(productId);
+      } else {
+        _productsInCart[productId]--;
+      }
+    }
+
+    notifyListeners();
+  }
+
+  // Returns the Product instance matching the provided id.
+  Product getProductById(int id) {
+    return _availableProducts.firstWhere((Product p) => p.id == id);
+  }
+
+  // Removes everything from the cart.
+  void clearCart() {
+    _productsInCart.clear();
+    notifyListeners();
+  }
+
+  // Loads the list of available products from the repo.
+  void loadProducts() {
+    _availableProducts = ProductsRepository.loadProducts(Category.all);
+    notifyListeners();
+  }
+
+  void setCategory(Category newCategory) {
+    _selectedCategory = newCategory;
+    notifyListeners();
+  }
+}
diff --git a/examples/flutter_gallery/lib/demo/shrine/model/product.dart b/examples/flutter_gallery/lib/demo/shrine/model/product.dart
new file mode 100644
index 0000000..ffedcc3
--- /dev/null
+++ b/examples/flutter_gallery/lib/demo/shrine/model/product.dart
@@ -0,0 +1,48 @@
+// Copyright 2018-present the Flutter authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'package:flutter/foundation.dart';
+
+enum Category {
+  all,
+  accessories,
+  clothing,
+  home,
+}
+
+class Product {
+  const Product({
+    @required this.category,
+    @required this.id,
+    @required this.isFeatured,
+    @required this.name,
+    @required this.price,
+  })  : assert(category != null),
+        assert(id != null),
+        assert(isFeatured != null),
+        assert(name != null),
+        assert(price != null);
+
+  final Category category;
+  final int id;
+  final bool isFeatured;
+  final String name;
+  final int price;
+
+  String get assetName => '$id-0.jpg';
+  String get assetPackage => 'shrine_images';
+
+  @override
+  String toString() => '$name (id=$id)';
+}
diff --git a/examples/flutter_gallery/lib/demo/shrine/model/products_repository.dart b/examples/flutter_gallery/lib/demo/shrine/model/products_repository.dart
new file mode 100644
index 0000000..75bf4b3
--- /dev/null
+++ b/examples/flutter_gallery/lib/demo/shrine/model/products_repository.dart
@@ -0,0 +1,293 @@
+// Copyright 2018-present the Flutter authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'package:flutter_gallery/demo/shrine/model/product.dart';
+
+class ProductsRepository {
+  static List<Product> loadProducts(Category category) {
+    const List<Product> allProducts = <Product>[
+      Product(
+        category: Category.accessories,
+        id: 0,
+        isFeatured: true,
+        name: 'Vagabond sack',
+        price: 120,
+      ),
+      Product(
+        category: Category.accessories,
+        id: 1,
+        isFeatured: true,
+        name: 'Stella sunglasses',
+        price: 58,
+      ),
+      Product(
+        category: Category.accessories,
+        id: 2,
+        isFeatured: false,
+        name: 'Whitney belt',
+        price: 35,
+      ),
+      Product(
+        category: Category.accessories,
+        id: 3,
+        isFeatured: true,
+        name: 'Garden strand',
+        price: 98,
+      ),
+      Product(
+        category: Category.accessories,
+        id: 4,
+        isFeatured: false,
+        name: 'Strut earrings',
+        price: 34,
+      ),
+      Product(
+        category: Category.accessories,
+        id: 5,
+        isFeatured: false,
+        name: 'Varsity socks',
+        price: 12,
+      ),
+      Product(
+        category: Category.accessories,
+        id: 6,
+        isFeatured: false,
+        name: 'Weave keyring',
+        price: 16,
+      ),
+      Product(
+        category: Category.accessories,
+        id: 7,
+        isFeatured: true,
+        name: 'Gatsby hat',
+        price: 40,
+      ),
+      Product(
+        category: Category.accessories,
+        id: 8,
+        isFeatured: true,
+        name: 'Shrug bag',
+        price: 198,
+      ),
+      Product(
+        category: Category.home,
+        id: 9,
+        isFeatured: true,
+        name: 'Gilt desk trio',
+        price: 58,
+      ),
+      Product(
+        category: Category.home,
+        id: 10,
+        isFeatured: false,
+        name: 'Copper wire rack',
+        price: 18,
+      ),
+      Product(
+        category: Category.home,
+        id: 11,
+        isFeatured: false,
+        name: 'Soothe ceramic set',
+        price: 28,
+      ),
+      Product(
+        category: Category.home,
+        id: 12,
+        isFeatured: false,
+        name: 'Hurrahs tea set',
+        price: 34,
+      ),
+      Product(
+        category: Category.home,
+        id: 13,
+        isFeatured: true,
+        name: 'Blue stone mug',
+        price: 18,
+      ),
+      Product(
+        category: Category.home,
+        id: 14,
+        isFeatured: true,
+        name: 'Rainwater tray',
+        price: 27,
+      ),
+      Product(
+        category: Category.home,
+        id: 15,
+        isFeatured: true,
+        name: 'Chambray napkins',
+        price: 16,
+      ),
+      Product(
+        category: Category.home,
+        id: 16,
+        isFeatured: true,
+        name: 'Succulent planters',
+        price: 16,
+      ),
+      Product(
+        category: Category.home,
+        id: 17,
+        isFeatured: false,
+        name: 'Quartet table',
+        price: 175,
+      ),
+      Product(
+        category: Category.home,
+        id: 18,
+        isFeatured: true,
+        name: 'Kitchen quattro',
+        price: 129,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 19,
+        isFeatured: false,
+        name: 'Clay sweater',
+        price: 48,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 20,
+        isFeatured: false,
+        name: 'Sea tunic',
+        price: 45,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 21,
+        isFeatured: false,
+        name: 'Plaster tunic',
+        price: 38,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 22,
+        isFeatured: false,
+        name: 'White pinstripe shirt',
+        price: 70,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 23,
+        isFeatured: false,
+        name: 'Chambray shirt',
+        price: 70,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 24,
+        isFeatured: true,
+        name: 'Seabreeze sweater',
+        price: 60,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 25,
+        isFeatured: false,
+        name: 'Gentry jacket',
+        price: 178,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 26,
+        isFeatured: false,
+        name: 'Navy trousers',
+        price: 74,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 27,
+        isFeatured: true,
+        name: 'Walter henley (white)',
+        price: 38,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 28,
+        isFeatured: true,
+        name: 'Surf and perf shirt',
+        price: 48,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 29,
+        isFeatured: true,
+        name: 'Ginger scarf',
+        price: 98,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 30,
+        isFeatured: true,
+        name: 'Ramona crossover',
+        price: 68,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 31,
+        isFeatured: false,
+        name: 'Chambray shirt',
+        price: 38,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 32,
+        isFeatured: false,
+        name: 'Classic white collar',
+        price: 58,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 33,
+        isFeatured: true,
+        name: 'Cerise scallop tee',
+        price: 42,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 34,
+        isFeatured: false,
+        name: 'Shoulder rolls tee',
+        price: 27,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 35,
+        isFeatured: false,
+        name: 'Grey slouch tank',
+        price: 24,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 36,
+        isFeatured: false,
+        name: 'Sunshirt dress',
+        price: 58,
+      ),
+      Product(
+        category: Category.clothing,
+        id: 37,
+        isFeatured: true,
+        name: 'Fine lines tee',
+        price: 58,
+      ),
+    ];
+    if (category == Category.all) {
+      return allProducts;
+    } else {
+      return allProducts.where((Product p) => p.category == category).toList();
+    }
+  }
+}
diff --git a/examples/flutter_gallery/lib/demo/shrine/shopping_cart.dart b/examples/flutter_gallery/lib/demo/shrine/shopping_cart.dart
new file mode 100644
index 0000000..076e657
--- /dev/null
+++ b/examples/flutter_gallery/lib/demo/shrine/shopping_cart.dart
@@ -0,0 +1,275 @@
+// Copyright 2018-present the Flutter authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'package:flutter/material.dart';
+import 'package:intl/intl.dart';
+import 'package:scoped_model/scoped_model.dart';
+
+import 'package:flutter_gallery/demo/shrine/colors.dart';
+import 'package:flutter_gallery/demo/shrine/expanding_bottom_sheet.dart';
+import 'package:flutter_gallery/demo/shrine/model/app_state_model.dart';
+import 'package:flutter_gallery/demo/shrine/model/product.dart';
+
+const double _leftColumnWidth = 60.0;
+
+class ShoppingCartPage extends StatefulWidget {
+  @override
+  _ShoppingCartPageState createState() => _ShoppingCartPageState();
+}
+
+class _ShoppingCartPageState extends State<ShoppingCartPage> {
+  List<Widget> _createShoppingCartRows(AppStateModel model) {
+    return model.productsInCart.keys
+        .map((int id) => ShoppingCartRow(
+            product: model.getProductById(id),
+            quantity: model.productsInCart[id],
+            onPressed: () {
+              model.removeItemFromCart(id);
+            },
+          ),
+        )
+        .toList();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final ThemeData localTheme = Theme.of(context);
+
+    return Scaffold(
+      backgroundColor: kShrinePink50,
+      body: SafeArea(
+        child: Container(
+          child: ScopedModelDescendant<AppStateModel>(
+            builder: (BuildContext context, Widget child, AppStateModel model) {
+              return Stack(
+                children: <Widget>[
+                  ListView(
+                    children: <Widget>[
+                      Row(
+                        children: <Widget>[
+                          SizedBox(
+                            width: _leftColumnWidth,
+                            child: IconButton(
+                              icon: const Icon(Icons.keyboard_arrow_down),
+                              onPressed: () => ExpandingBottomSheet.of(context).close(),
+                            ),
+                          ),
+                          Text(
+                            'CART',
+                            style: localTheme.textTheme.subhead.copyWith(fontWeight: FontWeight.w600),
+                          ),
+                          const SizedBox(width: 16.0),
+                          Text('${model.totalCartQuantity} ITEMS'),
+                        ],
+                      ),
+                      const SizedBox(height: 16.0),
+                      Column(
+                        children: _createShoppingCartRows(model),
+                      ),
+                      ShoppingCartSummary(model: model),
+                      const SizedBox(height: 100.0),
+                    ],
+                  ),
+                  Positioned(
+                    bottom: 16.0,
+                    left: 16.0,
+                    right: 16.0,
+                    child: RaisedButton(
+                      shape: const BeveledRectangleBorder(
+                        borderRadius: BorderRadius.all(Radius.circular(7.0)),
+                      ),
+                      color: kShrinePink100,
+                      splashColor: kShrineBrown600,
+                      child: const Padding(
+                        padding: EdgeInsets.symmetric(vertical: 12.0),
+                        child: Text('CLEAR CART'),
+                      ),
+                      onPressed: () {
+                        model.clearCart();
+                        ExpandingBottomSheet.of(context).close();
+                      },
+                    ),
+                  ),
+                ],
+              );
+            },
+          ),
+        ),
+      ),
+    );
+  }
+}
+
+class ShoppingCartSummary extends StatelessWidget {
+  const ShoppingCartSummary({this.model});
+
+  final AppStateModel model;
+
+  @override
+  Widget build(BuildContext context) {
+    final TextStyle smallAmountStyle = Theme.of(context).textTheme.body1.copyWith(color: kShrineBrown600);
+    final TextStyle largeAmountStyle = Theme.of(context).textTheme.display1;
+    final NumberFormat formatter = NumberFormat.simpleCurrency(
+      decimalDigits: 2,
+      locale: Localizations.localeOf(context).toString(),
+    );
+
+    return Row(
+      children: <Widget>[
+        const SizedBox(width: _leftColumnWidth),
+        Expanded(
+          child: Padding(
+            padding: const EdgeInsets.only(right: 16.0),
+            child: Column(
+              children: <Widget>[
+                Row(
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  children: <Widget>[
+                    const Expanded(
+                      child: Text('TOTAL'),
+                    ),
+                    Text(
+                      formatter.format(model.totalCost),
+                      style: largeAmountStyle,
+                    ),
+                  ],
+                ),
+                const SizedBox(height: 16.0),
+                Row(
+                  children: <Widget>[
+                    const Expanded(
+                      child: Text('Subtotal:'),
+                    ),
+                    Text(
+                      formatter.format(model.subtotalCost),
+                      style: smallAmountStyle,
+                    ),
+                  ],
+                ),
+                const SizedBox(height: 4.0),
+                Row(
+                  children: <Widget>[
+                    const Expanded(
+                      child: Text('Shipping:'),
+                    ),
+                    Text(
+                      formatter.format(model.shippingCost),
+                      style: smallAmountStyle,
+                    ),
+                  ],
+                ),
+                const SizedBox(height: 4.0),
+                Row(
+                  children: <Widget>[
+                    const Expanded(
+                      child: Text('Tax:'),
+                    ),
+                    Text(
+                      formatter.format(model.tax),
+                      style: smallAmountStyle,
+                    ),
+                  ],
+                ),
+              ],
+            ),
+          ),
+        ),
+      ],
+    );
+  }
+}
+
+class ShoppingCartRow extends StatelessWidget {
+  const ShoppingCartRow({
+    @required this.product,
+    @required this.quantity,
+    this.onPressed,
+  });
+
+  final Product product;
+  final int quantity;
+  final VoidCallback onPressed;
+
+  @override
+  Widget build(BuildContext context) {
+    final NumberFormat formatter = NumberFormat.simpleCurrency(
+      decimalDigits: 0,
+      locale: Localizations.localeOf(context).toString(),
+    );
+    final ThemeData localTheme = Theme.of(context);
+
+    return Padding(
+      padding: const EdgeInsets.only(bottom: 16.0),
+      child: Row(
+        key: ValueKey<int>(product.id),
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: <Widget>[
+          SizedBox(
+            width: _leftColumnWidth,
+            child: IconButton(
+              icon: const Icon(Icons.remove_circle_outline),
+              onPressed: onPressed,
+            ),
+          ),
+          Expanded(
+            child: Padding(
+              padding: const EdgeInsets.only(right: 16.0),
+              child: Column(
+                children: <Widget>[
+                  Row(
+                    crossAxisAlignment: CrossAxisAlignment.start,
+                    children: <Widget>[
+                      Image.asset(
+                        product.assetName,
+                        package: product.assetPackage,
+                        fit: BoxFit.cover,
+                        width: 75.0,
+                        height: 75.0,
+                      ),
+                      const SizedBox(width: 16.0),
+                      Expanded(
+                        child: Column(
+                          crossAxisAlignment: CrossAxisAlignment.start,
+                          children: <Widget>[
+                            Row(
+                              children: <Widget>[
+                                Expanded(
+                                  child: Text('Quantity: $quantity'),
+                                ),
+                                Text('x ${formatter.format(product.price)}'),
+                              ],
+                            ),
+                            Text(
+                              product.name,
+                              style: localTheme.textTheme.subhead.copyWith(fontWeight: FontWeight.w600),
+                            ),
+                          ],
+                        ),
+                      ),
+                    ],
+                  ),
+                  const SizedBox(height: 16.0),
+                  const Divider(
+                    color: kShrineBrown900,
+                    height: 10.0,
+                  ),
+                ],
+              ),
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/examples/flutter_gallery/lib/demo/shrine/shrine_data.dart b/examples/flutter_gallery/lib/demo/shrine/shrine_data.dart
deleted file mode 100644
index 85dcce3..0000000
--- a/examples/flutter_gallery/lib/demo/shrine/shrine_data.dart
+++ /dev/null
@@ -1,278 +0,0 @@
-// Copyright 2016 The Chromium 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 'shrine_types.dart';
-
-const String _kGalleryAssetsPackage = 'flutter_gallery_assets';
-
-const Vendor _ali = Vendor(
-  name: 'Ali’s shop',
-  avatarAsset: 'people/square/ali.png',
-  avatarAssetPackage: _kGalleryAssetsPackage,
-  description:
-    'Ali Connor’s makes custom goods for folks of all shapes and sizes '
-    'made by hand and sometimes by machine, but always with love and care. '
-    'Custom orders are available upon request if you need something extra special.'
-);
-
-const Vendor _peter = Vendor(
-  name: 'Peter’s shop',
-  avatarAsset: 'people/square/peter.png',
-  avatarAssetPackage: _kGalleryAssetsPackage,
-  description:
-    'Peter makes great stuff for awesome people like you. Super cool and extra '
-    'awesome all of his shop’s goods are handmade with love. Custom orders are '
-    'available upon request if you need something extra special.'
-);
-
-const Vendor _sandra = Vendor(
-    name: 'Sandra’s shop',
-    avatarAsset: 'people/square/sandra.png',
-    avatarAssetPackage: _kGalleryAssetsPackage,
-    description:
-    'Sandra specializes in furniture, beauty and travel products with a classic vibe. '
-        'Custom orders are available if you’re looking for a certain color or material.'
-);
-
-const Vendor _stella = Vendor(
-  name: 'Stella’s shop',
-  avatarAsset: 'people/square/stella.png',
-  avatarAssetPackage: _kGalleryAssetsPackage,
-  description:
-    'Stella sells awesome stuff at lovely prices. made by hand and sometimes by '
-    'machine, but always with love and care. Custom orders are available upon request '
-    'if you need something extra special.'
-);
-
-const Vendor _trevor = Vendor(
-    name: 'Trevor’s shop',
-    avatarAsset: 'people/square/trevor.png',
-    avatarAssetPackage: _kGalleryAssetsPackage,
-    description:
-    'Trevor makes great stuff for awesome people like you. Super cool and extra '
-        'awesome all of his shop’s goods are handmade with love. Custom orders are '
-        'available upon request if you need something extra special.'
-);
-
-const List<Product> _allProducts = <Product> [
-  Product(
-    name: 'Vintage Brown Belt',
-    imageAsset: 'products/belt.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['fashion', 'latest'],
-    price: 300.00,
-    vendor: _sandra,
-    description:
-      'Isn’t it cool when things look old, but they\'re not. Looks Old But Not makes '
-      'awesome vintage goods that are super smart. This ol’ belt just got an upgrade. '
-  ),
-  Product(
-    name: 'Sunglasses',
-    imageAsset: 'products/sunnies.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['travel', 'fashion', 'beauty'],
-    price: 20.00,
-    vendor: _trevor,
-    description:
-      'Be an optimist. Carry Sunglasses with you at all times. All Tints and '
-      'Shades products come with polarized lenses and super duper UV protection '
-      'so you can look at the sun for however long you want. Sunglasses make you '
-      'look cool, wear them.'
-  ),
-  Product(
-    name: 'Flatwear',
-    imageAsset: 'products/flatwear.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['furniture'],
-    price: 30.00,
-    vendor: _trevor,
-    description:
-    'Leave the tunnel and the rain is fallin amazing things happen when you wait'
-  ),
-  Product(
-    name: 'Salmon Sweater',
-    imageAsset: 'products/sweater.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['fashion'],
-    price: 300.00,
-    vendor: _stella,
-    description:
-      'Looks can be deceiving. This sweater comes in a wide variety of '
-      'flavors, including salmon, that pop as soon as they hit your eyes. '
-      'Sweaters heat quickly, so savor the warmth.'
-  ),
-  Product(
-    name: 'Pine Table',
-    imageAsset: 'products/table.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['furniture'],
-    price: 63.00,
-    vendor: _stella,
-    description:
-      'Leave the tunnel and the rain is fallin amazing things happen when you wait'
-  ),
-  Product(
-    name: 'Green Comfort Jacket',
-    imageAsset: 'products/jacket.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['fashion'],
-    price: 36.00,
-    vendor: _ali,
-    description:
-      'Leave the tunnel and the rain is fallin amazing things happen when you wait'
-  ),
-  Product(
-    name: 'Chambray Top',
-    imageAsset: 'products/top.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['fashion'],
-    price: 125.00,
-    vendor: _peter,
-    description:
-      'Leave the tunnel and the rain is fallin amazing things happen when you wait'
-  ),
-  Product(
-    name: 'Blue Cup',
-    imageAsset: 'products/cup.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['travel', 'furniture'],
-    price: 75.00,
-    vendor: _sandra,
-    description:
-      'Drinksy has been making extraordinary mugs for decades. With each '
-      'cup purchased Drinksy donates a cup to those in need. Buy yourself a mug, '
-      'buy someone else a mug.'
-  ),
-  Product(
-    name: 'Tea Set',
-    imageAsset: 'products/teaset.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['furniture', 'fashion'],
-    price: 70.00,
-    vendor: _trevor,
-    featureTitle: 'Beautiful glass teapot',
-    featureDescription:
-      'Teapot holds extremely hot liquids and pours them from the spout.',
-    description:
-      'Impress your guests with Tea Set by Kitchen Stuff. Teapot holds extremely '
-      'hot liquids and pours them from the spout. Use the handle, shown on the right, '
-      'so your fingers don’t get burnt while pouring.'
-  ),
-  Product(
-    name: 'Blue linen napkins',
-    imageAsset: 'products/napkins.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['furniture', 'fashion'],
-    price: 89.00,
-    vendor: _trevor,
-    description:
-      'Blue linen napkins were meant to go with friends, so you may want to pick '
-      'up a bunch of these. These things are absorbant.'
-  ),
-  Product(
-    name: 'Dipped Earrings',
-    imageAsset: 'products/earrings.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['fashion', 'beauty'],
-    price: 25.00,
-    vendor: _stella,
-    description:
-      'WeDipIt does it again. These hand-dipped 4 inch earrings are perfect for '
-      'the office or the beach. Just be sure you don’t drop it in a bucket of '
-      'red paint, then they won’t look dipped anymore.'
-  ),
-  Product(
-    name: 'Perfect Planters',
-    imageAsset: 'products/planters.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['latest', 'furniture'],
-    price: 30.00,
-    vendor: _ali,
-    description:
-      'The Perfect Planter Co makes the best vessels for just about anything you '
-      'can pot. This set of Perfect Planters holds succulents and cuttings perfectly. '
-      'Looks great in any room. Keep out of reach from cats.'
-  ),
-  Product(
-    name: 'Cloud-White Dress',
-    imageAsset: 'products/dress.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['fashion'],
-    price: 54.00,
-    vendor: _sandra,
-    description:
-      'Trying to find the perfect outift to match your mood? Try no longer. '
-      'This Cloud-White Dress has you covered for those nights when you need '
-      'to get out, or even if you’re just headed to work.'
-  ),
-  Product(
-    name: 'Backpack',
-    imageAsset: 'products/backpack.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['travel', 'fashion'],
-    price: 25.00,
-    vendor: _peter,
-    description:
-      'This backpack by Bags ‘n’ stuff can hold just about anything: a laptop, '
-      'a pen, a protractor, notebooks, small animals, plugs for your devices, '
-      'sunglasses, gym clothes, shoes, gloves, two kittens, and even lunch!'
-  ),
-  Product(
-    name: 'Charcoal Straw Hat',
-    imageAsset: 'products/hat.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['travel', 'fashion', 'latest'],
-    price: 25.00,
-    vendor: _ali,
-    description:
-      'This is the  helmet for those warm summer days on the road. '
-      'Jetset approved, these hats have been rigorously tested. Keep that face '
-      'protected from the sun.'
-  ),
-  Product(
-    name: 'Ginger Scarf',
-    imageAsset: 'products/scarf.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['latest', 'fashion'],
-    price: 17.00,
-    vendor: _peter,
-    description:
-    'Leave the tunnel and the rain is fallin amazing things happen when you wait'
-  ),
-  Product(
-    name: 'Blush Sweats',
-    imageAsset: 'products/sweats.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['travel', 'fashion', 'latest'],
-    price: 25.00,
-    vendor: _stella,
-    description:
-    'Leave the tunnel and the rain is fallin amazing things happen when you wait'
-  ),
-  Product(
-    name: 'Mint Jumper',
-    imageAsset: 'products/jumper.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>['travel', 'fashion', 'beauty'],
-    price: 25.00,
-    vendor: _peter,
-    description:
-    'Leave the tunnel and the rain is fallin amazing things happen when you wait'
-  ),
-  Product(
-    name: 'Ochre Shirt',
-    imageAsset: 'products/shirt.png',
-    imageAssetPackage: _kGalleryAssetsPackage,
-    categories: <String>[ 'fashion', 'latest'],
-    price: 120.00,
-    vendor: _stella,
-    description:
-    'Leave the tunnel and the rain is fallin amazing things happen when you wait'
-  )
-];
-
-List<Product> allProducts() {
-  assert(_allProducts.every((Product product) => product.isValid()));
-  return List<Product>.unmodifiable(_allProducts);
-}
diff --git a/examples/flutter_gallery/lib/demo/shrine/shrine_home.dart b/examples/flutter_gallery/lib/demo/shrine/shrine_home.dart
deleted file mode 100644
index a7aa943..0000000
--- a/examples/flutter_gallery/lib/demo/shrine/shrine_home.dart
+++ /dev/null
@@ -1,411 +0,0 @@
-// Copyright 2016 The Chromium 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 'dart:async';
-
-import 'package:flutter/material.dart';
-import 'package:flutter/rendering.dart';
-import 'package:meta/meta.dart';
-
-import 'shrine_data.dart';
-import 'shrine_order.dart';
-import 'shrine_page.dart';
-import 'shrine_theme.dart';
-import 'shrine_types.dart';
-
-const double unitSize = kToolbarHeight;
-
-final List<Product> _products = List<Product>.from(allProducts());
-final Map<Product, Order> _shoppingCart = <Product, Order>{};
-
-const int _childrenPerBlock = 8;
-const int _rowsPerBlock = 5;
-
-int _minIndexInRow(int rowIndex) {
-  final int blockIndex = rowIndex ~/ _rowsPerBlock;
-  return const <int>[0, 2, 4, 6, 7][rowIndex % _rowsPerBlock] + blockIndex * _childrenPerBlock;
-}
-
-int _maxIndexInRow(int rowIndex) {
-  final int blockIndex = rowIndex ~/ _rowsPerBlock;
-  return const <int>[1, 3, 5, 6, 7][rowIndex % _rowsPerBlock] + blockIndex * _childrenPerBlock;
-}
-
-int _rowAtIndex(int index) {
-  final int blockCount = index ~/ _childrenPerBlock;
-  return const <int>[0, 0, 1, 1, 2, 2, 3, 4][index - blockCount * _childrenPerBlock] + blockCount * _rowsPerBlock;
-}
-
-int _columnAtIndex(int index) {
-  return const <int>[0, 1, 0, 1, 0, 1, 0, 0][index % _childrenPerBlock];
-}
-
-int _columnSpanAtIndex(int index) {
-  return const <int>[1, 1, 1, 1, 1, 1, 2, 2][index % _childrenPerBlock];
-}
-
-// The Shrine home page arranges the product cards into two columns. The card
-// on every 4th and 5th row spans two columns.
-class _ShrineGridLayout extends SliverGridLayout {
-  const _ShrineGridLayout({
-    @required this.rowStride,
-    @required this.columnStride,
-    @required this.tileHeight,
-    @required this.tileWidth,
-  });
-
-  final double rowStride;
-  final double columnStride;
-  final double tileHeight;
-  final double tileWidth;
-
-  @override
-  int getMinChildIndexForScrollOffset(double scrollOffset) {
-    return _minIndexInRow(scrollOffset ~/ rowStride);
-  }
-
-  @override
-  int getMaxChildIndexForScrollOffset(double scrollOffset) {
-    return _maxIndexInRow(scrollOffset ~/ rowStride);
-  }
-
-  @override
-  SliverGridGeometry getGeometryForChildIndex(int index) {
-    final int row = _rowAtIndex(index);
-    final int column = _columnAtIndex(index);
-    final int columnSpan = _columnSpanAtIndex(index);
-    return SliverGridGeometry(
-      scrollOffset: row * rowStride,
-      crossAxisOffset: column * columnStride,
-      mainAxisExtent: tileHeight,
-      crossAxisExtent: tileWidth + (columnSpan - 1) * columnStride,
-    );
-  }
-
-  @override
-  double computeMaxScrollOffset(int childCount) {
-    if (childCount == 0)
-      return 0.0;
-    final int rowCount = _rowAtIndex(childCount - 1) + 1;
-    final double rowSpacing = rowStride - tileHeight;
-    return rowStride * rowCount - rowSpacing;
-  }
-}
-
-class _ShrineGridDelegate extends SliverGridDelegate {
-  static const double _spacing = 8.0;
-
-  @override
-  SliverGridLayout getLayout(SliverConstraints constraints) {
-    final double tileWidth = (constraints.crossAxisExtent - _spacing) / 2.0;
-    const double tileHeight = 40.0 + 144.0 + 40.0;
-    return _ShrineGridLayout(
-      tileWidth: tileWidth,
-      tileHeight: tileHeight,
-      rowStride: tileHeight + _spacing,
-      columnStride: tileWidth + _spacing,
-    );
-  }
-
-  @override
-  bool shouldRelayout(covariant SliverGridDelegate oldDelegate) => false;
-}
-
-// Displays the Vendor's name and avatar.
-class _VendorItem extends StatelessWidget {
-  const _VendorItem({ Key key, @required this.vendor })
-    : assert(vendor != null),
-      super(key: key);
-
-  final Vendor vendor;
-
-  @override
-  Widget build(BuildContext context) {
-    return SizedBox(
-      height: 24.0,
-      child: Row(
-        children: <Widget>[
-          SizedBox(
-            width: 24.0,
-            child: ClipRRect(
-              borderRadius: BorderRadius.circular(12.0),
-              child: Image.asset(
-                vendor.avatarAsset,
-                package: vendor.avatarAssetPackage,
-                fit: BoxFit.cover,
-              ),
-            ),
-          ),
-          const SizedBox(width: 8.0),
-          Expanded(
-            child: Text(vendor.name, style: ShrineTheme.of(context).vendorItemStyle),
-          ),
-        ],
-      ),
-    );
-  }
-}
-
-// Displays the product's price. If the product is in the shopping cart then the
-// background is highlighted.
-abstract class _PriceItem extends StatelessWidget {
-  const _PriceItem({ Key key, @required this.product })
-      : assert(product != null),
-        super(key: key);
-
-  final Product product;
-
-  Widget buildItem(BuildContext context, TextStyle style, EdgeInsets padding) {
-    BoxDecoration decoration;
-    if (_shoppingCart[product] != null)
-      decoration = BoxDecoration(color: ShrineTheme.of(context).priceHighlightColor);
-
-    return Container(
-      padding: padding,
-      decoration: decoration,
-      child: Text(product.priceString, style: style),
-    );
-  }
-}
-
-class _ProductPriceItem extends _PriceItem {
-  const _ProductPriceItem({ Key key, Product product }) : super(key: key, product: product);
-
-  @override
-  Widget build(BuildContext context) {
-    return buildItem(
-      context,
-      ShrineTheme.of(context).priceStyle,
-      const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
-    );
-  }
-}
-
-class _FeaturePriceItem extends _PriceItem {
-  const _FeaturePriceItem({ Key key, Product product }) : super(key: key, product: product);
-
-  @override
-  Widget build(BuildContext context) {
-    return buildItem(
-      context,
-      ShrineTheme.of(context).featurePriceStyle,
-      const EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0),
-    );
-  }
-}
-
-class _HeadingLayout extends MultiChildLayoutDelegate {
-  _HeadingLayout();
-
-  static const String price = 'price';
-  static const String image = 'image';
-  static const String title = 'title';
-  static const String description = 'description';
-  static const String vendor = 'vendor';
-
-  @override
-  void performLayout(Size size) {
-    final Size priceSize = layoutChild(price, BoxConstraints.loose(size));
-    positionChild(price, Offset(size.width - priceSize.width, 0.0));
-
-    final double halfWidth = size.width / 2.0;
-    final double halfHeight = size.height / 2.0;
-    const double halfUnit = unitSize / 2.0;
-    const double margin = 16.0;
-
-    final Size imageSize = layoutChild(image, BoxConstraints.loose(size));
-    final double imageX = imageSize.width < halfWidth - halfUnit
-      ? halfWidth / 2.0 - imageSize.width / 2.0 - halfUnit
-      : halfWidth - imageSize.width;
-    positionChild(image, Offset(imageX, halfHeight - imageSize.height / 2.0));
-
-    final double maxTitleWidth = halfWidth + unitSize - margin;
-    final BoxConstraints titleBoxConstraints = BoxConstraints(maxWidth: maxTitleWidth);
-    final Size titleSize = layoutChild(title, titleBoxConstraints);
-    final double titleX = halfWidth - unitSize;
-    final double titleY = halfHeight - titleSize.height;
-    positionChild(title, Offset(titleX, titleY));
-
-    final Size descriptionSize = layoutChild(description, titleBoxConstraints);
-    final double descriptionY = titleY + titleSize.height + margin;
-    positionChild(description, Offset(titleX, descriptionY));
-
-    layoutChild(vendor, titleBoxConstraints);
-    final double vendorY = descriptionY + descriptionSize.height + margin;
-    positionChild(vendor, Offset(titleX, vendorY));
-  }
-
-  @override
-  bool shouldRelayout(_HeadingLayout oldDelegate) => false;
-}
-
-// A card that highlights the "featured" catalog item.
-class _Heading extends StatelessWidget {
-  _Heading({ Key key, @required this.product })
-    : assert(product != null),
-      assert(product.featureTitle != null),
-      assert(product.featureDescription != null),
-      super(key: key);
-
-  final Product product;
-
-  @override
-  Widget build(BuildContext context) {
-    final Size screenSize = MediaQuery.of(context).size;
-    final ShrineTheme theme = ShrineTheme.of(context);
-    return MergeSemantics(
-      child: SizedBox(
-        height: screenSize.width > screenSize.height
-          ? (screenSize.height - kToolbarHeight) * 0.85
-          : (screenSize.height - kToolbarHeight) * 0.70,
-        child: Container(
-          decoration: BoxDecoration(
-            color: theme.cardBackgroundColor,
-            border: Border(bottom: BorderSide(color: theme.dividerColor)),
-          ),
-          child: CustomMultiChildLayout(
-            delegate: _HeadingLayout(),
-            children: <Widget>[
-              LayoutId(
-                id: _HeadingLayout.price,
-                child: _FeaturePriceItem(product: product),
-              ),
-              LayoutId(
-                id: _HeadingLayout.image,
-                child: Image.asset(
-                  product.imageAsset,
-                  package: product.imageAssetPackage,
-                  fit: BoxFit.cover,
-                ),
-              ),
-              LayoutId(
-                id: _HeadingLayout.title,
-                child: Text(product.featureTitle, style: theme.featureTitleStyle),
-              ),
-              LayoutId(
-                id: _HeadingLayout.description,
-                child: Text(product.featureDescription, style: theme.featureStyle),
-              ),
-              LayoutId(
-                id: _HeadingLayout.vendor,
-                child: _VendorItem(vendor: product.vendor),
-              ),
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-}
-
-// A card that displays a product's image, price, and vendor. The _ProductItem
-// cards appear in a grid below the heading.
-class _ProductItem extends StatelessWidget {
-  const _ProductItem({ Key key, @required this.product, this.onPressed })
-    : assert(product != null),
-      super(key: key);
-
-  final Product product;
-  final VoidCallback onPressed;
-
-  @override
-  Widget build(BuildContext context) {
-    return MergeSemantics(
-      child: Card(
-        child: Stack(
-          children: <Widget>[
-            Column(
-              children: <Widget>[
-                Align(
-                  alignment: Alignment.centerRight,
-                  child: _ProductPriceItem(product: product),
-                ),
-                Container(
-                  width: 144.0,
-                  height: 144.0,
-                  padding: const EdgeInsets.symmetric(horizontal: 8.0),
-                  child: Hero(
-                      tag: product.tag,
-                      child: Image.asset(
-                        product.imageAsset,
-                        package: product.imageAssetPackage,
-                        fit: BoxFit.contain,
-                      ),
-                    ),
-                  ),
-                Padding(
-                  padding: const EdgeInsets.symmetric(horizontal: 8.0),
-                  child: _VendorItem(vendor: product.vendor),
-                ),
-              ],
-            ),
-            Material(
-              type: MaterialType.transparency,
-              child: InkWell(onTap: onPressed),
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-}
-
-// The Shrine app's home page. Displays the featured item above a grid
-// of the product items.
-class ShrineHome extends StatefulWidget {
-  @override
-  _ShrineHomeState createState() => _ShrineHomeState();
-}
-
-class _ShrineHomeState extends State<ShrineHome> {
-  static final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(debugLabel: 'Shrine Home');
-  static final _ShrineGridDelegate gridDelegate = _ShrineGridDelegate();
-
-  Future<void> _showOrderPage(Product product) async {
-    final Order order = _shoppingCart[product] ?? Order(product: product);
-    final Order completedOrder = await Navigator.push(context, ShrineOrderRoute(
-      order: order,
-      builder: (BuildContext context) {
-        return OrderPage(
-          order: order,
-          products: _products,
-          shoppingCart: _shoppingCart,
-        );
-      }
-    ));
-    assert(completedOrder.product != null);
-    if (completedOrder.quantity == 0)
-      _shoppingCart.remove(completedOrder.product);
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final Product featured = _products.firstWhere((Product product) => product.featureDescription != null);
-    return ShrinePage(
-      scaffoldKey: _scaffoldKey,
-      products: _products,
-      shoppingCart: _shoppingCart,
-      body: CustomScrollView(
-        slivers: <Widget>[
-          SliverToBoxAdapter(child: _Heading(product: featured)),
-          SliverSafeArea(
-            top: false,
-            minimum: const EdgeInsets.all(16.0),
-            sliver: SliverGrid(
-              gridDelegate: gridDelegate,
-              delegate: SliverChildListDelegate(
-                _products.map<Widget>((Product product) {
-                  return _ProductItem(
-                    product: product,
-                    onPressed: () { _showOrderPage(product); },
-                  );
-                }).toList(),
-              ),
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-}
diff --git a/examples/flutter_gallery/lib/demo/shrine/shrine_order.dart b/examples/flutter_gallery/lib/demo/shrine/shrine_order.dart
deleted file mode 100644
index 135f1c9..0000000
--- a/examples/flutter_gallery/lib/demo/shrine/shrine_order.dart
+++ /dev/null
@@ -1,340 +0,0 @@
-// Copyright 2016 The Chromium 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:flutter/material.dart';
-
-import '../shrine_demo.dart' show ShrinePageRoute;
-import 'shrine_page.dart';
-import 'shrine_theme.dart';
-import 'shrine_types.dart';
-
-// Displays the product title's, description, and order quantity dropdown.
-class _ProductItem extends StatelessWidget {
-  const _ProductItem({
-    Key key,
-    @required this.product,
-    @required this.quantity,
-    @required this.onChanged,
-  }) : assert(product != null),
-       assert(quantity != null),
-       assert(onChanged != null),
-       super(key: key);
-
-  final Product product;
-  final int quantity;
-  final ValueChanged<int> onChanged;
-
-  @override
-  Widget build(BuildContext context) {
-    final ShrineTheme theme = ShrineTheme.of(context);
-    return Column(
-      mainAxisSize: MainAxisSize.min,
-      crossAxisAlignment: CrossAxisAlignment.stretch,
-      children: <Widget>[
-        Text(product.name, style: theme.featureTitleStyle),
-        const SizedBox(height: 24.0),
-        Text(product.description, style: theme.featureStyle),
-        const SizedBox(height: 16.0),
-        Padding(
-          padding: const EdgeInsets.only(top: 8.0, bottom: 8.0, right: 88.0),
-          child: DropdownButtonHideUnderline(
-            child: Container(
-              decoration: BoxDecoration(
-                border: Border.all(
-                  color: const Color(0xFFD9D9D9),
-                ),
-              ),
-              child: DropdownButton<int>(
-                items: <int>[0, 1, 2, 3, 4, 5].map<DropdownMenuItem<int>>((int value) {
-                  return DropdownMenuItem<int>(
-                    value: value,
-                    child: Padding(
-                      padding: const EdgeInsets.only(left: 8.0),
-                      child: Text('Quantity $value', style: theme.quantityMenuStyle),
-                    ),
-                  );
-                }).toList(),
-                value: quantity,
-                onChanged: onChanged,
-              ),
-            ),
-          ),
-        ),
-      ],
-    );
-  }
-}
-
-// Vendor name and description
-class _VendorItem extends StatelessWidget {
-  const _VendorItem({ Key key, @required this.vendor })
-    : assert(vendor != null),
-      super(key: key);
-
-  final Vendor vendor;
-
-  @override
-  Widget build(BuildContext context) {
-    final ShrineTheme theme = ShrineTheme.of(context);
-    return Column(
-      mainAxisSize: MainAxisSize.min,
-      crossAxisAlignment: CrossAxisAlignment.stretch,
-      children: <Widget>[
-        SizedBox(
-          height: 24.0,
-          child: Align(
-            alignment: Alignment.bottomLeft,
-            child: Text(vendor.name, style: theme.vendorTitleStyle),
-          ),
-        ),
-        const SizedBox(height: 16.0),
-        Text(vendor.description, style: theme.vendorStyle),
-      ],
-    );
-  }
-}
-
-// Layout the order page's heading: the product's image, the
-// title/description/dropdown product item, and the vendor item.
-class _HeadingLayout extends MultiChildLayoutDelegate {
-  _HeadingLayout();
-
-  static const String image = 'image';
-  static const String icon = 'icon';
-  static const String product = 'product';
-  static const String vendor = 'vendor';
-
-  @override
-  void performLayout(Size size) {
-    const double margin = 56.0;
-    final bool landscape = size.width > size.height;
-    final double imageWidth = (landscape ? size.width / 2.0 : size.width) - margin * 2.0;
-    final BoxConstraints imageConstraints = BoxConstraints(maxHeight: 224.0, maxWidth: imageWidth);
-    final Size imageSize = layoutChild(image, imageConstraints);
-    const double imageY = 0.0;
-    positionChild(image, const Offset(margin, imageY));
-
-    final double productWidth = landscape ? size.width / 2.0 : size.width - margin;
-    final BoxConstraints productConstraints = BoxConstraints(maxWidth: productWidth);
-    final Size productSize = layoutChild(product, productConstraints);
-    final double productX = landscape ? size.width / 2.0 : margin;
-    final double productY = landscape ? 0.0 : imageY + imageSize.height + 16.0;
-    positionChild(product, Offset(productX, productY));
-
-    final Size iconSize = layoutChild(icon, BoxConstraints.loose(size));
-    positionChild(icon, Offset(productX - iconSize.width - 16.0, productY + 8.0));
-
-    final double vendorWidth = landscape ? size.width - margin : productWidth;
-    layoutChild(vendor, BoxConstraints(maxWidth: vendorWidth));
-    final double vendorX = landscape ? margin : productX;
-    final double vendorY = productY + productSize.height + 16.0;
-    positionChild(vendor, Offset(vendorX, vendorY));
-  }
-
-  @override
-  bool shouldRelayout(_HeadingLayout oldDelegate) => true;
-}
-
-// Describes a product and vendor in detail, supports specifying
-// a order quantity (0-5). Appears at the top of the OrderPage.
-class _Heading extends StatelessWidget {
-  const _Heading({
-    Key key,
-    @required this.product,
-    @required this.quantity,
-    this.quantityChanged,
-  }) : assert(product != null),
-       assert(quantity != null && quantity >= 0 && quantity <= 5),
-       super(key: key);
-
-  final Product product;
-  final int quantity;
-  final ValueChanged<int> quantityChanged;
-
-  @override
-  Widget build(BuildContext context) {
-    final Size screenSize = MediaQuery.of(context).size;
-    return SizedBox(
-      height: (screenSize.height - kToolbarHeight) * 1.35,
-      child: Material(
-        type: MaterialType.card,
-        elevation: 0.0,
-        child: Padding(
-          padding: const EdgeInsets.only(left: 16.0, top: 18.0, right: 16.0, bottom: 24.0),
-          child: CustomMultiChildLayout(
-            delegate: _HeadingLayout(),
-            children: <Widget>[
-              LayoutId(
-                id: _HeadingLayout.image,
-                child: Hero(
-                  tag: product.tag,
-                  child: Image.asset(
-                    product.imageAsset,
-                    package: product.imageAssetPackage,
-                    fit: BoxFit.contain,
-                    alignment: Alignment.center,
-                  ),
-                ),
-              ),
-              LayoutId(
-                id: _HeadingLayout.icon,
-                child: const Icon(
-                  Icons.info_outline,
-                  size: 24.0,
-                  color: Color(0xFFFFE0E0),
-                ),
-              ),
-              LayoutId(
-                id: _HeadingLayout.product,
-                child: _ProductItem(
-                  product: product,
-                  quantity: quantity,
-                  onChanged: quantityChanged,
-                ),
-              ),
-              LayoutId(
-                id: _HeadingLayout.vendor,
-                child: _VendorItem(vendor: product.vendor),
-              ),
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-}
-
-class OrderPage extends StatefulWidget {
-  OrderPage({
-    Key key,
-    @required this.order,
-    @required this.products,
-    @required this.shoppingCart,
-  }) : assert(order != null),
-       assert(products != null && products.isNotEmpty),
-       assert(shoppingCart != null),
-       super(key: key);
-
-  final Order order;
-  final List<Product> products;
-  final Map<Product, Order> shoppingCart;
-
-  @override
-  _OrderPageState createState() => _OrderPageState();
-}
-
-// Displays a product's heading above photos of all of the other products
-// arranged in two columns. Enables the user to specify a quantity and add an
-// order to the shopping cart.
-class _OrderPageState extends State<OrderPage> {
-  GlobalKey<ScaffoldState> scaffoldKey;
-
-  @override
-  void initState() {
-    super.initState();
-    scaffoldKey = GlobalKey<ScaffoldState>(debugLabel: 'Shrine Order ${widget.order}');
-  }
-
-  Order get currentOrder => ShrineOrderRoute.of(context).order;
-
-  set currentOrder(Order value) {
-    ShrineOrderRoute.of(context).order = value;
-  }
-
-  void updateOrder({ int quantity, bool inCart }) {
-    final Order newOrder = currentOrder.copyWith(quantity: quantity, inCart: inCart);
-    if (currentOrder != newOrder) {
-      setState(() {
-        widget.shoppingCart[newOrder.product] = newOrder;
-        currentOrder = newOrder;
-      });
-    }
-  }
-
-  void showSnackBarMessage(String message) {
-    scaffoldKey.currentState.showSnackBar(SnackBar(content: Text(message)));
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return ShrinePage(
-      scaffoldKey: scaffoldKey,
-      products: widget.products,
-      shoppingCart: widget.shoppingCart,
-      floatingActionButton: FloatingActionButton(
-        onPressed: () {
-          updateOrder(inCart: true);
-          final int n = currentOrder.quantity;
-          final String item = currentOrder.product.name;
-          showSnackBarMessage(
-            'There ${ n == 1 ? "is one $item item" : "are $n $item items" } in the shopping cart.'
-          );
-        },
-        backgroundColor: const Color(0xFF16F0F0),
-        tooltip: 'Add to cart',
-        child: const Icon(
-          Icons.add_shopping_cart,
-          color: Colors.black,
-        ),
-      ),
-      body: CustomScrollView(
-        slivers: <Widget>[
-          SliverToBoxAdapter(
-            child: _Heading(
-              product: widget.order.product,
-              quantity: currentOrder.quantity,
-              quantityChanged: (int value) { updateOrder(quantity: value); },
-            ),
-          ),
-          SliverSafeArea(
-            top: false,
-            minimum: const EdgeInsets.fromLTRB(8.0, 32.0, 8.0, 8.0),
-            sliver: SliverGrid(
-              gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
-                maxCrossAxisExtent: 248.0,
-                mainAxisSpacing: 8.0,
-                crossAxisSpacing: 8.0,
-              ),
-              delegate: SliverChildListDelegate(
-                widget.products
-                  .where((Product product) => product != widget.order.product)
-                  .map((Product product) {
-                    return Card(
-                      elevation: 1.0,
-                      child: Image.asset(
-                        product.imageAsset,
-                        package: product.imageAssetPackage,
-                        fit: BoxFit.contain,
-                      ),
-                    );
-                  }).toList(),
-              ),
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-}
-
-// Displays a full-screen modal OrderPage.
-//
-// The order field will be replaced each time the user reconfigures the order.
-// When the user backs out of this route the completer's value will be the
-// final value of the order field.
-class ShrineOrderRoute extends ShrinePageRoute<Order> {
-  ShrineOrderRoute({
-    @required this.order,
-    WidgetBuilder builder,
-    RouteSettings settings,
-  }) : assert(order != null),
-       super(builder: builder, settings: settings);
-
-  Order order;
-
-  @override
-  Order get currentResult => order;
-
-  static ShrineOrderRoute of(BuildContext context) => ModalRoute.of<Order>(context);
-}
diff --git a/examples/flutter_gallery/lib/demo/shrine/shrine_page.dart b/examples/flutter_gallery/lib/demo/shrine/shrine_page.dart
deleted file mode 100644
index b31cb3d..0000000
--- a/examples/flutter_gallery/lib/demo/shrine/shrine_page.dart
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2016 The Chromium 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:flutter/material.dart';
-
-import 'shrine_theme.dart';
-import 'shrine_types.dart';
-
-enum ShrineAction {
-  sortByPrice,
-  sortByProduct,
-  emptyCart
-}
-
-class ShrinePage extends StatefulWidget {
-  const ShrinePage({
-    Key key,
-    @required this.scaffoldKey,
-    @required this.body,
-    this.floatingActionButton,
-    this.products,
-    this.shoppingCart
-  }) : assert(body != null),
-       assert(scaffoldKey != null),
-       super(key: key);
-
-  final GlobalKey<ScaffoldState> scaffoldKey;
-  final Widget body;
-  final Widget floatingActionButton;
-  final List<Product> products;
-  final Map<Product, Order> shoppingCart;
-
-  @override
-  ShrinePageState createState() => ShrinePageState();
-}
-
-/// Defines the Scaffold, AppBar, etc that the demo pages have in common.
-class ShrinePageState extends State<ShrinePage> {
-  double _appBarElevation = 0.0;
-
-  bool _handleScrollNotification(ScrollNotification notification) {
-    final double elevation = notification.metrics.extentBefore <= 0.0 ? 0.0 : 1.0;
-    if (elevation != _appBarElevation) {
-      setState(() {
-        _appBarElevation = elevation;
-      });
-    }
-    return false;
-  }
-
-  void _showShoppingCart() {
-    showModalBottomSheet<void>(context: context, builder: (BuildContext context) {
-      if (widget.shoppingCart.isEmpty) {
-        return const Padding(
-          padding: EdgeInsets.all(24.0),
-          child: Text('The shopping cart is empty')
-        );
-      }
-      return ListView(
-        padding: kMaterialListPadding,
-        children: widget.shoppingCart.values.map((Order order) {
-          return ListTile(
-            title: Text(order.product.name),
-            leading: Text('${order.quantity}'),
-            subtitle: Text(order.product.vendor.name)
-          );
-        }).toList(),
-      );
-    });
-  }
-
-  void _sortByPrice() {
-    widget.products.sort((Product a, Product b) => a.price.compareTo(b.price));
-  }
-
-  void _sortByProduct() {
-    widget.products.sort((Product a, Product b) => a.name.compareTo(b.name));
-  }
-
-  void _emptyCart() {
-    widget.shoppingCart.clear();
-    widget.scaffoldKey.currentState.showSnackBar(const SnackBar(content: Text('Shopping cart is empty')));
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final ShrineTheme theme = ShrineTheme.of(context);
-    return Scaffold(
-      key: widget.scaffoldKey,
-      appBar: AppBar(
-        elevation: _appBarElevation,
-        backgroundColor: theme.appBarBackgroundColor,
-        iconTheme: Theme.of(context).iconTheme,
-        brightness: Brightness.light,
-        flexibleSpace: Container(
-          decoration: BoxDecoration(
-            border: Border(
-              bottom: BorderSide(color: theme.dividerColor)
-            )
-          )
-        ),
-        title: Text('SHRINE', style: ShrineTheme.of(context).appBarTitleStyle),
-        centerTitle: true,
-        actions: <Widget>[
-          IconButton(
-            icon: const Icon(Icons.shopping_cart),
-            tooltip: 'Shopping cart',
-            onPressed: _showShoppingCart
-          ),
-          PopupMenuButton<ShrineAction>(
-            itemBuilder: (BuildContext context) => <PopupMenuItem<ShrineAction>>[
-              const PopupMenuItem<ShrineAction>(
-                value: ShrineAction.sortByPrice,
-                child: Text('Sort by price')
-              ),
-              const PopupMenuItem<ShrineAction>(
-                value: ShrineAction.sortByProduct,
-                child: Text('Sort by product')
-              ),
-              const PopupMenuItem<ShrineAction>(
-                value: ShrineAction.emptyCart,
-                child: Text('Empty shopping cart')
-              )
-            ],
-            onSelected: (ShrineAction action) {
-              switch (action) {
-                case ShrineAction.sortByPrice:
-                  setState(_sortByPrice);
-                  break;
-                case ShrineAction.sortByProduct:
-                  setState(_sortByProduct);
-                  break;
-                case ShrineAction.emptyCart:
-                  setState(_emptyCart);
-                  break;
-              }
-            }
-          )
-        ]
-      ),
-      floatingActionButton: widget.floatingActionButton,
-      body: NotificationListener<ScrollNotification>(
-        onNotification: _handleScrollNotification,
-        child: widget.body
-      )
-    );
-  }
-}
diff --git a/examples/flutter_gallery/lib/demo/shrine/shrine_theme.dart b/examples/flutter_gallery/lib/demo/shrine/shrine_theme.dart
deleted file mode 100644
index 8e14634..0000000
--- a/examples/flutter_gallery/lib/demo/shrine/shrine_theme.dart
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2016 The Chromium 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:flutter/material.dart';
-
-class ShrineStyle extends TextStyle {
-  const ShrineStyle.roboto(double size, FontWeight weight, Color color)
-    : super(inherit: false, color: color, fontSize: size, fontWeight: weight, textBaseline: TextBaseline.alphabetic);
-
-  const ShrineStyle.abrilFatface(double size, FontWeight weight, Color color)
-    : super(inherit: false, color: color, fontFamily: 'AbrilFatface', fontSize: size, fontWeight: weight, textBaseline: TextBaseline.alphabetic);
-}
-
-TextStyle robotoRegular12(Color color) => ShrineStyle.roboto(12.0, FontWeight.w500, color);
-TextStyle robotoLight12(Color color) => ShrineStyle.roboto(12.0, FontWeight.w300, color);
-TextStyle robotoRegular14(Color color) => ShrineStyle.roboto(14.0, FontWeight.w500, color);
-TextStyle robotoMedium14(Color color) => ShrineStyle.roboto(14.0, FontWeight.w600, color);
-TextStyle robotoLight14(Color color) => ShrineStyle.roboto(14.0, FontWeight.w300, color);
-TextStyle robotoRegular16(Color color) => ShrineStyle.roboto(16.0, FontWeight.w500, color);
-TextStyle robotoRegular20(Color color) => ShrineStyle.roboto(20.0, FontWeight.w500, color);
-TextStyle abrilFatfaceRegular24(Color color) => ShrineStyle.abrilFatface(24.0, FontWeight.w500, color);
-TextStyle abrilFatfaceRegular34(Color color) => ShrineStyle.abrilFatface(34.0, FontWeight.w500, color);
-
-/// The TextStyles and Colors used for titles, labels, and descriptions. This
-/// InheritedWidget is shared by all of the routes and widgets created for
-/// the Shrine app.
-class ShrineTheme extends InheritedWidget {
-  ShrineTheme({ Key key, @required Widget child })
-    : assert(child != null),
-      super(key: key, child: child);
-
-  final Color cardBackgroundColor = Colors.white;
-  final Color appBarBackgroundColor = Colors.white;
-  final Color dividerColor = const Color(0xFFD9D9D9);
-  final Color priceHighlightColor = const Color(0xFFFFE0E0);
-
-  final TextStyle appBarTitleStyle = robotoRegular20(Colors.black87);
-  final TextStyle vendorItemStyle = robotoRegular12(const Color(0xFF81959D));
-  final TextStyle priceStyle = robotoRegular14(Colors.black87);
-  final TextStyle featureTitleStyle = abrilFatfaceRegular34(const Color(0xFF0A3142));
-  final TextStyle featurePriceStyle = robotoRegular16(Colors.black87);
-  final TextStyle featureStyle = robotoLight14(Colors.black54);
-  final TextStyle orderTitleStyle = abrilFatfaceRegular24(Colors.black87);
-  final TextStyle orderStyle = robotoLight14(Colors.black54);
-  final TextStyle vendorTitleStyle = robotoMedium14(Colors.black87);
-  final TextStyle vendorStyle = robotoLight14(Colors.black54);
-  final TextStyle quantityMenuStyle = robotoLight14(Colors.black54);
-
-  static ShrineTheme of(BuildContext context) => context.inheritFromWidgetOfExactType(ShrineTheme);
-
-  @override
-  bool updateShouldNotify(ShrineTheme oldWidget) => false;
-}
diff --git a/examples/flutter_gallery/lib/demo/shrine/shrine_types.dart b/examples/flutter_gallery/lib/demo/shrine/shrine_types.dart
deleted file mode 100644
index 884e646..0000000
--- a/examples/flutter_gallery/lib/demo/shrine/shrine_types.dart
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2016 The Chromium 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 'dart:ui' show hashValues;
-
-import 'package:flutter/foundation.dart';
-
-class Vendor {
-  const Vendor({
-    this.name,
-    this.description,
-    this.avatarAsset,
-    this.avatarAssetPackage,
-  });
-
-  final String name;
-  final String description;
-  final String avatarAsset;
-  final String avatarAssetPackage;
-
-  bool isValid() {
-    return name != null &&
-      description != null &&
-      avatarAsset != null;
-  }
-
-  @override
-  String toString() => 'Vendor($name)';
-}
-
-class Product {
-  const Product({
-    this.name,
-    this.description,
-    this.featureTitle,
-    this.featureDescription,
-    this.imageAsset,
-    this.imageAssetPackage,
-    this.categories,
-    this.price,
-    this.vendor
-  });
-
-  final String name;
-  final String description;
-  final String featureTitle;
-  final String featureDescription;
-  final String imageAsset;
-  final String imageAssetPackage;
-  final List<String> categories;
-  final double price;
-  final Vendor vendor;
-
-  String get tag => name; // Unique value for Heroes
-  String get priceString => '\$${price.floor()}';
-
-  bool isValid() {
-    return name != null &&
-      description != null &&
-      imageAsset != null &&
-      categories != null &&
-      categories.isNotEmpty &&
-      price != null &&
-      vendor.isValid();
-  }
-
-  @override
-  String toString() => 'Product($name)';
-}
-
-class Order {
-  Order({ @required this.product, this.quantity = 1, this.inCart = false })
-    : assert(product != null),
-      assert(quantity != null && quantity >= 0),
-      assert(inCart != null);
-
-  final Product product;
-  final int quantity;
-  final bool inCart;
-
-  Order copyWith({ Product product, int quantity, bool inCart }) {
-    return Order(
-      product: product ?? this.product,
-      quantity: quantity ?? this.quantity,
-      inCart: inCart ?? this.inCart
-    );
-  }
-
-  @override
-  bool operator ==(dynamic other) {
-    if (identical(this, other))
-      return true;
-    if (other.runtimeType != runtimeType)
-      return false;
-    final Order typedOther = other;
-    return product == typedOther.product &&
-           quantity == typedOther.quantity &&
-           inCart == typedOther.inCart;
-  }
-
-  @override
-  int get hashCode => hashValues(product, quantity, inCart);
-
-  @override
-  String toString() => 'Order($product, quantity=$quantity, inCart=$inCart)';
-}
diff --git a/examples/flutter_gallery/lib/demo/shrine/supplemental/asymmetric_view.dart b/examples/flutter_gallery/lib/demo/shrine/supplemental/asymmetric_view.dart
new file mode 100644
index 0000000..10922a1
--- /dev/null
+++ b/examples/flutter_gallery/lib/demo/shrine/supplemental/asymmetric_view.dart
@@ -0,0 +1,95 @@
+// Copyright 2018-present the Flutter authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'package:flutter/material.dart';
+
+import 'package:flutter_gallery/demo/shrine/model/product.dart';
+import 'package:flutter_gallery/demo/shrine/supplemental/product_columns.dart';
+
+class AsymmetricView extends StatelessWidget {
+  const AsymmetricView({Key key, this.products}) : super(key: key);
+
+  final List<Product> products;
+
+  List<Container> _buildColumns(BuildContext context) {
+    if (products == null || products.isEmpty) {
+      return const <Container>[];
+    }
+
+    // This will return a list of columns. It will oscillate between the two
+    // kinds of columns. Even cases of the index (0, 2, 4, etc) will be
+    // TwoProductCardColumn and the odd cases will be OneProductCardColumn.
+    //
+    // Each pair of columns will advance us 3 products forward (2 + 1). That's
+    // some kinda awkward math so we use _evenCasesIndex and _oddCasesIndex as
+    // helpers for creating the index of the product list that will correspond
+    // to the index of the list of columns.
+    return List<Container>.generate(_listItemCount(products.length), (int index) {
+      double width = .59 * MediaQuery.of(context).size.width;
+      Widget column;
+      if (index % 2 == 0) {
+        /// Even cases
+        final int bottom = _evenCasesIndex(index);
+        column = TwoProductCardColumn(
+          bottom: products[bottom],
+          top: products.length - 1 >= bottom + 1
+            ? products[bottom + 1]
+            : null,
+        );
+        width += 32.0;
+      } else {
+        /// Odd cases
+        column = OneProductCardColumn(
+          product: products[_oddCasesIndex(index)],
+        );
+      }
+      return Container(
+        width: width,
+        child: Padding(
+          padding: const EdgeInsets.symmetric(horizontal: 16.0),
+          child: column,
+        ),
+      );
+    }).toList();
+  }
+
+  int _evenCasesIndex(int input) {
+    // The operator ~/ is a cool one. It's the truncating division operator. It
+    // divides the number and if there's a remainder / decimal, it cuts it off.
+    // This is like dividing and then casting the result to int. Also, it's
+    // functionally equivalent to floor() in this case.
+    return input ~/ 2 * 3;
+  }
+
+  int _oddCasesIndex(int input) {
+    assert(input > 0);
+    return (input / 2).ceil() * 3 - 1;
+  }
+
+  int _listItemCount(int totalItems) {
+    return (totalItems % 3 == 0)
+      ? totalItems ~/ 3 * 2
+      : (totalItems / 3).ceil() * 2 - 1;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return ListView(
+      scrollDirection: Axis.horizontal,
+      padding: const EdgeInsets.fromLTRB(0.0, 34.0, 16.0, 44.0),
+      children: _buildColumns(context),
+      physics: const AlwaysScrollableScrollPhysics(),
+    );
+  }
+}
diff --git a/examples/flutter_gallery/lib/demo/shrine/supplemental/cut_corners_border.dart b/examples/flutter_gallery/lib/demo/shrine/supplemental/cut_corners_border.dart
new file mode 100644
index 0000000..687685b
--- /dev/null
+++ b/examples/flutter_gallery/lib/demo/shrine/supplemental/cut_corners_border.dart
@@ -0,0 +1,136 @@
+// Copyright 2018-present the Flutter authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'dart:ui' show lerpDouble;
+
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+
+class CutCornersBorder extends OutlineInputBorder {
+  const CutCornersBorder({
+    BorderSide borderSide = BorderSide.none,
+    BorderRadius borderRadius = const BorderRadius.all(Radius.circular(2.0)),
+    this.cut = 7.0,
+    double gapPadding = 2.0,
+  }) : super(
+    borderSide: borderSide,
+    borderRadius: borderRadius,
+    gapPadding: gapPadding,
+  );
+
+  @override
+  CutCornersBorder copyWith({
+    BorderSide borderSide,
+    BorderRadius borderRadius,
+    double gapPadding,
+    double cut,
+  }) {
+    return CutCornersBorder(
+      borderSide: borderSide ?? this.borderSide,
+      borderRadius: borderRadius ?? this.borderRadius,
+      gapPadding: gapPadding ?? this.gapPadding,
+      cut: cut ?? this.cut,
+    );
+  }
+
+  final double cut;
+
+  @override
+  ShapeBorder lerpFrom(ShapeBorder a, double t) {
+    if (a is CutCornersBorder) {
+      final CutCornersBorder outline = a;
+      return CutCornersBorder(
+        borderRadius: BorderRadius.lerp(outline.borderRadius, borderRadius, t),
+        borderSide: BorderSide.lerp(outline.borderSide, borderSide, t),
+        cut: cut,
+        gapPadding: outline.gapPadding,
+      );
+    }
+    return super.lerpFrom(a, t);
+  }
+
+  @override
+  ShapeBorder lerpTo(ShapeBorder b, double t) {
+    if (b is CutCornersBorder) {
+      final CutCornersBorder outline = b;
+      return CutCornersBorder(
+        borderRadius: BorderRadius.lerp(borderRadius, outline.borderRadius, t),
+        borderSide: BorderSide.lerp(borderSide, outline.borderSide, t),
+        cut: cut,
+        gapPadding: outline.gapPadding,
+      );
+    }
+    return super.lerpTo(b, t);
+  }
+
+  Path _notchedCornerPath(Rect center, [double start = 0.0, double extent = 0.0]) {
+    final Path path = Path();
+    if (start > 0.0 || extent > 0.0) {
+      path.relativeMoveTo(extent + start, center.top);
+      _notchedSidesAndBottom(center, path);
+      path..lineTo(center.left + cut, center.top)..lineTo(start, center.top);
+    } else {
+      path.moveTo(center.left + cut, center.top);
+      _notchedSidesAndBottom(center, path);
+      path.lineTo(center.left + cut, center.top);
+    }
+    return path;
+  }
+
+  Path _notchedSidesAndBottom(Rect center, Path path) {
+    return path
+      ..lineTo(center.right - cut, center.top)
+      ..lineTo(center.right, center.top + cut)
+      ..lineTo(center.right, center.top + center.height - cut)
+      ..lineTo(center.right - cut, center.top + center.height)
+      ..lineTo(center.left + cut, center.top + center.height)
+      ..lineTo(center.left, center.top + center.height - cut)
+      ..lineTo(center.left, center.top + cut);
+  }
+
+  @override
+  void paint(
+    Canvas canvas,
+    Rect rect, {
+    double gapStart,
+    double gapExtent = 0.0,
+    double gapPercentage = 0.0,
+    TextDirection textDirection,
+  }) {
+    assert(gapExtent != null);
+    assert(gapPercentage >= 0.0 && gapPercentage <= 1.0);
+
+    final Paint paint = borderSide.toPaint();
+    final RRect outer = borderRadius.toRRect(rect);
+    if (gapStart == null || gapExtent <= 0.0 || gapPercentage == 0.0) {
+      canvas.drawPath(_notchedCornerPath(outer.middleRect), paint);
+    } else {
+      final double extent = lerpDouble(0.0, gapExtent + gapPadding * 2.0, gapPercentage);
+      switch (textDirection) {
+        case TextDirection.rtl:
+          {
+            final Path path = _notchedCornerPath(outer.middleRect, gapStart + gapPadding - extent, extent);
+            canvas.drawPath(path, paint);
+            break;
+          }
+        case TextDirection.ltr:
+          {
+            final Path path = _notchedCornerPath(outer.middleRect, gapStart - gapPadding, extent);
+            canvas.drawPath(path, paint);
+            break;
+          }
+      }
+    }
+  }
+}
diff --git a/examples/flutter_gallery/lib/demo/shrine/supplemental/product_card.dart b/examples/flutter_gallery/lib/demo/shrine/supplemental/product_card.dart
new file mode 100644
index 0000000..2ac33e3
--- /dev/null
+++ b/examples/flutter_gallery/lib/demo/shrine/supplemental/product_card.dart
@@ -0,0 +1,98 @@
+// Copyright 2018-present the Flutter authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'package:flutter/material.dart';
+import 'package:intl/intl.dart';
+import 'package:scoped_model/scoped_model.dart';
+
+import 'package:flutter_gallery/demo/shrine/model/app_state_model.dart';
+import 'package:flutter_gallery/demo/shrine/model/product.dart';
+
+class ProductCard extends StatelessWidget {
+  const ProductCard({ this.imageAspectRatio = 33 / 49, this.product })
+      : assert(imageAspectRatio == null || imageAspectRatio > 0);
+
+  final double imageAspectRatio;
+  final Product product;
+
+  static const double kTextBoxHeight = 65.0;
+
+  @override
+  Widget build(BuildContext context) {
+    final NumberFormat formatter = NumberFormat.simpleCurrency(
+      decimalDigits: 0,
+      locale: Localizations.localeOf(context).toString(),
+    );
+
+    final ThemeData theme = Theme.of(context);
+
+    final Image imageWidget = Image.asset(
+      product.assetName,
+      package: product.assetPackage,
+      fit: BoxFit.cover,
+    );
+
+    return ScopedModelDescendant<AppStateModel>(
+      builder: (BuildContext context, Widget child, AppStateModel model) {
+        return GestureDetector(
+          onTap: () {
+            model.addProductToCart(product.id);
+            // TODO: Add Snackbar
+          },
+          child: child,
+        );
+      },
+      child: Stack(
+        children: <Widget>[
+          Column(
+            mainAxisAlignment: MainAxisAlignment.center,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: <Widget>[
+              AspectRatio(
+                aspectRatio: imageAspectRatio,
+                child: imageWidget,
+              ),
+              SizedBox(
+                height: kTextBoxHeight * MediaQuery.of(context).textScaleFactor,
+                width: 121.0,
+                child: Column(
+                  mainAxisAlignment: MainAxisAlignment.end,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  children: <Widget>[
+                    Text(
+                      product == null ? '' : product.name,
+                      style: theme.textTheme.button,
+                      softWrap: false,
+                      overflow: TextOverflow.ellipsis,
+                      maxLines: 1,
+                    ),
+                    const SizedBox(height: 4.0),
+                    Text(
+                      product == null ? '' : formatter.format(product.price),
+                      style: theme.textTheme.caption,
+                    ),
+                  ],
+                ),
+              ),
+            ],
+          ),
+          const Padding(
+            padding: EdgeInsets.all(16.0),
+            child: Icon(Icons.add_shopping_cart),
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/examples/flutter_gallery/lib/demo/shrine/supplemental/product_columns.dart b/examples/flutter_gallery/lib/demo/shrine/supplemental/product_columns.dart
new file mode 100644
index 0000000..6889716
--- /dev/null
+++ b/examples/flutter_gallery/lib/demo/shrine/supplemental/product_columns.dart
@@ -0,0 +1,85 @@
+// Copyright 2018-present the Flutter authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'package:flutter/material.dart';
+
+import 'package:flutter_gallery/demo/shrine/model/product.dart';
+import 'package:flutter_gallery/demo/shrine/supplemental/product_card.dart';
+
+class TwoProductCardColumn extends StatelessWidget {
+  const TwoProductCardColumn({
+    @required this.bottom,
+    this.top,
+  }) : assert(bottom != null);
+
+  final Product bottom, top;
+
+  @override
+  Widget build(BuildContext context) {
+    return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
+      const double spacerHeight = 44.0;
+
+      final double heightOfCards = (constraints.biggest.height - spacerHeight) / 2.0;
+      final double heightOfImages = heightOfCards - ProductCard.kTextBoxHeight;
+      final double imageAspectRatio = (heightOfImages >= 0.0 && constraints.biggest.width > heightOfImages)
+        ? constraints.biggest.width / heightOfImages
+        : 33 / 49;
+
+      return ListView(
+        children: <Widget>[
+          Padding(
+            padding: const EdgeInsetsDirectional.only(start: 28.0),
+            child: top != null
+              ? ProductCard(
+                  imageAspectRatio: imageAspectRatio,
+                  product: top,
+                )
+              : SizedBox(
+                  height: heightOfCards > 0 ? heightOfCards : spacerHeight,
+                ),
+          ),
+          const SizedBox(height: spacerHeight),
+          Padding(
+            padding: const EdgeInsetsDirectional.only(end: 28.0),
+            child: ProductCard(
+              imageAspectRatio: imageAspectRatio,
+              product: bottom,
+            ),
+          ),
+        ],
+      );
+    });
+  }
+}
+
+class OneProductCardColumn extends StatelessWidget {
+  const OneProductCardColumn({this.product});
+
+  final Product product;
+
+  @override
+  Widget build(BuildContext context) {
+    return ListView(
+      reverse: true,
+      children: <Widget>[
+        const SizedBox(
+          height: 40.0,
+        ),
+        ProductCard(
+          product: product,
+        ),
+      ],
+    );
+  }
+}
diff --git a/examples/flutter_gallery/lib/demo/shrine_demo.dart b/examples/flutter_gallery/lib/demo/shrine_demo.dart
index 24cd2d8..6c58ecd 100644
--- a/examples/flutter_gallery/lib/demo/shrine_demo.dart
+++ b/examples/flutter_gallery/lib/demo/shrine_demo.dart
@@ -3,40 +3,13 @@
 // found in the LICENSE file.
 
 import 'package:flutter/material.dart';
-
-import 'shrine/shrine_home.dart' show ShrineHome;
-import 'shrine/shrine_theme.dart' show ShrineTheme;
-
-// This code would ordinarily be part of the MaterialApp's home. It's being
-// used by the ShrineDemo and by each route pushed from there because this
-// isn't a standalone app with its own main() and MaterialApp.
-Widget buildShrine(BuildContext context, Widget child) {
-  return Theme(
-    data: ThemeData(
-      primarySwatch: Colors.grey,
-      iconTheme: const IconThemeData(color: Color(0xFF707070)),
-      platform: Theme.of(context).platform,
-    ),
-    child: ShrineTheme(child: child)
-  );
-}
-
-// In a standalone version of this app, MaterialPageRoute<T> could be used directly.
-class ShrinePageRoute<T> extends MaterialPageRoute<T> {
-  ShrinePageRoute({
-    WidgetBuilder builder,
-    RouteSettings settings,
-  }) : super(builder: builder, settings: settings);
-
-  @override
-  Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
-    return buildShrine(context, super.buildPage(context, animation, secondaryAnimation));
-  }
-}
+import 'package:flutter_gallery/demo/shrine/app.dart';
 
 class ShrineDemo extends StatelessWidget {
+  const ShrineDemo({ Key key }) : super(key: key);
+
   static const String routeName = '/shrine'; // Used by the Gallery app.
 
   @override
-  Widget build(BuildContext context) => buildShrine(context, ShrineHome());
+  Widget build(BuildContext context) => ShrineApp();
 }
diff --git a/examples/flutter_gallery/lib/gallery/app.dart b/examples/flutter_gallery/lib/gallery/app.dart
index f1c6d71..2d364d8 100644
--- a/examples/flutter_gallery/lib/gallery/app.dart
+++ b/examples/flutter_gallery/lib/gallery/app.dart
@@ -7,6 +7,8 @@
 import 'package:flutter/foundation.dart' show defaultTargetPlatform;
 import 'package:flutter/material.dart';
 import 'package:flutter/scheduler.dart' show timeDilation;
+import 'package:flutter_gallery/demo/shrine/model/app_state_model.dart';
+import 'package:scoped_model/scoped_model.dart';
 
 import 'package:url_launcher/url_launcher.dart';
 
@@ -42,6 +44,7 @@
 class _GalleryAppState extends State<GalleryApp> {
   GalleryOptions _options;
   Timer _timeDilationTimer;
+  AppStateModel model;
 
   Map<String, WidgetBuilder> _buildRoutes() {
     // For a different example of how to set up an application routing table
@@ -63,6 +66,7 @@
       timeDilation: timeDilation,
       platform: defaultTargetPlatform,
     );
+    model = AppStateModel()..loadProducts();
   }
 
   @override
@@ -125,22 +129,24 @@
         child: home,
       );
     }
-
-    return MaterialApp(
-      theme: _options.theme.data.copyWith(platform: _options.platform),
-      title: 'Flutter Gallery',
-      color: Colors.grey,
-      showPerformanceOverlay: _options.showPerformanceOverlay,
-      checkerboardOffscreenLayers: _options.showOffscreenLayersCheckerboard,
-      checkerboardRasterCacheImages: _options.showRasterCacheImagesCheckerboard,
-      routes: _buildRoutes(),
-      builder: (BuildContext context, Widget child) {
-        return Directionality(
-          textDirection: _options.textDirection,
-          child: _applyTextScaleFactor(child),
-        );
-      },
-      home: home,
+    return ScopedModel<AppStateModel>(
+      model: model,
+      child: MaterialApp(
+        theme: _options.theme.data.copyWith(platform: _options.platform),
+        title: 'Flutter Gallery',
+        color: Colors.grey,
+        showPerformanceOverlay: _options.showPerformanceOverlay,
+        checkerboardOffscreenLayers: _options.showOffscreenLayersCheckerboard,
+        checkerboardRasterCacheImages: _options.showRasterCacheImagesCheckerboard,
+        routes: _buildRoutes(),
+        builder: (BuildContext context, Widget child) {
+          return Directionality(
+            textDirection: _options.textDirection,
+            child: _applyTextScaleFactor(child),
+          );
+        },
+        home: home,
+      ),
     );
   }
 }
diff --git a/examples/flutter_gallery/lib/gallery/demos.dart b/examples/flutter_gallery/lib/gallery/demos.dart
index 0b18552..3f7a891 100644
--- a/examples/flutter_gallery/lib/gallery/demos.dart
+++ b/examples/flutter_gallery/lib/gallery/demos.dart
@@ -93,7 +93,7 @@
       icon: GalleryIcons.shrine,
       category: _kDemos,
       routeName: ShrineDemo.routeName,
-      buildRoute: (BuildContext context) => ShrineDemo(),
+      buildRoute: (BuildContext context) => const ShrineDemo(),
     ),
     GalleryDemo(
       title: 'Contact profile',
diff --git a/examples/flutter_gallery/pubspec.yaml b/examples/flutter_gallery/pubspec.yaml
index 4c2bd6f..e6b5c39 100644
--- a/examples/flutter_gallery/pubspec.yaml
+++ b/examples/flutter_gallery/pubspec.yaml
@@ -15,6 +15,8 @@
   url_launcher: 4.0.1
   cupertino_icons: 0.1.2
   video_player: 0.7.2
+  scoped_model: 0.3.0
+  shrine_images: 1.1.0
 
   # Also update dev/benchmarks/complex_layout/pubspec.yaml
   flutter_gallery_assets: 0.1.6
@@ -34,7 +36,7 @@
   flutter_goldens:
     sdk: flutter
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -42,7 +44,7 @@
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   file: 5.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -51,7 +53,7 @@
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -64,7 +66,7 @@
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   process: 3.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -147,6 +149,46 @@
     - packages/flutter_gallery_assets/people/square/sandra.png
     - packages/flutter_gallery_assets/people/square/stella.png
     - packages/flutter_gallery_assets/people/square/trevor.png
+    - packages/shrine_images/diamond.png
+    - packages/shrine_images/slanted_menu.png
+    - packages/shrine_images/0-0.jpg
+    - packages/shrine_images/1-0.jpg
+    - packages/shrine_images/2-0.jpg
+    - packages/shrine_images/3-0.jpg
+    - packages/shrine_images/4-0.jpg
+    - packages/shrine_images/5-0.jpg
+    - packages/shrine_images/6-0.jpg
+    - packages/shrine_images/7-0.jpg
+    - packages/shrine_images/8-0.jpg
+    - packages/shrine_images/9-0.jpg
+    - packages/shrine_images/10-0.jpg
+    - packages/shrine_images/11-0.jpg
+    - packages/shrine_images/12-0.jpg
+    - packages/shrine_images/13-0.jpg
+    - packages/shrine_images/14-0.jpg
+    - packages/shrine_images/15-0.jpg
+    - packages/shrine_images/16-0.jpg
+    - packages/shrine_images/17-0.jpg
+    - packages/shrine_images/18-0.jpg
+    - packages/shrine_images/19-0.jpg
+    - packages/shrine_images/20-0.jpg
+    - packages/shrine_images/21-0.jpg
+    - packages/shrine_images/22-0.jpg
+    - packages/shrine_images/23-0.jpg
+    - packages/shrine_images/24-0.jpg
+    - packages/shrine_images/25-0.jpg
+    - packages/shrine_images/26-0.jpg
+    - packages/shrine_images/27-0.jpg
+    - packages/shrine_images/28-0.jpg
+    - packages/shrine_images/29-0.jpg
+    - packages/shrine_images/30-0.jpg
+    - packages/shrine_images/31-0.jpg
+    - packages/shrine_images/32-0.jpg
+    - packages/shrine_images/33-0.jpg
+    - packages/shrine_images/34-0.jpg
+    - packages/shrine_images/35-0.jpg
+    - packages/shrine_images/36-0.jpg
+    - packages/shrine_images/37-0.jpg
   fonts:
     - family: Raleway
       fonts:
@@ -196,4 +238,4 @@
         - asset: packages/flutter_gallery_assets/fonts/private/googlesans/GoogleSansDisplay-Regular.ttf
           weight: 400
 
-# PUBSPEC CHECKSUM: 0fd2
+# PUBSPEC CHECKSUM: 351b
diff --git a/examples/hello_world/pubspec.yaml b/examples/hello_world/pubspec.yaml
index 8d30d42..29dcfd3 100644
--- a/examples/hello_world/pubspec.yaml
+++ b/examples/hello_world/pubspec.yaml
@@ -17,7 +17,7 @@
   flutter_test:
     sdk: flutter
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -25,7 +25,7 @@
   convert: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -34,7 +34,7 @@
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -46,7 +46,7 @@
   plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -68,4 +68,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: e771
+# PUBSPEC CHECKSUM: 53cf
diff --git a/examples/layers/pubspec.yaml b/examples/layers/pubspec.yaml
index 7a1f0d2..131921f 100644
--- a/examples/layers/pubspec.yaml
+++ b/examples/layers/pubspec.yaml
@@ -17,7 +17,7 @@
   flutter_test:
     sdk: flutter
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -25,7 +25,7 @@
   convert: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -34,7 +34,7 @@
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -46,7 +46,7 @@
   plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -70,4 +70,4 @@
     - services/data.json
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: e771
+# PUBSPEC CHECKSUM: 53cf
diff --git a/examples/platform_channel/pubspec.yaml b/examples/platform_channel/pubspec.yaml
index e6fe6d2..63fa9fe 100644
--- a/examples/platform_channel/pubspec.yaml
+++ b/examples/platform_channel/pubspec.yaml
@@ -19,7 +19,7 @@
   flutter_driver:
     sdk: flutter
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -28,7 +28,7 @@
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   file: 5.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -38,7 +38,7 @@
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -50,7 +50,7 @@
   plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -72,4 +72,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: 27a2
+# PUBSPEC CHECKSUM: 3901
diff --git a/examples/platform_channel_swift/pubspec.yaml b/examples/platform_channel_swift/pubspec.yaml
index a5c5406..b4befd0 100644
--- a/examples/platform_channel_swift/pubspec.yaml
+++ b/examples/platform_channel_swift/pubspec.yaml
@@ -19,7 +19,7 @@
   flutter_driver:
     sdk: flutter
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -28,7 +28,7 @@
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   file: 5.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -38,7 +38,7 @@
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -50,7 +50,7 @@
   plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -72,4 +72,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: 27a2
+# PUBSPEC CHECKSUM: 3901
diff --git a/examples/stocks/pubspec.yaml b/examples/stocks/pubspec.yaml
index a6806b8..4561cc5 100644
--- a/examples/stocks/pubspec.yaml
+++ b/examples/stocks/pubspec.yaml
@@ -14,7 +14,7 @@
   http: 0.12.0
   isolate: 2.0.2
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   charcode: 1.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -23,11 +23,11 @@
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   dart_style: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -61,7 +61,7 @@
   package_resolver: 1.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -78,4 +78,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: 8bbb
+# PUBSPEC CHECKSUM: af1a
diff --git a/packages/flutter/lib/src/animation/tween_sequence.dart b/packages/flutter/lib/src/animation/tween_sequence.dart
index 1ff8861..78fcfd1 100644
--- a/packages/flutter/lib/src/animation/tween_sequence.dart
+++ b/packages/flutter/lib/src/animation/tween_sequence.dart
@@ -82,6 +82,9 @@
     assert(false, 'TweenSequence.evaluate() could not find a interval for $t');
     return null;
   }
+
+  @override
+  String toString() => 'TweenSequence(${_items.length} items)';
 }
 
 /// A simple holder for one element of a [TweenSequence].
diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml
index b30fa41..2a7b03c 100644
--- a/packages/flutter/pubspec.yaml
+++ b/packages/flutter/pubspec.yaml
@@ -24,7 +24,7 @@
     sdk: flutter
   mockito: 3.0.0
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -33,7 +33,7 @@
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   file: 5.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -43,7 +43,7 @@
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -57,7 +57,7 @@
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   process: 3.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -76,4 +76,4 @@
   web_socket_channel: 1.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   yaml: 2.1.15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
 
-# PUBSPEC CHECKSUM: 23ea
+# PUBSPEC CHECKSUM: 7849
diff --git a/packages/flutter_driver/pubspec.yaml b/packages/flutter_driver/pubspec.yaml
index e5f4e62..a279306 100644
--- a/packages/flutter_driver/pubspec.yaml
+++ b/packages/flutter_driver/pubspec.yaml
@@ -21,7 +21,7 @@
   fuchsia_remote_debug_protocol:
     sdk: flutter
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -30,7 +30,7 @@
   convert: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -39,7 +39,7 @@
   intl: 0.15.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -72,6 +72,6 @@
 dev_dependencies:
   test: 1.3.4
   mockito: 3.0.0
-  quiver: 2.0.0+1
+  quiver: 2.0.1
 
-# PUBSPEC CHECKSUM: 23ea
+# PUBSPEC CHECKSUM: 7849
diff --git a/packages/flutter_goldens/pubspec.yaml b/packages/flutter_goldens/pubspec.yaml
index 40e0777..a067942 100644
--- a/packages/flutter_goldens/pubspec.yaml
+++ b/packages/flutter_goldens/pubspec.yaml
@@ -16,7 +16,7 @@
   flutter_goldens_client:
     path: ../flutter_goldens_client
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -24,7 +24,7 @@
   convert: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -34,7 +34,7 @@
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -46,7 +46,7 @@
   plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -70,4 +70,4 @@
 dev_dependencies:
   mockito: 3.0.0
 
-# PUBSPEC CHECKSUM: 23ea
+# PUBSPEC CHECKSUM: 7849
diff --git a/packages/flutter_localizations/pubspec.yaml b/packages/flutter_localizations/pubspec.yaml
index 2c52973..a0ed455 100644
--- a/packages/flutter_localizations/pubspec.yaml
+++ b/packages/flutter_localizations/pubspec.yaml
@@ -22,7 +22,7 @@
     sdk: flutter
   mockito: 3.0.0
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -30,7 +30,7 @@
   convert: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -39,7 +39,7 @@
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -50,7 +50,7 @@
   plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -69,4 +69,4 @@
   web_socket_channel: 1.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   yaml: 2.1.15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
 
-# PUBSPEC CHECKSUM: 5df1
+# PUBSPEC CHECKSUM: cc50
diff --git a/packages/flutter_test/pubspec.yaml b/packages/flutter_test/pubspec.yaml
index 9a1cbcf..469dfb3 100644
--- a/packages/flutter_test/pubspec.yaml
+++ b/packages/flutter_test/pubspec.yaml
@@ -19,7 +19,7 @@
   path: 1.6.2
 
   # We use FakeAsync and other testing utilities.
-  quiver: 2.0.0+1
+  quiver: 2.0.1
 
   # We import stack_trace because the test packages uses it and we
   # need to be able to unmangle the stack traces that it passed to
@@ -29,7 +29,7 @@
   # Used by globalToLocal et al.
   vector_math: 2.0.8
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -38,7 +38,7 @@
   convert: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -47,7 +47,7 @@
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -81,4 +81,4 @@
 
   intl: 0.15.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
 
-# PUBSPEC CHECKSUM: 27a2
+# PUBSPEC CHECKSUM: 3901
diff --git a/packages/flutter_tools/pubspec.yaml b/packages/flutter_tools/pubspec.yaml
index f8d1c94..305a587 100644
--- a/packages/flutter_tools/pubspec.yaml
+++ b/packages/flutter_tools/pubspec.yaml
@@ -9,7 +9,7 @@
 
 dependencies:
   # To update these, use "flutter update-packages --force-upgrade".
-  analyzer: 0.33.0
+  analyzer: 0.33.1
   archive: 2.0.4
   args: 1.5.0
   cli_util: 0.1.3+2
@@ -28,7 +28,7 @@
   platform: 2.2.0
   plugin: 0.2.0+3
   process: 3.0.5
-  quiver: 2.0.0+1
+  quiver: 2.0.1
   stack_trace: 1.9.3
   stream_channel: 1.6.8
   usage: 3.4.1
@@ -50,14 +50,14 @@
   convert: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   dart2_constant: 1.0.2+dart2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http_multi_server: 2.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -90,4 +90,4 @@
   # Exclude this package from the hosted API docs.
   nodoc: true
 
-# PUBSPEC CHECKSUM: c4f6
+# PUBSPEC CHECKSUM: dd55
diff --git a/packages/fuchsia_remote_debug_protocol/pubspec.yaml b/packages/fuchsia_remote_debug_protocol/pubspec.yaml
index 8f71f37..c8ffbd6 100644
--- a/packages/fuchsia_remote_debug_protocol/pubspec.yaml
+++ b/packages/fuchsia_remote_debug_protocol/pubspec.yaml
@@ -16,7 +16,7 @@
   flutter_driver:
     sdk: flutter
 
-  analyzer: 0.33.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  analyzer: 0.33.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   args: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -26,7 +26,7 @@
   crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   file: 5.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  front_end: 0.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   http: 0.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -35,7 +35,7 @@
   intl: 0.15.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  kernel: 0.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.6+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -49,7 +49,7 @@
   plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pool: 1.3.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  quiver: 2.0.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -72,4 +72,4 @@
   mockito: 3.0.0
   test: 1.3.4
 
-# PUBSPEC CHECKSUM: 23ea
+# PUBSPEC CHECKSUM: 7849