├── .fvm └── fvm_config.json ├── .gitattributes ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build ├── test_cache │ └── build │ │ └── c075001b96339384a97db4862b8ab8db.cache.dill.track.dill └── unit_test_assets │ ├── AssetManifest.json │ ├── FontManifest.json │ └── NOTICES.Z ├── example ├── .gitignore ├── .metadata ├── README.md ├── analysis_options.yaml ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── chips_choice_example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values-night │ │ │ │ └── styles.xml │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── build │ └── web │ │ ├── .last_build_id │ │ ├── assets │ │ ├── AssetManifest.json │ │ ├── FontManifest.json │ │ ├── NOTICES │ │ ├── fonts │ │ │ └── MaterialIcons-Regular.otf │ │ └── packages │ │ │ └── cupertino_icons │ │ │ └── assets │ │ │ └── CupertinoIcons.ttf │ │ ├── canvaskit │ │ ├── canvaskit.js │ │ ├── canvaskit.wasm │ │ └── profiling │ │ │ ├── canvaskit.js │ │ │ └── canvaskit.wasm │ │ ├── favicon.png │ │ ├── flutter.js │ │ ├── flutter_service_worker.js │ │ ├── icons │ │ ├── Icon-192.png │ │ ├── Icon-512.png │ │ ├── Icon-maskable-192.png │ │ └── Icon-maskable-512.png │ │ ├── index.html │ │ ├── main.dart.js │ │ ├── main.dart.js.map │ │ ├── manifest.json │ │ └── version.json ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h ├── lib │ └── main.dart ├── linux │ ├── .gitignore │ ├── CMakeLists.txt │ ├── flutter │ │ ├── CMakeLists.txt │ │ ├── generated_plugin_registrant.cc │ │ ├── generated_plugin_registrant.h │ │ └── generated_plugins.cmake │ ├── main.cc │ ├── my_application.cc │ └── my_application.h ├── macos │ ├── .gitignore │ ├── Flutter │ │ ├── Flutter-Debug.xcconfig │ │ ├── Flutter-Release.xcconfig │ │ └── GeneratedPluginRegistrant.swift │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── app_icon_1024.png │ │ │ ├── app_icon_128.png │ │ │ ├── app_icon_16.png │ │ │ ├── app_icon_256.png │ │ │ ├── app_icon_32.png │ │ │ ├── app_icon_512.png │ │ │ └── app_icon_64.png │ │ ├── Base.lproj │ │ └── MainMenu.xib │ │ ├── Configs │ │ ├── AppInfo.xcconfig │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── Warnings.xcconfig │ │ ├── DebugProfile.entitlements │ │ ├── Info.plist │ │ ├── MainFlutterWindow.swift │ │ └── Release.entitlements ├── pubspec.lock ├── pubspec.yaml ├── test │ └── widget_test.dart ├── web │ ├── favicon.png │ ├── icons │ │ ├── Icon-192.png │ │ ├── Icon-512.png │ │ ├── Icon-maskable-192.png │ │ └── Icon-maskable-512.png │ ├── index.html │ └── manifest.json └── windows │ ├── .gitignore │ ├── CMakeLists.txt │ ├── flutter │ ├── CMakeLists.txt │ ├── generated_plugin_registrant.cc │ ├── generated_plugin_registrant.h │ └── generated_plugins.cmake │ └── runner │ ├── CMakeLists.txt │ ├── Runner.rc │ ├── flutter_window.cpp │ ├── flutter_window.h │ ├── main.cpp │ ├── resource.h │ ├── resources │ └── app_icon.ico │ ├── runner.exe.manifest │ ├── utils.cpp │ ├── utils.h │ ├── win32_window.cpp │ └── win32_window.h ├── lib ├── chips_choice.dart └── src │ ├── chip.dart │ ├── choice.dart │ ├── state.dart │ ├── state_multi.dart │ ├── state_single.dart │ ├── types.dart │ ├── utils.dart │ └── widget.dart ├── media └── preview.gif ├── pubspec.lock ├── pubspec.yaml └── test ├── multiple_choice_test.dart └── single_choice_test.dart /.fvm/fvm_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "flutterSdkVersion": "3.0.5", 3 | "flavors": {} 4 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | build/** linguist-vendored 2 | android/** linguist-vendored 3 | ios/** linguist-vendored 4 | web/** linguist-vendored 5 | linux/** linguist-vendored 6 | macos/** linguist-vendored 7 | windows/** linguist-vendored 8 | docs/** linguist-vendored 9 | example/build/** linguist-vendored 10 | example/android/** linguist-vendored 11 | example/ios/** linguist-vendored 12 | example/linux/** linguist-vendored 13 | example/macos/** linguist-vendored 14 | example/windows/** linguist-vendored 15 | example/docs/** linguist-vendored -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | .fvm/flutter_sdk 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # Visual Studio Code related 20 | .vscode/ 21 | 22 | # Flutter/Dart/Pub related 23 | **/doc/api/ 24 | .dart_tool/ 25 | .flutter-plugins 26 | .packages 27 | .pub-cache/ 28 | .pub/ 29 | 30 | # Android related 31 | **/android/**/gradle-wrapper.jar 32 | **/android/.gradle 33 | **/android/captures/ 34 | **/android/gradlew 35 | **/android/gradlew.bat 36 | **/android/local.properties 37 | **/android/**/GeneratedPluginRegistrant.java 38 | 39 | # iOS/XCode related 40 | **/ios/**/*.mode1v3 41 | **/ios/**/*.mode2v3 42 | **/ios/**/*.moved-aside 43 | **/ios/**/*.pbxuser 44 | **/ios/**/*.perspectivev3 45 | **/ios/**/*sync/ 46 | **/ios/**/.sconsign.dblite 47 | **/ios/**/.tags* 48 | **/ios/**/.vagrant/ 49 | **/ios/**/DerivedData/ 50 | **/ios/**/Icon? 51 | **/ios/**/Pods/ 52 | **/ios/**/.symlinks/ 53 | **/ios/**/profile 54 | **/ios/**/xcuserdata 55 | **/ios/.generated/ 56 | **/ios/Flutter/App.framework 57 | **/ios/Flutter/Flutter.framework 58 | **/ios/Flutter/Generated.xcconfig 59 | **/ios/Flutter/app.flx 60 | **/ios/Flutter/app.zip 61 | **/ios/Flutter/flutter_assets/ 62 | **/ios/ServiceDefinitions.json 63 | **/ios/Runner/GeneratedPluginRegistrant.* 64 | 65 | # Exceptions to above rules. 66 | !**/ios/**/default.mode1v3 67 | !**/ios/**/default.mode2v3 68 | !**/ios/**/default.pbxuser 69 | !**/ios/**/default.perspectivev3 70 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 27321ebbad34b0a3fafe99fac037102196d655ff 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 3.0.1 2 | 3 | * Changed sdk constrains 4 | 5 | ## 3.0.0 6 | 7 | * Changed default chip to `flexi_chip` 8 | * C2Chip is alias to `FlexiChip` now 9 | * C2ChoiceStyle changed to C2ChipStyle and alias to `FlexiChipStyle` 10 | * Removed `ChipsChoice.choiceActiveStyle` and `C2Choice.activeStyle` since the C2ChipStyle can be an event driven properties 11 | * Removed `C2ChoiceStyle.useCheckmark`, changed to `ChipsChoice.choiceCheckmark` 12 | * Removed `ChipsChoice.choiceAvatarBuilder` 13 | * Added `ChipsChoice.choiceLeadingBuilder` 14 | * Added `ChipsChoice.choiceTrailingBuilder` 15 | * Added `ChipsChoice.choiceOnDelete` 16 | * Added `C2Choice.avatarImage` 17 | * Added `C2Choice.avatarText` 18 | * Fixed issue #26, add leading and trailing widget 19 | * Improved performance 20 | * More flexibility on styling 21 | 22 | ## 2.1.1 23 | 24 | * Hotfix static analysis error 25 | 26 | ## 2.1.0 27 | 28 | * Improve performance 29 | * Fixed chip run spacing 30 | * Fixed tooltip error 31 | 32 | ## 2.1.0-nullsafety.1 33 | 34 | * Improve performance 35 | * Value of multiple choice cannot be null 36 | * Fixed issue #37 37 | * Fixed wrapped chips run spacing on web 38 | * Improve async choices loader with asyncMemoizer 39 | * Provide `C2ChoiceMemoizer` which is an alias to `AsyncMemoizer>>` 40 | 41 | ## 2.1.0-nullsafety.0 42 | 43 | * Support sound null safety 44 | * The chip widget respective to app theme 45 | * Introduce chip appearance (elevated, outlined, flatten) 46 | * Configurable scrollController 47 | 48 | ## 2.0.1 49 | 50 | * Fixed issue #11 51 | 52 | ## 2.0.0 53 | 54 | * The `options` parameter is changed to `choiceItems` 55 | * The `ChipsChoiceOption` class is changed to `C2Choice`, 56 | * Removed the `avatar` parameter from choice item class, instead use `ChipsChoice.choiceAvatarBuilder` 57 | * The `ChipsChoice.isWrapped` parameter is changed to `ChipsChoice.wrapped` 58 | * The `ChipsChoice.itemBuilder` parameter is changed to `ChipsChoice.choiceBuilder` 59 | * The `ChipsChoice.wrapAlignment` parameter is changed to `ChipsChoice.alignment` 60 | * The `ChipsChoice.itemConfig` parameter and `ChipsChoiceItemConfig` class is removed, instead use `C2ChoiceStyle` class with `ChipsChoice.choiceStyle` and `ChipsChoice.choiceActiveStyle` 61 | * Easily configure unselected and selected choice style using `ChipsChoice.choiceStyle` and `ChipsChoice.choiceActiveStyle` 62 | * Individual choice style using `C2Choice.style` and `C2Choice.activeStyle` 63 | * Added parameter `ChipsChoice.choiceLoader` to easily load async choice items 64 | * Added `ChipsChoice.choiceLabelBuilder`, `ChipsChoice.choiceAvatarBuilder`, `ChipsChoice.choiceBuilder`, `ChipsChoice.spinnerBuilder`, `ChipsChoice.placeholderBuilder`, `ChipsChoice.errorBuilder`, 65 | * Added `ChipsChoice.direction`, `ChipsChoice.verticalDirection`, `ChipsChoice.textDirection`, `ChipsChoice.clipBehavior`, `ChipsChoice.scrollPhysics`, `ChipsChoice.mainAxisSize`, `ChipsChoice.mainAxisAlignment`, `ChipsChoice.crossAxisAlignment`, `ChipsChoice.alignment`, `ChipsChoice.runAlignment`, `ChipsChoice.wrapCrossAlignment`, `ChipsChoice.spacing`, `ChipsChoice.runSpacing`, `ChipsChoice.placeholder`, `ChipsChoice.placeholderStyle`, `ChipsChoice.placeholderAlign`, `ChipsChoice.errorStyle`, `ChipsChoice.errorAlign`, `ChipsChoice.spinnerSize`, `ChipsChoice.spinnerColor`, `ChipsChoice.spinnerThickness` 66 | * Changed `FilterChip` to `RawChip` 67 | 68 | ## 1.4.1 69 | 70 | * Added wrap alignment parameter, thanks to @deandreamatias 71 | * Added support for setting materialTapTargetSize on chips - directly affecting the ability to reduce padding of chips, thanks to @noliran 72 | * Fixed a bug preventing us from setting a custom margin, thanks to @noliran 73 | * Added `itemConfig.shapeBuilder` to example 74 | 75 | ## 1.2.0 76 | 77 | * Add `labelStyle` to `ChipsChoiceItemConfig` 78 | 79 | ## 1.1.0 80 | 81 | * Improve performance, since `Theme.of(context)` in default choice widget is moved outside, so this only fired once 82 | * `ChipsChoiceBuilder` parameter `select` function now only need one parameter `bool selected` 83 | * Add `meta` to `ChipsChoiceOption`, this useful with custom choice widget 84 | * Add more option to `ChipsChoiceItemConfig` 85 | * Add more usage example 86 | 87 | ## 1.0.0 88 | 89 | * Initial release 90 | * Select single or multiple choice 91 | * Display in scrollable or wrapped List 92 | * Customizable choice input 93 | * Build choice option from any List 94 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022 Irfan Vigma Taufik 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | * Redistributions of source code must retain the above copyright notice, 6 | this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright notice, 8 | this list of conditions and the following disclaimer in the documentation 9 | and/or other materials provided with the distribution. 10 | * Neither the name of the copyright holder nor the names of its contributors 11 | may be used to endorse or promote products derived from this software 12 | without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Pub Version](https://img.shields.io/pub/v/chips_choice) ![GitHub](https://img.shields.io/github/license/davigmacode/flutter_chips_choice) 2 | 3 | Buy Me A Coffee 4 | 5 | > [!IMPORTANT] 6 | > 7 | > Hi everyone, 8 | > 9 | > I'm sorry to announce that I'm no longer maintaining the [chips_choice](https://pub.dev/packages/chips_choice) package. It's been a great project, but it's become too difficult to maintain. 10 | > 11 | > In its place, I've released a new package called [choice](https://pub.dev/packages/choice). The combination to [smart_select](https://pub.dev/packages/smart_select) and [chips_choice](https://pub.dev/packages/chips_choice) with cleaner, more flexible, and composable API for creating inline or prompted choice widgets with single or multiple selection. 12 | > 13 | > I hope you'll check out [choice](https://pub.dev/packages/choice). I think you'll find it to be a great replacement for [chips_choice](https://pub.dev/packages/chips_choice). 14 | > 15 | > Thanks for your understanding. 16 | 17 | Lite version of [smart_select](https://pub.dev/packages/smart_select) package, zero dependencies, an easy way to provide a single or multiple choice chips. 18 | 19 | ## What's New in Version 3.x.x 20 | 21 | * Changed default chip to [flexi_chip](https://pub.dev/packages/flexi_chip) 22 | * C2Chip is alias to `FlexiChip` now 23 | * C2ChoiceStyle changed to C2ChipStyle and alias to `FlexiChipStyle` 24 | * Removed `ChipsChoice.choiceActiveStyle` and `C2Choice.activeStyle` since the C2ChipStyle can be an event driven properties 25 | * Removed `C2ChoiceStyle.useCheckmark`, changed to `ChipsChoice.choiceCheckmark` 26 | * Removed `ChipsChoice.choiceAvatarBuilder` 27 | * Added `ChipsChoice.choiceLeadingBuilder` 28 | * Added `ChipsChoice.choiceTrailingBuilder` 29 | * Added `C2Choice.delete` 30 | * Added `C2Choice.avatarImage` 31 | * Added `C2Choice.avatarText` 32 | * Fixed issue #26, add leading and trailing widget 33 | * Improved performance 34 | * More flexibility on styling 35 | 36 | ## Demo 37 | 38 | ### Preview 39 | 40 | [![Preview](https://github.com/davigmacode/flutter_chips_choice/raw/master/media/preview.gif)](https://davigmacode.github.io/flutter_chips_choice) 41 | 42 | [Demo](https://davigmacode.github.io/flutter_chips_choice) 43 | 44 | 45 | ## Features 46 | 47 | * Select single or multiple choice 48 | * Display in scrollable or wrapped list 49 | * Build choice items from any `List` 50 | * Customizable choice widget 51 | 52 | ## Usage 53 | 54 | For a complete usage, please see the [example](https://pub.dev/packages/chips_choice#-example-tab-). 55 | 56 | To read more about classes and other references used by `chips_choice`, see the [API Reference](https://pub.dev/documentation/chips_choice/latest/). 57 | 58 | ### Single Choice 59 | 60 | ```dart 61 | // available configuration for single choice 62 | ChipsChoice.single({ 63 | 64 | // The current value of the single choice widget. 65 | @required T value, 66 | 67 | // Called when single choice value changed 68 | @required C2Changed onChanged, 69 | 70 | // choice item list 71 | @required List> choiceItems, 72 | 73 | // Async loader of choice items 74 | C2ChoiceLoader choiceLoader, 75 | 76 | // other available configuration 77 | // explained below 78 | ..., 79 | ..., 80 | 81 | }) 82 | ``` 83 | Simple usage 84 | ```dart 85 | int tag = 1; 86 | List options = [ 87 | 'News', 'Entertainment', 'Politics', 88 | 'Automotive', 'Sports', 'Education', 89 | 'Fashion', 'Travel', 'Food', 'Tech', 90 | 'Science', 91 | ]; 92 | 93 | @override 94 | Widget build(BuildContext context) { 95 | return ChipsChoice.single( 96 | value: tag, 97 | onChanged: (val) => setState(() => tag = val), 98 | choiceItems: C2Choice.listFrom( 99 | source: options, 100 | value: (i, v) => i, 101 | label: (i, v) => v, 102 | ), 103 | ); 104 | } 105 | ``` 106 | 107 | ### Multiple Choice 108 | ```dart 109 | // available configuration for multiple choice 110 | ChipsChoice.multiple({ 111 | 112 | // The current value of the multiple choice widget. 113 | @required List value, 114 | 115 | // Called when multiple choice value changed 116 | @required C2Changed> onChanged, 117 | 118 | // choice item list 119 | @required List> choiceItems, 120 | 121 | // Async loader of choice items 122 | C2ChoiceLoader choiceLoader, 123 | 124 | // other available configuration 125 | // explained below 126 | ..., 127 | ..., 128 | 129 | }) 130 | ``` 131 | Simple usage 132 | ```dart 133 | List tags = []; 134 | List options = [ 135 | 'News', 'Entertainment', 'Politics', 136 | 'Automotive', 'Sports', 'Education', 137 | 'Fashion', 'Travel', 'Food', 'Tech', 138 | 'Science', 139 | ]; 140 | 141 | @override 142 | Widget build(BuildContext context) { 143 | return ChipsChoice.multiple( 144 | value: tags, 145 | onChanged: (val) => setState(() => tags = val), 146 | choiceItems: C2Choice.listFrom( 147 | source: options, 148 | value: (i, v) => v, 149 | label: (i, v) => v, 150 | ), 151 | ); 152 | } 153 | ``` 154 | 155 | ### Style Configuration 156 | 157 | See the [API References](https://pub.dev/documentation/flexi_chip/latest/flexi_chip/FlexiChipStyle-class.html), to find out all of the parameters. 158 | 159 | ```dart 160 | // available configuration for single and multiple choice 161 | ChipsChoice.[single|multiple]({ 162 | 163 | // other available configuration 164 | // explained below 165 | ..., 166 | ..., 167 | 168 | // Choice item style 169 | C2ChipStyle choiceStyle, 170 | 171 | // other available configuration 172 | // explained below 173 | ..., 174 | ..., 175 | 176 | }) 177 | ``` 178 | 179 | ### Custom Builder 180 | 181 | ```dart 182 | // available configuration for single and multiple choice 183 | ChipsChoice.[single|multiple]({ 184 | 185 | // other available configuration 186 | // explained below 187 | ..., 188 | ..., 189 | 190 | // Builder for custom choice item label 191 | C2Builder choiceLabelBuilder, 192 | 193 | // Builder for custom widget to display prior to the chip's [label]. 194 | C2Builder? choiceLeadingBuilder; 195 | 196 | // Builder for custom widget to display next to the chip's [label]. 197 | C2Builder? choiceTrailingBuilder; 198 | 199 | // Builder for custom choice item 200 | C2Builder choiceBuilder, 201 | 202 | // Builder for spinner widget 203 | WidgetBuilder spinnerBuilder, 204 | 205 | // Builder for placeholder widget 206 | WidgetBuilder placeholderBuilder, 207 | 208 | // Builder for error widget 209 | WidgetBuilder errorBuilder, 210 | 211 | // other available configuration 212 | // explained below 213 | ..., 214 | ..., 215 | 216 | }) 217 | ``` 218 | 219 | ### Container Configuration 220 | 221 | ```dart 222 | // available configuration for single and multiple choice 223 | ChipsChoice.[single|multiple]({ 224 | 225 | // other available configuration 226 | // explained below 227 | ..., 228 | ..., 229 | 230 | // Whether the chips is wrapped or scrollable 231 | bool wrapped, 232 | 233 | // Container padding 234 | EdgeInsetsGeometry padding, 235 | 236 | // The direction to use as the main axis. 237 | Axis direction, 238 | 239 | // Determines the order to lay children out vertically and how to interpret start and end in the vertical direction. 240 | VerticalDirection verticalDirection, 241 | 242 | // Determines the order to lay children out horizontally and how to interpret start and end in the horizontal direction. 243 | TextDirection textDirection, 244 | 245 | // if [wrapped] is [false], How the scroll view should respond to user input. 246 | ScrollPhysics scrollPhysics, 247 | 248 | // if [wrapped] is [false], How much space should be occupied in the main axis. 249 | MainAxisSize mainAxisSize, 250 | 251 | // if [wrapped] is [false], How the children should be placed along the main axis. 252 | MainAxisAlignment mainAxisAlignment, 253 | 254 | // if [wrapped] is [false], How the children should be placed along the cross axis. 255 | CrossAxisAlignment crossAxisAlignment, 256 | 257 | // if [wrapped] is [true], how the children within a run should be aligned relative to each other in the cross axis. 258 | WrapCrossAlignment wrapCrossAlignment, 259 | 260 | // if [wrapped] is [true], determines how wrap will align the objects 261 | WrapAlignment alignment, 262 | 263 | // if [wrapped] is [true], how the runs themselves should be placed in the cross axis. 264 | WrapAlignment runAlignment, 265 | 266 | // if [wrapped] is [true], how much space to place between children in a run in the main axis. 267 | double spacing, 268 | 269 | // if [wrapped] is [true], how much space to place between the runs themselves in the cross axis. 270 | double runSpacing, 271 | 272 | // Clip behavior 273 | Clip clipBehavior, 274 | 275 | // String to display when choice items is empty 276 | String placeholder, 277 | 278 | // placeholder text style 279 | TextStyle placeholderStyle, 280 | 281 | // placeholder text align 282 | TextAlign placeholderAlign, 283 | 284 | // error text style 285 | TextStyle errorStyle, 286 | 287 | // error text align 288 | TextAlign errorAlign, 289 | 290 | // spinner size 291 | double spinnerSize, 292 | 293 | // spinner color 294 | Color spinnerColor, 295 | 296 | // spinner thickness 297 | double spinnerThickness, 298 | 299 | // other available configuration 300 | // explained below 301 | ..., 302 | ..., 303 | 304 | }) 305 | ``` 306 | 307 | ### Build Choice List 308 | 309 | `choiceItems` property is `List>`, it can be input directly as in the example below, more info about `C2Choice` can be found on the [API Reference](https://pub.dev/documentation/chips_choice/latest/chips_choice/C2Choice-class.html) 310 | 311 | ```dart 312 | ChipsChoice.[single|multiple]( 313 | ..., 314 | ..., 315 | choiceItems: >[ 316 | C2Choice(value: 1, label: 'Entertainment'), 317 | C2Choice(value: 2, label: 'Education'), 318 | C2Choice(value: 3, label: 'Fashion'), 319 | ], 320 | ); 321 | ``` 322 | 323 | `choiceItems` also can be created from any list using helper provided by this package, like the example below 324 | 325 | ```dart 326 | List> days = [ 327 | { 'value': 'mon', 'title': 'Monday' }, 328 | { 'value': 'tue', 'title': 'Tuesday' }, 329 | { 'value': 'wed', 'title': 'Wednesday' }, 330 | { 'value': 'thu', 'title': 'Thursday' }, 331 | { 'value': 'fri', 'title': 'Friday' }, 332 | { 'value': 'sat', 'title': 'Saturday' }, 333 | { 'value': 'sun', 'title': 'Sunday' }, 334 | ]; 335 | 336 | ChipsChoice.[single|multiple]( 337 | ..., 338 | ..., 339 | choiceItems: C2Choice.listFrom>( 340 | source: days, 341 | value: (index, item) => item['value'], 342 | label: (index, item) => item['title'], 343 | ), 344 | ); 345 | ``` 346 | Use `choiceLoader` to easily load choice items from async function 347 | ```dart 348 | import 'package:dio/dio.dart'; 349 | 350 | String value; 351 | 352 | Future>> getChoices() async { 353 | String url = "https://randomuser.me/api/?inc=gender,name,nat,picture,email&results=25"; 354 | Response res = await Dio().get(url); 355 | return C2Choice.listFrom( 356 | source: res.data['results'], 357 | value: (index, item) => item['email'], 358 | label: (index, item) => item['name']['first'] + ' ' + item['name']['last'], 359 | meta: (index, item) => item, 360 | )..insert(0, C2Choice(value: 'all', label: 'All')); 361 | } 362 | 363 | @override 364 | Widget build(BuildContext context) { 365 | return ChipsChoice.single( 366 | value: value, 367 | onChanged: (val) => setState(() => value = val), 368 | choiceItems: null, 369 | choiceLoader: getChoices, 370 | ); 371 | } 372 | ``` 373 | 374 | -------------------------------------------------------------------------------- /build/test_cache/build/c075001b96339384a97db4862b8ab8db.cache.dill.track.dill: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/build/test_cache/build/c075001b96339384a97db4862b8ab8db.cache.dill.track.dill -------------------------------------------------------------------------------- /build/unit_test_assets/AssetManifest.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /build/unit_test_assets/FontManifest.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /build/unit_test_assets/NOTICES.Z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/build/unit_test_assets/NOTICES.Z -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | **/ios/Flutter/.last_build_id 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .packages 31 | .pub-cache/ 32 | .pub/ 33 | build/* 34 | !build/web/ 35 | !build/web/** 36 | 37 | # Web related 38 | lib/generated_plugin_registrant.dart 39 | 40 | # Symbolication related 41 | app.*.symbols 42 | 43 | # Obfuscation related 44 | app.*.map.json 45 | 46 | # Android Studio will place build artifacts here 47 | /android/app/debug 48 | /android/app/profile 49 | /android/app/release 50 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled. 5 | 6 | version: 7 | revision: f1875d570e39de09040c8f79aa13cc56baab8db1 8 | channel: stable 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 17 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 18 | - platform: android 19 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 20 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 21 | - platform: ios 22 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 23 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 24 | - platform: linux 25 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 26 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 27 | - platform: macos 28 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 29 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 30 | - platform: web 31 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 32 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 33 | - platform: windows 34 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 35 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 36 | 37 | # User provided section 38 | 39 | # List of Local paths (relative to this file) that should be 40 | # ignored by the migrate tool. 41 | # 42 | # Files that are not part of the templates will be ignored by default. 43 | unmanaged_files: 44 | - 'lib/main.dart' 45 | - 'ios/Runner.xcodeproj/project.pbxproj' 46 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # chips_choice_example 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) 13 | 14 | For help getting started with Flutter development, view the 15 | [online documentation](https://docs.flutter.dev/), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at 17 | # https://dart-lang.github.io/linter/lints/index.html. 18 | # 19 | # Instead of disabling a lint rule for the entire project in the 20 | # section below, it can also be suppressed for a single line of code 21 | # or a specific dart file by using the `// ignore: name_of_lint` and 22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 23 | # producing the lint. 24 | rules: 25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 27 | 28 | # Additional information about this file can be found at 29 | # https://dart.dev/guides/language/analysis-options 30 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion flutter.compileSdkVersion 30 | ndkVersion flutter.ndkVersion 31 | 32 | compileOptions { 33 | sourceCompatibility JavaVersion.VERSION_1_8 34 | targetCompatibility JavaVersion.VERSION_1_8 35 | } 36 | 37 | kotlinOptions { 38 | jvmTarget = '1.8' 39 | } 40 | 41 | sourceSets { 42 | main.java.srcDirs += 'src/main/kotlin' 43 | } 44 | 45 | defaultConfig { 46 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 47 | applicationId "com.example.chips_choice_example" 48 | // You can update the following values to match your application needs. 49 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. 50 | minSdkVersion flutter.minSdkVersion 51 | targetSdkVersion flutter.targetSdkVersion 52 | versionCode flutterVersionCode.toInteger() 53 | versionName flutterVersionName 54 | } 55 | 56 | buildTypes { 57 | release { 58 | // TODO: Add your own signing config for the release build. 59 | // Signing with the debug keys for now, so `flutter run --release` works. 60 | signingConfig signingConfigs.debug 61 | } 62 | } 63 | } 64 | 65 | flutter { 66 | source '../..' 67 | } 68 | 69 | dependencies { 70 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 71 | } 72 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/example/chips_choice_example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.chips_choice_example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.6.10' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:7.1.2' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip 7 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /example/build/web/.last_build_id: -------------------------------------------------------------------------------- 1 | 069c0007814ce03a89ed796f3f914506 -------------------------------------------------------------------------------- /example/build/web/assets/AssetManifest.json: -------------------------------------------------------------------------------- 1 | {"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"]} -------------------------------------------------------------------------------- /example/build/web/assets/FontManifest.json: -------------------------------------------------------------------------------- 1 | [{"family":"MaterialIcons","fonts":[{"asset":"fonts/MaterialIcons-Regular.otf"}]},{"family":"packages/cupertino_icons/CupertinoIcons","fonts":[{"asset":"packages/cupertino_icons/assets/CupertinoIcons.ttf"}]}] -------------------------------------------------------------------------------- /example/build/web/assets/fonts/MaterialIcons-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/build/web/assets/fonts/MaterialIcons-Regular.otf -------------------------------------------------------------------------------- /example/build/web/assets/packages/cupertino_icons/assets/CupertinoIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/build/web/assets/packages/cupertino_icons/assets/CupertinoIcons.ttf -------------------------------------------------------------------------------- /example/build/web/canvaskit/canvaskit.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/build/web/canvaskit/canvaskit.wasm -------------------------------------------------------------------------------- /example/build/web/canvaskit/profiling/canvaskit.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/build/web/canvaskit/profiling/canvaskit.wasm -------------------------------------------------------------------------------- /example/build/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/build/web/favicon.png -------------------------------------------------------------------------------- /example/build/web/flutter.js: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Flutter Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | /** 6 | * This script installs service_worker.js to provide PWA functionality to 7 | * application. For more information, see: 8 | * https://developers.google.com/web/fundamentals/primers/service-workers 9 | */ 10 | 11 | if (!_flutter) { 12 | var _flutter = {}; 13 | } 14 | _flutter.loader = null; 15 | 16 | (function() { 17 | "use strict"; 18 | class FlutterLoader { 19 | /** 20 | * Creates a FlutterLoader, and initializes its instance methods. 21 | */ 22 | constructor() { 23 | // TODO: Move the below methods to "#private" once supported by all the browsers 24 | // we support. In the meantime, we use the "revealing module" pattern. 25 | 26 | // Watchdog to prevent injecting the main entrypoint multiple times. 27 | this._scriptLoaded = null; 28 | 29 | // Resolver for the pending promise returned by loadEntrypoint. 30 | this._didCreateEngineInitializerResolve = null; 31 | 32 | // Called by Flutter web. 33 | // Bound to `this` now, so "this" is preserved across JS <-> Flutter jumps. 34 | this.didCreateEngineInitializer = this._didCreateEngineInitializer.bind(this); 35 | } 36 | 37 | /** 38 | * Initializes the main.dart.js with/without serviceWorker. 39 | * @param {*} options 40 | * @returns a Promise that will eventually resolve with an EngineInitializer, 41 | * or will be rejected with the error caused by the loader. 42 | */ 43 | loadEntrypoint(options) { 44 | const { 45 | entrypointUrl = "main.dart.js", 46 | serviceWorker, 47 | } = (options || {}); 48 | return this._loadWithServiceWorker(entrypointUrl, serviceWorker); 49 | } 50 | 51 | /** 52 | * Resolves the promise created by loadEntrypoint. 53 | * Called by Flutter through the public `didCreateEngineInitializer` method, 54 | * which is bound to the correct instance of the FlutterLoader on the page. 55 | * @param {*} engineInitializer 56 | */ 57 | _didCreateEngineInitializer(engineInitializer) { 58 | if (typeof this._didCreateEngineInitializerResolve != "function") { 59 | console.warn("Do not call didCreateEngineInitializer by hand. Start with loadEntrypoint instead."); 60 | } 61 | this._didCreateEngineInitializerResolve(engineInitializer); 62 | // Remove the public method after it's done, so Flutter Web can hot restart. 63 | delete this.didCreateEngineInitializer; 64 | } 65 | 66 | _loadEntrypoint(entrypointUrl) { 67 | if (!this._scriptLoaded) { 68 | this._scriptLoaded = new Promise((resolve, reject) => { 69 | let scriptTag = document.createElement("script"); 70 | scriptTag.src = entrypointUrl; 71 | scriptTag.type = "application/javascript"; 72 | // Cache the resolve, so it can be called from Flutter. 73 | // Note: Flutter hot restart doesn't re-create this promise, so this 74 | // can only be called once. Instead, we need to model this as a stream 75 | // of `engineCreated` events coming from Flutter that are handled by JS. 76 | this._didCreateEngineInitializerResolve = resolve; 77 | scriptTag.addEventListener("error", reject); 78 | document.body.append(scriptTag); 79 | }); 80 | } 81 | 82 | return this._scriptLoaded; 83 | } 84 | 85 | _waitForServiceWorkerActivation(serviceWorker, entrypointUrl) { 86 | if (!serviceWorker || serviceWorker.state == "activated") { 87 | if (!serviceWorker) { 88 | console.warn("Cannot activate a null service worker. Falling back to plain 39 | 40 | 41 | 42 | 43 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /example/build/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chips_choice_example", 3 | "short_name": "chips_choice_example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /example/build/web/version.json: -------------------------------------------------------------------------------- 1 | {"app_name":"chips_choice_example","version":"1.0.0","build_number":"1","package_name":"chips_choice_example"} -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Chips Choice Example 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | chips_choice_example 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | CADisableMinimumFrameDurationOnPhone 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/linux/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral 2 | -------------------------------------------------------------------------------- /example/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Project-level configuration. 2 | cmake_minimum_required(VERSION 3.10) 3 | project(runner LANGUAGES CXX) 4 | 5 | # The name of the executable created for the application. Change this to change 6 | # the on-disk name of your application. 7 | set(BINARY_NAME "chips_choice_example") 8 | # The unique GTK application identifier for this application. See: 9 | # https://wiki.gnome.org/HowDoI/ChooseApplicationID 10 | set(APPLICATION_ID "com.example.chips_choice_example") 11 | 12 | # Explicitly opt in to modern CMake behaviors to avoid warnings with recent 13 | # versions of CMake. 14 | cmake_policy(SET CMP0063 NEW) 15 | 16 | # Load bundled libraries from the lib/ directory relative to the binary. 17 | set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") 18 | 19 | # Root filesystem for cross-building. 20 | if(FLUTTER_TARGET_PLATFORM_SYSROOT) 21 | set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) 22 | set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) 23 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 24 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 25 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 26 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 27 | endif() 28 | 29 | # Define build configuration options. 30 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 31 | set(CMAKE_BUILD_TYPE "Debug" CACHE 32 | STRING "Flutter build mode" FORCE) 33 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 34 | "Debug" "Profile" "Release") 35 | endif() 36 | 37 | # Compilation settings that should be applied to most targets. 38 | # 39 | # Be cautious about adding new options here, as plugins use this function by 40 | # default. In most cases, you should add new options to specific targets instead 41 | # of modifying this function. 42 | function(APPLY_STANDARD_SETTINGS TARGET) 43 | target_compile_features(${TARGET} PUBLIC cxx_std_14) 44 | target_compile_options(${TARGET} PRIVATE -Wall -Werror) 45 | target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") 46 | target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") 47 | endfunction() 48 | 49 | # Flutter library and tool build rules. 50 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 51 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 52 | 53 | # System-level dependencies. 54 | find_package(PkgConfig REQUIRED) 55 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 56 | 57 | add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") 58 | 59 | # Define the application target. To change its name, change BINARY_NAME above, 60 | # not the value here, or `flutter run` will no longer work. 61 | # 62 | # Any new source files that you add to the application should be added here. 63 | add_executable(${BINARY_NAME} 64 | "main.cc" 65 | "my_application.cc" 66 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 67 | ) 68 | 69 | # Apply the standard set of build settings. This can be removed for applications 70 | # that need different build settings. 71 | apply_standard_settings(${BINARY_NAME}) 72 | 73 | # Add dependency libraries. Add any application-specific dependencies here. 74 | target_link_libraries(${BINARY_NAME} PRIVATE flutter) 75 | target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) 76 | 77 | # Run the Flutter tool portions of the build. This must not be removed. 78 | add_dependencies(${BINARY_NAME} flutter_assemble) 79 | 80 | # Only the install-generated bundle's copy of the executable will launch 81 | # correctly, since the resources must in the right relative locations. To avoid 82 | # people trying to run the unbundled copy, put it in a subdirectory instead of 83 | # the default top-level location. 84 | set_target_properties(${BINARY_NAME} 85 | PROPERTIES 86 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" 87 | ) 88 | 89 | # Generated plugin build rules, which manage building the plugins and adding 90 | # them to the application. 91 | include(flutter/generated_plugins.cmake) 92 | 93 | 94 | # === Installation === 95 | # By default, "installing" just makes a relocatable bundle in the build 96 | # directory. 97 | set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") 98 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 99 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 100 | endif() 101 | 102 | # Start with a clean build bundle directory every time. 103 | install(CODE " 104 | file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") 105 | " COMPONENT Runtime) 106 | 107 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 108 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") 109 | 110 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 111 | COMPONENT Runtime) 112 | 113 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 114 | COMPONENT Runtime) 115 | 116 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 117 | COMPONENT Runtime) 118 | 119 | foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) 120 | install(FILES "${bundled_library}" 121 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 122 | COMPONENT Runtime) 123 | endforeach(bundled_library) 124 | 125 | # Fully re-copy the assets directory on each build to avoid having stale files 126 | # from a previous install. 127 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 128 | install(CODE " 129 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 130 | " COMPONENT Runtime) 131 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 132 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 133 | 134 | # Install the AOT library on non-Debug builds only. 135 | if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") 136 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 137 | COMPONENT Runtime) 138 | endif() 139 | -------------------------------------------------------------------------------- /example/linux/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file controls Flutter-level build steps. It should not be edited. 2 | cmake_minimum_required(VERSION 3.10) 3 | 4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 5 | 6 | # Configuration provided via flutter tool. 7 | include(${EPHEMERAL_DIR}/generated_config.cmake) 8 | 9 | # TODO: Move the rest of this into files in ephemeral. See 10 | # https://github.com/flutter/flutter/issues/57146. 11 | 12 | # Serves the same purpose as list(TRANSFORM ... PREPEND ...), 13 | # which isn't available in 3.10. 14 | function(list_prepend LIST_NAME PREFIX) 15 | set(NEW_LIST "") 16 | foreach(element ${${LIST_NAME}}) 17 | list(APPEND NEW_LIST "${PREFIX}${element}") 18 | endforeach(element) 19 | set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) 20 | endfunction() 21 | 22 | # === Flutter Library === 23 | # System-level dependencies. 24 | find_package(PkgConfig REQUIRED) 25 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 26 | pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) 27 | pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) 28 | 29 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") 30 | 31 | # Published to parent scope for install step. 32 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 33 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 34 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 35 | set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) 36 | 37 | list(APPEND FLUTTER_LIBRARY_HEADERS 38 | "fl_basic_message_channel.h" 39 | "fl_binary_codec.h" 40 | "fl_binary_messenger.h" 41 | "fl_dart_project.h" 42 | "fl_engine.h" 43 | "fl_json_message_codec.h" 44 | "fl_json_method_codec.h" 45 | "fl_message_codec.h" 46 | "fl_method_call.h" 47 | "fl_method_channel.h" 48 | "fl_method_codec.h" 49 | "fl_method_response.h" 50 | "fl_plugin_registrar.h" 51 | "fl_plugin_registry.h" 52 | "fl_standard_message_codec.h" 53 | "fl_standard_method_codec.h" 54 | "fl_string_codec.h" 55 | "fl_value.h" 56 | "fl_view.h" 57 | "flutter_linux.h" 58 | ) 59 | list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") 60 | add_library(flutter INTERFACE) 61 | target_include_directories(flutter INTERFACE 62 | "${EPHEMERAL_DIR}" 63 | ) 64 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") 65 | target_link_libraries(flutter INTERFACE 66 | PkgConfig::GTK 67 | PkgConfig::GLIB 68 | PkgConfig::GIO 69 | ) 70 | add_dependencies(flutter flutter_assemble) 71 | 72 | # === Flutter tool backend === 73 | # _phony_ is a non-existent file to force this command to run every time, 74 | # since currently there's no way to get a full input/output list from the 75 | # flutter tool. 76 | add_custom_command( 77 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 78 | ${CMAKE_CURRENT_BINARY_DIR}/_phony_ 79 | COMMAND ${CMAKE_COMMAND} -E env 80 | ${FLUTTER_TOOL_ENVIRONMENT} 81 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" 82 | ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} 83 | VERBATIM 84 | ) 85 | add_custom_target(flutter_assemble DEPENDS 86 | "${FLUTTER_LIBRARY}" 87 | ${FLUTTER_LIBRARY_HEADERS} 88 | ) 89 | -------------------------------------------------------------------------------- /example/linux/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | 10 | void fl_register_plugins(FlPluginRegistry* registry) { 11 | } 12 | -------------------------------------------------------------------------------- /example/linux/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void fl_register_plugins(FlPluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /example/linux/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | ) 7 | 8 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 9 | ) 10 | 11 | set(PLUGIN_BUNDLED_LIBRARIES) 12 | 13 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 14 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) 15 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 16 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 18 | endforeach(plugin) 19 | 20 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 21 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) 22 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 23 | endforeach(ffi_plugin) 24 | -------------------------------------------------------------------------------- /example/linux/main.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | int main(int argc, char** argv) { 4 | g_autoptr(MyApplication) app = my_application_new(); 5 | return g_application_run(G_APPLICATION(app), argc, argv); 6 | } 7 | -------------------------------------------------------------------------------- /example/linux/my_application.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | #include 4 | #ifdef GDK_WINDOWING_X11 5 | #include 6 | #endif 7 | 8 | #include "flutter/generated_plugin_registrant.h" 9 | 10 | struct _MyApplication { 11 | GtkApplication parent_instance; 12 | char** dart_entrypoint_arguments; 13 | }; 14 | 15 | G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) 16 | 17 | // Implements GApplication::activate. 18 | static void my_application_activate(GApplication* application) { 19 | MyApplication* self = MY_APPLICATION(application); 20 | GtkWindow* window = 21 | GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); 22 | 23 | // Use a header bar when running in GNOME as this is the common style used 24 | // by applications and is the setup most users will be using (e.g. Ubuntu 25 | // desktop). 26 | // If running on X and not using GNOME then just use a traditional title bar 27 | // in case the window manager does more exotic layout, e.g. tiling. 28 | // If running on Wayland assume the header bar will work (may need changing 29 | // if future cases occur). 30 | gboolean use_header_bar = TRUE; 31 | #ifdef GDK_WINDOWING_X11 32 | GdkScreen* screen = gtk_window_get_screen(window); 33 | if (GDK_IS_X11_SCREEN(screen)) { 34 | const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); 35 | if (g_strcmp0(wm_name, "GNOME Shell") != 0) { 36 | use_header_bar = FALSE; 37 | } 38 | } 39 | #endif 40 | if (use_header_bar) { 41 | GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); 42 | gtk_widget_show(GTK_WIDGET(header_bar)); 43 | gtk_header_bar_set_title(header_bar, "chips_choice_example"); 44 | gtk_header_bar_set_show_close_button(header_bar, TRUE); 45 | gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); 46 | } else { 47 | gtk_window_set_title(window, "chips_choice_example"); 48 | } 49 | 50 | gtk_window_set_default_size(window, 1280, 720); 51 | gtk_widget_show(GTK_WIDGET(window)); 52 | 53 | g_autoptr(FlDartProject) project = fl_dart_project_new(); 54 | fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); 55 | 56 | FlView* view = fl_view_new(project); 57 | gtk_widget_show(GTK_WIDGET(view)); 58 | gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); 59 | 60 | fl_register_plugins(FL_PLUGIN_REGISTRY(view)); 61 | 62 | gtk_widget_grab_focus(GTK_WIDGET(view)); 63 | } 64 | 65 | // Implements GApplication::local_command_line. 66 | static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { 67 | MyApplication* self = MY_APPLICATION(application); 68 | // Strip out the first argument as it is the binary name. 69 | self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); 70 | 71 | g_autoptr(GError) error = nullptr; 72 | if (!g_application_register(application, nullptr, &error)) { 73 | g_warning("Failed to register: %s", error->message); 74 | *exit_status = 1; 75 | return TRUE; 76 | } 77 | 78 | g_application_activate(application); 79 | *exit_status = 0; 80 | 81 | return TRUE; 82 | } 83 | 84 | // Implements GObject::dispose. 85 | static void my_application_dispose(GObject* object) { 86 | MyApplication* self = MY_APPLICATION(object); 87 | g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); 88 | G_OBJECT_CLASS(my_application_parent_class)->dispose(object); 89 | } 90 | 91 | static void my_application_class_init(MyApplicationClass* klass) { 92 | G_APPLICATION_CLASS(klass)->activate = my_application_activate; 93 | G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; 94 | G_OBJECT_CLASS(klass)->dispose = my_application_dispose; 95 | } 96 | 97 | static void my_application_init(MyApplication* self) {} 98 | 99 | MyApplication* my_application_new() { 100 | return MY_APPLICATION(g_object_new(my_application_get_type(), 101 | "application-id", APPLICATION_ID, 102 | "flags", G_APPLICATION_NON_UNIQUE, 103 | nullptr)); 104 | } 105 | -------------------------------------------------------------------------------- /example/linux/my_application.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUTTER_MY_APPLICATION_H_ 2 | #define FLUTTER_MY_APPLICATION_H_ 3 | 4 | #include 5 | 6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, 7 | GtkApplication) 8 | 9 | /** 10 | * my_application_new: 11 | * 12 | * Creates a new Flutter-based application. 13 | * 14 | * Returns: a new #MyApplication. 15 | */ 16 | MyApplication* my_application_new(); 17 | 18 | #endif // FLUTTER_MY_APPLICATION_H_ 19 | -------------------------------------------------------------------------------- /example/macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | 9 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 10 | } 11 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @NSApplicationMain 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /example/macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = chips_choice_example 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.chipsChoiceExample 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2022 com.example. All rights reserved. 15 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /example/macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /example/macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController.init() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | animated_checkmark: 5 | dependency: "direct main" 6 | description: 7 | name: animated_checkmark 8 | sha256: "878db0c6754c4145e9e17b46f20e304da060ac7a65f8ab4ab43494093f3f8443" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "1.0.1" 12 | async: 13 | dependency: transitive 14 | description: 15 | name: async 16 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.11.0" 20 | boolean_selector: 21 | dependency: transitive 22 | description: 23 | name: boolean_selector 24 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "2.1.1" 28 | characters: 29 | dependency: transitive 30 | description: 31 | name: characters 32 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.3.0" 36 | chips_choice: 37 | dependency: "direct main" 38 | description: 39 | path: ".." 40 | relative: true 41 | source: path 42 | version: "3.0.1" 43 | clock: 44 | dependency: transitive 45 | description: 46 | name: clock 47 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf 48 | url: "https://pub.dev" 49 | source: hosted 50 | version: "1.1.1" 51 | collection: 52 | dependency: transitive 53 | description: 54 | name: collection 55 | sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" 56 | url: "https://pub.dev" 57 | source: hosted 58 | version: "1.17.1" 59 | cupertino_icons: 60 | dependency: "direct main" 61 | description: 62 | name: cupertino_icons 63 | sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be 64 | url: "https://pub.dev" 65 | source: hosted 66 | version: "1.0.5" 67 | dio: 68 | dependency: "direct main" 69 | description: 70 | name: dio 71 | sha256: "7d328c4d898a61efc3cd93655a0955858e29a0aa647f0f9e02d59b3bb275e2e8" 72 | url: "https://pub.dev" 73 | source: hosted 74 | version: "4.0.6" 75 | fake_async: 76 | dependency: transitive 77 | description: 78 | name: fake_async 79 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" 80 | url: "https://pub.dev" 81 | source: hosted 82 | version: "1.3.1" 83 | flexi_chip: 84 | dependency: transitive 85 | description: 86 | name: flexi_chip 87 | sha256: ca33b720bfee32218e2874d571d139009a125c6ebae46162322e7a9abfc9bab8 88 | url: "https://pub.dev" 89 | source: hosted 90 | version: "1.0.7" 91 | flutter: 92 | dependency: "direct main" 93 | description: flutter 94 | source: sdk 95 | version: "0.0.0" 96 | flutter_lints: 97 | dependency: "direct dev" 98 | description: 99 | name: flutter_lints 100 | sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c 101 | url: "https://pub.dev" 102 | source: hosted 103 | version: "2.0.1" 104 | flutter_test: 105 | dependency: "direct dev" 106 | description: flutter 107 | source: sdk 108 | version: "0.0.0" 109 | http_parser: 110 | dependency: transitive 111 | description: 112 | name: http_parser 113 | sha256: db3060f22889f3d9d55f6a217565486737037eec3609f7f3eca4d0c67ee0d8a0 114 | url: "https://pub.dev" 115 | source: hosted 116 | version: "4.0.1" 117 | js: 118 | dependency: transitive 119 | description: 120 | name: js 121 | sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 122 | url: "https://pub.dev" 123 | source: hosted 124 | version: "0.6.7" 125 | lints: 126 | dependency: transitive 127 | description: 128 | name: lints 129 | sha256: "5cfd6509652ff5e7fe149b6df4859e687fca9048437857cb2e65c8d780f396e3" 130 | url: "https://pub.dev" 131 | source: hosted 132 | version: "2.0.0" 133 | matcher: 134 | dependency: transitive 135 | description: 136 | name: matcher 137 | sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" 138 | url: "https://pub.dev" 139 | source: hosted 140 | version: "0.12.15" 141 | material_color_utilities: 142 | dependency: transitive 143 | description: 144 | name: material_color_utilities 145 | sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 146 | url: "https://pub.dev" 147 | source: hosted 148 | version: "0.2.0" 149 | meta: 150 | dependency: transitive 151 | description: 152 | name: meta 153 | sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" 154 | url: "https://pub.dev" 155 | source: hosted 156 | version: "1.9.1" 157 | path: 158 | dependency: transitive 159 | description: 160 | name: path 161 | sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" 162 | url: "https://pub.dev" 163 | source: hosted 164 | version: "1.8.3" 165 | sky_engine: 166 | dependency: transitive 167 | description: flutter 168 | source: sdk 169 | version: "0.0.99" 170 | source_span: 171 | dependency: transitive 172 | description: 173 | name: source_span 174 | sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 175 | url: "https://pub.dev" 176 | source: hosted 177 | version: "1.9.1" 178 | stack_trace: 179 | dependency: transitive 180 | description: 181 | name: stack_trace 182 | sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 183 | url: "https://pub.dev" 184 | source: hosted 185 | version: "1.11.0" 186 | stream_channel: 187 | dependency: transitive 188 | description: 189 | name: stream_channel 190 | sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" 191 | url: "https://pub.dev" 192 | source: hosted 193 | version: "2.1.1" 194 | string_scanner: 195 | dependency: transitive 196 | description: 197 | name: string_scanner 198 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" 199 | url: "https://pub.dev" 200 | source: hosted 201 | version: "1.2.0" 202 | term_glyph: 203 | dependency: transitive 204 | description: 205 | name: term_glyph 206 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 207 | url: "https://pub.dev" 208 | source: hosted 209 | version: "1.2.1" 210 | test_api: 211 | dependency: transitive 212 | description: 213 | name: test_api 214 | sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb 215 | url: "https://pub.dev" 216 | source: hosted 217 | version: "0.5.1" 218 | theme_patrol: 219 | dependency: "direct main" 220 | description: 221 | name: theme_patrol 222 | sha256: e1634b1751c54b1e5ee1991758baaedf219745b71fa8072d672991a976feb707 223 | url: "https://pub.dev" 224 | source: hosted 225 | version: "2.1.0" 226 | typed_data: 227 | dependency: transitive 228 | description: 229 | name: typed_data 230 | sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" 231 | url: "https://pub.dev" 232 | source: hosted 233 | version: "1.3.1" 234 | vector_math: 235 | dependency: transitive 236 | description: 237 | name: vector_math 238 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 239 | url: "https://pub.dev" 240 | source: hosted 241 | version: "2.1.4" 242 | widget_event: 243 | dependency: transitive 244 | description: 245 | name: widget_event 246 | sha256: b71014bc7d8ec85a325357e76e6b5769ee1d8a67d099a6ce5c429440a19dbf18 247 | url: "https://pub.dev" 248 | source: hosted 249 | version: "1.2.5" 250 | sdks: 251 | dart: ">=3.0.0-0 <4.0.0" 252 | flutter: ">=2.0.0" 253 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: chips_choice_example 2 | description: An example of chips_choice package. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `flutter pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | # The following defines the version and build number for your application. 9 | # A version number is three numbers separated by dots, like 1.2.43 10 | # followed by an optional build number separated by a +. 11 | # Both the version and the builder number may be overridden in flutter 12 | # build by specifying --build-name and --build-number, respectively. 13 | # In Android, build-name is used as versionName while build-number used as versionCode. 14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 16 | # Read more about iOS versioning at 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 18 | version: 1.0.0+1 19 | 20 | environment: 21 | sdk: ">=2.17.6 <3.0.0" 22 | 23 | # Dependencies specify other packages that your package needs in order to work. 24 | # To automatically upgrade your package dependencies to the latest versions 25 | # consider running `flutter pub upgrade --major-versions`. Alternatively, 26 | # dependencies can be manually updated by changing the version numbers below to 27 | # the latest version available on pub.dev. To see which dependencies have newer 28 | # versions available, run `flutter pub outdated`. 29 | dependencies: 30 | flutter: 31 | sdk: flutter 32 | chips_choice: 33 | path: ../ 34 | theme_patrol: ^2.1.0 35 | animated_checkmark: ^1.0.1 36 | dio: ^4.0.0 37 | 38 | 39 | # The following adds the Cupertino Icons font to your application. 40 | # Use with the CupertinoIcons class for iOS style icons. 41 | cupertino_icons: ^1.0.2 42 | 43 | dev_dependencies: 44 | flutter_test: 45 | sdk: flutter 46 | 47 | # The "flutter_lints" package below contains a set of recommended lints to 48 | # encourage good coding practices. The lint set provided by the package is 49 | # activated in the `analysis_options.yaml` file located at the root of your 50 | # package. See that file for information about deactivating specific lint 51 | # rules and activating additional ones. 52 | flutter_lints: ^2.0.0 53 | 54 | # For information on the generic Dart part of this file, see the 55 | # following page: https://dart.dev/tools/pub/pubspec 56 | 57 | # The following section is specific to Flutter packages. 58 | flutter: 59 | 60 | # The following line ensures that the Material Icons font is 61 | # included with your application, so that you can use the icons in 62 | # the material Icons class. 63 | uses-material-design: true 64 | 65 | # To add assets to your application, add an assets section, like this: 66 | # assets: 67 | # - images/a_dot_burr.jpeg 68 | # - images/a_dot_ham.jpeg 69 | 70 | # An image asset can refer to one or more resolution-specific "variants", see 71 | # https://flutter.dev/assets-and-images/#resolution-aware 72 | 73 | # For details regarding adding assets from package dependencies, see 74 | # https://flutter.dev/assets-and-images/#from-packages 75 | 76 | # To add custom fonts to your application, add a fonts section here, 77 | # in this "flutter" section. Each entry in this list should have a 78 | # "family" key with the font family name, and a "fonts" key with a 79 | # list giving the asset and other descriptors for the font. For 80 | # example: 81 | # fonts: 82 | # - family: Schyler 83 | # fonts: 84 | # - asset: fonts/Schyler-Regular.ttf 85 | # - asset: fonts/Schyler-Italic.ttf 86 | # style: italic 87 | # - family: Trajan Pro 88 | # fonts: 89 | # - asset: fonts/TrajanPro.ttf 90 | # - asset: fonts/TrajanPro_Bold.ttf 91 | # weight: 700 92 | # 93 | # For details regarding fonts from package dependencies, 94 | # see https://flutter.dev/custom-fonts/#from-packages 95 | -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility in the flutter_test package. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:chips_choice_example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/web/favicon.png -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | chips_choice_example 33 | 34 | 35 | 39 | 40 | 41 | 42 | 43 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chips_choice_example", 3 | "short_name": "chips_choice_example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /example/windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /example/windows/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Project-level configuration. 2 | cmake_minimum_required(VERSION 3.14) 3 | project(chips_choice_example LANGUAGES CXX) 4 | 5 | # The name of the executable created for the application. Change this to change 6 | # the on-disk name of your application. 7 | set(BINARY_NAME "chips_choice_example") 8 | 9 | # Explicitly opt in to modern CMake behaviors to avoid warnings with recent 10 | # versions of CMake. 11 | cmake_policy(SET CMP0063 NEW) 12 | 13 | # Define build configuration option. 14 | get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) 15 | if(IS_MULTICONFIG) 16 | set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" 17 | CACHE STRING "" FORCE) 18 | else() 19 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 20 | set(CMAKE_BUILD_TYPE "Debug" CACHE 21 | STRING "Flutter build mode" FORCE) 22 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 23 | "Debug" "Profile" "Release") 24 | endif() 25 | endif() 26 | # Define settings for the Profile build mode. 27 | set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") 28 | set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") 29 | set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") 30 | set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") 31 | 32 | # Use Unicode for all projects. 33 | add_definitions(-DUNICODE -D_UNICODE) 34 | 35 | # Compilation settings that should be applied to most targets. 36 | # 37 | # Be cautious about adding new options here, as plugins use this function by 38 | # default. In most cases, you should add new options to specific targets instead 39 | # of modifying this function. 40 | function(APPLY_STANDARD_SETTINGS TARGET) 41 | target_compile_features(${TARGET} PUBLIC cxx_std_17) 42 | target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") 43 | target_compile_options(${TARGET} PRIVATE /EHsc) 44 | target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") 45 | target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") 46 | endfunction() 47 | 48 | # Flutter library and tool build rules. 49 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 50 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 51 | 52 | # Application build; see runner/CMakeLists.txt. 53 | add_subdirectory("runner") 54 | 55 | # Generated plugin build rules, which manage building the plugins and adding 56 | # them to the application. 57 | include(flutter/generated_plugins.cmake) 58 | 59 | 60 | # === Installation === 61 | # Support files are copied into place next to the executable, so that it can 62 | # run in place. This is done instead of making a separate bundle (as on Linux) 63 | # so that building and running from within Visual Studio will work. 64 | set(BUILD_BUNDLE_DIR "$") 65 | # Make the "install" step default, as it's required to run. 66 | set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) 67 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 68 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 69 | endif() 70 | 71 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 72 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") 73 | 74 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 75 | COMPONENT Runtime) 76 | 77 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 78 | COMPONENT Runtime) 79 | 80 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 81 | COMPONENT Runtime) 82 | 83 | if(PLUGIN_BUNDLED_LIBRARIES) 84 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" 85 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 86 | COMPONENT Runtime) 87 | endif() 88 | 89 | # Fully re-copy the assets directory on each build to avoid having stale files 90 | # from a previous install. 91 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 92 | install(CODE " 93 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 94 | " COMPONENT Runtime) 95 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 96 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 97 | 98 | # Install the AOT library on non-Debug builds only. 99 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 100 | CONFIGURATIONS Profile;Release 101 | COMPONENT Runtime) 102 | -------------------------------------------------------------------------------- /example/windows/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file controls Flutter-level build steps. It should not be edited. 2 | cmake_minimum_required(VERSION 3.14) 3 | 4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 5 | 6 | # Configuration provided via flutter tool. 7 | include(${EPHEMERAL_DIR}/generated_config.cmake) 8 | 9 | # TODO: Move the rest of this into files in ephemeral. See 10 | # https://github.com/flutter/flutter/issues/57146. 11 | set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") 12 | 13 | # === Flutter Library === 14 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") 15 | 16 | # Published to parent scope for install step. 17 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 18 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 19 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 20 | set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) 21 | 22 | list(APPEND FLUTTER_LIBRARY_HEADERS 23 | "flutter_export.h" 24 | "flutter_windows.h" 25 | "flutter_messenger.h" 26 | "flutter_plugin_registrar.h" 27 | "flutter_texture_registrar.h" 28 | ) 29 | list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") 30 | add_library(flutter INTERFACE) 31 | target_include_directories(flutter INTERFACE 32 | "${EPHEMERAL_DIR}" 33 | ) 34 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") 35 | add_dependencies(flutter flutter_assemble) 36 | 37 | # === Wrapper === 38 | list(APPEND CPP_WRAPPER_SOURCES_CORE 39 | "core_implementations.cc" 40 | "standard_codec.cc" 41 | ) 42 | list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") 43 | list(APPEND CPP_WRAPPER_SOURCES_PLUGIN 44 | "plugin_registrar.cc" 45 | ) 46 | list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") 47 | list(APPEND CPP_WRAPPER_SOURCES_APP 48 | "flutter_engine.cc" 49 | "flutter_view_controller.cc" 50 | ) 51 | list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") 52 | 53 | # Wrapper sources needed for a plugin. 54 | add_library(flutter_wrapper_plugin STATIC 55 | ${CPP_WRAPPER_SOURCES_CORE} 56 | ${CPP_WRAPPER_SOURCES_PLUGIN} 57 | ) 58 | apply_standard_settings(flutter_wrapper_plugin) 59 | set_target_properties(flutter_wrapper_plugin PROPERTIES 60 | POSITION_INDEPENDENT_CODE ON) 61 | set_target_properties(flutter_wrapper_plugin PROPERTIES 62 | CXX_VISIBILITY_PRESET hidden) 63 | target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) 64 | target_include_directories(flutter_wrapper_plugin PUBLIC 65 | "${WRAPPER_ROOT}/include" 66 | ) 67 | add_dependencies(flutter_wrapper_plugin flutter_assemble) 68 | 69 | # Wrapper sources needed for the runner. 70 | add_library(flutter_wrapper_app STATIC 71 | ${CPP_WRAPPER_SOURCES_CORE} 72 | ${CPP_WRAPPER_SOURCES_APP} 73 | ) 74 | apply_standard_settings(flutter_wrapper_app) 75 | target_link_libraries(flutter_wrapper_app PUBLIC flutter) 76 | target_include_directories(flutter_wrapper_app PUBLIC 77 | "${WRAPPER_ROOT}/include" 78 | ) 79 | add_dependencies(flutter_wrapper_app flutter_assemble) 80 | 81 | # === Flutter tool backend === 82 | # _phony_ is a non-existent file to force this command to run every time, 83 | # since currently there's no way to get a full input/output list from the 84 | # flutter tool. 85 | set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") 86 | set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) 87 | add_custom_command( 88 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 89 | ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} 90 | ${CPP_WRAPPER_SOURCES_APP} 91 | ${PHONY_OUTPUT} 92 | COMMAND ${CMAKE_COMMAND} -E env 93 | ${FLUTTER_TOOL_ENVIRONMENT} 94 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" 95 | windows-x64 $ 96 | VERBATIM 97 | ) 98 | add_custom_target(flutter_assemble DEPENDS 99 | "${FLUTTER_LIBRARY}" 100 | ${FLUTTER_LIBRARY_HEADERS} 101 | ${CPP_WRAPPER_SOURCES_CORE} 102 | ${CPP_WRAPPER_SOURCES_PLUGIN} 103 | ${CPP_WRAPPER_SOURCES_APP} 104 | ) 105 | -------------------------------------------------------------------------------- /example/windows/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | 10 | void RegisterPlugins(flutter::PluginRegistry* registry) { 11 | } 12 | -------------------------------------------------------------------------------- /example/windows/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void RegisterPlugins(flutter::PluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /example/windows/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | ) 7 | 8 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 9 | ) 10 | 11 | set(PLUGIN_BUNDLED_LIBRARIES) 12 | 13 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 14 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) 15 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 16 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 18 | endforeach(plugin) 19 | 20 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 21 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) 22 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 23 | endforeach(ffi_plugin) 24 | -------------------------------------------------------------------------------- /example/windows/runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | project(runner LANGUAGES CXX) 3 | 4 | # Define the application target. To change its name, change BINARY_NAME in the 5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer 6 | # work. 7 | # 8 | # Any new source files that you add to the application should be added here. 9 | add_executable(${BINARY_NAME} WIN32 10 | "flutter_window.cpp" 11 | "main.cpp" 12 | "utils.cpp" 13 | "win32_window.cpp" 14 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 15 | "Runner.rc" 16 | "runner.exe.manifest" 17 | ) 18 | 19 | # Apply the standard set of build settings. This can be removed for applications 20 | # that need different build settings. 21 | apply_standard_settings(${BINARY_NAME}) 22 | 23 | # Add preprocessor definitions for the build version. 24 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") 25 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") 26 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") 27 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") 28 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") 29 | 30 | # Disable Windows macros that collide with C++ standard library functions. 31 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") 32 | 33 | # Add dependency libraries and include directories. Add any application-specific 34 | # dependencies here. 35 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) 36 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") 37 | 38 | # Run the Flutter tool portions of the build. This must not be removed. 39 | add_dependencies(${BINARY_NAME} flutter_assemble) 40 | -------------------------------------------------------------------------------- /example/windows/runner/Runner.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #pragma code_page(65001) 4 | #include "resource.h" 5 | 6 | #define APSTUDIO_READONLY_SYMBOLS 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // 9 | // Generated from the TEXTINCLUDE 2 resource. 10 | // 11 | #include "winres.h" 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | #undef APSTUDIO_READONLY_SYMBOLS 15 | 16 | ///////////////////////////////////////////////////////////////////////////// 17 | // English (United States) resources 18 | 19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // Icon 51 | // 52 | 53 | // Icon with lowest ID value placed first to ensure application icon 54 | // remains consistent on all systems. 55 | IDI_APP_ICON ICON "resources\\app_icon.ico" 56 | 57 | 58 | ///////////////////////////////////////////////////////////////////////////// 59 | // 60 | // Version 61 | // 62 | 63 | #if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) 64 | #define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD 65 | #else 66 | #define VERSION_AS_NUMBER 1,0,0,0 67 | #endif 68 | 69 | #if defined(FLUTTER_VERSION) 70 | #define VERSION_AS_STRING FLUTTER_VERSION 71 | #else 72 | #define VERSION_AS_STRING "1.0.0" 73 | #endif 74 | 75 | VS_VERSION_INFO VERSIONINFO 76 | FILEVERSION VERSION_AS_NUMBER 77 | PRODUCTVERSION VERSION_AS_NUMBER 78 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 79 | #ifdef _DEBUG 80 | FILEFLAGS VS_FF_DEBUG 81 | #else 82 | FILEFLAGS 0x0L 83 | #endif 84 | FILEOS VOS__WINDOWS32 85 | FILETYPE VFT_APP 86 | FILESUBTYPE 0x0L 87 | BEGIN 88 | BLOCK "StringFileInfo" 89 | BEGIN 90 | BLOCK "040904e4" 91 | BEGIN 92 | VALUE "CompanyName", "com.example" "\0" 93 | VALUE "FileDescription", "chips_choice_example" "\0" 94 | VALUE "FileVersion", VERSION_AS_STRING "\0" 95 | VALUE "InternalName", "chips_choice_example" "\0" 96 | VALUE "LegalCopyright", "Copyright (C) 2022 com.example. All rights reserved." "\0" 97 | VALUE "OriginalFilename", "chips_choice_example.exe" "\0" 98 | VALUE "ProductName", "chips_choice_example" "\0" 99 | VALUE "ProductVersion", VERSION_AS_STRING "\0" 100 | END 101 | END 102 | BLOCK "VarFileInfo" 103 | BEGIN 104 | VALUE "Translation", 0x409, 1252 105 | END 106 | END 107 | 108 | #endif // English (United States) resources 109 | ///////////////////////////////////////////////////////////////////////////// 110 | 111 | 112 | 113 | #ifndef APSTUDIO_INVOKED 114 | ///////////////////////////////////////////////////////////////////////////// 115 | // 116 | // Generated from the TEXTINCLUDE 3 resource. 117 | // 118 | 119 | 120 | ///////////////////////////////////////////////////////////////////////////// 121 | #endif // not APSTUDIO_INVOKED 122 | -------------------------------------------------------------------------------- /example/windows/runner/flutter_window.cpp: -------------------------------------------------------------------------------- 1 | #include "flutter_window.h" 2 | 3 | #include 4 | 5 | #include "flutter/generated_plugin_registrant.h" 6 | 7 | FlutterWindow::FlutterWindow(const flutter::DartProject& project) 8 | : project_(project) {} 9 | 10 | FlutterWindow::~FlutterWindow() {} 11 | 12 | bool FlutterWindow::OnCreate() { 13 | if (!Win32Window::OnCreate()) { 14 | return false; 15 | } 16 | 17 | RECT frame = GetClientArea(); 18 | 19 | // The size here must match the window dimensions to avoid unnecessary surface 20 | // creation / destruction in the startup path. 21 | flutter_controller_ = std::make_unique( 22 | frame.right - frame.left, frame.bottom - frame.top, project_); 23 | // Ensure that basic setup of the controller was successful. 24 | if (!flutter_controller_->engine() || !flutter_controller_->view()) { 25 | return false; 26 | } 27 | RegisterPlugins(flutter_controller_->engine()); 28 | SetChildContent(flutter_controller_->view()->GetNativeWindow()); 29 | return true; 30 | } 31 | 32 | void FlutterWindow::OnDestroy() { 33 | if (flutter_controller_) { 34 | flutter_controller_ = nullptr; 35 | } 36 | 37 | Win32Window::OnDestroy(); 38 | } 39 | 40 | LRESULT 41 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message, 42 | WPARAM const wparam, 43 | LPARAM const lparam) noexcept { 44 | // Give Flutter, including plugins, an opportunity to handle window messages. 45 | if (flutter_controller_) { 46 | std::optional result = 47 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, 48 | lparam); 49 | if (result) { 50 | return *result; 51 | } 52 | } 53 | 54 | switch (message) { 55 | case WM_FONTCHANGE: 56 | flutter_controller_->engine()->ReloadSystemFonts(); 57 | break; 58 | } 59 | 60 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam); 61 | } 62 | -------------------------------------------------------------------------------- /example/windows/runner/flutter_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_FLUTTER_WINDOW_H_ 2 | #define RUNNER_FLUTTER_WINDOW_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "win32_window.h" 10 | 11 | // A window that does nothing but host a Flutter view. 12 | class FlutterWindow : public Win32Window { 13 | public: 14 | // Creates a new FlutterWindow hosting a Flutter view running |project|. 15 | explicit FlutterWindow(const flutter::DartProject& project); 16 | virtual ~FlutterWindow(); 17 | 18 | protected: 19 | // Win32Window: 20 | bool OnCreate() override; 21 | void OnDestroy() override; 22 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, 23 | LPARAM const lparam) noexcept override; 24 | 25 | private: 26 | // The project to run. 27 | flutter::DartProject project_; 28 | 29 | // The Flutter instance hosted by this window. 30 | std::unique_ptr flutter_controller_; 31 | }; 32 | 33 | #endif // RUNNER_FLUTTER_WINDOW_H_ 34 | -------------------------------------------------------------------------------- /example/windows/runner/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "flutter_window.h" 6 | #include "utils.h" 7 | 8 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, 9 | _In_ wchar_t *command_line, _In_ int show_command) { 10 | // Attach to console when present (e.g., 'flutter run') or create a 11 | // new console when running with a debugger. 12 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { 13 | CreateAndAttachConsole(); 14 | } 15 | 16 | // Initialize COM, so that it is available for use in the library and/or 17 | // plugins. 18 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); 19 | 20 | flutter::DartProject project(L"data"); 21 | 22 | std::vector command_line_arguments = 23 | GetCommandLineArguments(); 24 | 25 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); 26 | 27 | FlutterWindow window(project); 28 | Win32Window::Point origin(10, 10); 29 | Win32Window::Size size(1280, 720); 30 | if (!window.CreateAndShow(L"chips_choice_example", origin, size)) { 31 | return EXIT_FAILURE; 32 | } 33 | window.SetQuitOnClose(true); 34 | 35 | ::MSG msg; 36 | while (::GetMessage(&msg, nullptr, 0, 0)) { 37 | ::TranslateMessage(&msg); 38 | ::DispatchMessage(&msg); 39 | } 40 | 41 | ::CoUninitialize(); 42 | return EXIT_SUCCESS; 43 | } 44 | -------------------------------------------------------------------------------- /example/windows/runner/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Runner.rc 4 | // 5 | #define IDI_APP_ICON 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /example/windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/example/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /example/windows/runner/runner.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PerMonitorV2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /example/windows/runner/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | void CreateAndAttachConsole() { 11 | if (::AllocConsole()) { 12 | FILE *unused; 13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) { 14 | _dup2(_fileno(stdout), 1); 15 | } 16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) { 17 | _dup2(_fileno(stdout), 2); 18 | } 19 | std::ios::sync_with_stdio(); 20 | FlutterDesktopResyncOutputStreams(); 21 | } 22 | } 23 | 24 | std::vector GetCommandLineArguments() { 25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. 26 | int argc; 27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); 28 | if (argv == nullptr) { 29 | return std::vector(); 30 | } 31 | 32 | std::vector command_line_arguments; 33 | 34 | // Skip the first argument as it's the binary name. 35 | for (int i = 1; i < argc; i++) { 36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i])); 37 | } 38 | 39 | ::LocalFree(argv); 40 | 41 | return command_line_arguments; 42 | } 43 | 44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) { 45 | if (utf16_string == nullptr) { 46 | return std::string(); 47 | } 48 | int target_length = ::WideCharToMultiByte( 49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 50 | -1, nullptr, 0, nullptr, nullptr); 51 | std::string utf8_string; 52 | if (target_length == 0 || target_length > utf8_string.max_size()) { 53 | return utf8_string; 54 | } 55 | utf8_string.resize(target_length); 56 | int converted_length = ::WideCharToMultiByte( 57 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 58 | -1, utf8_string.data(), 59 | target_length, nullptr, nullptr); 60 | if (converted_length == 0) { 61 | return std::string(); 62 | } 63 | return utf8_string; 64 | } 65 | -------------------------------------------------------------------------------- /example/windows/runner/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_UTILS_H_ 2 | #define RUNNER_UTILS_H_ 3 | 4 | #include 5 | #include 6 | 7 | // Creates a console for the process, and redirects stdout and stderr to 8 | // it for both the runner and the Flutter library. 9 | void CreateAndAttachConsole(); 10 | 11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string 12 | // encoded in UTF-8. Returns an empty std::string on failure. 13 | std::string Utf8FromUtf16(const wchar_t* utf16_string); 14 | 15 | // Gets the command line arguments passed in as a std::vector, 16 | // encoded in UTF-8. Returns an empty std::vector on failure. 17 | std::vector GetCommandLineArguments(); 18 | 19 | #endif // RUNNER_UTILS_H_ 20 | -------------------------------------------------------------------------------- /example/windows/runner/win32_window.cpp: -------------------------------------------------------------------------------- 1 | #include "win32_window.h" 2 | 3 | #include 4 | 5 | #include "resource.h" 6 | 7 | namespace { 8 | 9 | constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; 10 | 11 | // The number of Win32Window objects that currently exist. 12 | static int g_active_window_count = 0; 13 | 14 | using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); 15 | 16 | // Scale helper to convert logical scaler values to physical using passed in 17 | // scale factor 18 | int Scale(int source, double scale_factor) { 19 | return static_cast(source * scale_factor); 20 | } 21 | 22 | // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. 23 | // This API is only needed for PerMonitor V1 awareness mode. 24 | void EnableFullDpiSupportIfAvailable(HWND hwnd) { 25 | HMODULE user32_module = LoadLibraryA("User32.dll"); 26 | if (!user32_module) { 27 | return; 28 | } 29 | auto enable_non_client_dpi_scaling = 30 | reinterpret_cast( 31 | GetProcAddress(user32_module, "EnableNonClientDpiScaling")); 32 | if (enable_non_client_dpi_scaling != nullptr) { 33 | enable_non_client_dpi_scaling(hwnd); 34 | FreeLibrary(user32_module); 35 | } 36 | } 37 | 38 | } // namespace 39 | 40 | // Manages the Win32Window's window class registration. 41 | class WindowClassRegistrar { 42 | public: 43 | ~WindowClassRegistrar() = default; 44 | 45 | // Returns the singleton registar instance. 46 | static WindowClassRegistrar* GetInstance() { 47 | if (!instance_) { 48 | instance_ = new WindowClassRegistrar(); 49 | } 50 | return instance_; 51 | } 52 | 53 | // Returns the name of the window class, registering the class if it hasn't 54 | // previously been registered. 55 | const wchar_t* GetWindowClass(); 56 | 57 | // Unregisters the window class. Should only be called if there are no 58 | // instances of the window. 59 | void UnregisterWindowClass(); 60 | 61 | private: 62 | WindowClassRegistrar() = default; 63 | 64 | static WindowClassRegistrar* instance_; 65 | 66 | bool class_registered_ = false; 67 | }; 68 | 69 | WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; 70 | 71 | const wchar_t* WindowClassRegistrar::GetWindowClass() { 72 | if (!class_registered_) { 73 | WNDCLASS window_class{}; 74 | window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); 75 | window_class.lpszClassName = kWindowClassName; 76 | window_class.style = CS_HREDRAW | CS_VREDRAW; 77 | window_class.cbClsExtra = 0; 78 | window_class.cbWndExtra = 0; 79 | window_class.hInstance = GetModuleHandle(nullptr); 80 | window_class.hIcon = 81 | LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); 82 | window_class.hbrBackground = 0; 83 | window_class.lpszMenuName = nullptr; 84 | window_class.lpfnWndProc = Win32Window::WndProc; 85 | RegisterClass(&window_class); 86 | class_registered_ = true; 87 | } 88 | return kWindowClassName; 89 | } 90 | 91 | void WindowClassRegistrar::UnregisterWindowClass() { 92 | UnregisterClass(kWindowClassName, nullptr); 93 | class_registered_ = false; 94 | } 95 | 96 | Win32Window::Win32Window() { 97 | ++g_active_window_count; 98 | } 99 | 100 | Win32Window::~Win32Window() { 101 | --g_active_window_count; 102 | Destroy(); 103 | } 104 | 105 | bool Win32Window::CreateAndShow(const std::wstring& title, 106 | const Point& origin, 107 | const Size& size) { 108 | Destroy(); 109 | 110 | const wchar_t* window_class = 111 | WindowClassRegistrar::GetInstance()->GetWindowClass(); 112 | 113 | const POINT target_point = {static_cast(origin.x), 114 | static_cast(origin.y)}; 115 | HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); 116 | UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); 117 | double scale_factor = dpi / 96.0; 118 | 119 | HWND window = CreateWindow( 120 | window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, 121 | Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), 122 | Scale(size.width, scale_factor), Scale(size.height, scale_factor), 123 | nullptr, nullptr, GetModuleHandle(nullptr), this); 124 | 125 | if (!window) { 126 | return false; 127 | } 128 | 129 | return OnCreate(); 130 | } 131 | 132 | // static 133 | LRESULT CALLBACK Win32Window::WndProc(HWND const window, 134 | UINT const message, 135 | WPARAM const wparam, 136 | LPARAM const lparam) noexcept { 137 | if (message == WM_NCCREATE) { 138 | auto window_struct = reinterpret_cast(lparam); 139 | SetWindowLongPtr(window, GWLP_USERDATA, 140 | reinterpret_cast(window_struct->lpCreateParams)); 141 | 142 | auto that = static_cast(window_struct->lpCreateParams); 143 | EnableFullDpiSupportIfAvailable(window); 144 | that->window_handle_ = window; 145 | } else if (Win32Window* that = GetThisFromHandle(window)) { 146 | return that->MessageHandler(window, message, wparam, lparam); 147 | } 148 | 149 | return DefWindowProc(window, message, wparam, lparam); 150 | } 151 | 152 | LRESULT 153 | Win32Window::MessageHandler(HWND hwnd, 154 | UINT const message, 155 | WPARAM const wparam, 156 | LPARAM const lparam) noexcept { 157 | switch (message) { 158 | case WM_DESTROY: 159 | window_handle_ = nullptr; 160 | Destroy(); 161 | if (quit_on_close_) { 162 | PostQuitMessage(0); 163 | } 164 | return 0; 165 | 166 | case WM_DPICHANGED: { 167 | auto newRectSize = reinterpret_cast(lparam); 168 | LONG newWidth = newRectSize->right - newRectSize->left; 169 | LONG newHeight = newRectSize->bottom - newRectSize->top; 170 | 171 | SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, 172 | newHeight, SWP_NOZORDER | SWP_NOACTIVATE); 173 | 174 | return 0; 175 | } 176 | case WM_SIZE: { 177 | RECT rect = GetClientArea(); 178 | if (child_content_ != nullptr) { 179 | // Size and position the child window. 180 | MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, 181 | rect.bottom - rect.top, TRUE); 182 | } 183 | return 0; 184 | } 185 | 186 | case WM_ACTIVATE: 187 | if (child_content_ != nullptr) { 188 | SetFocus(child_content_); 189 | } 190 | return 0; 191 | } 192 | 193 | return DefWindowProc(window_handle_, message, wparam, lparam); 194 | } 195 | 196 | void Win32Window::Destroy() { 197 | OnDestroy(); 198 | 199 | if (window_handle_) { 200 | DestroyWindow(window_handle_); 201 | window_handle_ = nullptr; 202 | } 203 | if (g_active_window_count == 0) { 204 | WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); 205 | } 206 | } 207 | 208 | Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { 209 | return reinterpret_cast( 210 | GetWindowLongPtr(window, GWLP_USERDATA)); 211 | } 212 | 213 | void Win32Window::SetChildContent(HWND content) { 214 | child_content_ = content; 215 | SetParent(content, window_handle_); 216 | RECT frame = GetClientArea(); 217 | 218 | MoveWindow(content, frame.left, frame.top, frame.right - frame.left, 219 | frame.bottom - frame.top, true); 220 | 221 | SetFocus(child_content_); 222 | } 223 | 224 | RECT Win32Window::GetClientArea() { 225 | RECT frame; 226 | GetClientRect(window_handle_, &frame); 227 | return frame; 228 | } 229 | 230 | HWND Win32Window::GetHandle() { 231 | return window_handle_; 232 | } 233 | 234 | void Win32Window::SetQuitOnClose(bool quit_on_close) { 235 | quit_on_close_ = quit_on_close; 236 | } 237 | 238 | bool Win32Window::OnCreate() { 239 | // No-op; provided for subclasses. 240 | return true; 241 | } 242 | 243 | void Win32Window::OnDestroy() { 244 | // No-op; provided for subclasses. 245 | } 246 | -------------------------------------------------------------------------------- /example/windows/runner/win32_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_WIN32_WINDOW_H_ 2 | #define RUNNER_WIN32_WINDOW_H_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | // A class abstraction for a high DPI-aware Win32 Window. Intended to be 11 | // inherited from by classes that wish to specialize with custom 12 | // rendering and input handling 13 | class Win32Window { 14 | public: 15 | struct Point { 16 | unsigned int x; 17 | unsigned int y; 18 | Point(unsigned int x, unsigned int y) : x(x), y(y) {} 19 | }; 20 | 21 | struct Size { 22 | unsigned int width; 23 | unsigned int height; 24 | Size(unsigned int width, unsigned int height) 25 | : width(width), height(height) {} 26 | }; 27 | 28 | Win32Window(); 29 | virtual ~Win32Window(); 30 | 31 | // Creates and shows a win32 window with |title| and position and size using 32 | // |origin| and |size|. New windows are created on the default monitor. Window 33 | // sizes are specified to the OS in physical pixels, hence to ensure a 34 | // consistent size to will treat the width height passed in to this function 35 | // as logical pixels and scale to appropriate for the default monitor. Returns 36 | // true if the window was created successfully. 37 | bool CreateAndShow(const std::wstring& title, 38 | const Point& origin, 39 | const Size& size); 40 | 41 | // Release OS resources associated with window. 42 | void Destroy(); 43 | 44 | // Inserts |content| into the window tree. 45 | void SetChildContent(HWND content); 46 | 47 | // Returns the backing Window handle to enable clients to set icon and other 48 | // window properties. Returns nullptr if the window has been destroyed. 49 | HWND GetHandle(); 50 | 51 | // If true, closing this window will quit the application. 52 | void SetQuitOnClose(bool quit_on_close); 53 | 54 | // Return a RECT representing the bounds of the current client area. 55 | RECT GetClientArea(); 56 | 57 | protected: 58 | // Processes and route salient window messages for mouse handling, 59 | // size change and DPI. Delegates handling of these to member overloads that 60 | // inheriting classes can handle. 61 | virtual LRESULT MessageHandler(HWND window, 62 | UINT const message, 63 | WPARAM const wparam, 64 | LPARAM const lparam) noexcept; 65 | 66 | // Called when CreateAndShow is called, allowing subclass window-related 67 | // setup. Subclasses should return false if setup fails. 68 | virtual bool OnCreate(); 69 | 70 | // Called when Destroy is called. 71 | virtual void OnDestroy(); 72 | 73 | private: 74 | friend class WindowClassRegistrar; 75 | 76 | // OS callback called by message pump. Handles the WM_NCCREATE message which 77 | // is passed when the non-client area is being created and enables automatic 78 | // non-client DPI scaling so that the non-client area automatically 79 | // responsponds to changes in DPI. All other messages are handled by 80 | // MessageHandler. 81 | static LRESULT CALLBACK WndProc(HWND const window, 82 | UINT const message, 83 | WPARAM const wparam, 84 | LPARAM const lparam) noexcept; 85 | 86 | // Retrieves a class instance pointer for |window| 87 | static Win32Window* GetThisFromHandle(HWND const window) noexcept; 88 | 89 | bool quit_on_close_ = false; 90 | 91 | // window handle for top level window. 92 | HWND window_handle_ = nullptr; 93 | 94 | // window handle for hosted content. 95 | HWND child_content_ = nullptr; 96 | }; 97 | 98 | #endif // RUNNER_WIN32_WINDOW_H_ 99 | -------------------------------------------------------------------------------- /lib/chips_choice.dart: -------------------------------------------------------------------------------- 1 | library chips_choice; 2 | 3 | export 'src/widget.dart'; 4 | export 'src/chip.dart'; 5 | export 'src/choice.dart'; 6 | export 'src/types.dart'; 7 | -------------------------------------------------------------------------------- /lib/src/chip.dart: -------------------------------------------------------------------------------- 1 | import 'package:flexi_chip/flexi_chip.dart'; 2 | 3 | typedef C2Chip = FlexiChip; 4 | typedef C2ChipStyle = FlexiChipStyle; 5 | typedef C2ChipCheckmarkStyle = FlexiChipCheckmarkStyle; 6 | typedef C2ChipEvent = FlexiChipEvent; 7 | -------------------------------------------------------------------------------- /lib/src/choice.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'chip.dart'; 3 | 4 | /// Choice item 5 | class C2Choice { 6 | /// Value to return 7 | final T value; 8 | 9 | /// Represent as primary text 10 | final String label; 11 | 12 | /// Typically used as profile image. 13 | /// 14 | /// If the avatar is to have the user's initials, use [avatarText] instead. 15 | final ImageProvider? avatarImage; 16 | 17 | /// The primary content of the chip avatar. 18 | /// 19 | /// Typically a [Text] widget. 20 | final Widget? avatarText; 21 | 22 | /// Tooltip string to be used for the body area (where the label and avatar are) of the chip. 23 | final String? tooltip; 24 | 25 | /// This prop is useful for choice builder 26 | final dynamic meta; 27 | 28 | /// Individual choice unselected item style 29 | final C2ChipStyle? style; 30 | 31 | /// Called when the user taps the [deleteIcon] to delete the chip. 32 | /// 33 | /// If null, the delete button will not appear on the chip. 34 | /// 35 | /// The chip will not automatically remove itself: this just tells the app 36 | /// that the user tapped the delete button. 37 | final VoidCallback? delete; 38 | 39 | /// Callback to select choice 40 | /// autofill by the system 41 | /// used in choice builder 42 | final Function(bool selected)? select; 43 | 44 | /// Whether the choice is selected or not 45 | /// autofill by the system 46 | /// used in choice builder 47 | final bool selected; 48 | 49 | /// Whether the choice is disabled or not 50 | final bool disabled; 51 | 52 | /// Whether the choice is hidden or displayed 53 | final bool hidden; 54 | 55 | /// Default Constructor 56 | const C2Choice({ 57 | required this.value, 58 | required this.label, 59 | this.avatarImage, 60 | this.avatarText, 61 | this.tooltip, 62 | this.meta, 63 | this.style, 64 | this.delete, 65 | this.select, 66 | this.selected = false, 67 | this.disabled = false, 68 | this.hidden = false, 69 | }); 70 | 71 | @override 72 | bool operator ==(Object other) => 73 | identical(this, other) || 74 | other is C2Choice && 75 | runtimeType == other.runtimeType && 76 | value == other.value && 77 | label == other.label && 78 | avatarImage == other.avatarImage && 79 | avatarText == other.avatarText && 80 | tooltip == other.tooltip && 81 | delete == other.delete && 82 | disabled == other.disabled && 83 | hidden == other.hidden && 84 | selected == other.selected; 85 | 86 | @override 87 | int get hashCode => Object.hash( 88 | value, 89 | label, 90 | avatarImage, 91 | avatarText, 92 | tooltip, 93 | delete, 94 | disabled, 95 | hidden, 96 | selected, 97 | ); 98 | 99 | /// Helper to create choice items from any list 100 | static List> listFrom({ 101 | required List source, 102 | required R Function(int index, E item) value, 103 | required String Function(int index, E item) label, 104 | _C2ChoiceProp? avatarImage, 105 | _C2ChoiceProp? avatarText, 106 | _C2ChoiceProp? tooltip, 107 | _C2ChoiceProp? disabled, 108 | _C2ChoiceProp? hidden, 109 | _C2ChoiceProp? meta, 110 | _C2ChoiceProp? style, 111 | _C2ChoiceProp? delete, 112 | }) { 113 | return source 114 | .asMap() 115 | .map((index, item) { 116 | return MapEntry( 117 | index, 118 | C2Choice( 119 | value: value.call(index, item), 120 | label: label.call(index, item), 121 | avatarImage: avatarImage?.call(index, item), 122 | avatarText: avatarText?.call(index, item), 123 | tooltip: tooltip?.call(index, item), 124 | disabled: disabled?.call(index, item) ?? false, 125 | hidden: hidden?.call(index, item) ?? false, 126 | meta: meta?.call(index, item), 127 | style: style?.call(index, item), 128 | delete: delete?.call(index, item), 129 | ), 130 | ); 131 | }) 132 | .values 133 | .toList() 134 | .cast>(); 135 | } 136 | 137 | /// Creates a copy of this [C2Choice] but with 138 | /// the given fields replaced with the new values. 139 | C2Choice copyWith({ 140 | T? value, 141 | String? label, 142 | ImageProvider? avatarImage, 143 | Widget? avatarText, 144 | String? tooltip, 145 | bool? disabled, 146 | bool? hidden, 147 | dynamic meta, 148 | C2ChipStyle? style, 149 | VoidCallback? delete, 150 | Function(bool selected)? select, 151 | bool? selected, 152 | }) { 153 | return C2Choice( 154 | value: value ?? this.value, 155 | label: label ?? this.label, 156 | avatarImage: avatarImage ?? this.avatarImage, 157 | avatarText: avatarText ?? this.avatarText, 158 | tooltip: tooltip ?? this.tooltip, 159 | disabled: disabled ?? this.disabled, 160 | hidden: hidden ?? this.hidden, 161 | meta: meta ?? this.meta, 162 | style: style ?? this.style, 163 | delete: delete ?? this.delete, 164 | select: select ?? this.select, 165 | selected: selected ?? this.selected, 166 | ); 167 | } 168 | 169 | /// Creates a copy of this [S2Choice] but with 170 | /// the given fields replaced with the new values. 171 | C2Choice merge(C2Choice? other) { 172 | // if null return current object 173 | if (other == null) return this; 174 | 175 | return copyWith( 176 | value: other.value, 177 | label: other.label, 178 | avatarImage: other.avatarImage, 179 | avatarText: other.avatarText, 180 | tooltip: other.tooltip, 181 | disabled: other.disabled, 182 | hidden: other.hidden, 183 | meta: other.meta, 184 | style: other.style, 185 | delete: other.delete, 186 | select: other.select, 187 | selected: other.selected, 188 | ); 189 | } 190 | } 191 | 192 | /// Builder for option prop 193 | typedef R? _C2ChoiceProp(int index, E item); 194 | -------------------------------------------------------------------------------- /lib/src/state.dart: -------------------------------------------------------------------------------- 1 | part of 'widget.dart'; 2 | 3 | /// Chips Choice State 4 | abstract class C2State extends State> { 5 | /// Whether the chips is scrollable or not 6 | bool get isScrollable => !widget.wrapped; 7 | 8 | /// Whether the widget is multiple choice or not 9 | bool get isMultiChoice => widget.isMultiChoice; 10 | 11 | /// Whether the widget is single choice or not 12 | bool get isSingleChoice => !isMultiChoice; 13 | 14 | /// Current selected value 15 | get value; 16 | 17 | /// Called when value changed 18 | get onChanged; 19 | 20 | /// Default chip margin 21 | EdgeInsetsGeometry get defaultChipMargin => isScrollable 22 | ? ChipsChoice.defaultScrollableChipMargin 23 | : ChipsChoice.defaultWrappedChipMargin; 24 | 25 | /// Default style for unselected choice item 26 | C2ChipStyle get defaultChoiceStyle => C2ChipStyle.toned( 27 | margin: defaultChipMargin, 28 | ); 29 | 30 | /// Default style for selected choice item 31 | C2ChipStyle get defaultActiveChoiceStyle => defaultChoiceStyle; 32 | 33 | /// Placeholder string 34 | String get placeholder => 35 | widget.placeholder ?? ChipsChoice.defaultPlaceholder; 36 | 37 | /// Choice items 38 | List> choiceItems = []; 39 | 40 | /// Async memoizer for choice items 41 | C2ChoiceMemoizer? choiceItemsMemoizer; 42 | 43 | bool get hasChoiceLoader => widget.choiceLoader != null; 44 | 45 | bool get hasChoiceLoaderRun => choiceItemsMemoizer?.hasRun ?? false; 46 | 47 | /// Whether the choice items is loading or not 48 | bool loading = false; 49 | 50 | /// Choice loader error 51 | String error = ''; 52 | 53 | ScrollController? _internalScrollController; 54 | ScrollController? get scrollController { 55 | return isScrollable 56 | ? (widget.scrollController ?? _internalScrollController) 57 | : null; 58 | } 59 | 60 | @protected 61 | BuildContext? selectedContext; 62 | 63 | /// Function to select a value 64 | void select(T val, {bool selected = true}); 65 | 66 | @override 67 | void setState(fn) { 68 | if (mounted) { 69 | super.setState(fn); 70 | } 71 | } 72 | 73 | @override 74 | void initState() { 75 | initScrollController(); 76 | loadChoiceItems(ensureSelectedVisibility: true); 77 | super.initState(); 78 | } 79 | 80 | @override 81 | void dispose() { 82 | disposeScrollController(); 83 | super.dispose(); 84 | } 85 | 86 | @override 87 | void didUpdateWidget(ChipsChoice oldWidget) { 88 | if (oldWidget.scrollController != widget.scrollController) { 89 | initScrollController(); 90 | } 91 | 92 | if (!listEquals(oldWidget.choiceItems, widget.choiceItems) || 93 | oldWidget.choiceLoader != widget.choiceLoader) { 94 | loadChoiceItems(); 95 | } 96 | 97 | super.didUpdateWidget(oldWidget); 98 | } 99 | 100 | @protected 101 | void initScrollController() { 102 | _internalScrollController = isScrollable && widget.scrollController == null 103 | ? ScrollController() 104 | : null; 105 | scrollController?.addListener(didChangeScrollController); 106 | } 107 | 108 | @protected 109 | void didChangeScrollController() { 110 | setState(() {}); 111 | } 112 | 113 | @protected 114 | void disposeScrollController() { 115 | scrollController?.removeListener(didChangeScrollController); 116 | _internalScrollController?.dispose(); 117 | } 118 | 119 | @protected 120 | 121 | /// load the choice items 122 | void loadChoiceItems({ensureSelectedVisibility = false}) async { 123 | try { 124 | setState(() => choiceItems = widget.choiceItems); 125 | 126 | // load async choice items 127 | if (hasChoiceLoader) { 128 | choiceItemsMemoizer = choiceItemsMemoizer ?? C2ChoiceMemoizer(); 129 | await loadAsyncChoiceItems(); 130 | } 131 | } finally { 132 | if (ensureSelectedVisibility == true) scrollToSelected(); 133 | } 134 | } 135 | 136 | @protected 137 | Future loadAsyncChoiceItems() async { 138 | if (hasChoiceLoaderRun) return; 139 | try { 140 | setState(() { 141 | error = ''; 142 | loading = true; 143 | }); 144 | final List> items = await choiceItemsMemoizer!.runOnce( 145 | () => widget.choiceLoader!(), 146 | ); 147 | setState(() => choiceItems = items); 148 | } catch (e) { 149 | setState(() => error = e.toString()); 150 | } finally { 151 | setState(() => loading = false); 152 | } 153 | } 154 | 155 | /// Scroll to the selected choice item 156 | void scrollToSelected() { 157 | WidgetsBinding.instance.addPostFrameCallback((_) { 158 | final renderObject = selectedContext?.findRenderObject(); 159 | if (isScrollable && renderObject != null) { 160 | scrollController?.position.ensureVisible(renderObject); 161 | } 162 | }); 163 | } 164 | 165 | @override 166 | Widget build(BuildContext context) { 167 | final EdgeInsetsGeometry padding = 168 | widget.padding ?? ChipsChoice.defaultPadding; 169 | return loading == true 170 | ? C2Spinner( 171 | padding: padding, 172 | size: widget.spinnerSize, 173 | color: widget.spinnerColor, 174 | thickness: widget.spinnerThickness, 175 | ) 176 | : choiceItems.isNotEmpty 177 | ? isScrollable 178 | ? listScrollable 179 | : listWrapped 180 | : error.isNotEmpty 181 | ? widget.errorBuilder?.call(context) ?? 182 | C2Placeholder( 183 | padding: padding, 184 | style: widget.errorStyle, 185 | align: widget.errorAlign, 186 | message: error, 187 | ) 188 | : widget.placeholderBuilder?.call(context) ?? 189 | C2Placeholder( 190 | padding: padding, 191 | style: widget.placeholderStyle, 192 | align: widget.placeholderAlign, 193 | message: placeholder, 194 | ); 195 | } 196 | 197 | /// The scrollable choice items 198 | Widget get listScrollable { 199 | return SingleChildScrollView( 200 | primary: false, 201 | padding: widget.padding ?? ChipsChoice.defaultScrollablePadding, 202 | scrollDirection: widget.direction, 203 | clipBehavior: widget.clipBehavior, 204 | physics: widget.scrollPhysics, 205 | controller: scrollController, 206 | child: Flex( 207 | direction: widget.direction, 208 | verticalDirection: widget.verticalDirection, 209 | textDirection: widget.textDirection, 210 | clipBehavior: widget.clipBehavior, 211 | crossAxisAlignment: widget.crossAxisAlignment, 212 | mainAxisAlignment: widget.mainAxisAlignment, 213 | mainAxisSize: widget.mainAxisSize, 214 | children: choiceChips, 215 | ), 216 | ); 217 | } 218 | 219 | /// The non scrollable choice items 220 | Widget get listWrapped { 221 | return Padding( 222 | padding: widget.padding ?? ChipsChoice.defaultWrappedPadding, 223 | child: Wrap( 224 | direction: widget.direction, 225 | textDirection: widget.textDirection, 226 | verticalDirection: widget.verticalDirection, 227 | alignment: widget.alignment, 228 | runAlignment: widget.runAlignment, 229 | crossAxisAlignment: widget.wrapCrossAlignment, 230 | spacing: widget.spacing, // gap between adjacent chips 231 | runSpacing: widget.runSpacing, // gap between lines 232 | clipBehavior: widget.clipBehavior, 233 | children: choiceChips, 234 | ), 235 | ); 236 | } 237 | 238 | /// List of widget of the choice items 239 | List get choiceChips { 240 | final choiceWidgets = List.generate( 241 | choiceItems.length, 242 | (i) => choiceChip(i), 243 | growable: false, 244 | ); 245 | return [ 246 | widget.leading, 247 | ...choiceWidgets, 248 | widget.trailing, 249 | ].whereType().toList(); 250 | } 251 | 252 | Widget choiceLabelBuilder(C2Choice item, int i) { 253 | return widget.choiceLabelBuilder?.call(item, i) ?? Text(item.label); 254 | } 255 | 256 | /// Widget generator for choice items 257 | Widget? choiceChip(int i) { 258 | final data = choiceItems[i]; 259 | final selected = isMultiChoice 260 | ? widget.multiValue.contains(data.value) 261 | : widget.singleValue == data.value; 262 | final item = data.copyWith( 263 | style: defaultChoiceStyle.merge(widget.choiceStyle).merge(data.style), 264 | selected: selected, 265 | select: (selected) => select(data.value, selected: selected), 266 | ); 267 | final isSelectedTarget = isScrollable 268 | ? isMultiChoice 269 | ? selected && (widget.multiValue[0] == item.value) 270 | : selected 271 | : false; 272 | return item.hidden == true 273 | ? null 274 | : Builder( 275 | key: ValueKey('${item.value}'), 276 | builder: (context) { 277 | if (isSelectedTarget) { 278 | selectedContext = context; 279 | } 280 | return widget.choiceBuilder?.call(item, i) ?? 281 | C2Chip( 282 | label: choiceLabelBuilder.call(item, i), 283 | avatarImage: item.avatarImage, 284 | avatarText: item.avatarText, 285 | leading: widget.choiceLeadingBuilder?.call(item, i), 286 | trailing: widget.choiceTrailingBuilder?.call(item, i), 287 | checkmark: widget.choiceCheckmark, 288 | style: item.style, 289 | disabled: item.disabled, 290 | selected: item.selected, 291 | onSelected: item.select, 292 | onDeleted: item.delete, 293 | tooltip: item.tooltip, 294 | ); 295 | }, 296 | ); 297 | } 298 | } 299 | 300 | /// This allows a value of type T or T? 301 | /// to be treated as a value of type T?. 302 | /// 303 | /// We use this so that APIs that have become 304 | /// non-nullable can still be used with `!` and `?` 305 | /// to support older versions of the API as well. 306 | // T? _ambiguate(T? value) => value; 307 | -------------------------------------------------------------------------------- /lib/src/state_multi.dart: -------------------------------------------------------------------------------- 1 | part of 'widget.dart'; 2 | 3 | /// State for Single Choice 4 | class C2MultiState extends C2State { 5 | @override 6 | List get value => widget.multiValue; 7 | 8 | @override 9 | C2Changed>? get onChanged => widget.multiOnChanged; 10 | 11 | @override 12 | void select(T val, {bool selected = true}) { 13 | final List values = List.from(value); 14 | if (selected) { 15 | values.add(val); 16 | } else { 17 | values.remove(val); 18 | } 19 | onChanged?.call(values); 20 | } 21 | 22 | @override 23 | void didUpdateWidget(ChipsChoice oldWidget) { 24 | super.didUpdateWidget(oldWidget); 25 | 26 | // scroll to selected 27 | if (!listEquals(oldWidget.multiValue, widget.multiValue) && 28 | widget.scrollToSelectedOnChanged) { 29 | scrollToSelected(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/src/state_single.dart: -------------------------------------------------------------------------------- 1 | part of 'widget.dart'; 2 | 3 | /// State for Single Choice 4 | class C2SingleState extends C2State { 5 | @override 6 | T? get value => widget.singleValue; 7 | 8 | @override 9 | C2Changed? get onChanged => widget.singleOnChanged; 10 | 11 | @override 12 | void select(T val, {bool selected = true}) { 13 | onChanged?.call(val); 14 | } 15 | 16 | @override 17 | void didUpdateWidget(ChipsChoice oldWidget) { 18 | super.didUpdateWidget(oldWidget); 19 | 20 | // scroll to selected 21 | if (oldWidget.singleValue != widget.singleValue && 22 | widget.scrollToSelectedOnChanged) { 23 | scrollToSelected(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/src/types.dart: -------------------------------------------------------------------------------- 1 | import 'package:async/async.dart'; 2 | import 'package:flutter/widgets.dart'; 3 | import 'choice.dart'; 4 | 5 | /// Callback when the value changed 6 | typedef C2Changed = void Function(T value); 7 | 8 | /// Callback to load the choice items 9 | typedef C2ChoiceLoader = Future>> Function(); 10 | 11 | /// Builder for custom choice item 12 | typedef C2Builder = Widget? Function(C2Choice item, int i); 13 | 14 | /// alias to AsyncMemoizer 15 | class C2ChoiceMemoizer extends AsyncMemoizer>> {} 16 | -------------------------------------------------------------------------------- /lib/src/utils.dart: -------------------------------------------------------------------------------- 1 | part of 'widget.dart'; 2 | 3 | /// Default spinner widget 4 | class C2Spinner extends StatelessWidget { 5 | /// Spinner padding 6 | final EdgeInsetsGeometry? padding; 7 | 8 | /// Spinner size 9 | final double? size; 10 | 11 | /// Spinner color 12 | final Color? color; 13 | 14 | /// Spinner thickness 15 | final double? thickness; 16 | 17 | /// Default constructor 18 | const C2Spinner({ 19 | Key? key, 20 | this.padding, 21 | this.size, 22 | this.color, 23 | this.thickness, 24 | }) : super(key: key); 25 | 26 | /// Default spinner padding 27 | static final EdgeInsetsGeometry defaultPadding = const EdgeInsets.all(25); 28 | 29 | /// Default spinner size 30 | static final double defaultSize = 20; 31 | 32 | /// Default spinner thickness 33 | static final double defaultThickness = 2; 34 | 35 | @override 36 | Widget build(BuildContext context) { 37 | return Padding( 38 | padding: padding ?? C2Spinner.defaultPadding, 39 | child: Center( 40 | child: SizedBox( 41 | width: size ?? C2Spinner.defaultSize, 42 | height: size ?? C2Spinner.defaultSize, 43 | child: CircularProgressIndicator( 44 | strokeWidth: thickness ?? C2Spinner.defaultThickness, 45 | valueColor: AlwaysStoppedAnimation( 46 | color ?? Theme.of(context).colorScheme.secondary, 47 | ), 48 | ), 49 | ), 50 | ), 51 | ); 52 | } 53 | } 54 | 55 | /// Default placeholder widget 56 | class C2Placeholder extends StatelessWidget { 57 | /// String to display 58 | final String message; 59 | 60 | /// Placeholder text style 61 | final TextStyle? style; 62 | 63 | /// Placeholder text align 64 | final TextAlign? align; 65 | 66 | /// Placeholder padding 67 | final EdgeInsetsGeometry? padding; 68 | 69 | /// Default constructor 70 | const C2Placeholder({ 71 | Key? key, 72 | required this.message, 73 | this.style, 74 | this.align, 75 | this.padding, 76 | }) : super(key: key); 77 | 78 | /// Default text style 79 | static final TextStyle defaultStyle = const TextStyle(); 80 | 81 | /// Default text align 82 | static final TextAlign defaultAlign = TextAlign.left; 83 | 84 | /// Default padding 85 | static final EdgeInsetsGeometry defaultPadding = const EdgeInsets.all(25); 86 | 87 | @override 88 | Widget build(BuildContext context) { 89 | return Padding( 90 | padding: padding ?? C2Placeholder.defaultPadding, 91 | child: Text( 92 | message, 93 | textAlign: align ?? C2Placeholder.defaultAlign, 94 | style: C2Placeholder.defaultStyle.merge(style), 95 | ), 96 | ); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /media/preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davigmacode/flutter_chips_choice/df12206943793a50fb001ebd1741c74eff1385e2/media/preview.gif -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | animated_checkmark: 5 | dependency: transitive 6 | description: 7 | name: animated_checkmark 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "1.0.1" 11 | async: 12 | dependency: "direct main" 13 | description: 14 | name: async 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.8.2" 18 | boolean_selector: 19 | dependency: transitive 20 | description: 21 | name: boolean_selector 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.1.0" 25 | characters: 26 | dependency: transitive 27 | description: 28 | name: characters 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.2.0" 32 | charcode: 33 | dependency: transitive 34 | description: 35 | name: charcode 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.3.1" 39 | clock: 40 | dependency: transitive 41 | description: 42 | name: clock 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.1.0" 46 | collection: 47 | dependency: transitive 48 | description: 49 | name: collection 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.16.0" 53 | fake_async: 54 | dependency: transitive 55 | description: 56 | name: fake_async 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.3.0" 60 | flexi_chip: 61 | dependency: "direct main" 62 | description: 63 | name: flexi_chip 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "1.0.7" 67 | flutter: 68 | dependency: "direct main" 69 | description: flutter 70 | source: sdk 71 | version: "0.0.0" 72 | flutter_test: 73 | dependency: "direct dev" 74 | description: flutter 75 | source: sdk 76 | version: "0.0.0" 77 | matcher: 78 | dependency: transitive 79 | description: 80 | name: matcher 81 | url: "https://pub.dartlang.org" 82 | source: hosted 83 | version: "0.12.11" 84 | material_color_utilities: 85 | dependency: transitive 86 | description: 87 | name: material_color_utilities 88 | url: "https://pub.dartlang.org" 89 | source: hosted 90 | version: "0.1.4" 91 | meta: 92 | dependency: transitive 93 | description: 94 | name: meta 95 | url: "https://pub.dartlang.org" 96 | source: hosted 97 | version: "1.7.0" 98 | path: 99 | dependency: transitive 100 | description: 101 | name: path 102 | url: "https://pub.dartlang.org" 103 | source: hosted 104 | version: "1.8.1" 105 | sky_engine: 106 | dependency: transitive 107 | description: flutter 108 | source: sdk 109 | version: "0.0.99" 110 | source_span: 111 | dependency: transitive 112 | description: 113 | name: source_span 114 | url: "https://pub.dartlang.org" 115 | source: hosted 116 | version: "1.8.2" 117 | stack_trace: 118 | dependency: transitive 119 | description: 120 | name: stack_trace 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "1.10.0" 124 | stream_channel: 125 | dependency: transitive 126 | description: 127 | name: stream_channel 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "2.1.0" 131 | string_scanner: 132 | dependency: transitive 133 | description: 134 | name: string_scanner 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "1.1.0" 138 | term_glyph: 139 | dependency: transitive 140 | description: 141 | name: term_glyph 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "1.2.0" 145 | test_api: 146 | dependency: transitive 147 | description: 148 | name: test_api 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "0.4.9" 152 | vector_math: 153 | dependency: transitive 154 | description: 155 | name: vector_math 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "2.1.2" 159 | widget_event: 160 | dependency: transitive 161 | description: 162 | name: widget_event 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "1.2.5" 166 | sdks: 167 | dart: ">=2.17.0-0 <3.0.0" 168 | flutter: ">=2.0.0" 169 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: chips_choice 2 | description: Lite version of smart_select package, zero dependencies, an easy way to provide a single or multiple choice chips. 3 | version: 3.0.1 4 | homepage: https://github.com/davigmacode/flutter_chips_choice 5 | 6 | environment: 7 | sdk: '>=2.14.0 <3.0.0' 8 | flutter: '>=2.0.0' 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | async: ^2.8.2 14 | flexi_chip: ^1.0.7 15 | 16 | dev_dependencies: 17 | flutter_test: 18 | sdk: flutter 19 | 20 | # For information on the generic Dart part of this file, see the 21 | # following page: https://dart.dev/tools/pub/pubspec 22 | 23 | # The following section is specific to Flutter. 24 | flutter: 25 | 26 | # To add assets to your package, add an assets section, like this: 27 | # assets: 28 | # - images/a_dot_burr.jpeg 29 | # - images/a_dot_ham.jpeg 30 | # 31 | # For details regarding assets in packages, see 32 | # https://flutter.dev/assets-and-images/#from-packages 33 | # 34 | # An image asset can refer to one or more resolution-specific "variants", see 35 | # https://flutter.dev/assets-and-images/#resolution-aware. 36 | 37 | # To add custom fonts to your package, add a fonts section here, 38 | # in this "flutter" section. Each entry in this list should have a 39 | # "family" key with the font family name, and a "fonts" key with a 40 | # list giving the asset and other descriptors for the font. For 41 | # example: 42 | # fonts: 43 | # - family: Schyler 44 | # fonts: 45 | # - asset: fonts/Schyler-Regular.ttf 46 | # - asset: fonts/Schyler-Italic.ttf 47 | # style: italic 48 | # - family: Trajan Pro 49 | # fonts: 50 | # - asset: fonts/TrajanPro.ttf 51 | # - asset: fonts/TrajanPro_Bold.ttf 52 | # weight: 700 53 | # 54 | # For details regarding fonts in packages, see 55 | # https://flutter.dev/custom-fonts/#from-packages 56 | -------------------------------------------------------------------------------- /test/multiple_choice_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | import 'package:chips_choice/chips_choice.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | void main() { 6 | List value = []; 7 | List options = [ 8 | 'News', 9 | 'Entertainment', 10 | 'Politics', 11 | 'Automotive', 12 | 'Sports', 13 | 'Education', 14 | 'Fashion', 15 | 'Travel', 16 | 'Food', 17 | 'Tech', 18 | 'Science', 19 | ]; 20 | 21 | setUp(() { 22 | value = []; 23 | }); 24 | 25 | testWidgets( 26 | 'Choice items and the initial value displayed correctly', 27 | (WidgetTester tester) async { 28 | final c2Widget = ChipsChoice.multiple( 29 | value: value, 30 | onChanged: (value) => value = value, 31 | choiceItems: C2Choice.listFrom( 32 | source: options, 33 | value: (i, v) => v.toLowerCase(), 34 | label: (i, v) => v, 35 | ), 36 | ); 37 | 38 | await tester.pumpWidget(Bootstrap(child: c2Widget)); 39 | await tester.pumpAndSettle(); 40 | 41 | final c2Finder = find.byWidget(c2Widget); 42 | expect( 43 | c2Finder, 44 | findsOneWidget, 45 | reason: 'ChipsChoice widget is displayed', 46 | ); 47 | 48 | // expect the choice items displayed correctly 49 | final choiceFinder = find.descendant( 50 | of: c2Finder, 51 | matching: find.byWidgetPredicate( 52 | (widget) => widget is C2Chip && widget.selected == false, 53 | ), 54 | ); 55 | expect( 56 | choiceFinder, 57 | findsNWidgets(11), 58 | reason: 'List of choice items is displayed', 59 | ); 60 | }, 61 | ); 62 | } 63 | 64 | class Bootstrap extends StatelessWidget { 65 | final Widget child; 66 | 67 | const Bootstrap({ 68 | Key? key, 69 | required this.child, 70 | }) : super(key: key); 71 | 72 | @override 73 | Widget build(BuildContext context) { 74 | return MaterialApp( 75 | title: 'ChipsChoice Test', 76 | home: Scaffold( 77 | body: Center( 78 | child: child, 79 | ), 80 | ), 81 | ); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /test/single_choice_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | import 'package:chips_choice/chips_choice.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | void main() { 6 | List options = [ 7 | 'News', 8 | 'Entertainment', 9 | 'Politics', 10 | 'Automotive', 11 | 'Sports', 12 | 'Education', 13 | 'Fashion', 14 | 'Travel', 15 | 'Food', 16 | 'Tech', 17 | 'Science', 18 | ]; 19 | 20 | testWidgets( 21 | 'Choice items and the initial value displayed correctly', 22 | (WidgetTester tester) async { 23 | int? selectedValue; 24 | 25 | final c2Widget = ChipsChoice.single( 26 | value: selectedValue, 27 | onChanged: (val) => selectedValue = val, 28 | choiceItems: C2Choice.listFrom( 29 | source: options, 30 | value: (i, v) => i, 31 | label: (i, v) => v, 32 | ), 33 | ); 34 | 35 | await tester.pumpWidget(Bootstrap(child: c2Widget)); 36 | await tester.pumpAndSettle(); 37 | 38 | final c2Finder = find.byWidget(c2Widget); 39 | expect( 40 | c2Finder, 41 | findsOneWidget, 42 | reason: 'ChipsChoice widget is displayed', 43 | ); 44 | 45 | // expect available choice items displayed correctly 46 | final choiceFinder = find.descendant( 47 | of: c2Finder, 48 | matching: find.byWidgetPredicate( 49 | (widget) => widget is C2Chip && widget.selected == false, 50 | ), 51 | ); 52 | expect( 53 | choiceFinder, 54 | findsNWidgets(11), 55 | reason: 'List of choice items is displayed', 56 | ); 57 | 58 | // select a choice options[4] = Sports 59 | final int selectionValue = 4; 60 | final selectionFinder = find.descendant( 61 | of: c2Finder, 62 | matching: find.byWidgetPredicate( 63 | (widget) => 64 | widget is C2Chip && 65 | widget.key == ValueKey(selectionValue) && 66 | widget.selected == false, 67 | ), 68 | ); 69 | expect( 70 | selectionFinder, 71 | findsOneWidget, 72 | reason: 'Choice to select is displayed', 73 | ); 74 | 75 | // Tap the widget 76 | await tester.tap(selectionFinder); 77 | // Rebuild the widget after the state has changed. 78 | await tester.pumpAndSettle(); 79 | 80 | // expect selected choice items displayed correctly 81 | final selectedFinder = find.descendant( 82 | of: c2Finder, 83 | matching: find.byWidgetPredicate( 84 | (widget) => 85 | widget is C2Chip && 86 | widget.key == ValueKey(selectionValue) && 87 | widget.selected == true, 88 | ), 89 | ); 90 | expect( 91 | selectedFinder, 92 | findsOneWidget, 93 | reason: 'New selected choice item is correctly displayed', 94 | ); 95 | 96 | expect(selectedValue, selectionValue); 97 | }, 98 | ); 99 | } 100 | 101 | class Bootstrap extends StatelessWidget { 102 | final Widget child; 103 | 104 | const Bootstrap({ 105 | Key? key, 106 | required this.child, 107 | }) : super(key: key); 108 | 109 | @override 110 | Widget build(BuildContext context) { 111 | return MaterialApp( 112 | title: 'ChipsChoice Test', 113 | home: Scaffold( 114 | body: child, 115 | ), 116 | ); 117 | } 118 | } 119 | --------------------------------------------------------------------------------