diff --git a/.gitignore b/.gitignore index 9d7edcf..bd504c0 100644 --- a/.gitignore +++ b/.gitignore @@ -68,3 +68,4 @@ build/ !**/ios/**/default.pbxuser !**/ios/**/default.perspectivev3 !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages +pubspec.lock \ No newline at end of file diff --git a/README.md b/README.md index ae1b8f5..7898cd0 100644 --- a/README.md +++ b/README.md @@ -127,11 +127,69 @@ to display the previously selected location. void showPlacePicker() async { LocationResult result = await Navigator.of(context).push(MaterialPageRoute( builder: (context) => - PlacePicker("YOUR API KEY", - displayLocation: customLocation, - ))); - - // Handle the result in your way - print(result); + PlacePicker( + "YOUR_API_KEY", + displayLocation: LatLng(33.2, 66.4), + localizationItem: LocalizationItem(languageCode: "fa_IR"), + searchBarOptions: SearchBarOptions( + padding: EdgeInsets.zero, + backgroundColor: Colors.white, + elevation: 2, + overlyTopPadding: + MediaQuery.of(context).padding.top + kToolbarHeight, + searchIcon: Icon( + Feather.search, + color: Colors.red, + ), + clearTextIcon: Icon( + AntDesign.close, + color: Colors.red, + ), + inputDecoration: InputDecoration( + hintText: "Search Place", + border: InputBorder.none, + hintStyle: TextStyle(), + ), + // height: 50, + searchIconPadding: + EdgeInsets.symmetric(horizontal: 16, vertical: 4), + clearTextIconPadding: + EdgeInsets.symmetric(horizontal: 16, vertical: 4), + decoration: BoxDecoration( + // color: Colors.white, + ), + ), + //searchAutoCompletLoadingBuilder: () => Material( + // child: SizedBox( + // height: 50, + // width: 50, + // child: Center(child: CircularProgressIndicator()), + // ), + //), + //bottomResultWidgetBuilder: (_, __, ___, h, _____) => SizedBox( + // height: h / 4, + //), + //searchAutoCompleteItemBuilder: (a, b) => GestureDetector( + // onTap: b, + //child: Text( + // a.text, + // ), + //), + //searchAutoCompleteBuilder: (list) => Material( + // elevation: 1, + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: list, + // ), + //), + mapOptions: MapOptions( + myLocationButtonEnabled: true, + ), + ), + ), + ); + + // Handle the result in your way + print(result); } ``` diff --git a/lib/entities/map_options.dart b/lib/entities/map_options.dart new file mode 100644 index 0000000..1ac68ff --- /dev/null +++ b/lib/entities/map_options.dart @@ -0,0 +1,29 @@ +import 'package:google_maps_flutter/google_maps_flutter.dart'; + +class MapOptions { + ///this will override the displyLocation of google maps. + final CameraPosition? initialCameraPosition; + final bool? compassEnabled; + final bool? mapToolbarEnabled; + final bool? scrollGestureEnabled; + final bool? myLocationEnabled; + final bool? myLocationButtonEnabled; + final bool? zoomControllEnabled; + final bool? zoomGestureEnabled; + final bool? rotateGestureEnabled; + final BitmapDescriptor? markerIcon; + final MapType? mapType; + MapOptions({ + this.initialCameraPosition, + this.compassEnabled, + this.mapToolbarEnabled, + this.scrollGestureEnabled, + this.myLocationEnabled, + this.myLocationButtonEnabled, + this.zoomControllEnabled, + this.markerIcon, + this.mapType, + this.rotateGestureEnabled, + this.zoomGestureEnabled, + }); +} diff --git a/lib/entities/search_bar_options_model.dart b/lib/entities/search_bar_options_model.dart new file mode 100644 index 0000000..98c0e4d --- /dev/null +++ b/lib/entities/search_bar_options_model.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; + +class SearchBarOptions { + ///To Wrap search bar with padding + final EdgeInsetsGeometry? padding; + + ///Search icon padding + final EdgeInsetsGeometry? searchIconPadding; + + ///clear Text button icon padding + final EdgeInsetsGeometry? clearTextIconPadding; + + ///A background color to set if the search bar hasPadding + final Color? backgroundColor; + + ///elavtion of Searchbar in case for example you add a transparetnt background color to searchbar + final double? elevation; + + ///This is used to add extra space on top of autosuggestion. + ///This is usefull for example when you use PlacePicker inside another Scaffold which has appbar + /// + ///Simple Usage: `overlyTopPadding: MediaQuery.of(context).padding.top + kToolbarHeight,` + final double? overlyTopPadding; + + ///Search Bar height, + final double? height; + + ///Icon for SearchBar + final Widget? searchIcon; + + ///Icon for clear text button + final Widget? clearTextIcon; + + ///Decoration to apply to search input + final InputDecoration? inputDecoration; + + ///Decoration for searchbar + final Decoration? decoration; + + const SearchBarOptions({ + this.padding, + this.backgroundColor, + this.elevation, + this.clearTextIcon, + this.overlyTopPadding, + this.searchIcon, + this.inputDecoration, + this.searchIconPadding, + this.decoration, + this.height, + this.clearTextIconPadding, + }); +} diff --git a/lib/place_picker.dart b/lib/place_picker.dart index c73ab89..59a8e0c 100644 --- a/lib/place_picker.dart +++ b/lib/place_picker.dart @@ -1,3 +1,6 @@ export 'widgets/widgets.dart'; export 'entities/entities.dart'; export 'package:google_maps_flutter/google_maps_flutter.dart' show LatLng; +export 'entities/search_bar_options_model.dart'; +export 'entities/map_options.dart'; +export 'package:google_maps_flutter/google_maps_flutter.dart'; diff --git a/lib/widgets/place_picker.dart b/lib/widgets/place_picker.dart index 6b31169..a29389c 100644 --- a/lib/widgets/place_picker.dart +++ b/lib/widgets/place_picker.dart @@ -7,8 +7,10 @@ import 'package:location/location.dart'; import 'package:http/http.dart' as http; import 'package:place_picker/entities/entities.dart'; import 'package:place_picker/entities/localization_item.dart'; +import 'package:place_picker/entities/map_options.dart'; import 'package:place_picker/widgets/widgets.dart'; +import '../place_picker.dart'; import '../uuid.dart'; /// Place picker widget made with map widget from @@ -27,7 +29,60 @@ class PlacePicker extends StatefulWidget { final LatLng? displayLocation; LocalizationItem? localizationItem; - PlacePicker(this.apiKey, {this.displayLocation, this.localizationItem}) { + ///SeachBar customization + final SearchBarOptions? searchBarOptions; + + ///This is used to create your own widget while as loading of autocomplete of search + /// + final Widget Function()? searchAutoCompletLoadingBuilder; + + ///This is used to create your own Widget to show at the buttom of Map + /// + ///Paramters: [locationName, locationResult, nearbyPlaces, maxHeight, selectPlace] + /// + ///__maxHeight includes the height of Map as well. be carefull__ + final Widget Function( + String locationName, + LocationResult? locationResult, + List nearbyPlaces, + double maxHeight, + VoidCallback selectPlace, + )? bottomResultWidgetBuilder; + + ///This is used to create your own layout for each item in auto complete while searching a place. + /// + final Widget Function( + AutoCompleteItem autoCompleteItem, + VoidCallback onTap, + )? searchAutoCompleteItemBuilder; + + ///This is used to create your own layout for autocomplete suggestion. + ///each item in + ///`List` + /// can be built using [searchAutoCompleteBuilder] + ///default is `Material(elevation: 1, child: Column(children: suggestions))`, + final Widget Function( + List itemList, + )? searchAutoCompleteBuilder; + + ///More map options to change + MapOptions? mapOptions; + + //custom Icon for mylocation button + Widget? myLocationIcon; + + PlacePicker( + this.apiKey, { + this.displayLocation, + this.localizationItem, + this.searchBarOptions, + this.searchAutoCompletLoadingBuilder, + this.bottomResultWidgetBuilder, + this.searchAutoCompleteItemBuilder, + this.searchAutoCompleteBuilder, + this.mapOptions, + this.myLocationIcon, + }) { if (this.localizationItem == null) { this.localizationItem = new LocalizationItem(); } @@ -60,6 +115,8 @@ class PlacePickerState extends State { bool hasSearchTerm = false; String previousSearchTerm = ''; + Location _location = Location(); + LocationData? _locationData; // constructor PlacePickerState(); @@ -80,9 +137,17 @@ class PlacePickerState extends State { void initState() { super.initState(); markers.add(Marker( - position: widget.displayLocation ?? LatLng(5.6037, 0.1870), + position: widget.mapOptions?.initialCameraPosition?.target ?? + widget.displayLocation ?? + LatLng(5.6037, 0.1870), markerId: MarkerId("selected-location"), + icon: widget.mapOptions?.markerIcon ?? BitmapDescriptor.defaultMarker, )); + _location.getLocation().then((value) { + setState(() { + _locationData = value; + }); + }); } @override @@ -96,54 +161,148 @@ class PlacePickerState extends State { return Scaffold( appBar: AppBar( key: this.appBarKey, - title: SearchInput(searchPlace), + backgroundColor: widget.searchBarOptions?.backgroundColor, + elevation: widget.searchBarOptions?.elevation, + title: Padding( + padding: widget.searchBarOptions?.padding ?? + EdgeInsets.symmetric(horizontal: 16), + child: SearchInput( + searchPlace, + searchBarOptions: widget.searchBarOptions, + ), + ), centerTitle: true, automaticallyImplyLeading: false, + + //we use this because we now have padding + titleSpacing: 0, + toolbarHeight: widget.searchBarOptions?.height, ), - body: Column( - children: [ - Expanded( - child: GoogleMap( - initialCameraPosition: CameraPosition( - target: widget.displayLocation ?? LatLng(5.6037, 0.1870), - zoom: 15, - ), - myLocationButtonEnabled: true, - myLocationEnabled: true, - onMapCreated: onMapCreated, - onTap: (latLng) { - clearOverlay(); - moveToLocation(latLng); - }, - markers: markers, - ), - ), - if (!this.hasSearchTerm) - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + body: Stack( + alignment: Alignment.center, + children: [ + LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + return Column( children: [ - SelectPlaceAction( - getLocationName(), - () => Navigator.of(context).pop(this.locationResult), - widget.localizationItem!.tapToSelectLocation), - Divider(height: 8), - Padding( - child: Text(widget.localizationItem!.nearBy, - style: TextStyle(fontSize: 16)), - padding: EdgeInsets.symmetric(horizontal: 24, vertical: 8), - ), Expanded( - child: ListView( - children: nearbyPlaces - .map((it) => NearbyPlaceItem( - it, () => moveToLocation(it.latLng!))) - .toList(), + child: GoogleMap( + initialCameraPosition: + widget.mapOptions?.initialCameraPosition ?? + CameraPosition( + target: widget.displayLocation ?? + LatLng(5.6037, 0.1870), + zoom: 15, + ), + myLocationButtonEnabled: false, + myLocationEnabled: false, + onMapCreated: onMapCreated, + compassEnabled: widget.mapOptions?.compassEnabled ?? true, + mapToolbarEnabled: + widget.mapOptions?.mapToolbarEnabled ?? true, + scrollGesturesEnabled: + widget.mapOptions?.scrollGestureEnabled ?? true, + zoomControlsEnabled: + widget.mapOptions?.zoomControllEnabled ?? true, + zoomGesturesEnabled: + widget.mapOptions?.zoomGestureEnabled ?? true, + rotateGesturesEnabled: + widget.mapOptions?.rotateGestureEnabled ?? true, + mapType: widget.mapOptions?.mapType ?? MapType.normal, + onTap: (latLng) { + clearOverlay(); + moveToLocation(latLng); + }, + markers: markers, ), ), + if (!this.hasSearchTerm) + SizedBox( + //user can set height of the bottom result from [maxHeight] of [widget.bottomResultWidgetBilder] + height: widget.bottomResultWidgetBuilder != null + ? null + : constraints.maxHeight / 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [] + ..addAll(widget.bottomResultWidgetBuilder != null + ? [ + widget.bottomResultWidgetBuilder!( + getLocationName(), + this.locationResult, + nearbyPlaces, + constraints.maxHeight, + () => Navigator.of(context) + .pop(this.locationResult), + ) + ] + : [ + SelectPlaceAction( + getLocationName(), + () => Navigator.of(context) + .pop(this.locationResult), + widget.localizationItem! + .tapToSelectLocation), + Divider(height: 8), + Padding( + child: Text( + widget.localizationItem!.nearBy, + style: TextStyle(fontSize: 16)), + padding: EdgeInsets.symmetric( + horizontal: 24, vertical: 8), + ), + Expanded( + child: ListView( + children: nearbyPlaces + .map((it) => NearbyPlaceItem( + it, + () => + moveToLocation(it.latLng!))) + .toList(), + ), + ), + ])), + ), ], - ), - ), + ); + }, + ), + () { + if (widget.mapOptions?.myLocationButtonEnabled != null && + widget.mapOptions?.myLocationButtonEnabled == true) { + print( + "User Lat,Lon: ${_locationData?.latitude}, ${_locationData?.longitude}"); + return Positioned.directional( + top: 20, + start: 10, + textDirection: Directionality.of(context), + child: Material( + elevation: 2, + child: InkWell( + onTap: _locationData != null + ? () { + // setState(() { + // _locationData = null; + // }); + clearOverlay(); + moveToLocation(LatLng(_locationData!.latitude!, + _locationData!.longitude!)); + } + : null, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: widget.myLocationIcon ?? + Icon( + Icons.my_location_sharp, + size: 22, + ), + ), + ), + ), + ); + } + return SizedBox(); + }(), ], ), ); @@ -192,26 +351,29 @@ class PlacePickerState extends State { this.overlayEntry = OverlayEntry( builder: (context) => Positioned( - top: appBarBox!.size.height, + top: appBarBox!.size.height + + (widget.searchBarOptions?.overlyTopPadding ?? 0.0), width: size.width, - child: Material( - elevation: 1, - child: Container( - padding: EdgeInsets.symmetric(vertical: 16, horizontal: 24), - child: Row( - children: [ - SizedBox( - height: 24, - width: 24, - child: CircularProgressIndicator(strokeWidth: 3)), - SizedBox(width: 24), - Expanded( - child: Text(widget.localizationItem!.findingPlace, - style: TextStyle(fontSize: 16))) - ], - ), - ), - ), + child: widget.searchAutoCompletLoadingBuilder != null + ? widget.searchAutoCompletLoadingBuilder!() + : Material( + elevation: 1, + child: Container( + padding: EdgeInsets.symmetric(vertical: 16, horizontal: 24), + child: Row( + children: [ + SizedBox( + height: 24, + width: 24, + child: CircularProgressIndicator(strokeWidth: 3)), + SizedBox(width: 24), + Expanded( + child: Text(widget.localizationItem!.findingPlace, + style: TextStyle(fontSize: 16))) + ], + ), + ), + ), ), ); @@ -258,7 +420,11 @@ class PlacePickerState extends State { aci.offset = 0; aci.length = 0; - suggestions.add(RichSuggestion(aci, () {})); + suggestions.add(RichSuggestion( + aci, + () {}, + autoCompleteItemBuilder: null, + )); } else { for (dynamic t in predictions) { final aci = AutoCompleteItem() @@ -267,10 +433,14 @@ class PlacePickerState extends State { ..offset = t['matched_substrings'][0]['offset'] ..length = t['matched_substrings'][0]['length']; - suggestions.add(RichSuggestion(aci, () { - FocusScope.of(context).requestFocus(FocusNode()); - decodeAndSelectPlace(aci.id); - })); + suggestions.add(RichSuggestion( + aci, + () { + FocusScope.of(context).requestFocus(FocusNode()); + decodeAndSelectPlace(aci.id); + }, + autoCompleteItemBuilder: widget.searchAutoCompleteItemBuilder, + )); } } @@ -324,8 +494,11 @@ class PlacePickerState extends State { this.overlayEntry = OverlayEntry( builder: (context) => Positioned( width: size.width, - top: appBarBox!.size.height, - child: Material(elevation: 1, child: Column(children: suggestions)), + top: appBarBox!.size.height + + (widget.searchBarOptions?.overlyTopPadding ?? 0.0), + child: widget.searchAutoCompleteBuilder != null + ? widget.searchAutoCompleteBuilder!(suggestions) + : Material(elevation: 1, child: Column(children: suggestions)), ), ); @@ -358,8 +531,11 @@ class PlacePickerState extends State { // markers.clear(); setState(() { markers.clear(); - markers.add( - Marker(markerId: MarkerId("selected-location"), position: latLng)); + markers.add(Marker( + markerId: MarkerId("selected-location"), + position: widget.mapOptions?.initialCameraPosition?.target ?? latLng, + icon: + widget.mapOptions?.markerIcon ?? BitmapDescriptor.defaultMarker)); }); } diff --git a/lib/widgets/rich_suggestion.dart b/lib/widgets/rich_suggestion.dart index 3b27c75..012e59e 100644 --- a/lib/widgets/rich_suggestion.dart +++ b/lib/widgets/rich_suggestion.dart @@ -4,38 +4,50 @@ import 'package:place_picker/entities/entities.dart'; class RichSuggestion extends StatelessWidget { final VoidCallback onTap; final AutoCompleteItem autoCompleteItem; - - RichSuggestion(this.autoCompleteItem, this.onTap); + final Widget Function( + AutoCompleteItem autoCompleteItem, + VoidCallback onTap, + )? autoCompleteItemBuilder; + RichSuggestion(this.autoCompleteItem, this.onTap, + {this.autoCompleteItemBuilder}); @override Widget build(BuildContext context) { - return Material( - child: InkWell( - child: Container( - padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16), - child: RichText(text: TextSpan(children: getStyledTexts(context))), - ), - onTap: onTap, - ), - ); + return autoCompleteItemBuilder != null + ? autoCompleteItemBuilder!(autoCompleteItem, onTap) + : Material( + child: InkWell( + child: Container( + padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16), + child: + RichText(text: TextSpan(children: getStyledTexts(context))), + ), + onTap: onTap, + ), + ); } List getStyledTexts(BuildContext context) { final List result = []; final style = TextStyle(color: Colors.grey, fontSize: 15); - final startText = autoCompleteItem.text!.substring(0, autoCompleteItem.offset); + final startText = + autoCompleteItem.text!.substring(0, autoCompleteItem.offset); if (startText.isNotEmpty) { result.add(TextSpan(text: startText, style: style)); } - final boldText = - autoCompleteItem.text!.substring(autoCompleteItem.offset!, autoCompleteItem.offset! + autoCompleteItem.length!); + final boldText = autoCompleteItem.text!.substring(autoCompleteItem.offset!, + autoCompleteItem.offset! + autoCompleteItem.length!); result.add( - TextSpan(text: boldText, style: style.copyWith(color: Theme.of(context).textTheme.body1!.color)), + TextSpan( + text: boldText, + style: style.copyWith( + color: Theme.of(context).textTheme.bodyText1!.color)), ); - final remainingText = autoCompleteItem.text!.substring(autoCompleteItem.offset! + autoCompleteItem.length!); + final remainingText = autoCompleteItem.text! + .substring(autoCompleteItem.offset! + autoCompleteItem.length!); result.add(TextSpan(text: remainingText, style: style)); return result; diff --git a/lib/widgets/search_input.dart b/lib/widgets/search_input.dart index 3847983..7ccbe27 100644 --- a/lib/widgets/search_input.dart +++ b/lib/widgets/search_input.dart @@ -1,12 +1,15 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:place_picker/entities/search_bar_options_model.dart'; +import 'package:place_picker/place_picker.dart'; /// Custom Search input field, showing the search and clear icons. class SearchInput extends StatefulWidget { final ValueChanged onSearchInput; + final SearchBarOptions? searchBarOptions; - SearchInput(this.onSearchInput); + SearchInput(this.onSearchInput, {this.searchBarOptions}); @override State createState() => SearchInputState(); @@ -54,14 +57,21 @@ class SearchInputState extends State { @override Widget build(BuildContext context) { return Container( - padding: EdgeInsets.symmetric(horizontal: 8), + // padding: EdgeInsets.symmetric(horizontal: 8), child: Row( children: [ - Icon(Icons.search, color: Theme.of(context).textTheme.body1!.color), - SizedBox(width: 8), + Padding( + padding: widget.searchBarOptions?.searchIconPadding ?? + const EdgeInsets.symmetric(horizontal: 8, vertical: 2), + child: widget.searchBarOptions?.searchIcon ?? + Icon(Icons.search, + color: Theme.of(context).textTheme.bodyText1!.color), + ), Expanded( child: TextField( - decoration: InputDecoration(hintText: "Search place", border: InputBorder.none), + decoration: widget.searchBarOptions?.inputDecoration ?? + InputDecoration( + hintText: "Search place", border: InputBorder.none), controller: this.editController, onChanged: (value) { setState(() { @@ -70,23 +80,30 @@ class SearchInputState extends State { }, ), ), - SizedBox(width: 8), if (this.hasSearchEntry) - GestureDetector( - child: Icon(Icons.clear), - onTap: () { - this.editController.clear(); - setState(() { - this.hasSearchEntry = false; - }); - }, + Padding( + padding: widget.searchBarOptions?.clearTextIconPadding ?? + EdgeInsets.zero, + child: GestureDetector( + onTap: () { + this.editController.clear(); + setState(() { + this.hasSearchEntry = false; + }); + }, + child: widget.searchBarOptions?.clearTextIcon ?? + Icon( + Icons.clear, + ), + ), ), ], ), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(16), - color: Theme.of(context).canvasColor, - ), + decoration: widget.searchBarOptions?.decoration ?? + BoxDecoration( + borderRadius: BorderRadius.circular(16), + color: Theme.of(context).canvasColor, + ), ); } } diff --git a/pubspec.lock b/pubspec.lock deleted file mode 100644 index b775812..0000000 --- a/pubspec.lock +++ /dev/null @@ -1,236 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - async: - dependency: transitive - description: - name: async - url: "https://pub.dartlang.org" - source: hosted - version: "2.5.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - characters: - dependency: transitive - description: - name: characters - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - clock: - dependency: transitive - description: - name: clock - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - collection: - dependency: transitive - description: - name: collection - url: "https://pub.dartlang.org" - source: hosted - version: "1.15.0" - fake_async: - dependency: transitive - description: - name: fake_async - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_plugin_android_lifecycle: - dependency: transitive - description: - name: flutter_plugin_android_lifecycle - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - google_maps_flutter: - dependency: "direct main" - description: - name: google_maps_flutter - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - google_maps_flutter_platform_interface: - dependency: transitive - description: - name: google_maps_flutter_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.2" - http: - dependency: "direct main" - description: - name: http - url: "https://pub.dartlang.org" - source: hosted - version: "0.13.1" - http_parser: - dependency: transitive - description: - name: http_parser - url: "https://pub.dartlang.org" - source: hosted - version: "4.0.0" - js: - dependency: transitive - description: - name: js - url: "https://pub.dartlang.org" - source: hosted - version: "0.6.3" - location: - dependency: "direct main" - description: - name: location - url: "https://pub.dartlang.org" - source: hosted - version: "4.1.1" - location_platform_interface: - dependency: transitive - description: - name: location_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - location_web: - dependency: transitive - description: - name: location_web - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.0" - matcher: - dependency: transitive - description: - name: matcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.10" - meta: - dependency: transitive - description: - name: meta - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - path: - dependency: transitive - description: - name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0" - pedantic: - dependency: transitive - description: - name: pedantic - url: "https://pub.dartlang.org" - source: hosted - version: "1.11.0" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_span: - dependency: transitive - description: - name: source_span - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0" - stack_trace: - dependency: transitive - description: - name: stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.10.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - stream_transform: - dependency: transitive - description: - name: stream_transform - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - string_scanner: - dependency: transitive - description: - name: string_scanner - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - test_api: - dependency: transitive - description: - name: test_api - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.19" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - vector_math: - dependency: transitive - description: - name: vector_math - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" -sdks: - dart: ">=2.12.0 <3.0.0" - flutter: ">=1.22.0"