[
  {
    "path": ".gitignore",
    "content": "#OS X\n.DS_Store\n\n# Xcode\nbuild/*\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\nxcuserdata\nprofile\n*.moved-aside\n*.playground\n*.framework\nDerivedData\nIndex\nBuild\nCheckouts\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"Sources/Frameworks/Motion\"]\n\tpath = Sources/Frameworks/Motion\n\turl = https://github.com/CosmicMind/Motion.git\n"
  },
  {
    "path": ".swift-version",
    "content": "5.0\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "## 3.1.8\n\n- [pr-1269](https://github.com/CosmicMind/Material/pull/1269): Fixed Xcode 11 crash, where layoutMargins are not available before iOS 13.\n- [pr-1270](https://github.com/CosmicMind/Material/pull/1270): Fixed missing argument in Swift Package Manager.\n* Updated to [Motion 3.1.3](https://github.com/CosmicMind/Motion/releases/tag/3.1.3). \n\n## 3.1.7\n\n* Fixed Grid issues, where the layout calculations were being deferred and causing inconsistencies in layouts.\n* Updated to [Motion 3.1.2](https://github.com/CosmicMind/Motion/releases/tag/3.1.2).\n\n## 3.1.6\n- [issue-1245](https://github.com/CosmicMind/Material/issues/1245): Fixed issue where completion block was not executed when calling Switch.toggle.\n\n## 3.1.5\n\n- [pr-1248](https://github.com/CosmicMind/Material/pull/1248): Exposed Obj-C methods for NavigationDrawerController.\n  - [issue-1247](https://github.com/CosmicMind/Material/issues/1247): Several methods in NavigationDrawerController not visible in Obj-C.\n\n## 3.1.4\n\n- [pr-1239](https://github.com/CosmicMind/Material/pull/1239): Fixed regression with intrinsic content sizing in Switch control. \n- [pr-1240](https://github.com/CosmicMind/Material/pull/1240): Fixed prepare method called twice.\n  - [issue-1215](https://github.com/CosmicMind/Material/issues/1215): prepare() is called twice on NavigationDrawerController.\n  \n## 3.1.3\n\n* Added installation instructions to README.\n\n- [pr-1236](https://github.com/CosmicMind/Material/pull/1236): Added Layout relations.\n  - [issue-1220](https://github.com/CosmicMind/Material/issues/1220): Support all relations for Layout constraints.\n\n## 3.1.2\n\n- [pr-1233](https://github.com/CosmicMind/Material/pull/1233): Fixed Layout breaks - subview ordering.\n  - [issue-1232](https://github.com/CosmicMind/Material/issues/1232): Layout breaks view arrangements.\n  \n## 3.1.1\n\n- [pr-2131](https://github.com/CosmicMind/Material/pull/2131): Storyboard TextField fixes.\n  - [issue-1229](https://github.com/CosmicMind/Material/issues/1229): TextField's tintColor doesn't support user setting.\n  - [issue-1230](https://github.com/CosmicMind/Material/issues/1230): Button's title font doesn't support user setting.\n\n## 3.1.0\n\n- Updated to swift 5.\n\n## 3.0.0\n\n- Updated to swift 4.2.\n- [pr-1124](https://github.com/CosmicMind/Material/pull/1124): Fixed issue-1123, TextField is not scrolling.\n  - [issue-1123](https://github.com/CosmicMind/Material/issues/1123): TextField is not scrolling when inputing characters and using a large Font size.\n- [pr-1126](https://github.com/CosmicMind/Material/pull/1126): Cleaned up TextField.\n- [pr-1130](https://github.com/CosmicMind/Material/pull/1130): Addressed multiple issues.\n  - [issue-1125](https://github.com/CosmicMind/Material/issues/1125): TextView with animated placeholder.\n  - [issue-1127](https://github.com/CosmicMind/Material/issues/1127): TextView auto-adjust height based on text lines.\n  - [issue-1128](https://github.com/CosmicMind/Material/issues/1128): TextField animates weird when text alignment is .right and we have textInset.\n  - Removed `textInset: CGFloat` and added `textInsets: EdgeInsets` to `TextField`.\n- [pr-1134](https://github.com/CosmicMind/Material/pull/1134): Added swipe feature to BottomNavigationController.\n  - [issue-1132](https://github.com/CosmicMind/Material/issues/1132): BottomNavigationController same swipe behaviour as TabsController.\n- [pr-1147](https://github.com/CosmicMind/Material/pull/1147): Allow framework to be linked from extensions.\n- [pr-1151](https://github.com/CosmicMind/Material/pull/1151): New features.\n  - Added `left/right/above/below` directions to `DepthPreset`.\n  - Added `.custom(x)` case for `HeightPreset`.\n  - Added support for `heightPreset` in `BottomNavigationController`. [issue-1150](https://github.com/CosmicMind/Material/issues/1150)\n- [pr-1165](https://github.com/CosmicMind/Material/pull/1165): Added interactive swipe.\n  - [issue-1135](https://github.com/CosmicMind/Material/issues/1135): Convert swiping in TabsController and BottomNavigationController to interactive.\n- [pr-1115](https://github.com/CosmicMind/Material/pull/1115): Introducing Theming to Material.\n- [pr-1173](https://github.com/CosmicMind/Material/pull/1173): Added dialogs.\n- [pr-1174](https://github.com/CosmicMind/Material/pull/1174): Added disabling theming globally and per-class.\n- [pr-1183](https://github.com/CosmicMind/Material/pull/1183): Added global theme font.\n- [pr-1185](https://github.com/CosmicMind/Material/pull/1185): Reworked layout system.\n- [pr-1186](https://github.com/CosmicMind/Material/pull/1186): Fixed SnackBar laid out incorrectly.\n- [pr-1187](https://github.com/CosmicMind/Material/pull/1187): Added option for disabling snackbar layout edge inset calculation \n\n## 2.17.0\n\n* Updated for Swift 4.2.\n* Updated to [Motion 1.5.0](https://github.com/CosmicMind/Motion/releases/tag/1.5.0)\n\n## 2.16.4\n\n* [pr-1120](https://github.com/CosmicMind/Material/pull/1120): Fixed issue where TextField cursor was not being repositioned correctly.\n  * [issue-1119](https://github.com/CosmicMind/Material/issues/1119): Cursor position was incorrectly being positioned when toggling security entry.\n\n## 2.16.3\n\n* Updated to [Motion 1.4.3](https://github.com/CosmicMind/Motion/releases/tag/1.4.3)\n* [pr-1116](https://github.com/CosmicMind/Material/pull/1116): ViewController-oriented clean up.\n* [pr-1117](https://github.com/CosmicMind/Material/pull/1117): Fixed TextView font issue with emojis.\n  * [issue-838](https://github.com/CosmicMind/Material/issues/838): TextView's font breaks when you type emoji.\n\n## 2.16.2\n\n* [pr-1113](https://github.com/CosmicMind/Material/pull/1113): Added update() to Grid.\n* [pr-1112](https://github.com/CosmicMind/Material/pull/1112): Added tab bar centering.\n  * [issue-926](https://github.com/CosmicMind/Material/issues/926): TabsController - centering TabItem after selection.\n* [pr-1114](https://github.com/CosmicMind/Material/pull/1114): Added option to adjust tabBar line width.\n  * [issue-1109](https://github.com/CosmicMind/Material/issues/1109): Want to change TabBar line width.\n\n## 2.16.1\n\n* [issue-1110](https://github.com/CosmicMind/Material/issues/1110): Fixed an issue where the depth of a view was being clipped incorrectly. \n* [pr-1111](https://github.com/CosmicMind/Material/pull/1111): Fixed TabItem - was not being changed on swipe.\n* [pr-1106](https://github.com/CosmicMind/Material/pull/1106): Added ability to show visibility and clear button at the same time.\n  * [issue-992](https://github.com/CosmicMind/Material/issues/992): Visibility & Clear Button can't be shown in TextField at the same time.\n* [pr-1104](https://github.com/CosmicMind/Material/pull/1104): Added missing devices.\n* [pr-1101](https://github.com/CosmicMind/Material/pull/1101): Enum for support iPhoneX.\n\n## 2.16.0\n\n* Updated to [Motion 1.4.2](https://github.com/CosmicMind/Motion/releases/tag/1.4.2).\n* [pr-1004](https://github.com/CosmicMind/Material/pull/1004): Added RadioButton/CheckButton and RadioButtonGroup/CheckButtonGroup.\n  * [issue-505](https://github.com/CosmicMind/Material/issues/505): Add RadioButton and Checkbox.\n* Updated to [Motion 1.4.0](https://github.com/CosmicMind/Motion/releases/tag/1.4.0). \n  * [issue-1078](https://github.com/CosmicMind/Material/issues/1078): Update Motion Dependency.  \n* [pr-1047](https://github.com/CosmicMind/Material/pull/1047): Document material color codes.\n  * [issue-1000](https://github.com/CosmicMind/Material/issues/1000): Color: Document mapping from codes (e.g. a400) to names (e.g. accent1).  \n* [pr-1055](https://github.com/CosmicMind/Material/pull/1055): Open up FABMenu a little bit.  \n* Updated Copyright years.\n* [pr-1079](https://github.com/CosmicMind/Material/pull/1079): Added custom navigationBarClass support to NavigationController.\n  * [issue-1074](https://github.com/CosmicMind/Material/issues/1074): Need to use a NavigationBar subclass with NavigationController.\n* [pr-1080](https://github.com/CosmicMind/Material/pull/1080): Fixed license badge href.\n* [pr-1046](https://github.com/CosmicMind/Material/pull/1046): Added ShouldOpen and ShouldClose delegate methods to FABMenuDelegate.\n  * [issue-1043](https://github.com/CosmicMind/Material/issues/1043): ShouldOpen and ShouldClose delegate methods FABMenu.\n* [pr-1086](https://github.com/CosmicMind/Material/pull/1086): Fix delegations never fired on tab swipe.\n  * [issue-1087](https://github.com/CosmicMind/Material/issues/1087): TabBar item is selected even though TabsController delegate shouldSelect always returns false.\n  * [issue-1056](https://github.com/CosmicMind/Material/issues/1056): Delegation methods never fired on Tab swipe.\n* [pr-1088](https://github.com/CosmicMind/Material/pull/1088): Removed unnecessary convenience initializers.\n    * [issue-1085](https://github.com/CosmicMind/Material/issues/1085): `convenience init()` across the framework prevents generic initialization of the components.\n* [pr-1082](https://github.com/CosmicMind/Material/pull/1082): Added ErrorTextField validation.\n  * [issue-1017](https://github.com/CosmicMind/Material/issues/1017): Can we make the error detail for textfields dynamic?\n  * [issue-1053](https://github.com/CosmicMind/Material/issues/1053): TextField Detail Label not Layed-Out correctly with Left-Image.\n* [pr-1103](https://github.com/CosmicMind/Material/pull/1103): Added ability to change password visibility icons.\n* [pr-1097](https://github.com/CosmicMind/Material/pull/1097):: Added new extensions: UIColor(argb:), UIColor(rgb:), UIButton.fontSize, UILabel.fontSize.\n* [pr-1093](https://github.com/CosmicMind/Material/pull/1093):: Fix TextField placeholderLabel position.\n  * [issue-1092](https://github.com/CosmicMind/Material/issues/1092): TextField.placeholderLabel is positioned higher than before in version 2.x.x.\n* [pr-1103](https://github.com/CosmicMind/Material/pull/1103): Added ability to change password visibility icons.\n  * [issue-1012](https://github.com/CosmicMind/Material/issues/1012): Can we set visibility icon custom for password textfield.\n\n\n## 2.15.0\n\n* [issue-1057](https://github.com/CosmicMind/Material/issues/1057): Added image states for TabItems used in TabBar and TabsController.\n\n## 2.14.0\n\n* [issue-995](https://github.com/CosmicMind/Material/issues/995): Updated iOS 11 layout margins for NavigationBar.\n* [pr-1038](https://github.com/CosmicMind/Material/pull/1038): Merged PR for iOS 11 layout margins fix. \n\n## 2.13.7\n\n* Updated TabsController to no longer force the default animation to change between tabs and not return to normal behavior.  \n* [issue-1044](https://github.com/CosmicMind/Material/issues/1044): Fixed issue where TabBar items were not correctly laying out. \n\n## 2.13.6\n\n* [issue-841](https://github.com/CosmicMind/Material/issues/841): Adjusted default sizing for Switch to be more like the original sizing.\n* [pr-1030](https://github.com/CosmicMind/Material/pull/1032): Added workaround for known issue where trailing whitespace is apparent in UITextField.\n* Updated to [Motion 1.3.5](https://github.com/CosmicMind/Motion/releases/tag/1.3.5). \n\n## 2.13.5\n\n* [pr-1019](https://github.com/CosmicMind/Material/pull/1019): Added swipe gesture handling to TabsController.\n* Updated to [Motion 1.3.4](https://github.com/CosmicMind/Motion/releases/tag/1.3.4).\n\n## 2.13.4\n\n* [issue-1016](https://github.com/CosmicMind/Material/issues/1016): Updated hierarchy traversal for TransitionController types to no longer skip over non TransitionController types. \n\n## 2.13.3\n\n* [issue-1015](https://github.com/CosmicMind/Material/issues/1015): Fixed regression where view lifecycle functions were not being called.\n* Motion disabled by default for NavigationController to avoid unbalanced calls to view lifecycle when presenting a NavigationController modally. \n* Updated to [Motion 1.3.3](https://github.com/CosmicMind/Motion/releases/tag/1.3.3).\n\n## 2.13.2\n\n* Updated to [Motion 1.3.2](https://github.com/CosmicMind/Motion/releases/tag/1.3.2).\n* Fixed unbalanced calls in Motion transitions.\n\n## 2.13.1\n\n* Updated to [Motion 1.3.1](https://github.com/CosmicMind/Motion/releases/tag/1.3.1). \n\n## 2.13.0\n\n* Updated to [Motion 1.3.0](https://github.com/CosmicMind/Motion/releases/tag/1.3.0). \n\n## 2.12.19\n\n* [issue-997](https://github.com/CosmicMind/Material/issues/977): Fixed NavigationDrawerController where swiping off device caused a partial correct state.\n\n## 2.12.18\n\n* Fixed layout issues in CollectionView, where the sizing was not correctlly being initialized.\n* [issue-495](https://github.com/CosmicMind/Material/issues/495): Made TextField.textInset available in Obj-C.\n\n## 2.12.17\n\n* [pr-979](https://github.com/CosmicMind/Material/pull/979): Added `visibilityOff` icon and updated `TextField` to utilize it.\n* [issue-982](https://github.com/CosmicMind/Material/issues/982): Updated Icon let declarations to var declarations to allow custom icon sets. \n* [issue-980](https://github.com/CosmicMind/Material/issues/980): Added `@objc` to extension properties in Material+UIView.\n* [issue-650](https://github.com/CosmicMind/Material/issues/650): Fixed issue where `NavigationBar.backButton` would incorrectly be laid out when caching view controllers.\n* [issue-973](https://github.com/CosmicMind/Material/issues/973): Fixed issue where `Button.prepare` was not being called in the correct order.\n\n## 2.12.16\n\n* [issue-965](https://github.com/CosmicMind/Material/issues/965): Removed duplicate `prepare` call in initializer.\n* Rework of Layout's internal process - removed an async call to layout views.\n* Updated the layout calls for FABMenu's fabButton.\n\n## 2.12.15\n\n* [issue-957](https://github.com/CosmicMind/Material/issues/957): Fixed StatusBar height issue in iOS 9 and iOS 10. \n\n## 2.12.14\n\n* [samples issue-95](https://github.com/CosmicMind/Samples/issues/95): Fixed TabBar image colors that were not correctly being set for a given state.\n* Fixed layout issue, where the calculation of the layout item was not being set in the current render cycle.\n\n## 2.12.13\n\n* Fixed issue where sizing of pulse was incorrectly animating when using the NavigationController on iOS 11.\n\n## 2.12.12\n\n* [issue-924](https://github.com/CosmicMind/Material/issues/924):  Fixed NavigationController display in iOS 10.\n\n## 2.12.11\n\n* Fixed iPhoneX topLayoutGuide constraints not properly being set for StatusBarController types.\n* Fixed iOS 11 layout issues for NavigationController.\n* [pr-945](https://github.com/CosmicMind/Material/pull/945): iPhoneX update for TabBar bottom line alignment. \n\n## 2.12.10\n\n* [samples-issue-78](https://github.com/CosmicMind/Samples/issues/78): Fixed iPhoneX bottomLayoutGuide constraints not properly being set.\n\n## 2.12.9\n\n* Fixed breaking change to loading the TabsController.\n\n## 2.12.8\n\n* [issue-933](https://github.com/CosmicMind/Material/issues/933): Fixed issue where `NavigationDrawerController` was not displaying the `leftViewController` and `rightViewController`.\n* [issue-940](https://github.com/CosmicMind/Material/issues/940): Fixed an issue where the `TransitionController` was not executing the lifecycle functions for the initial `rootViewController`. \n\n## 2.12.7\n\n* [pr-938](https://github.com/CosmicMind/Material/pull/938): An expansion on this PR to fix the lifecycle issues with transitions.\n\n## 2.12.6\n\n* Fixed issue where TabBar.lineColor was incorrectly being updated.\n\n## 2.12.5\n\n* Updated to [Motion 1.2.4](https://github.com/CosmicMind/Motion/releases/tag/1.2.4).\n* [issue-937](https://github.com/CosmicMind/Material/issues/937): Added @objc to `TabBar.lineColor` for access availability.\n* [pr-934](https://github.com/CosmicMind/Material/pull/934): Added access to the `TabBar.line` view.\n\n## 2.12.4\n\n* Updated to [Motion 1.2.3](https://github.com/CosmicMind/Motion/releases/tag/1.2.3).\n* [issue-919](https://github.com/CosmicMind/Material/issues/919): Fixed issue where lifecycle methods were being called on tab item view controllers prematurely.\n* [pr-923](https://github.com/CosmicMind/Material/pull/923): Merge PR that fixes [issue-919](https://github.com/CosmicMind/Material/issues/919).\n* [issue-931](https://github.com/CosmicMind/Material/issues/931): Fixed issue where selectedTabItem was not updated correctly during a porgrammatic transition. \n\n## 2.12.3\n\n* [issue-907](https://github.com/CosmicMind/Material/issues/907): Fixed Layout ordering issues.\n\n## 2.12.2\n\n* [issue-860](https://github.com/CosmicMind/Material/issues/860): Updated TabBar color states and added an independent line color state.\n\n## 2.12.1\n\n* [issue-911](https://github.com/CosmicMind/Material/issues/911): Added @objc to TabBar.tabItems for visibility in Obj-C.\n\n## 2.12.0\n\n* [issue-860](https://github.com/CosmicMind/Material/issues/860): Added `TabBar` color states.\n\n## 2.11.4\n\n* Added Cartfile for Carthage package manager, which includes the Motion dependency.\n\n## 2.11.3\n\n* Updated Motion submodule to use `https` over `git@`. \n\n## 2.11.2\n\n* Updated to [Motion 1.2.2](https://github.com/CosmicMind/Motion/releases/tag/1.2.2).\n\n## 2.11.1\n\n* Fixed duplicate `prepare` call in `TabsController`.\n\n## 2.11.0\n\n* Updated the installation guide for Material, [Material - It's time to download](https://www.cosmicmind.com/danieldahan/lesson/6). Material now uses [Motion](https://github.com/CosmicMind/Motion) as a submodule and CocoaPods dependancy. \n* [samples issue-70](https://github.com/CosmicMind/Samples/issues/70#issuecomment-335533243): Made an internal `_TabBarDelegate` to avoid needing to override the `TabBarDelegate` in `TabsController`. \n\n## 2.10.4\n\n* [issue-891](https://github.com/CosmicMind/Material/pull/891): Fixed conflict with addAttributes method in the NSMutableAttributedString extension.\n\n## 2.10.3\n\n* [issue-773](https://github.com/CosmicMind/Material/pull/773): Added `Swift 4` support.\n* [pr-873](https://github.com/CosmicMind/Material/pull/873): Fixes PlaceholderLabel position when right-aligned - iOS 11.0\n* [issue-886](https://github.com/CosmicMind/Material/issues/886): Fixed a memory leak within Motion's references to previous `UINavigationControllerDelegate` and `UITabBarControllerDelegate`.\n* [issue-861](https://github.com/CosmicMind/Material/pull/861): Fixed `NavigationBar` being `nil` in some cases.\n* [issue-845](https://github.com/CosmicMind/Material/pull/845): Fixed ambiguity issues with all properties.\n\n## 2.10.2\n\n* [issue-849](https://github.com/CosmicMind/Material/issues/849): Fixed issue where `TextView.placeholderNormalColor` was not correctly displaying. Renamed `TextView.placeholderNormalColor` to `TextView.placeholderColor`.\n* [issue-856](https://github.com/CosmicMind/Material/issues/856): Fixed issue where `TextField.placeholderAnimation = .hidden` was not correctly being displayed when text was set to nil.\n* All default instances of `Color.grey.lighten3` have been switched to `Color.grey.lighten2`.\n\n## 2.10.1\n\n* [issue-833](https://github.com/CosmicMind/Material/issues/833): `TabsController` now be selected programmatically.\n* [issue-859](https://github.com/CosmicMind/Material/issues/859): `TabsController` now has a delegation protocol `TabsControllerDelegate`.\n* [issue-830](https://github.com/CosmicMind/Material/issues/830): Bug fix where `TabsController` did not animate to the correct tab when programmatically set.\n\n## 2.10.0\n\n* [issue-857](https://github.com/CosmicMind/Material/issues/857): Fixed an issue where setting the `statusBar` property for the `ToolbarController` was not updating the background color correctly.\n* [issue-858](https://github.com/CosmicMind/Material/issues/858): Fixed `Photos` sample project that was not updated to reflect the changes in the `TabBar`.\n* [pr-715](https://github.com/CosmicMind/Material/pull/715): Added `isPlaceholderUppercasedWhenEditing` property to `TextField`.\n* [pr-721](https://github.com/CosmicMind/Material/pull/721): Added `FABMenuItemTitleLabelPosition` which allows the `FABMenu` to place its `FABBMenuItems` to either the `left` or `right` position of the `FABButton`.\n* [pr-851](https://github.com/CosmicMind/Material/pull/851): Added `placeholderHorizontalOffset` property to `TextField`.\n* [pr-847](https://github.com/CosmicMind/Material/pull/847): Added `placeholderActiveScale` property to `TextField`.\n* [pr-848](https://github.com/CosmicMind/Material/pull/848): Natural motion transition added to `TabsController` when view controller `motionModalTransitionType` is set to `.auto`.\n* `Card` types default to a `depthPreset` of `.none`.\n* Added `shouldSelect` method to `TabBarDelegate`.\n* Updated `TabsController` to use `TabBarDelegate` rather than button handlers.\n* Updated `EdgeInsetsPreset` values to:\n\n```swift\n.square1: EdgeInsets(top: 4, left: 4, bottom: 4, right: 4)\n.square2: EdgeInsets(top: 8, left: 8, bottom: 8, right: 8)\n.square3: EdgeInsets(top: 16, left: 16, bottom: 16, right: 16)\n.square4: EdgeInsets(top: 20, left: 20, bottom: 20, right: 20)\n.square5: EdgeInsets(top: 24, left: 24, bottom: 24, right: 24)\n.square6: EdgeInsets(top: 28, left: 28, bottom: 28, right: 28)\n.square7: EdgeInsets(top: 32, left: 32, bottom: 32, right: 32)\n.square8: EdgeInsets(top: 36, left: 36, bottom: 36, right: 36)\n.square9: EdgeInsets(top: 40, left: 40, bottom: 40, right: 40)\n.square10: EdgeInsets(top: 44, left: 44, bottom: 44, right: 44)\n.square11: EdgeInsets(top: 48, left: 48, bottom: 48, right: 48)\n.square12: EdgeInsets(top: 52, left: 52, bottom: 52, right: 52)\n.square13: EdgeInsets(top: 56, left: 56, bottom: 56, right: 56)\n.square14: EdgeInsets(top: 60, left: 60, bottom: 60, right: 60)\n.square15: EdgeInsets(top: 64, left: 64, bottom: 64, right: 64)\n```\n\n## 2.9.4\n\n* Added `ToolbarAlignment` to allow placement of the `Toolbar` at the top or bottom of the view controller.\n* Added `SearchBarAlignment` to allow placement of the `SearchBar` at the top or bottom of the view controller.\n\n## 2.9.3\n\n* Renamed `TabBarController` to `TabsController` to avoid name confusion with iOS `UITabBarController` helper properties.\n* Updated layout with `TabsController` to properly adjust during orientation changes.\n\n## 2.9.2\n\n* `TabBarController` now subclasses `TransitionController` to minimize code.\n* Fixed regression in `TabBarController` where line was incorrectly animation upon initial interaction.\n\n## 2.9.1\n\n* Renamed `TabsController` to `TabBarController`.\n* Renamed `ChipsController` to `ChipBarController`.\n* [issue-832](https://github.com/CosmicMind/Material/issues/832): Fixed issue where `TabBar` line was incorrectly laying out.\n\n## 2.9.0\n\n* Replaced `RootController` with `TransitionController`.\n* Updated CharacterAttribute API.\n* Added Chips - alpha phase.\n* [issue-824](https://github.com/CosmicMind/Material/issues/824): Fixed issue where `TabBar` line alignment was not correctly animating when initial engaged.\n* [issue-820](https://github.com/CosmicMind/Material/issues/820): Fixed retain cycle found in FABMenuController.\n\n## 2.8.1\n\n* [issue-815](https://github.com/CosmicMind/Material/issues/815): Fixed the TabBar line alignment issue when rotating the device orientation.\n\n## 2.8.0\n\nRemoved PageTabBarController and added the TabsController. Now removing the following issues and feature requests:\n\n* [issue-642](https://github.com/CosmicMind/Material/issues/642)\n* [issue-742](https://github.com/CosmicMind/Material/issues/742)\n* [issue-768](https://github.com/CosmicMind/Material/issues/768)\n* [issue-605](https://github.com/CosmicMind/Material/issues/605)\n* [issue-743](https://github.com/CosmicMind/Material/issues/743)\n* [issue-619](https://github.com/CosmicMind/Material/issues/619)\n\n## 2.7.1\n\n* [issue-811](https://github.com/CosmicMind/Material/issues/811): Removed scrollable TabBar style, until feature is ready.\n\n## 2.7.0\n\n* Added [Motion](https://github.com/CosmicMind/Motion) framework to Material as new animation and transitions library.\n* Removed `Capture`.\n* Removed `PhotoLibrary`.\n* Removed `Reminders`.\n* [issue-809](https://github.com/CosmicMind/Material/issues/809): Fixed detailTextLabel visibility issue.\n* [issue-797](https://github.com/CosmicMind/Material/issues/797): Added `back button` hiding features to `NavigationController`.\n* [issue-552](https://github.com/CosmicMind/Material/issues/552): Fixed `@objc` declaration issues.\n* [pr-662](https://github.com/CosmicMind/Material/pull/662): Added the ability to set a text inset for a `TextField`.\n* [pr-707](https://github.com/CosmicMind/Material/pull/707): Moved the `statusBarStyle` extension to `NavigationController` from `UINavigationController`.\n* Updated `Display` to `DisplayStyle` and renamed corresponding properties, in `ToolbarController`, `StatusBarController`, `SearchBarController`, `CaptureController`, and `ImageCard`.\n\n## 2.6.3\n\n* Fixed an issue where using child view controllers would break `presenting` and `dismissing` transition animations.\n\n## 2.6.2\n\n* [issue-608](https://github.com/CosmicMind/Material/issues/608): Updated `PageTabBarController` to allow programmatic selection of the current index using the `selectedIndex` property.\n\n## 2.6.1\n\n* Updated for Xcode 8.3.\n\n## 2.6.0\n\n* [issue-704](https://github.com/CosmicMind/Material/issues/704): Fixed an issue where `TextView.clipsToBounds` was revealing the scrollable text.\n* [issue-663](https://github.com/CosmicMind/Material/issues/663): Added the ability to add insets for the `TextView`.\n* [issue-598](https://github.com/CosmicMind/Material/issues/598): Added a placeholder to the `TextView`.\n* Removed `Editor` and added all the necessary functionality in `TextView`.\n\n## 2.5.2\n\n* [issue-695](https://github.com/CosmicMind/Material/issues/695): Fixed issue with [pr-696](https://github.com/CosmicMind/Material/pull/696), where FABMenu was incorrectly being displayed used the SpringAnimation API.\n\n## 2.5.1\n\n* [issue-681](https://github.com/CosmicMind/Material/issues/681): Fixed regression where `NavigationBar` was not properly setting the background color.\n* Fixed issue where transitions using `UINavigationController` would sometimes flicker.\n\n## 2.5.0\n\n* Renamed `FabButton` to `FABButton`.\n* Moved `Menu` to `FABMenu`.\n* Moved `MenuController` to `FABMenuController`.\n* Added `FABMenuBacking` enum type to set a `blur` or `fade` for the opened `FABMenu` state using a `FABMenuController`.\n* Renamed `MenuItem` to `FABMenuItem`.\n* Added `SpringAnimation` animation API.\n* [issue-641](https://github.com/CosmicMind/Material/issues/641): Added a new `PulseAnimation.tap` type, which has an instant feedback response when tapping.\n* Updated `Toolbar.display` to `Toolbar.toolbarDisplay`.\n* Updated `SearchBar.display` to `SearchBar.searchBarDisplay`.\n* Added `StatusBar.statusBarDisplay`.\n* Added `MotionAnimation` enum type and helper methods to `CALayer` and `UIView` as extensions.\n* Added [Motion](https://github.com/CosmicMind/Motion) to Material.\n\n## 2.4.19\n\n* [issue-692](https://github.com/CosmicMind/Material/issues/692): Fixed issue where Carthage was failing to build the macOS target for Material.\n\n## 2.4.18\n\n* Removed macOS support.\n\n## 2.4.17\n\n* Updated Material.podspec to fix potential macOS issue.\n\n## 2.4.16\n\n* [issue-678](https://github.com/CosmicMind/Material/issues/678): Fixed issue where `Card` was incorrectly displaying its `contentView`.\n\n## 2.4.15\n\n* Fixed an issue where the `Card` was not displaying the `contentView` and `presenterView` correctly on initial load.\n\n## 2.4.14\n\n* Added missing `UIView` properties to `Material+UIView` extension that are used in the [Motion](https://github.com/CosmicMind/Motion) [PhotoCollection](https://github.com/CosmicMind/Samples/tree/master/Motion/PhotoCollection) sample.\n\n## 2.4.13\n\n* Added [Motion](https://github.com/CosmicMind/Motion) as a separate framework from [Material](https://github.com/CosmicMind/Material).\n\n## 2.4.12\n\n* [issue-676](https://github.com/CosmicMind/Material/issues/676): Fixed an issue where `Card` types were not adjusting size correctly when using `UILabels`.\n\n## 2.4.11\n\n* [issue-658](https://github.com/CosmicMind/Material/issues/658): Added `TextFieldPlaceholderAnimation` enum type to enable `TextField` to have different animations.\n\n## 2.4.10\n\n* Fixed an issue where `TabBar` was not correctly setting the `contentEdgeInsets*` and `interimSpace*`.\n\n## 2.4.9\n\n* [issue-655](https://github.com/CosmicMind/Material/issues/655): Updated date for release in README to 2017.\n\n## 2.4.8\n\n* [issue-653](https://github.com/CosmicMind/Material/issues/653): Fixed a `TextField` issue where the animation was not correctly responding to a programmatic text update.\n\n## 2.4.7\n\n* Updated README release dates.\n\n## 2.4.6\n\n* [issue-640](https://github.com/CosmicMind/Material/issues/640): Fixed an issue where `TextField` was not laying out correctly when setting the text programmatically.\n\n## 2.4.5\n\n* [issue-646](https://github.com/CosmicMind/Material/issues/646): Fixed an issue where calling `TextField.becomeFirstResponder` in `viewDidLoad` would cause a layout issue.\n\n## 2.4.4\n\n* [issue-644](https://github.com/CosmicMind/Material/issues/644): Fixed issue where `Switch.isOn` and `Switch.switchState` were not updating correctly.\n\n## 2.4.3\n\n* [issue-643](https://github.com/CosmicMind/Material/issues/643): Fixed an issue where `Layout` was not anchoring correctly for `View` subclasses.\n\n## 2.4.2\n\n* Fixed double `Menu.hitTest` call that was causing the delegation method to be fired more than once.\n* Updated `Toolbar.title`, `Toolbar.titleLabel`, `Toolbar.detail`, and `Toolbar.detailLabel` to be `@IBInspectable`.\n\n## 2.4.1\n\n* [issue-194](https://github.com/CosmicMind/Material/issues/194): Fixed an issue where hitTest was failing after translation animation.\n* [issue-624](https://github.com/CosmicMind/Material/issues/624): Updated `Switch` & `TabBar` control to only call the delegation methods when the control is updated through a user interaction.\n* Renamed `Switch.on` to `Switch.isOn`.\n* Removed `Switch.setOn` function.\n* [issue-630](https://github.com/CosmicMind/Material/issues/630): Added `Reminders` and `RemindersController`.\n* Added `isDividerHidden` for the `Divider UIView` extension.\n\n## 2.4.0\n\n* [issue-551](https://github.com/CosmicMind/Material/issues/551): Fixed issue where `TabBar` was not laying out buttons correctly when more than 6 were used.\n* [issue-618](https://github.com/CosmicMind/Material/issues/618): Updated `Grid` and `Layout` to solve a `Toolbar` layout challenge.\n* [issue-620](https://github.com/CosmicMind/Material/issues/620): Fixed issue where setting the `CAAnimation.delegate` was causing an animation issue.\n\n## 2.3.22\n\n* [issue-597](https://github.com/CosmicMind/Material/issues/597): Fixed an issue where `NavigationBar` was not adjusting to all sizes correctly when using modal presentation styles.\n* Fixed an issue when `cornerRadius` was not being calculated correctly when the `CALayer` was rotated.\n\n## 2.3.21\n\n* [issue-612](https://github.com/CosmicMind/Material/issues/612): Fixed issue where SnackbarController was not resizing correctly.\n* [issue-615](https://github.com/CosmicMind/Material/issues/615): Added `snackbarEdgeInsets` and `snackbarEdgeInsetsPreset` to position the `Snackbar` from the `SnackbarController's` edges.\n\n## 2.3.20\n\n* [issue-613](https://github.com/CosmicMind/Material/issues/613): Fixed an issue where the Grid system was not laying out in all cases that it should.\n* Removed `statusBarStyle` and `isStatusBarHidden` properties from `RootController` types, in favor of using the `Application` class. `StatusBarController` now provides `statusBarStyle` and `isStatusBarHidden` properties.\n\n## 2.3.19\n\n* [issue-553](https://github.com/CosmicMind/Material/issues/553): Fixed an issue where the `NavigationDrawerController.leftViewController` was sizing incorrectly.\n\n## 2.3.18\n\n* [issue-610](https://github.com/CosmicMind/Material/issues/610): Fixed issue where the `RootController.rootViewController` was not transitioning correctly when using certain UIViewController types.\n\n## 2.3.17\n\n* Added the ability to modify the `contentViewAlignment` of a `NavigationItem` dynamically.\n* Renamed the `ContentViewAlignment.any` value to `ContentViewAlignment.full`.\n\n## 2.3.16\n\n* Minor updates to `Card` types for code clarity.\n\n## 2.3.15\n\n* Fixed issue where `ImageCard` was not ordering the `UIImageView` behind the `Toolbar` correctly.\n\n## 2.3.14\n\n* Fixed an issue where iOS animations with `Motion` were not correctly writing their end value using `CAAnimationDelegate`.\n\n## 2.3.13\n\n* Fixed an issue where the `NavigationBar.backButton` was not placed at the most left position when present.\n\n## 2.3.12\n\n* Updates `Motion.translation*` to `Motion.translate*`.\n* [issue-595](https://github.com/CosmicMind/Material/issues/595): Fixed issue where CAAnimations for iOS 10 were not working correctly.\n* [issue-600](https://github.com/CosmicMind/Material/issues/600): Fixed issue where `Carthage` was not able to build due to failing to recognize the `NavigationDrawerController` gesture recognizer.\n\n## 2.3.11\n\n* [issue-600](https://github.com/CosmicMind/Material/issues/600): Fixed issue where `Carthage` was not able to build due to failing to recognize the `NavigationDrawerController` gesture recognizer.\n\n## 2.3.10\n\n* [issue-583](https://github.com/CosmicMind/Material/issues/583): Fixed issue where `TextField.detail` was not being displayed unless it was set upon preparation time.\n* [issue-594](https://github.com/CosmicMind/Material/issues/594): Added feature request to set the `TextField.leftView` coloring based on the `normal` or `active` states, using the `TextField.detail .leftViewNormalColor` and `TextField.detail .leftViewActiveColor` properties respectively.\n\n## 2.3.9\n\n* [issue-584](https://github.com/CosmicMind/Material/issues/584): Added enum types for `Device.model` value.\n* Divided `Device` into `Application`, `Device`, and `Screen`. This is for expansion of their APIs.\n* Fixed issue where `NavigationDrawer` and `RootController` types would conflict when showing the statusBar.\n\n## 2.3.8\n\n* [issue-588](https://github.com/CosmicMind/Material/issues/588): removed memory leaks that surround Grid.\n* `Grid` is now a struct from a class type.\n* `Divider` is now a struct from a class type.\n* `Pulse` is now a struct and views that have pulse now conform to the `Pulseable` protocol.\n\n## 2.3.7\n\n* [issue-592](https://github.com/CosmicMind/Material/issues/592): fixed `NavigationDrawerController` regression, where transitioning the `rootViewController` would go behind the `contentViewController`.\n\n## 2.3.6\n\n* Updated blur logic.\n\n## 2.3.5\n\n* [issue-591](https://github.com/CosmicMind/Material/issues/591): Fixed `blur` calculation complexity for `Carthage` compilation.\n\n## 2.3.4\n\n* [issue-588](https://github.com/CosmicMind/Material/issues/588): Fixed GridAxis memory leak issue.\n\n## 2.3.3\n\n* [issue-568](https://github.com/CosmicMind/Material/issues/568): fixed issue where `placeholderActiveColor` was not being set correctly when `TextField` was in an active state.\n* [issue-568](https://github.com/CosmicMind/Material/issues/568): fixed issue where setting `text` to `nil` broke the `TextField` layout.\n* [issue-581](https://github.com/CosmicMind/Material/issues/568): Added `UIImage.blur` extension.\n\n## 2.3.2\n\n* Fixed [issue-557](https://github.com/CosmicMind/Material/issues/577) where the transitioned view controller was overlapping the `RootController` type controls.\n\n## 2.3.1\n\n* Added `Capture` delegation methods that notify when `videoOrientation` changes.\n\n## 2.3.0\n\n* Merged in [PR-566](https://github.com/CosmicMind/Material/pull/566) to move `CAAnimation` String constants to enum types.\n* Renamed the `Animation` struct to `Motion`, in order to initiate the expansion of the Motion library within Material.\n* Fixed [issue-573](https://github.com/CosmicMind/Material/issues/573) where sample had incorrect spelling for `Material`.\n* Updated `Bar` type layout mathematics.\n* Updated `FabButton` default `backgroundColor` to `white`.\n* Updated `Capture` API with [sample project](https://github.com/CosmicMind/Samples/tree/master/Material/Programmatic/CaptureController).\n\n## 2.2.5\n\n* Merged in [PR-563](https://github.com/CosmicMind/Material/pull/563) for [issue-549](https://github.com/CosmicMind/Material/issues/549), where Privacy related features are now using CocoaPods subspecs.\n\n## 2.2.4\n\n* Fixed issue where `ImageCard` `top` and `bottom` `EdgeInsets` were not being applied correctly.\n\n## 2.2.3\n\n* Updated Card internals for better performance.\n* Added sample [CardTableView](https://github.com/CosmicMind/Samples/tree/master/Graph/CardTableView).\n\n## 2.2.2\n\nWe moved all sample projects to a separate repo named [Samples](https://github.com/CosmicMind/Samples) to allow their development to be independent of the Material framework. There has been instances where we needed to update the versions of the framework to accommodate changes that only occurred in the sample projects.\n\n## 2.2.1\n\n* Fixed recursion issue with `Snackbar` and reloading.\n* issue-552: Removed extraneous @objc declarations.\n* Added `dividerContentEdgeInsets` and `dividerContentEdgeInsetsPreset` to Material+UIView extension.\n\n## 2.2.0\n\n* Updated default `pulseColor` to `Color.grey.base`.\n* Added `HeightPreset` type to dynamically set the height of the `CALayer` & `UIView` types.\n* `UIImage.tintWithColor(color: UIColor)` is now `UIImage.tint(with color: UIColor)` and always returns with `.alwaysOriginal` rendering mode.\n* `UIImage.imageWithColor(color: UIColor)` is now `UIImage.image(with color: UIColor)` and always returns with `.alwaysOriginal` rendering mode.\n* Merged in [PR 544](https://github.com/CosmicMind/Material/pull/544#pullrequestreview-3892111), which allows for the left view to be used in the `TextField`.\n* Updated the `TextField` example project to reflect [PR 544](https://github.com/CosmicMind/Material/pull/544#pullrequestreview-3892111).\n* Reworked `TextField`.\n* Added `contentEdgeInsets` to `Divider`.\n* Fixed issue where `pulse layer` was covering `Button` images when engaged.\n* For `Divider`, renamed `dividerHeight` to `dividerThickness` to accommodate alignment logic.\n* Added SearchBar delegation methods for when text changes and for when the text has been cleared.\n\n## 2.1.2\n\n* Updated default `pulseColor` to `Color.white`.\n* Updated [NavigationDrawerController Example Project](https://github.com/CosmicMind/Material/tree/master/Examples/Programmatic/NavigationDrawerController) to demonstrate how to transition the `rootViewController`, both with a `ToolbarController` and without, issue-546.\n\n## 2.1.1\n\n* Moved the Switch `trackLayer` property from a `CAShapeLayer` to a `UIView` that is now named `track`.\n* Fixed an issue where `Switch` in a `Bar` type or `NavigationBar` would behave incorrectly, issue-540.\n* Added a `ToolbarController` to the programmatic `NavigationDrawerController` example project.\n\n## 2.1.0\n\n* Added a new feature where `TextField`'s `placeholder` can be fixed at the top and not animated by setting the `isPlaceholderAnimated` property to `false` (issue-534).\n* Added a new feature where a `centerViews` property is added to `Bar` types, to automatically align views in the center outward positions. Updated sample `Card` projects and `Bar` projects to reflect this.\n* Added a new feature to `Grid`, where `columns` and `rows` are automatically set if their values have not been changed from the default `0` value.\n\n## 2.0.0\n\n* Renamed `MaterialColor` to `Color`.\n* Renamed `MaterialIcon` to `Icon`.\n* Renamed `MaterialSpacing` to `InterimSpacePreset`.\n* Renamed `MaterialButton` to `Button`.\n* Renamed `MaterialView` to `View`.\n* Renamed `MaterialPulseView` to `PulseView`.\n* Renamed `MaterialSwitch` to `Switch`.\n* Renamed `MaterialLayer` to `Layer`.\n* Renamed `MaterialFont` to `Font.\n* Renamed `MaterialEdgeInset` to `EdgeInsetsPreset`.\n* Renamed `MaterialDevice` to `Device`.\n* Renamed `MaterialDepth` to `Depth`.\n* Renamed `CaptureView` to `Capture`.\n* Renamed `CardView` to `Card`.\n* Renamed `ImageCardView` to `ImageCard`.\n* Renamed `MaterialBorder` to `BorderWidthPreset`.\n* Renamed `MaterialRadius` to `CornerRadiusPreset`.\n* Renamed `MaterialDataSourceItem` to `DataSourceItem`.\n* Renamed `MaterialTableViewCell` to `TableViewCell`.\n* Renamed `shadowPathAutoSizeEnabled` to `isShadowPathAutoSizing`.\n\n* Fixed issue where TextField placeholder was not respecting initial vertical offset (issue-469).\n* Added @objc to all enums to allow Obj-C to see the enum types and associated methods (issue-472).\n\n* Added `PageTabBarController`.\n* Added `JSON` to simplify working with JSON objects.\n\n## 1.42.9\n\n* Fixed issue where `textColor` was not being respected in Storyboards for `TextField` (issue-487).\n\n## 1.42.8\n\n* Fixed issue where initially setting the `TextField` did not correctly align the `placeholder` offset (issue-469).\n\n## 1.42.7\n\n* Fixed issue where `TextField` alignment was incorrect with RTL (issue-456).\n\n## 1.42.6\n\n* Fixed issue where `StatusBarController` was not calling its `super.prepareView` method.\n\n## 1.42.5\n\n* Fixed issue where NavigationBar was not aligning correctly with Storyboards.\n* Updated `CGRectZero` values to `CGRect.zero`.\n* Minor cleanups.\n\n## 1.42.4\n\n* Fixed issue where left and right view controllers are not enabled on `NavigationDrawerController` (issue-452).\n\n## 1.42.3\n\n* Fixed an issue where `MaterialSwitch` was exposing a memory leak with its `delegate` (issue-449).\n* Fixed a regression where FabButton was losing shape (issue-450).\n* Updated property `enableHideStatusbar` to `enableHideStatusBar` for `NavigationDrawerController`.\n* Updated `CGRectZero` to `CGRect.zero`.\n\n## 1.42.2\n\n* Fixed an issue where `Toolbar` and `NavigationBar` `title` alignment was off with a `detail` value of \"\" (issue-445).\n* Fixed an issue where `NavigationDrawerController` was crashing when transitioning between `rootViewController` (issue-444).\n\n## 1.42.1\n\n* Fixed issue with NavigationDrawerController rightView not aligning correctly when rotating device.\n\n## 1.42.0\n\n* Update `shadowPath` animation to happen when laying out subviews, rather than when laying out sublayers.\n* Renamed `MaterialLayout` to `Layout` for simplicity.\n* Added `Layout` extension to ease the usage of AutoLayout.\n* Added [Layout Documentation](http://www.cosmicmind.io/material/layout).\n* Updated the `MaterialLayout` project to `Layout`.\n* fixed width issue for all `ControlView` types when using dynamic `intrinsicContentSize` (issue-436).\n* Renamed `SideNavigationController` to `NavigationDrawerController`.\n* Removed `SideNavigationController` example project for both programmatic and storyboards.\n* Added `NavigationDrawerController` example project for both programmatic.\n* Added `StatusBarController` to manage a statusBarView.\n\n## 1.41.8\n\n* Fixed an issue where the `UINavigationItem.title` KVO would crash when releasing the instance. The fix completely removes KVO and utilizes Swift `nonobjc` tagging.\n\n## 1.41.7\n\n* Added `adjustOrientationForImage` to `CaptureSession` in order to fix image alignment issues.\n* Updated `CaptureView` sample project to reflect changes made in `ToolbarController`.\n* Updated `MaterialView` sample project to demonstrate aligning a `MaterialView` in the `center` of a view controller.\n* Fixed issue where UINavigationItem.title was not updating the titleLabel text.\n\n## 1.41.6\n\n* Fixed issue with ellipses in NavigationBar showing when panning back to the backItem (pr-409).\n\n## 1.41.5\n\n* Added delegation method `menuViewDidTapOutside` to `MenuView` to support closing the `Menu`, `MenuView`, or `MenuController` items when opened and clicking on any area of the view (issue-406).\n\n## 1.41.4\n\n* Removed `statusBarStyle` from `BarView` types.\n* Added `statusBarStyle` to BarController types.\n* Added `layoutInset` to `Grid` for an additional layer of flexibility.\n* Fixed an issue where BarControllers were not allowing `contentInset.top` to be used correctly.\n* Updated projects to reflect framework changes.\n\n## 1.41.3\n\n* Fixed issue where `MaterialSwitch` was referencing self and creating a bad access (issue-399).\n* Fixed issue where `TextField.secureTextEntry` would break the font being displayed (issue-400).\n* Moved `MenuViewController` to `MenuController`.\n* Updated `MenuController.itemViewSize` to `MenuController.itemSize`.\n* Updated `MenuController.baseViewSize` to `MenuController.baseSize`.\n* Updated all references to `unowned self` to `weak self`.\n* Added convenience properties `title` and `detail` to the `Toolbar`, which reload the view when changed.\n* Added convenience properties `title` and `detail` to UINavigationItem to easily handle text changes.\n* added to `TextField` the `placeholderVerticalOffset` and `detailVerticalOffset` to determine the alignment during animations and loading of the `placeholderLabel` and `detailLabel`.\n\n## 1.41.2\n\n* Fixed issue where Toolbar was not respective the frame size set (issue-382).\n* Fixed issue where Toolbar was not drawing the titleLabel and detailLabel text without left/right controls (issue-381).\n* `StatusBarView` is now `BarView`.\n* `StatusBarViewController` is now `BarViewController`.\n\n## 1.41.1\n\n* Fixed text alignment issue in NavigationBar and Toolbar.\n\n## 1.41.0\n\n* All references to `detailView` are now `contentView`.\n* Updated NavigationBar interface.\n* Reworked NavigationBar.\n* Reworked Toolbar measurements.\n* Reworked SearchBar measurements.\n\n## 1.40.1\n\n* Fixed issue where initializing a Toolbar in a method was causing an ambiguous initializer error (issue-363).\n* Added Boolean properties to SideNavigationController to enable and disable gestures (issue-365).\n\n```swift\nsideNavigationController.enabled = true\n\nsideNavigationController.enabledLeftView = true\nsideNavigationController.enabledLeftTapGesture = true\nsideNavigationController.enabledLeftPanGesture = true\n\nsideNavigationController.enabledRightView = true\nsideNavigationController.enabledRightTapGesture = true\nsideNavigationController.enabledRightPanGesture = true\n```\n\n* Updated the SideNavigationController `leftThreshold` and `rightThreshold` to 64 as a default.\n* Updated MaterialIcon images to work better with CocoaPods (issue-362).\n\n## 1.40.0\n\n* Added Google visibility icon to MaterialIcon.\n* Added Google check icon to MaterialIcon.\n* Reworked TextField with [documentation](http://www.cosmicmind.io/material/textfield).\n* Added ErrorTextField.\n* Added visibility button and clear button auto enabling without conflicting with iOS clearButton for TextField.\n* Reworked pulse animations.\n* Added `PulseAnimation` enum type to select the type of pulse animation.\n* Added `IconButton` to simplify the usage of using icons and buttons.\n* Fixed issue where panning gestures were conflicting with the SideNavigationController rootViewController (1ssue-322, issue-320).\n\n## 1.39.17\n\n* Updated MaterialDepth to more accurately express Material Design's shadows (issue-323).\n* Fixed an issue where MaterialButtons could not update `textColor` (issue-333).\n\n## 1.39.16\n\n* Fixed issue where TextField `resignFirstResponder` was not hiding the `titleLabel` (issue-332).  \n* TextField no longer needs to setup `detailLabel` property.\n* TextField `detailLabel` now supports @IBInspectable.\n\n## 1.39.15\n\n* Fixed issue where TextField doesn't hide the titleLabel when programmatically cleared (issue-330) (pr-331).\n\n## 1.39.14\n\n* Added UIImage extension `tintWithColor`, which allows an image to be tinted with a passed in color.\n* Added `pulseCenter` property, which forces the pulse animation to animate from the center of the view (pr-325).\n* Updated `prepareView` to be public, which allows for better subclassing and preparation of views (pr-329).\n* Fixed issue where TextField regressed when updating the `placeholder` value (issue-316).\n\n## 1.39.13\n\n* Fixed issue where TextField `placeholder` could be updated while a text value exists (issue-316).\n\n## 1.39.12\n\n* Updated Example/Programmatic/SideNavigationController project to demonstrate how to transition the rootViewController (issue-309).\n\n## 1.39.11\n\n* Added a link to download our sticker sheet.\n* Updated App project with correct naming in AppDelegate file.\n\n## 1.39.10\n\n* README Update.\n\n## 1.39.9\n\n* Added storyboard CardView example with two CardViews (issue-304).\n\n## 1.39.8\n\n* Fixed issue where TextField animation references `unowned self` and should be `weak self` (issue-301) (pr-302).\n* Added `lineLayerThickness` and `lineLayerActiveThickness` to TextField in order to adjust lineLayer during different states (issue-307).\n\n## 1.39.7\n\n* Fixed issue where TextField delegate method `textFieldShouldClear` was not being respected (issue-296).\n\n## 1.39.6\n\n* Updated TextField's default colors to the correct Material Design colors (pr-290).\n* Added UIImage blur effect (pr-291).\n* Added UIImage blur example project, FilterBlur.\n* Added `SideNavigationController.statusBarUpdateAnimation` property to set the animation type when hiding the statusBar.\n* Added `SideNavigationController.statusBarStyle` property to set the statusBar style.\n\n## 1.39.5\n\n* Added MaterialIcon example project.\n* Added additional Google and CosmicMind icons.\n* Added MaterialFontLoader to aid in loading packaged fonts with Material.\n* Updated App project to properly handle SideNavigationController ```openLeftView``` if used.\n\n## 1.39.4\n\n* Updated the TextField animations.\n\n## 1.39.3\n\n* Fixed bundle identifier issue with CocoaPods and MaterialIcon.\n\n## 1.39.2\n\n* Updated Material bundle identifier.\n\n## 1.39.1\n\n* Updated TextField to match Material Design input text spec.\n\n## 1.39.0\n\n* Added early release of TabBar.\n* Updated default `spacing` to `Spacing1` for Toolbar and SearchBar.\n* Updated default `contentInsetPreset` to `Square1` for Toolbar, SearchBar, and NavigationBar.\n* Updated ```MaterialGravityToString``` to ```MaterialGravityToValue```.\n* TextField's ```clearButton``` no longer needs to be setup.\n* TextField's ```titleLabel``` no longer needs to be setup (issue-241).\n* TextField and SearchBar - added ```clearButtonAutoHandleEnabled``` flag that when set to ```false```, the handler for clearing text is removed (issue-229).\n* TextField's ```titleLabelAnimationDistance``` is now 4 by default.\n* TextField's ```titleLabel``` now floats when focused (issue-203).\n* TextField's ```bottomBorderLayerDistance``` is now ```lineLayerDistance```.\n* TextField now supports the ```lineLayerActiveColor```, which is set when the TextField is focused.\n* TextField now supports the ```lineLayerDetailActiveColor```, which is set when the TextField detailLabel is displayed.\n* Fixed issue-203, where TextField's ```lineLayer``` property was not the proper thickness when active.\n* Fixed regression, where the TextField's ```bottomLayer``` color was not showing (issue-276).\n* Removed shape code that was not needed in TextField and TextView.\n* Updated example projects using SearchBar, and simplified the configuration for the SearchBar.\n* Added OSX build target.\n* Added MaterialColor to OSX.\n* Added Google icons as default for ```MaterialIcon``` and additional CosmicMind icons with ```cm``` namespace (issue-285).\n\n## 1.38.5\n\n* Fix for MaterialIcon, [issue-279](https://github.com/CosmicMind/Material/issues/279).\n* Fix for touch consumption, [issue-280](https://github.com/CosmicMind/Material/issues/280).\n\n## 1.38.4\n\n* Added custom icons to MaterialIcon.\n\n## 1.38.3\n\n* Updated App example project.\n* Added MaterialCollectionView example project.\n* Added NavigationController storyboard example project.\n* Default colors for MaterialSwitch moved from MaterialColor.lightBlue.* to MaterialColor.blue.*.\n* Updated MaterialColor with corrections to the colors from Material Design (issue-271).\n\n## 1.38.2\n\n* Switched BottomNavigationBar to BottomTabBar, as it is more appropriate in the context of iOS. BottomNavigationController will be comprised of a SnackBar (coming soon), and BottomTabBar.\n* Added fix for Interface Builder, where MaterialSwitch was causing crashes (issue-259).\n* Fixed issue where MaterialSwitch color was not propagating until engaged (issue-260).\n\n## 1.38.1\n\n* Added missing imports for UIKit in MaterialCollectionView classes.\n\n## 1.38.0\n\n* Added BottomNavigationBar.\n* Added default Fade animation to BottomNavigationBar.\n* Added programmatic BottomNavigationBar example project.\n* Added storyboard BottomNavigationBar example project.\n* Added BottomNavigationController.\n* Added programmatic BottomNavigationController example.\n* Removed c-style ```for``` loops.\n* Updated bundle detection for MaterialIcon.\n* References for `mainViewController` are now `rootViewController`.\n* References for `transitionFromMainViewController` are now `transitionFromRootViewController`.\n* The example App project demonstrates how to hide the `statusBar` without the `navigationBar` being animated.\n* Fixed warnings for Swift 3.\n* Added detection for latest iPad and iPhone.\n\n## 1.37.3\n\n* Fixed issue-244, where Test Coverage flag was causing an error.\n\n## 1.37.2\n\n* Updated the default width of the SideNavigationController to reflect the Material Design spec more accurately. For mobile, the default width is 280px, and for tablet, the default width is 320px.\n\n## 1.37.1\n\n* Removed SideNavigationControllerDelegate call from NavigationController class that was not used.\n\n## 1.37.0\n\n* Added `pulseFocus` Boolean flag that keeps the pulse displayed as the button is highlighted (issue-217).\n* Switched `pulseColorOpacity` to `pulseOpacity`.\n* Added @IBInspectable where appropriate (issue-151).\n* Added @IBDesignable where appropriate (issue-151).\n* Fixed an issue where the tests were being broken (issue-224).\n* `NavigationBarView` is now called `Toolbar`.\n* `SearchBarView` is now called `SearchBar`.\n* `SideNavigationViewController` is now `SideNavigationController`.\n* Added public `leftThreshold` and `rightThreshold` to `SideNavigationController` (issue-220).\n\n## 1.36.0\n\n* Added class NavigationBar and NavigationController.\n* Added contentsGravityPreset where appropriate, and now contentsGravity takes a String.\n* Fixed issue-213, `shadowPathAutoSizeEnabled` now defaults to true, from false.\n\n## 1.35.3\n\n* MaterialAnimation.rotate now accepts an `angle` parameter or a `rotation` parameter.\n* Fixed issue-194, where the MaterialAnimation.translation animations were not capturing the final state value.\n* Fixed issue-201, by guaranteeing that the minimal iOS version is 8.\n\n## 1.35.2\n\n* Updated storyboard NavigationBarView example project to correctly set the height of the NavigationBarView when rotating orientations on both iPad and iPhone.\n* Removed NavigationBarViewDelegate and SearchBarViewDelegate.\n\n\n## 1.35.1\n\n* Fixed issue-195, where MaterialSwitch was switching the switchState automatically through the highlighted property.\n* Fixed issue-196, where NavigationBarView was not sizing correctly on iPad.\n* Added MaterialDevice helper class that provides useful values for orientation and bounds size.\n\n## 1.35.0\n\n* Removed backDropLayer for SideNavigationViewController. Now, the mainViewController.view property is set to 50% alpha when opened and 100% alpha when closed. The color is adopted from the backgroundColor of the mainViewController.view property.\n* MenuViewController now animates its backdrop effect.\n\n## 1.34.10\n\n* Added `shadowPathAutoSizeEnabled` property that enables auto sizing for the shadowPath property. Defaults to false.\n\n## 1.34.9\n\n* Fixed shadowPath animation on rotation.\n* Proposed fixed for NavigationBarView geometry issue.\n* Updated CardView and ImageCardView to have a default rounded corner of .Radius1 as in the Material Design spec.\n* Updated the example App project.\n\n## 1.34.8\n\n* Updated example App project.\n\n## 1.34.7\n\n* Updated App project example, by showing how to switch NavigationBarViewController's mainViewController from a SideNavigationViewController.\n* Added a FeedViewController to the example App project that shows how to use CardViews in a MaterialCollectionView.\n* Fixed a performance issue with shadows and animations, issue-186.\n\n## 1.34.6\n\n* Fixed issue with MaterialSwitch, issue-181.\n* Fixed issue with NavigationBarView Geometry, issue-179.\n* Added MaterialCollectionView, MaterialCollectionViewLayout, MaterialCollectionViewCell.\n* Added enum MaterialSpacing type for spacing presets, spacingPreset.\n* Added TextField storyboard example.\n* Rework to better the performance of animations with depth.\n\n## 1.34.5\n\n* Fixed breaking examples.\n\n## 1.34.4\n\n* Added **NavigationBarViewControllerDelegate** that monitors the state of the `floatingViewController` property.\n* Added **TextField** `detailLabelAutoHideEnabled`property that flags the animation to hide the detailLabel automatically when the text value has changed. Default is true.\n\n## 1.34.3\n\n* Added headers to public build phase.\n\n## 1.34.2\n\n* License text update.\n\n## 1.34.1\n\n* CaptureView example has been updated to use the latest NavigationBarView API.\n* NavigationBarView default sizing:\n    - Only titleLabel, font size is 20.\n    - With titleLabel and detailLabel, font size is 17 for titleLabel, and 12 for detailLabel.\n* Example projects updated.\n\n## 1.34.0\n\n* Added App example project in Examples/Programmatic.\n* Added ControlView.\n* Added StatusBarView.\n* NavigationViewController is now NavigationBarViewController.\n* Added StatusBarViewController.\n* Added SearchBarViewController.\n* MaterialSwitch now supports setting the \"on\", \"selected\", \"highlighted\", and \"switchState\" properties to toggle the state of the control.\n* MaterialSwitch now supports setOn(on: Bool, animated: Bool) method to switch the state of the control.\n* MaterialSwitch now supports 'on', 'highlighted', 'selected', 'state', and 'switchState' public mutators.\n* MaterialSwitchDelegate updated 'materialSwitchStateChanged' delegation method to only pass a reference to the control, rather than control and state value.\n* Added MenuViewController.\n* SideNavigationBarViewController is now SideNavigationViewController.\n* UIViewController Optional property sideNavigationBarViewController is now sideNavigationViewController.\n* Added TextField placeholderTextColor property to set the placeholder text color.\n* TextField detailLabel property hides automatically when typing.\n* TextField now supports a custom clear UIButton by setting the clearButton property.\n\n## 1.33.2\n\n* Updated SerchBarView Example.\n* A rotation issue is fixed when in landscape mode and toggling the SideNavigationViewController, where the statusBar would\n* Added MaterialSwitch UIControl component with example projects in the Examples/Programmatic directory.\n* MaterialEdgeInsetPreset is now MaterialEdgeInset.\n* MaterialRadius preset values are now supported through the cornerRadiusPreset property. The cornerRadius property now supports CGFloat values directly.\n* Updated TableCardView example.\n* Added SearchBarView.\n* Updated NavigationBarView API.\n* Added NavigationViewController.\n* Updated TextField and TextView issue, where letters such as \"y g p\" would not display correctly.\n* MaterialButton has updated contentInsetPreset to contentEdgeInsetsPreset.\n* Added MaterialTableViewCell with pulse animation.\n* Updated SideNavigationViewController example project.\n\n## 1.32.2\n\n* Fixed an issue with MenuView, where outside views were not detected when touched.\n* Updated API to reference views.\n\n## 1.32.1\n\n* MenuView wraps a Menu with a MaterialPulseView to ease the use of laying out menus, as well as, provide a more robust approach to Menus.\n* Menus now hold an array of UIViews, allowing any UIView to be animated with Menu.\n* The borderWidth property for Material views no longer uses an enum MaterialBorder type. It now supports the CGFloat type.\n\n## 1.32.0\n\n* CardView and ImageCardView no longer support the detailLabel property. Now, a detailView property has been added to allow any UIView, including UILabel to be added in the detail area.\n\n## 1.31.6\n\n* Grid now supports management of rows and columns in a single mapping.\n* Updated Grid examples.\n* Visit the Examples directory to see example projects using Material.\n\n## 1.31.5\n\n* Updated README.\n\n## 1.31.4\n\n* Updated Grid Example.\n* Updated README.\n\n## 1.31.3\n\n* Updated Material usage description.\n\n## 1.31.2\n\n* Introducing Material Grid. A flexible grid system to handle complex layouts.\n* Default depth is now .Depth1.\n\n## 1.31.1\n\n* Added two more examples using Menu.\n\n## 1.31.0\n\n* Added a new component, Menu!\n* A Menu manages a group of UIButtons that may be animated open in the Up, Down, Left, and Right directions. The animations\n\n## 1.30.2\n\n* Fixed an issue where toggling the SideNavigationViewController enabled property caused the 'left' and 'right' view to stop\n\n## 1.30.1\n\n* Updated MaterialView example.\n\n## 1.30.0\n\n* Updated pulse animation to be a wave.\n* Added `pulse` method to programmatically trigger the pulse animation.\n* Updated examples to reflect pulse changes.\n* Updated README to reflect pulse changes.\n* Removed `pulseFill` and `spotlight` from pulse animatable views as they are no longer needed.\n\n## 1.29.4\n\n* Some minor updates to the internal references used for animations.\n* Removed Task example to its own repository.\n\n## 1.29.3\n\n***This update is recommended.***\n\n* Major update to SideNavigationViewController internals and animation.\n* Added an additional duration parameter to setLeftViewWidth with animation and setRightViewWidth with animation.\n\n## 1.29.2\n\n***This is a recommended update.***\n\n* Updated internal animations to handle UIView animations correctly.\n* Updated SideNavigationViewController to allow quick swipe to close.\n* Updated SideNavigationViewController to not block view touches when tap gesture is triggered.\n* Updated workspace reference to Material project.\n\n## 1.29.1\n\n* To remove deprecated warnings, and provide an overall better solution, UIImage now utilizes NSURLSession for asynchronous image loading.\n* The MaterialLayer example project demonstrates this feature update.\n\n## 1.29.0\n\n* SideNavigationViewController now supports the Right position for View Controllers.\n* SideNavigationViewController API updates should be reviewed from the Class file.\n\n## 1.28.1\n\n* Updated README.\n\n## 1.28.0\n\n* Updated framework name to Material to avoid conflicts with other frameworks.\n* Updated default TextField animation distance for titleLabel to 8.\n* Updated default TextView animation distance for titleLabel to 8.\n\n## 1.27.14\n\n* The SideNavigationViewController example project has been updated.\n* Updated README.\n\n## 1.27.13\n\n* An updated SideNavigationViewController example has been added to the Examples Programmatic directory. It includes a fresh new look and a reusable template for your applications.\n\n## 1.27.12\n\n* Updates to the TextView and TextField were made to follow Google's spacing guidelines.\n* An issue with setting the TextView or TextField's text property has been fixed, where the title label was not being\n* Additional updates were made to many of the example projects.\n\n## 1.27.11\n\n* Updated License Format.\n\n## 1.27.10\n\n* Updated License Format.\n\n## 1.27.9\n\n* Material is moving to a BSD license.\n\n## 1.27.8\n\n* Added @objc to TextView and TextViewDelegate to eliminate conflicts when using swift within an Objective-C project.\nBelow is an example of a medium CardView using Grid.\n\n## 1.27.7\n\n* Fixed an issue where the optional TextView.text property was being accessed and throwing an error when used in combination with Objective-C.\n\n## 1.27.6\n\n* Updated TextView internals to avoid optimization build issue with Carthage.\n* Updated icon set in example projects.\n* Updated Resources folder with latest graphics.\n* Updated README.\n\n## 1.27.4\n\n* Removed the File Class.\n* Updated README to correct TextField example.\nRight out of the box to a fully customizable configuration, CardView always stands out. Take a look at a few examples in action.\n\n### 1.27.2\n\n* **titleLabelTextColor** is now **titleLabelColor**.\n* **titleLabelActiveTextColor** is now **titleLabelActiveColor**.\n* **detailLabelActiveTextColor** is now **detailLabelActiveColor**.\n* **titleLabelTextColor** is now **titleLabelColor**.\n* **titleLabelActiveTextColor** is now **titleLabelActiveColor**.\n\n## 1.27.1\n\n* Updated README to include Changelog link.\n\n## 1.27.0\n\n* Has been removed completely.\n* **MaterialEdgeInsets** is now **MaterialEdgeInsetPreset**.\n* **contentInsets** is now **contentInsetPreset**.\n* **contentInsetsRef** is now **contentInset**.\n* **dividerInsets** is now **dividerInsetPreset**.\n* **dividerInsetRef** is now **dividerInset**.\n* **contentInsets** is now **contentInsetPreset**.\n* **contentInsetsRef** is now **contentInset**.\n* **titleLabelInsets** is now **titleLabelInsetPreset**.\n* **titleLabelInsetsRef** is now **titleLabelInset**.\n* **detailLabelInsets** is now **detailLabelInsetPreset**.\n* **detailLabelInsetsRef** is now **detailLabelInset**.\n* **leftButtonsInsets** is now **leftButtonsInsetPreset**.\n* **leftButtonsInsetsRef** is now **leftButtonsInset**.\n* **rightButtonsInsets** is now **rightButtonsInsetPreset**.\n* **rightButtonsInsetsRef** is now **rightButtonsInset**.\n* **dividerInsets** is now **dividerInsetPreset**.\n* **dividerInsetRef** is now **dividerInset**.\n* **contentInsets** is now **contentInsetPreset**.\n* **contentInsetsRef** is now **contentInset**.\n* **titleLabelInsets** is now **titleLabelInsetPreset**.\n* **titleLabelInsetsRef** is now **titleLabelInset**.\n* **detailLabelInsets** is now **detailLabelInsetPreset**.\n* **detailLabelInsetsRef** is now **detailLabelInset**.\n* **leftButtonsInsets** is now **leftButtonsInsetPreset**.\n* **leftButtonsInsetsRef** is now **leftButtonsInset**.\n* **rightButtonsInsets** is now **rightButtonsInsetPreset**.\n* **rightButtonsInsetsRef** is now **rightButtonsInset**.\n* **shrink** is now **shrinkAnimation**.\n* **wrapped** is no longer an Optional.\n* **contentsScale** is no longer an Optional.\n* **shrink** is now **shrinkAnimation**.\n* **updatedPulseLayer** is now **updatePulseLayer**.\n* **contentInsets** is now **contentInsetPreset**.\n* **contentInsetsRef** is now **contentInset**.\n* **titleLabelInsets** is now **titleLabelInsetPreset**.\n* **titleLabelInsetsRef** is now **titleLabelInset**.\n* **detailLabelInsets** is now **detailLabelInsetPreset**.\n* **detailLabelInsetsRef** is now **detailLabelInset**.\n* **leftButtonsInsets** is now **leftButtonsInsetPreset**.\n* **leftButtonsInsetsRef** is now **leftButtonsInset**.\n* **rightButtonsInsets** is now **rightButtonsInsetPreset**.\n* **rightButtonsInsetsRef** is now **rightButtonsInset**.\n* When setting the **enabled** property, gestures are removed and added appropriately.\n* **titleLabelNormalColor** is now **titleLabelTextColor**.\n* **titleLabelHighlightedColor** is now **titleLabelActiveTextColor**. \n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment include:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at support@cosmicmind.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]\n\n[homepage]: http://contributor-covenant.org\n[version]: http://contributor-covenant.org/version/1/4/\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing Guidelines\n\nThis document contains information and guidelines about contributing to this project.\nPlease read it before you start participating.\n\n**Topics**\n\n* [Pull Request Submissions](#pull-request-submissions)\n* [Asking Questions](#asking-questions)\n* [Reporting Security Issues](#reporting-security-issues)\n* [Reporting Issues](#reporting-other-issues)\n* [Developers Certificate of Origin](#developers-certificate-of-origin)\n* [Code of Conduct](#code-of-conduct)\n\n<a href=\"#pull-request-submissions\"></a>\n## Pull Request Submissions.\n\nAll pull requests should be made to the development branch. Details should be available describing your fix. Before submitting a pull request, please confirm that merge issues are resolved.\n\n<a href=\"#asking-questions\"></a>\n## Asking Questions\n\nWe don't use GitHub as a support forum.\nFor any usage questions that are not specific to the project itself,\nplease ask on [Stack Overflow](http://stackoverflow.com/questions/tagged/cosmicmind) instead.\nBy doing so, you'll be more likely to quickly solve your problem,\nand you'll allow anyone else with the same question to find the answer.\nThis also allows maintainers to focus on improving the project for others.\n\n<a href=\"#reporting-security-issues\"></a>\n## Reporting Security Issues\n\nCosmicMind takes security seriously.\nIf you discover a security issue, please bring it to our attention right away!\n\nPlease **DO NOT** file a public issue,\ninstead send your report privately to <support@cosmicmind.com>.\nThis will help ensure that any vulnerabilities that _are_ found\ncan be [disclosed responsibly](http://en.wikipedia.org/wiki/Responsible_disclosure)\nto any affected parties.\n\n<a href=\"#reporting-other-issues\"></a>\n## Reporting Other Issues\n\nA great way to contribute to the project\nis to send a detailed issue when you encounter an problem.\nWe always appreciate a well-written, thorough bug report.\n\nCheck that the project issues database\ndoesn't already include that problem or suggestion before submitting an issue.\nIf you find a match, add a quick \"+1\" or \"I have this problem too.\"\nDoing this helps prioritize the most common problems and requests.\n\nWhen reporting issues, please include the following:\n\n* The version of Xcode you're using\n* The version of iOS you're targeting\n* The full output of any stack trace or compiler error\n* A code snippet that reproduces the described behavior, if applicable\n* Any other details that would be useful in understanding the problem\n\nThis information will help us review and fix your issue faster.\n\n<a href=\"#developers-certificate-of-origin\"></a>\n## Developer's Certificate of Origin 1.1\n\nBy making a contribution to this project, I certify that:\n\n- (a) The contribution was created in whole or in part by me and I\n      have the right to submit it under the open source license\n      indicated in the file; or\n\n- (b) The contribution is based upon previous work that, to the best\n      of my knowledge, is covered under an appropriate open source\n      license and I have the right under that license to submit that\n      work with modifications, whether created in whole or in part\n      by me, under the same open source license (unless I am\n      permitted to submit under a different license), as indicated\n      in the file; or\n\n- (c) The contribution was provided directly to me by some other\n      person who certified (a), (b) or (c) and I have not modified\n      it.\n\n- (d) I understand and agree that this project and the contribution\n      are public and that a record of the contribution (including all\n      personal information I submit with it, including my sign-off) is\n      maintained indefinitely and may be redistributed consistent with\n      this project or the open source license(s) involved.\n\n---\n\n*Some of the ideas and wording for the statements above were based on work by the [Alamofire](https://github.com/Alamofire/Alamofire/blob/master/CONTRIBUTING.md), [Docker](https://github.com/docker/docker/blob/master/CONTRIBUTING.md) and [Linux](http://elinux.org/Developer_Certificate_Of_Origin) communities. We commend them for their efforts to facilitate collaboration in their projects.*\n"
  },
  {
    "path": "Cartfile",
    "content": "github \"CosmicMind/Motion\" >= 1.2.2\n\n"
  },
  {
    "path": "LICENSE.md",
    "content": "The MIT License (MIT)\n\nCopyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\nAll rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "Material.podspec",
    "content": "Pod::Spec.new do |s|\n\ts.name = 'Material'\n\ts.version = '3.1.8'\n\ts.swift_version = '5.0'\n\ts.license = 'BSD-3-Clause'\n\ts.summary = 'A UI/UX framework for creating beautiful applications.'\n\ts.homepage = 'http://cosmicmind.com'\n\ts.social_media_url = 'https://www.facebook.com/cosmicmindcom'\n\ts.authors = { 'CosmicMind, Inc.' => 'support@cosmicmind.com' }\n \ts.source = { :git => 'https://github.com/CosmicMind/Material.git', :tag => s.version }\n\n\ts.default_subspec = 'Core'\n\ts.platform = :ios, '8.0'\n\n\ts.subspec 'Core' do |s|\n\t\ts.ios.deployment_target = '8.0'\n\t\ts.ios.source_files = 'Sources/**/*.swift'\n\t\ts.requires_arc = true\n\t\ts.resource_bundles = {\n\t\t\t'com.cosmicmind.material.icons' => ['Sources/**/*.xcassets'],\n\t\t\t'com.cosmicmind.material.fonts' => ['Sources/**/*.ttf']\n\t\t}\n\n\t\ts.dependency 'Motion', '~> 3.1.1'\n\tend\nend\n"
  },
  {
    "path": "Material.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t961154CC1F32A7B100A78D74 /* ChipBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961154CB1F32A7B100A78D74 /* ChipBar.swift */; };\n\t\t961527B91F3A509900E8B2AC /* ChipBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961527B81F3A509900E8B2AC /* ChipBarController.swift */; };\n\t\t9617B07D1DFCA8CF00410F8F /* Application.swift in Headers */ = {isa = PBXBuildFile; fileRef = 961E6BDE1DDA2A95004E6C93 /* Application.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9617B07E1DFCA8CF00410F8F /* Card.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB75D1CB40DC500C806FE /* Card.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9617B07F1DFCA8CF00410F8F /* ImageCard.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7621CB40DC500C806FE /* ImageCard.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9617B0801DFCA8CF00410F8F /* PresenterCard.swift in Headers */ = {isa = PBXBuildFile; fileRef = 9631A7C01D95E3AC00CFB109 /* PresenterCard.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9617B0861DFCA8CF00410F8F /* HeightPreset.swift in Headers */ = {isa = PBXBuildFile; fileRef = 9626CB9A1DAD3D1D003E2611 /* HeightPreset.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9617B08A1DFCA8CF00410F8F /* DisplayStyle.swift in Headers */ = {isa = PBXBuildFile; fileRef = 9626CA961DAB53A8003E2611 /* DisplayStyle.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9617B08B1DFCA8CF00410F8F /* Screen.swift in Headers */ = {isa = PBXBuildFile; fileRef = 961E6BE11DDA2AF3004E6C93 /* Screen.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9617B08C1DFCA8CF00410F8F /* SearchBar.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7951CB40DC500C806FE /* SearchBar.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9617B08D1DFCA8CF00410F8F /* SearchBarController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7961CB40DC500C806FE /* SearchBarController.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9617B08E1DFCA8CF00410F8F /* TabBar.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB79A1CB40DC500C806FE /* TabBar.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9617B08F1DFCA8CF00410F8F /* Material+NSMutableAttributedString.swift in Headers */ = {isa = PBXBuildFile; fileRef = 961276621DCD8B1800A7D920 /* Material+NSMutableAttributedString.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9617B0901DFCA8CF00410F8F /* Toolbar.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB79F1CB40DC500C806FE /* Toolbar.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9617B0911DFCA8CF00410F8F /* ToolbarController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7A01CB40DC500C806FE /* ToolbarController.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9618006D1F4D384200CD77A1 /* Material+UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9618006C1F4D384200CD77A1 /* Material+UIViewController.swift */; };\n\t\t9618006E1F4D38BC00CD77A1 /* ChipBar.swift in Headers */ = {isa = PBXBuildFile; fileRef = 961154CB1F32A7B100A78D74 /* ChipBar.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9618006F1F4D38BC00CD77A1 /* ChipBarController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 961527B81F3A509900E8B2AC /* ChipBarController.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t961800701F4D38BC00CD77A1 /* Material+UIViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 9618006C1F4D384200CD77A1 /* Material+UIViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t961E6BDF1DDA2A95004E6C93 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961E6BDE1DDA2A95004E6C93 /* Application.swift */; };\n\t\t961E6BE21DDA2AF3004E6C93 /* Screen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961E6BE11DDA2AF3004E6C93 /* Screen.swift */; };\n\t\t96328B7A1E020A41009A4C90 /* CollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96328B791E020A41009A4C90 /* CollectionViewController.swift */; };\n\t\t96328B971E05C0BB009A4C90 /* TableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96328B961E05C0BB009A4C90 /* TableView.swift */; };\n\t\t96328B991E05C0CE009A4C90 /* TableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96328B981E05C0CE009A4C90 /* TableViewController.swift */; };\n\t\t96328B9B1E05C24E009A4C90 /* CollectionViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96328B791E020A41009A4C90 /* CollectionViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96328B9E1E05C24E009A4C90 /* TableView.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96328B961E05C0BB009A4C90 /* TableView.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96328B9F1E05C24E009A4C90 /* TableViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96328B981E05C0CE009A4C90 /* TableViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96334EF61C8B84660083986B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 96334EF51C8B84660083986B /* Assets.xcassets */; };\n\t\t9656895F1F002F16001C656D /* CardCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9656895E1F002F16001C656D /* CardCollectionViewCell.swift */; };\n\t\t965689611F002F4C001C656D /* CardCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965689601F002F4C001C656D /* CardCollectionViewController.swift */; };\n\t\t965E80CC1DD4C50600D61E4B /* Bar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7981CB40DC500C806FE /* Bar.swift */; };\n\t\t965E80CD1DD4C50600D61E4B /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7701CB40DC500C806FE /* Button.swift */; };\n\t\t965E80CE1DD4C50600D61E4B /* FABButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB75F1CB40DC500C806FE /* FABButton.swift */; };\n\t\t965E80CF1DD4C50600D61E4B /* FlatButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7601CB40DC500C806FE /* FlatButton.swift */; };\n\t\t965E80D01DD4C50600D61E4B /* RaisedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7931CB40DC500C806FE /* RaisedButton.swift */; };\n\t\t965E80D11DD4C50600D61E4B /* IconButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9658F2161CD6FA4700B902C1 /* IconButton.swift */; };\n\t\t965E80D21DD4C50600D61E4B /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7761CB40DC500C806FE /* Color.swift */; };\n\t\t965E80D31DD4C50600D61E4B /* Device.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7791CB40DC500C806FE /* Device.swift */; };\n\t\t965E80D41DD4C50600D61E4B /* Divider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96230AB71D6A520C00AF47DC /* Divider.swift */; };\n\t\t965E80D51DD4C50600D61E4B /* Grid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7611CB40DC500C806FE /* Grid.swift */; };\n\t\t965E80D61DD4C50600D61E4B /* HeightPreset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9626CB9A1DAD3D1D003E2611 /* HeightPreset.swift */; };\n\t\t965E80D71DD4C50600D61E4B /* Icon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB77D1CB40DC500C806FE /* Icon.swift */; };\n\t\t965E80D81DD4C50600D61E4B /* Layer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7801CB40DC500C806FE /* Layer.swift */; };\n\t\t965E80D91DD4C50600D61E4B /* Layout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7811CB40DC500C806FE /* Layout.swift */; };\n\t\t965E80DA1DD4C50600D61E4B /* Border.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB76F1CB40DC500C806FE /* Border.swift */; };\n\t\t965E80DB1DD4C50600D61E4B /* InterimSpace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7871CB40DC500C806FE /* InterimSpace.swift */; };\n\t\t965E80DC1DD4C50600D61E4B /* Depth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7781CB40DC500C806FE /* Depth.swift */; };\n\t\t965E80DD1DD4C50600D61E4B /* EdgeInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB77A1CB40DC500C806FE /* EdgeInsets.swift */; };\n\t\t965E80DF1DD4C50600D61E4B /* CornerRadius.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7851CB40DC500C806FE /* CornerRadius.swift */; };\n\t\t965E80E01DD4C50600D61E4B /* Shape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7861CB40DC500C806FE /* Shape.swift */; };\n\t\t965E80E11DD4C50600D61E4B /* Offset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 968C99461D377849000074FF /* Offset.swift */; };\n\t\t965E80E21DD4C50600D61E4B /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB78C1CB40DC500C806FE /* View.swift */; };\n\t\t965E80E41DD4C53300D61E4B /* PulseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7841CB40DC500C806FE /* PulseView.swift */; };\n\t\t965E80E51DD4C53300D61E4B /* PulseAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7821CB40DC500C806FE /* PulseAnimation.swift */; };\n\t\t965E80E71DD4C55200D61E4B /* Material+UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96E3C3931D397AE90086A024 /* Material+UIView.swift */; };\n\t\t965E80E81DD4C55200D61E4B /* Material+CALayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96F1DC871D654FDF0025F925 /* Material+CALayer.swift */; };\n\t\t965E80E91DD4C55200D61E4B /* Material+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7641CB40DC500C806FE /* Material+String.swift */; };\n\t\t965E80EA1DD4C55200D61E4B /* Material+UIFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7651CB40DC500C806FE /* Material+UIFont.swift */; };\n\t\t965E80EB1DD4C55200D61E4B /* Material+UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB76C1CB40DC500C806FE /* Material+UIImage.swift */; };\n\t\t965E80EC1DD4C55200D61E4B /* Material+Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C1C8801D42C62800E6608F /* Material+Array.swift */; };\n\t\t965E80ED1DD4C55200D61E4B /* Material+UIWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 962864591D53FE3E00690B69 /* Material+UIWindow.swift */; };\n\t\t965E80F71DD4D59500D61E4B /* Card.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB75D1CB40DC500C806FE /* Card.swift */; };\n\t\t965E80F81DD4D59500D61E4B /* ImageCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7621CB40DC500C806FE /* ImageCard.swift */; };\n\t\t965E80F91DD4D59500D61E4B /* PresenterCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9631A7C01D95E3AC00CFB109 /* PresenterCard.swift */; };\n\t\t965E80FB1DD4D59500D61E4B /* SearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7951CB40DC500C806FE /* SearchBar.swift */; };\n\t\t965E80FC1DD4D59500D61E4B /* SearchBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7961CB40DC500C806FE /* SearchBarController.swift */; };\n\t\t965E80FD1DD4D59500D61E4B /* Toolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB79F1CB40DC500C806FE /* Toolbar.swift */; };\n\t\t965E80FE1DD4D59500D61E4B /* ToolbarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7A01CB40DC500C806FE /* ToolbarController.swift */; };\n\t\t965E80FF1DD4D5C800D61E4B /* BottomNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7581CB40DC500C806FE /* BottomNavigationController.swift */; };\n\t\t965E81031DD4D5C800D61E4B /* CollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7711CB40DC500C806FE /* CollectionView.swift */; };\n\t\t965E81041DD4D5C800D61E4B /* CollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7721CB40DC500C806FE /* CollectionViewCell.swift */; };\n\t\t965E81071DD4D5C800D61E4B /* CollectionViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7751CB40DC500C806FE /* CollectionViewLayout.swift */; };\n\t\t965E81081DD4D5C800D61E4B /* CollectionReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 966ECF291CF4C20100BB0BDF /* CollectionReusableView.swift */; };\n\t\t965E81091DD4D5C800D61E4B /* DataSourceItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7771CB40DC500C806FE /* DataSourceItem.swift */; };\n\t\t965E810A1DD4D5C800D61E4B /* Font.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB77B1CB40DC500C806FE /* Font.swift */; };\n\t\t965E810B1DD4D5C800D61E4B /* RobotoFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7941CB40DC500C806FE /* RobotoFont.swift */; };\n\t\t965E810C1DD4D5C800D61E4B /* DynamicFontType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9628645E1D540AF300690B69 /* DynamicFontType.swift */; };\n\t\t965E81101DD4D5C800D61E4B /* NavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7901CB40DC500C806FE /* NavigationBar.swift */; };\n\t\t965E81111DD4D5C800D61E4B /* NavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7911CB40DC500C806FE /* NavigationController.swift */; };\n\t\t965E81121DD4D5C800D61E4B /* NavigationItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7921CB40DC500C806FE /* NavigationItem.swift */; };\n\t\t965E81131DD4D5C800D61E4B /* NavigationDrawerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7971CB40DC500C806FE /* NavigationDrawerController.swift */; };\n\t\t965E81161DD4D5C800D61E4B /* DisplayStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9626CA961DAB53A8003E2611 /* DisplayStyle.swift */; };\n\t\t965E81171DD4D5C800D61E4B /* TransitionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7991CB40DC500C806FE /* TransitionController.swift */; };\n\t\t965E81181DD4D5C800D61E4B /* Snackbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 963FBEFC1D669510008F8512 /* Snackbar.swift */; };\n\t\t965E81191DD4D5C800D61E4B /* SnackbarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961EFC571D738FF600E84652 /* SnackbarController.swift */; };\n\t\t965E811A1DD4D5C800D61E4B /* StatusBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 967A48181D0F425A00B8CEB7 /* StatusBarController.swift */; };\n\t\t965E811B1DD4D5C800D61E4B /* Switch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7881CB40DC500C806FE /* Switch.swift */; };\n\t\t965E811C1DD4D5C800D61E4B /* TabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB79A1CB40DC500C806FE /* TabBar.swift */; };\n\t\t965E811D1DD4D5C800D61E4B /* TableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7891CB40DC500C806FE /* TableViewCell.swift */; };\n\t\t965E811E1DD4D5C800D61E4B /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB79C1CB40DC500C806FE /* TextField.swift */; };\n\t\t965E811F1DD4D5C800D61E4B /* ErrorTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961F18E71CD93E3E008927C5 /* ErrorTextField.swift */; };\n\t\t965E81211DD4D5C800D61E4B /* TextStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB79D1CB40DC500C806FE /* TextStorage.swift */; };\n\t\t965E81221DD4D5C800D61E4B /* TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB79E1CB40DC500C806FE /* TextView.swift */; };\n\t\t965E81261DD4D7C800D61E4B /* Material+NSMutableAttributedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961276621DCD8B1800A7D920 /* Material+NSMutableAttributedString.swift */; };\n\t\t966C17731F0439F600D3E83C /* Material+MotionAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 966C17721F0439F600D3E83C /* Material+MotionAnimation.swift */; };\n\t\t9685D5AF1F0F04CB00AFEB79 /* CardCollectionViewCell.swift in Headers */ = {isa = PBXBuildFile; fileRef = 9656895E1F002F16001C656D /* CardCollectionViewCell.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9685D5B01F0F04CB00AFEB79 /* CardCollectionViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 965689601F002F4C001C656D /* CardCollectionViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9685D5B11F0F04CB00AFEB79 /* Material+MotionAnimation.swift in Headers */ = {isa = PBXBuildFile; fileRef = 966C17721F0439F600D3E83C /* Material+MotionAnimation.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9697F7BF1D8F2572004741EC /* Divider.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96230AB71D6A520C00AF47DC /* Divider.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9697F7C01D8F2572004741EC /* Material+CALayer.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96F1DC871D654FDF0025F925 /* Material+CALayer.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9697F7C11D8F2572004741EC /* Material+Array.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96C1C8801D42C62800E6608F /* Material+Array.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9697F7C21D8F2572004741EC /* Material+UIWindow.swift in Headers */ = {isa = PBXBuildFile; fileRef = 962864591D53FE3E00690B69 /* Material+UIWindow.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9697F7C31D8F2572004741EC /* DynamicFontType.swift in Headers */ = {isa = PBXBuildFile; fileRef = 9628645E1D540AF300690B69 /* DynamicFontType.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9697F7CB1D8F2573004741EC /* Snackbar.swift in Headers */ = {isa = PBXBuildFile; fileRef = 963FBEFC1D669510008F8512 /* Snackbar.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9697F7CC1D8F2573004741EC /* SnackbarController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 961EFC571D738FF600E84652 /* SnackbarController.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96B8D22C20CF82D2008BD149 /* FABMenuController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96A183641E0C6DD400083C30 /* FABMenuController.swift */; };\n\t\t96B8D22D20CF82D5008BD149 /* FABMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96A183621E0C6CE200083C30 /* FABMenu.swift */; };\n\t\t96BCB7F31CB40DE900C806FE /* Roboto-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 96BCB7EE1CB40DE900C806FE /* Roboto-Bold.ttf */; };\n\t\t96BCB7F51CB40DE900C806FE /* Roboto-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 96BCB7EF1CB40DE900C806FE /* Roboto-Light.ttf */; };\n\t\t96BCB7F71CB40DE900C806FE /* Roboto-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 96BCB7F01CB40DE900C806FE /* Roboto-Medium.ttf */; };\n\t\t96BCB7F91CB40DE900C806FE /* Roboto-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 96BCB7F11CB40DE900C806FE /* Roboto-Regular.ttf */; };\n\t\t96BCB7FB1CB40DE900C806FE /* Roboto-Thin.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 96BCB7F21CB40DE900C806FE /* Roboto-Thin.ttf */; };\n\t\t96BCB8141CB4115200C806FE /* PulseAnimation.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7821CB40DC500C806FE /* PulseAnimation.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8151CB4115200C806FE /* FABButton.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB75F1CB40DC500C806FE /* FABButton.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8161CB4115200C806FE /* FlatButton.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7601CB40DC500C806FE /* FlatButton.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8171CB4115200C806FE /* Button.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7701CB40DC500C806FE /* Button.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8181CB4115200C806FE /* RaisedButton.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7931CB40DC500C806FE /* RaisedButton.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB81E1CB4115200C806FE /* DataSourceItem.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7771CB40DC500C806FE /* DataSourceItem.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB81F1CB4115200C806FE /* CollectionView.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7711CB40DC500C806FE /* CollectionView.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8201CB4115200C806FE /* CollectionViewCell.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7721CB40DC500C806FE /* CollectionViewCell.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8231CB4115200C806FE /* CollectionViewLayout.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7751CB40DC500C806FE /* CollectionViewLayout.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8241CB4115200C806FE /* TableViewCell.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7891CB40DC500C806FE /* TableViewCell.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8251CB4115200C806FE /* Color.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7761CB40DC500C806FE /* Color.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8261CB4115200C806FE /* Device.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7791CB40DC500C806FE /* Device.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8281CB4115200C806FE /* Material+String.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7641CB40DC500C806FE /* Material+String.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8291CB4115200C806FE /* Material+UIFont.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7651CB40DC500C806FE /* Material+UIFont.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8301CB4115200C806FE /* Material+UIImage.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB76C1CB40DC500C806FE /* Material+UIImage.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8311CB4115200C806FE /* Font.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB77B1CB40DC500C806FE /* Font.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8321CB4115200C806FE /* RobotoFont.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7941CB40DC500C806FE /* RobotoFont.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8331CB4115200C806FE /* Icon.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB77D1CB40DC500C806FE /* Icon.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8341CB4115200C806FE /* Layer.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7801CB40DC500C806FE /* Layer.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8361CB4115200C806FE /* Grid.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7611CB40DC500C806FE /* Grid.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8371CB4115200C806FE /* Layout.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7811CB40DC500C806FE /* Layout.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB83B1CB4115200C806FE /* NavigationDrawerController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7971CB40DC500C806FE /* NavigationDrawerController.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB83C1CB4115200C806FE /* Bar.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7981CB40DC500C806FE /* Bar.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB83D1CB4115200C806FE /* TransitionController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7991CB40DC500C806FE /* TransitionController.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8441CB4115200C806FE /* BottomNavigationController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7581CB40DC500C806FE /* BottomNavigationController.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8461CB4115200C806FE /* NavigationBar.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7901CB40DC500C806FE /* NavigationBar.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8471CB4115200C806FE /* NavigationController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7911CB40DC500C806FE /* NavigationController.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8481CB4115200C806FE /* NavigationItem.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7921CB40DC500C806FE /* NavigationItem.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB84A1CB4115200C806FE /* TextField.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB79C1CB40DC500C806FE /* TextField.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB84B1CB4115200C806FE /* TextStorage.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB79D1CB40DC500C806FE /* TextStorage.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB84C1CB4115200C806FE /* TextView.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB79E1CB40DC500C806FE /* TextView.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB84D1CB4115200C806FE /* Border.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB76F1CB40DC500C806FE /* Border.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB84E1CB4115200C806FE /* InterimSpace.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7871CB40DC500C806FE /* InterimSpace.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB84F1CB4115200C806FE /* Depth.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7781CB40DC500C806FE /* Depth.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8501CB4115200C806FE /* EdgeInsets.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB77A1CB40DC500C806FE /* EdgeInsets.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8521CB4115200C806FE /* CornerRadius.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7851CB40DC500C806FE /* CornerRadius.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8531CB4115200C806FE /* Shape.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7861CB40DC500C806FE /* Shape.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8551CB4115200C806FE /* PulseView.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7841CB40DC500C806FE /* PulseView.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8561CB4115200C806FE /* Switch.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7881CB40DC500C806FE /* Switch.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BCB8571CB4115200C806FE /* View.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB78C1CB40DC500C806FE /* View.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96BFC1541E5E486F0075DE1F /* SpringAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965532281E47E388005C2792 /* SpringAnimation.swift */; };\n\t\t96BFC16F1E63C10A0075DE1F /* SpringAnimation.swift in Headers */ = {isa = PBXBuildFile; fileRef = 965532281E47E388005C2792 /* SpringAnimation.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96D88C321C1328D800B91418 /* Material.h in Headers */ = {isa = PBXBuildFile; fileRef = 96D88C091C1328D800B91418 /* Material.h */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96E09DC81F2287E50000B121 /* TabsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96E09DC71F2287E50000B121 /* TabsController.swift */; };\n\t\t96E3C3951D3A1CC20086A024 /* IconButton.swift in Headers */ = {isa = PBXBuildFile; fileRef = 9658F2161CD6FA4700B902C1 /* IconButton.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96E3C3961D3A1CC20086A024 /* CollectionReusableView.swift in Headers */ = {isa = PBXBuildFile; fileRef = 966ECF291CF4C20100BB0BDF /* CollectionReusableView.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96E3C3971D3A1CC20086A024 /* Material+UIView.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96E3C3931D397AE90086A024 /* Material+UIView.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96E3C3991D3A1CC20086A024 /* StatusBarController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 967A48181D0F425A00B8CEB7 /* StatusBarController.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96E3C39A1D3A1CC20086A024 /* ErrorTextField.swift in Headers */ = {isa = PBXBuildFile; fileRef = 961F18E71CD93E3E008927C5 /* ErrorTextField.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96E3C39C1D3A1CC20086A024 /* Offset.swift in Headers */ = {isa = PBXBuildFile; fileRef = 968C99461D377849000074FF /* Offset.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t96F1A5531F24F17A001D8CAF /* TabsController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96E09DC71F2287E50000B121 /* TabsController.swift */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t9D00EBB4216675FB00DBCD69 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D00EBB3216675FB00DBCD69 /* Theme.swift */; };\n\t\t9D054A6520D175AC00D0528D /* Material+UIButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D054A6320D175AC00D0528D /* Material+UIButton.swift */; };\n\t\t9D054A6620D175AC00D0528D /* Material+UILabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D054A6420D175AC00D0528D /* Material+UILabel.swift */; };\n\t\t9D39A81B20FE8ED100BA8FA1 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D39A81A20FE8ED100BA8FA1 /* ViewController.swift */; };\n\t\t9D494A38217F6B63003D66F1 /* LayoutAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D494A37217F6B63003D66F1 /* LayoutAttribute.swift */; };\n\t\t9D494A3A217F6B70003D66F1 /* LayoutAnchor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D494A39217F6B70003D66F1 /* LayoutAnchor.swift */; };\n\t\t9D494A3C217F6B7D003D66F1 /* LayoutConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D494A3B217F6B7D003D66F1 /* LayoutConstraint.swift */; };\n\t\t9D9089B92118914500605DC9 /* Editor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D9089B82118914500605DC9 /* Editor.swift */; };\n\t\t9DE25DE02170D7AF000C04DF /* Dialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DE25DDF2170D7AF000C04DF /* Dialog.swift */; };\n\t\t9DE25DE22170D7C0000C04DF /* DialogController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DE25DE12170D7C0000C04DF /* DialogController.swift */; };\n\t\t9DE25DE42170D7FF000C04DF /* DialogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DE25DE32170D7FF000C04DF /* DialogView.swift */; };\n\t\t9DE84D721FF0252600586C8B /* RadioButtonGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DE84D6F1FF0252500586C8B /* RadioButtonGroup.swift */; };\n\t\t9DE84D731FF0252600586C8B /* BaseButtonGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DE84D701FF0252500586C8B /* BaseButtonGroup.swift */; };\n\t\t9DE84D741FF0252600586C8B /* CheckButtonGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DE84D711FF0252500586C8B /* CheckButtonGroup.swift */; };\n\t\t9DF352421FED20C900B2A11B /* BaseIconLayerButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DF352411FED20C900B2A11B /* BaseIconLayerButton.swift */; };\n\t\t9DF352441FED20ED00B2A11B /* RadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DF352431FED20ED00B2A11B /* RadioButton.swift */; };\n\t\t9DF352461FED210000B2A11B /* CheckButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DF352451FED210000B2A11B /* CheckButton.swift */; };\n\t\t9DF58CEE20C098C60098968D /* ErrorTextFieldValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DF58CED20C098C60098968D /* ErrorTextFieldValidator.swift */; };\n\t\t9DF74C4E20D15D84003C1D66 /* Material+UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DF74C4D20D15D84003C1D66 /* Material+UIColor.swift */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t968BA8351F8D201B0091852E /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 968BA8311F8D201B0091852E /* Motion.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 96C98DD11E424AB000B22906;\n\t\t\tremoteInfo = \"Motion iOS\";\n\t\t};\n\t\t968BA8371F8D20530091852E /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 968BA8311F8D201B0091852E /* Motion.xcodeproj */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 96C98DD01E424AB000B22906;\n\t\t\tremoteInfo = \"Motion iOS\";\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\t961154CB1F32A7B100A78D74 /* ChipBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChipBar.swift; sourceTree = \"<group>\"; };\n\t\t961276621DCD8B1800A7D920 /* Material+NSMutableAttributedString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"Material+NSMutableAttributedString.swift\"; sourceTree = \"<group>\"; };\n\t\t961527B81F3A509900E8B2AC /* ChipBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChipBarController.swift; sourceTree = \"<group>\"; };\n\t\t9618006C1F4D384200CD77A1 /* Material+UIViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"Material+UIViewController.swift\"; sourceTree = \"<group>\"; };\n\t\t961E6BDE1DDA2A95004E6C93 /* Application.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = \"<group>\"; };\n\t\t961E6BE11DDA2AF3004E6C93 /* Screen.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Screen.swift; sourceTree = \"<group>\"; };\n\t\t961EFC571D738FF600E84652 /* SnackbarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SnackbarController.swift; sourceTree = \"<group>\"; };\n\t\t961F18E71CD93E3E008927C5 /* ErrorTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorTextField.swift; sourceTree = \"<group>\"; };\n\t\t96230AB71D6A520C00AF47DC /* Divider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Divider.swift; sourceTree = \"<group>\"; };\n\t\t9626CA961DAB53A8003E2611 /* DisplayStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisplayStyle.swift; sourceTree = \"<group>\"; };\n\t\t9626CB9A1DAD3D1D003E2611 /* HeightPreset.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeightPreset.swift; sourceTree = \"<group>\"; };\n\t\t962864591D53FE3E00690B69 /* Material+UIWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"Material+UIWindow.swift\"; sourceTree = \"<group>\"; };\n\t\t9628645E1D540AF300690B69 /* DynamicFontType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicFontType.swift; sourceTree = \"<group>\"; };\n\t\t9631A7C01D95E3AC00CFB109 /* PresenterCard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PresenterCard.swift; sourceTree = \"<group>\"; };\n\t\t96328B791E020A41009A4C90 /* CollectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionViewController.swift; sourceTree = \"<group>\"; };\n\t\t96328B961E05C0BB009A4C90 /* TableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableView.swift; sourceTree = \"<group>\"; };\n\t\t96328B981E05C0CE009A4C90 /* TableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewController.swift; sourceTree = \"<group>\"; };\n\t\t96334EF51C8B84660083986B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t963832361B88DFD80015F710 /* Material.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Material.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t963FBEFC1D669510008F8512 /* Snackbar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Snackbar.swift; sourceTree = \"<group>\"; };\n\t\t965532281E47E388005C2792 /* SpringAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpringAnimation.swift; sourceTree = \"<group>\"; };\n\t\t9656895E1F002F16001C656D /* CardCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardCollectionViewCell.swift; sourceTree = \"<group>\"; };\n\t\t965689601F002F4C001C656D /* CardCollectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardCollectionViewController.swift; sourceTree = \"<group>\"; };\n\t\t9658F2161CD6FA4700B902C1 /* IconButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IconButton.swift; sourceTree = \"<group>\"; };\n\t\t966C17721F0439F600D3E83C /* Material+MotionAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"Material+MotionAnimation.swift\"; sourceTree = \"<group>\"; };\n\t\t966ECF291CF4C20100BB0BDF /* CollectionReusableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionReusableView.swift; sourceTree = \"<group>\"; };\n\t\t967A48181D0F425A00B8CEB7 /* StatusBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusBarController.swift; sourceTree = \"<group>\"; };\n\t\t968BA8311F8D201B0091852E /* Motion.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; path = Motion.xcodeproj; sourceTree = \"<group>\"; };\n\t\t968C99461D377849000074FF /* Offset.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Offset.swift; sourceTree = \"<group>\"; };\n\t\t96A183621E0C6CE200083C30 /* FABMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FABMenu.swift; sourceTree = \"<group>\"; };\n\t\t96A183641E0C6DD400083C30 /* FABMenuController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FABMenuController.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7581CB40DC500C806FE /* BottomNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BottomNavigationController.swift; sourceTree = \"<group>\"; };\n\t\t96BCB75D1CB40DC500C806FE /* Card.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Card.swift; sourceTree = \"<group>\"; };\n\t\t96BCB75F1CB40DC500C806FE /* FABButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FABButton.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7601CB40DC500C806FE /* FlatButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FlatButton.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7611CB40DC500C806FE /* Grid.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Grid.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7621CB40DC500C806FE /* ImageCard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageCard.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7641CB40DC500C806FE /* Material+String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"Material+String.swift\"; sourceTree = \"<group>\"; };\n\t\t96BCB7651CB40DC500C806FE /* Material+UIFont.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"Material+UIFont.swift\"; sourceTree = \"<group>\"; };\n\t\t96BCB76C1CB40DC500C806FE /* Material+UIImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"Material+UIImage.swift\"; sourceTree = \"<group>\"; };\n\t\t96BCB76F1CB40DC500C806FE /* Border.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Border.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7701CB40DC500C806FE /* Button.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7711CB40DC500C806FE /* CollectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionView.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7721CB40DC500C806FE /* CollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionViewCell.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7751CB40DC500C806FE /* CollectionViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionViewLayout.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7761CB40DC500C806FE /* Color.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7771CB40DC500C806FE /* DataSourceItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataSourceItem.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7781CB40DC500C806FE /* Depth.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Depth.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7791CB40DC500C806FE /* Device.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Device.swift; sourceTree = \"<group>\"; };\n\t\t96BCB77A1CB40DC500C806FE /* EdgeInsets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EdgeInsets.swift; sourceTree = \"<group>\"; };\n\t\t96BCB77B1CB40DC500C806FE /* Font.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Font.swift; sourceTree = \"<group>\"; };\n\t\t96BCB77D1CB40DC500C806FE /* Icon.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Icon.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7801CB40DC500C806FE /* Layer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Layer.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7811CB40DC500C806FE /* Layout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Layout.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7821CB40DC500C806FE /* PulseAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PulseAnimation.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7841CB40DC500C806FE /* PulseView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PulseView.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7851CB40DC500C806FE /* CornerRadius.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CornerRadius.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7861CB40DC500C806FE /* Shape.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Shape.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7871CB40DC500C806FE /* InterimSpace.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InterimSpace.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7881CB40DC500C806FE /* Switch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Switch.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7891CB40DC500C806FE /* TableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewCell.swift; sourceTree = \"<group>\"; };\n\t\t96BCB78C1CB40DC500C806FE /* View.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7901CB40DC500C806FE /* NavigationBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationBar.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7911CB40DC500C806FE /* NavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationController.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7921CB40DC500C806FE /* NavigationItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationItem.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7931CB40DC500C806FE /* RaisedButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RaisedButton.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7941CB40DC500C806FE /* RobotoFont.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RobotoFont.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7951CB40DC500C806FE /* SearchBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchBar.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7961CB40DC500C806FE /* SearchBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchBarController.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7971CB40DC500C806FE /* NavigationDrawerController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationDrawerController.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7981CB40DC500C806FE /* Bar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Bar.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7991CB40DC500C806FE /* TransitionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransitionController.swift; sourceTree = \"<group>\"; };\n\t\t96BCB79A1CB40DC500C806FE /* TabBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = TabBar.swift; sourceTree = \"<group>\"; tabWidth = 2; };\n\t\t96BCB79C1CB40DC500C806FE /* TextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = \"<group>\"; };\n\t\t96BCB79D1CB40DC500C806FE /* TextStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextStorage.swift; sourceTree = \"<group>\"; };\n\t\t96BCB79E1CB40DC500C806FE /* TextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextView.swift; sourceTree = \"<group>\"; };\n\t\t96BCB79F1CB40DC500C806FE /* Toolbar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Toolbar.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7A01CB40DC500C806FE /* ToolbarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToolbarController.swift; sourceTree = \"<group>\"; };\n\t\t96BCB7EE1CB40DE900C806FE /* Roboto-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"Roboto-Bold.ttf\"; sourceTree = \"<group>\"; };\n\t\t96BCB7EF1CB40DE900C806FE /* Roboto-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"Roboto-Light.ttf\"; sourceTree = \"<group>\"; };\n\t\t96BCB7F01CB40DE900C806FE /* Roboto-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"Roboto-Medium.ttf\"; sourceTree = \"<group>\"; };\n\t\t96BCB7F11CB40DE900C806FE /* Roboto-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"Roboto-Regular.ttf\"; sourceTree = \"<group>\"; };\n\t\t96BCB7F21CB40DE900C806FE /* Roboto-Thin.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = \"Roboto-Thin.ttf\"; sourceTree = \"<group>\"; };\n\t\t96C1C8801D42C62800E6608F /* Material+Array.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"Material+Array.swift\"; sourceTree = \"<group>\"; };\n\t\t96D88BFC1C1328D800B91418 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t96D88BFD1C1328D800B91418 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = \"<group>\"; };\n\t\t96D88C091C1328D800B91418 /* Material.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Material.h; sourceTree = \"<group>\"; };\n\t\t96E09DC71F2287E50000B121 /* TabsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabsController.swift; sourceTree = \"<group>\"; };\n\t\t96E3C3931D397AE90086A024 /* Material+UIView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"Material+UIView.swift\"; sourceTree = \"<group>\"; };\n\t\t96F1DC871D654FDF0025F925 /* Material+CALayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"Material+CALayer.swift\"; sourceTree = \"<group>\"; };\n\t\t9D00EBB3216675FB00DBCD69 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = \"<group>\"; };\n\t\t9D054A6320D175AC00D0528D /* Material+UIButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"Material+UIButton.swift\"; sourceTree = \"<group>\"; };\n\t\t9D054A6420D175AC00D0528D /* Material+UILabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"Material+UILabel.swift\"; sourceTree = \"<group>\"; };\n\t\t9D39A81A20FE8ED100BA8FA1 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = \"<group>\"; };\n\t\t9D494A37217F6B63003D66F1 /* LayoutAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutAttribute.swift; sourceTree = \"<group>\"; };\n\t\t9D494A39217F6B70003D66F1 /* LayoutAnchor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutAnchor.swift; sourceTree = \"<group>\"; };\n\t\t9D494A3B217F6B7D003D66F1 /* LayoutConstraint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutConstraint.swift; sourceTree = \"<group>\"; };\n\t\t9D9089B82118914500605DC9 /* Editor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Editor.swift; sourceTree = \"<group>\"; };\n\t\t9DE25DDF2170D7AF000C04DF /* Dialog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dialog.swift; sourceTree = \"<group>\"; };\n\t\t9DE25DE12170D7C0000C04DF /* DialogController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DialogController.swift; sourceTree = \"<group>\"; };\n\t\t9DE25DE32170D7FF000C04DF /* DialogView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DialogView.swift; sourceTree = \"<group>\"; };\n\t\t9DE84D6F1FF0252500586C8B /* RadioButtonGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioButtonGroup.swift; sourceTree = \"<group>\"; };\n\t\t9DE84D701FF0252500586C8B /* BaseButtonGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseButtonGroup.swift; sourceTree = \"<group>\"; };\n\t\t9DE84D711FF0252500586C8B /* CheckButtonGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckButtonGroup.swift; sourceTree = \"<group>\"; };\n\t\t9DF352411FED20C900B2A11B /* BaseIconLayerButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseIconLayerButton.swift; sourceTree = \"<group>\"; };\n\t\t9DF352431FED20ED00B2A11B /* RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButton.swift; sourceTree = \"<group>\"; };\n\t\t9DF352451FED210000B2A11B /* CheckButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckButton.swift; sourceTree = \"<group>\"; };\n\t\t9DF58CED20C098C60098968D /* ErrorTextFieldValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorTextFieldValidator.swift; sourceTree = \"<group>\"; };\n\t\t9DF74C4D20D15D84003C1D66 /* Material+UIColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = \"Material+UIColor.swift\"; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXGroup section */\n\t\t9602F00C1DA1163000F3FB79 /* Grid */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB7611CB40DC500C806FE /* Grid.swift */,\n\t\t\t);\n\t\t\tpath = Grid;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96090B031D9D709E00709CA6 /* Text */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9D9089B82118914500605DC9 /* Editor.swift */,\n\t\t\t\t961F18E71CD93E3E008927C5 /* ErrorTextField.swift */,\n\t\t\t\t9DF58CED20C098C60098968D /* ErrorTextFieldValidator.swift */,\n\t\t\t\t96BCB79C1CB40DC500C806FE /* TextField.swift */,\n\t\t\t\t96BCB79D1CB40DC500C806FE /* TextStorage.swift */,\n\t\t\t\t96BCB79E1CB40DC500C806FE /* TextView.swift */,\n\t\t\t);\n\t\t\tpath = Text;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t961154CA1F32999000A78D74 /* Chip */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t961154CB1F32A7B100A78D74 /* ChipBar.swift */,\n\t\t\t\t961527B81F3A509900E8B2AC /* ChipBarController.swift */,\n\t\t\t);\n\t\t\tpath = Chip;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t961527531F393C0E00E8B2AC /* Motion */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t968BA8311F8D201B0091852E /* Motion.xcodeproj */,\n\t\t\t);\n\t\t\tpath = Motion;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t961E6BDD1DDA2A7E004E6C93 /* Application */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t961E6BDE1DDA2A95004E6C93 /* Application.swift */,\n\t\t\t);\n\t\t\tpath = Application;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t961E6BE01DDA2ADD004E6C93 /* Screen */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t961E6BE11DDA2AF3004E6C93 /* Screen.swift */,\n\t\t\t);\n\t\t\tpath = Screen;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t961E6BEF1DDA4B04004E6C93 /* NavigationDrawer */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB7971CB40DC500C806FE /* NavigationDrawerController.swift */,\n\t\t\t);\n\t\t\tpath = NavigationDrawer;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96230AB61D6A51FD00AF47DC /* Divider */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96230AB71D6A520C00AF47DC /* Divider.swift */,\n\t\t\t);\n\t\t\tpath = Divider;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96264BE41D833C8400576F37 /* Bar */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB7981CB40DC500C806FE /* Bar.swift */,\n\t\t\t);\n\t\t\tpath = Bar;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t9626CA951DAB5370003E2611 /* Transition */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9626CA961DAB53A8003E2611 /* DisplayStyle.swift */,\n\t\t\t\t96BCB7991CB40DC500C806FE /* TransitionController.swift */,\n\t\t\t);\n\t\t\tpath = Transition;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t9626CBCC1DADA5F1003E2611 /* Height */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9626CB9A1DAD3D1D003E2611 /* HeightPreset.swift */,\n\t\t\t);\n\t\t\tpath = Height;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t962DDD081D6FBBD0001C307C /* BottomTabBar */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB7581CB40DC500C806FE /* BottomNavigationController.swift */,\n\t\t\t);\n\t\t\tpath = BottomTabBar;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t9630ACB71F29A26B00B4217D /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t961527531F393C0E00E8B2AC /* Motion */,\n\t\t\t);\n\t\t\tpath = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96328B9A1E05C135009A4C90 /* Data */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB7771CB40DC500C806FE /* DataSourceItem.swift */,\n\t\t\t);\n\t\t\tpath = Data;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t9638322C1B88DFD80015F710 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96D88BF41C1328D800B91418 /* Sources */,\n\t\t\t\t963832371B88DFD80015F710 /* Products */,\n\t\t\t);\n\t\t\tindentWidth = 2;\n\t\t\tsourceTree = \"<group>\";\n\t\t\ttabWidth = 2;\n\t\t\tusesTabs = 0;\n\t\t};\n\t\t963832371B88DFD80015F710 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t963832361B88DFD80015F710 /* Material.framework */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t963FBEFB1D6694E8008F8512 /* Snackbar */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t963FBEFC1D669510008F8512 /* Snackbar.swift */,\n\t\t\t\t961EFC571D738FF600E84652 /* SnackbarController.swift */,\n\t\t\t);\n\t\t\tpath = Snackbar;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t963FBF001D66964F008F8512 /* Toolbar */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB79F1CB40DC500C806FE /* Toolbar.swift */,\n\t\t\t\t96BCB7A01CB40DC500C806FE /* ToolbarController.swift */,\n\t\t\t);\n\t\t\tpath = Toolbar;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t963FBF011D6696AB008F8512 /* Tab */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB79A1CB40DC500C806FE /* TabBar.swift */,\n\t\t\t\t96E09DC71F2287E50000B121 /* TabsController.swift */,\n\t\t\t);\n\t\t\tpath = Tab;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t963FBF021D6696D0008F8512 /* FABMenu */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96A183621E0C6CE200083C30 /* FABMenu.swift */,\n\t\t\t\t96A183641E0C6DD400083C30 /* FABMenuController.swift */,\n\t\t\t);\n\t\t\tpath = FABMenu;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t963FBF031D6696EF008F8512 /* SearchBar */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB7951CB40DC500C806FE /* SearchBar.swift */,\n\t\t\t\t96BCB7961CB40DC500C806FE /* SearchBarController.swift */,\n\t\t\t);\n\t\t\tpath = SearchBar;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t965689641F003476001C656D /* CardCollectionView */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9656895E1F002F16001C656D /* CardCollectionViewCell.swift */,\n\t\t\t\t965689601F002F4C001C656D /* CardCollectionViewController.swift */,\n\t\t\t);\n\t\t\tpath = CardCollectionView;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t966ECF2B1CF4C21B00BB0BDF /* Table */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96328B961E05C0BB009A4C90 /* TableView.swift */,\n\t\t\t\t96BCB7891CB40DC500C806FE /* TableViewCell.swift */,\n\t\t\t\t96328B981E05C0CE009A4C90 /* TableViewController.swift */,\n\t\t\t);\n\t\t\tpath = Table;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t967A48171D0F424B00B8CEB7 /* StatusBar */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t967A48181D0F425A00B8CEB7 /* StatusBarController.swift */,\n\t\t\t);\n\t\t\tpath = StatusBar;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t968BA8321F8D201B0091852E /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t968BA8361F8D201B0091852E /* Motion.framework */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t968C99421D36EC9E000074FF /* Switch */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB7881CB40DC500C806FE /* Switch.swift */,\n\t\t\t);\n\t\t\tpath = Switch;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96BCB7571CB40DC500C806FE /* iOS */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96EF418E1E835E850012CA1C /* Animation */,\n\t\t\t\t961E6BDD1DDA2A7E004E6C93 /* Application */,\n\t\t\t\t96264BE41D833C8400576F37 /* Bar */,\n\t\t\t\t962DDD081D6FBBD0001C307C /* BottomTabBar */,\n\t\t\t\t96BCB8031CB40F4B00C806FE /* Button */,\n\t\t\t\t9DE84D6E1FF0250E00586C8B /* ButtonGroup */,\n\t\t\t\t96BCB8021CB40F3B00C806FE /* Card */,\n\t\t\t\t961154CA1F32999000A78D74 /* Chip */,\n\t\t\t\t96BCB8051CB40F9C00C806FE /* Collection */,\n\t\t\t\t96BCB8001CB40F0300C806FE /* Color */,\n\t\t\t\t96328B9A1E05C135009A4C90 /* Data */,\n\t\t\t\t96BCB80B1CB410CC00C806FE /* Device */,\n\t\t\t\t9DE25DDE2170D779000C04DF /* Dialogs */,\n\t\t\t\t96230AB61D6A51FD00AF47DC /* Divider */,\n\t\t\t\t96BCB80A1CB410A100C806FE /* Extension */,\n\t\t\t\t963FBF021D6696D0008F8512 /* FABMenu */,\n\t\t\t\t96BCB8071CB4101C00C806FE /* Font */,\n\t\t\t\t9602F00C1DA1163000F3FB79 /* Grid */,\n\t\t\t\t9626CBCC1DADA5F1003E2611 /* Height */,\n\t\t\t\t96BCB8081CB4105E00C806FE /* Icon */,\n\t\t\t\t96BCB80D1CB410FD00C806FE /* Layer */,\n\t\t\t\t96BCB8041CB40F6C00C806FE /* Layout */,\n\t\t\t\t96BCB8011CB40F1700C806FE /* Navigation */,\n\t\t\t\t961E6BEF1DDA4B04004E6C93 /* NavigationDrawer */,\n\t\t\t\t961E6BE01DDA2ADD004E6C93 /* Screen */,\n\t\t\t\t963FBF031D6696EF008F8512 /* SearchBar */,\n\t\t\t\t963FBEFB1D6694E8008F8512 /* Snackbar */,\n\t\t\t\t967A48171D0F424B00B8CEB7 /* StatusBar */,\n\t\t\t\t968C99421D36EC9E000074FF /* Switch */,\n\t\t\t\t963FBF011D6696AB008F8512 /* Tab */,\n\t\t\t\t966ECF2B1CF4C21B00BB0BDF /* Table */,\n\t\t\t\t96090B031D9D709E00709CA6 /* Text */,\n\t\t\t\t9D00EBB2216675A800DBCD69 /* Theme */,\n\t\t\t\t963FBF001D66964F008F8512 /* Toolbar */,\n\t\t\t\t9626CA951DAB5370003E2611 /* Transition */,\n\t\t\t\t96BCB8061CB40FD000C806FE /* Type */,\n\t\t\t\t96BCB80C1CB410DD00C806FE /* View */,\n\t\t\t);\n\t\t\tpath = iOS;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96BCB7EC1CB40DE900C806FE /* Font */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB7ED1CB40DE900C806FE /* Roboto */,\n\t\t\t);\n\t\t\tpath = Font;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96BCB7ED1CB40DE900C806FE /* Roboto */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB7EE1CB40DE900C806FE /* Roboto-Bold.ttf */,\n\t\t\t\t96BCB7EF1CB40DE900C806FE /* Roboto-Light.ttf */,\n\t\t\t\t96BCB7F01CB40DE900C806FE /* Roboto-Medium.ttf */,\n\t\t\t\t96BCB7F11CB40DE900C806FE /* Roboto-Regular.ttf */,\n\t\t\t\t96BCB7F21CB40DE900C806FE /* Roboto-Thin.ttf */,\n\t\t\t);\n\t\t\tpath = Roboto;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96BCB8001CB40F0300C806FE /* Color */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB7761CB40DC500C806FE /* Color.swift */,\n\t\t\t);\n\t\t\tpath = Color;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96BCB8011CB40F1700C806FE /* Navigation */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB7901CB40DC500C806FE /* NavigationBar.swift */,\n\t\t\t\t96BCB7911CB40DC500C806FE /* NavigationController.swift */,\n\t\t\t\t96BCB7921CB40DC500C806FE /* NavigationItem.swift */,\n\t\t\t);\n\t\t\tpath = Navigation;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96BCB8021CB40F3B00C806FE /* Card */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB75D1CB40DC500C806FE /* Card.swift */,\n\t\t\t\t96BCB7621CB40DC500C806FE /* ImageCard.swift */,\n\t\t\t\t9631A7C01D95E3AC00CFB109 /* PresenterCard.swift */,\n\t\t\t);\n\t\t\tpath = Card;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96BCB8031CB40F4B00C806FE /* Button */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9DF352411FED20C900B2A11B /* BaseIconLayerButton.swift */,\n\t\t\t\t96BCB7701CB40DC500C806FE /* Button.swift */,\n\t\t\t\t9DF352451FED210000B2A11B /* CheckButton.swift */,\n\t\t\t\t96BCB75F1CB40DC500C806FE /* FABButton.swift */,\n\t\t\t\t96BCB7601CB40DC500C806FE /* FlatButton.swift */,\n\t\t\t\t9658F2161CD6FA4700B902C1 /* IconButton.swift */,\n\t\t\t\t9DF352431FED20ED00B2A11B /* RadioButton.swift */,\n\t\t\t\t96BCB7931CB40DC500C806FE /* RaisedButton.swift */,\n\t\t\t);\n\t\t\tpath = Button;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96BCB8041CB40F6C00C806FE /* Layout */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB7811CB40DC500C806FE /* Layout.swift */,\n\t\t\t\t9D494A39217F6B70003D66F1 /* LayoutAnchor.swift */,\n\t\t\t\t9D494A37217F6B63003D66F1 /* LayoutAttribute.swift */,\n\t\t\t\t9D494A3B217F6B7D003D66F1 /* LayoutConstraint.swift */,\n\t\t\t);\n\t\t\tpath = Layout;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96BCB8051CB40F9C00C806FE /* Collection */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t965689641F003476001C656D /* CardCollectionView */,\n\t\t\t\t966ECF291CF4C20100BB0BDF /* CollectionReusableView.swift */,\n\t\t\t\t96BCB7711CB40DC500C806FE /* CollectionView.swift */,\n\t\t\t\t96BCB7721CB40DC500C806FE /* CollectionViewCell.swift */,\n\t\t\t\t96328B791E020A41009A4C90 /* CollectionViewController.swift */,\n\t\t\t\t96BCB7751CB40DC500C806FE /* CollectionViewLayout.swift */,\n\t\t\t);\n\t\t\tpath = Collection;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96BCB8061CB40FD000C806FE /* Type */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB76F1CB40DC500C806FE /* Border.swift */,\n\t\t\t\t96BCB7851CB40DC500C806FE /* CornerRadius.swift */,\n\t\t\t\t96BCB7781CB40DC500C806FE /* Depth.swift */,\n\t\t\t\t96BCB77A1CB40DC500C806FE /* EdgeInsets.swift */,\n\t\t\t\t96BCB7871CB40DC500C806FE /* InterimSpace.swift */,\n\t\t\t\t968C99461D377849000074FF /* Offset.swift */,\n\t\t\t\t96BCB7861CB40DC500C806FE /* Shape.swift */,\n\t\t\t);\n\t\t\tpath = Type;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96BCB8071CB4101C00C806FE /* Font */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9628645E1D540AF300690B69 /* DynamicFontType.swift */,\n\t\t\t\t96BCB77B1CB40DC500C806FE /* Font.swift */,\n\t\t\t\t96BCB7941CB40DC500C806FE /* RobotoFont.swift */,\n\t\t\t);\n\t\t\tpath = Font;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96BCB8081CB4105E00C806FE /* Icon */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB77D1CB40DC500C806FE /* Icon.swift */,\n\t\t\t);\n\t\t\tpath = Icon;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96BCB80A1CB410A100C806FE /* Extension */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96C1C8801D42C62800E6608F /* Material+Array.swift */,\n\t\t\t\t96F1DC871D654FDF0025F925 /* Material+CALayer.swift */,\n\t\t\t\t966C17721F0439F600D3E83C /* Material+MotionAnimation.swift */,\n\t\t\t\t961276621DCD8B1800A7D920 /* Material+NSMutableAttributedString.swift */,\n\t\t\t\t96BCB7641CB40DC500C806FE /* Material+String.swift */,\n\t\t\t\t9D054A6320D175AC00D0528D /* Material+UIButton.swift */,\n\t\t\t\t9DF74C4D20D15D84003C1D66 /* Material+UIColor.swift */,\n\t\t\t\t96BCB7651CB40DC500C806FE /* Material+UIFont.swift */,\n\t\t\t\t96BCB76C1CB40DC500C806FE /* Material+UIImage.swift */,\n\t\t\t\t9D054A6420D175AC00D0528D /* Material+UILabel.swift */,\n\t\t\t\t96E3C3931D397AE90086A024 /* Material+UIView.swift */,\n\t\t\t\t9618006C1F4D384200CD77A1 /* Material+UIViewController.swift */,\n\t\t\t\t962864591D53FE3E00690B69 /* Material+UIWindow.swift */,\n\t\t\t);\n\t\t\tpath = Extension;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96BCB80B1CB410CC00C806FE /* Device */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB7791CB40DC500C806FE /* Device.swift */,\n\t\t\t);\n\t\t\tpath = Device;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96BCB80C1CB410DD00C806FE /* View */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB7841CB40DC500C806FE /* PulseView.swift */,\n\t\t\t\t96BCB78C1CB40DC500C806FE /* View.swift */,\n\t\t\t\t9D39A81A20FE8ED100BA8FA1 /* ViewController.swift */,\n\t\t\t);\n\t\t\tpath = View;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96BCB80D1CB410FD00C806FE /* Layer */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB7801CB40DC500C806FE /* Layer.swift */,\n\t\t\t);\n\t\t\tpath = Layer;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96D88BF41C1328D800B91418 /* Sources */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB7EC1CB40DE900C806FE /* Font */,\n\t\t\t\t9630ACB71F29A26B00B4217D /* Frameworks */,\n\t\t\t\t96BCB7571CB40DC500C806FE /* iOS */,\n\t\t\t\t96334EF51C8B84660083986B /* Assets.xcassets */,\n\t\t\t\t96D88BFC1C1328D800B91418 /* Info.plist */,\n\t\t\t\t96D88BFD1C1328D800B91418 /* LICENSE */,\n\t\t\t\t96D88C091C1328D800B91418 /* Material.h */,\n\t\t\t);\n\t\t\tpath = Sources;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t96EF418E1E835E850012CA1C /* Animation */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t96BCB7821CB40DC500C806FE /* PulseAnimation.swift */,\n\t\t\t\t965532281E47E388005C2792 /* SpringAnimation.swift */,\n\t\t\t);\n\t\t\tpath = Animation;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t9D00EBB2216675A800DBCD69 /* Theme */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9D00EBB3216675FB00DBCD69 /* Theme.swift */,\n\t\t\t);\n\t\t\tpath = Theme;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t9DE25DDE2170D779000C04DF /* Dialogs */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9DE25DDF2170D7AF000C04DF /* Dialog.swift */,\n\t\t\t\t9DE25DE12170D7C0000C04DF /* DialogController.swift */,\n\t\t\t\t9DE25DE32170D7FF000C04DF /* DialogView.swift */,\n\t\t\t);\n\t\t\tpath = Dialogs;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t9DE84D6E1FF0250E00586C8B /* ButtonGroup */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9DE84D701FF0252500586C8B /* BaseButtonGroup.swift */,\n\t\t\t\t9DE84D711FF0252500586C8B /* CheckButtonGroup.swift */,\n\t\t\t\t9DE84D6F1FF0252500586C8B /* RadioButtonGroup.swift */,\n\t\t\t);\n\t\t\tpath = ButtonGroup;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXHeadersBuildPhase section */\n\t\t963832331B88DFD80015F710 /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t96D88C321C1328D800B91418 /* Material.h in Headers */,\n\t\t\t\t96BCB8141CB4115200C806FE /* PulseAnimation.swift in Headers */,\n\t\t\t\t96BCB8151CB4115200C806FE /* FABButton.swift in Headers */,\n\t\t\t\t96BCB8161CB4115200C806FE /* FlatButton.swift in Headers */,\n\t\t\t\t96BCB8171CB4115200C806FE /* Button.swift in Headers */,\n\t\t\t\t96BCB8181CB4115200C806FE /* RaisedButton.swift in Headers */,\n\t\t\t\t96BCB81E1CB4115200C806FE /* DataSourceItem.swift in Headers */,\n\t\t\t\t96BCB81F1CB4115200C806FE /* CollectionView.swift in Headers */,\n\t\t\t\t96BCB8201CB4115200C806FE /* CollectionViewCell.swift in Headers */,\n\t\t\t\t96BCB8231CB4115200C806FE /* CollectionViewLayout.swift in Headers */,\n\t\t\t\t96BCB8241CB4115200C806FE /* TableViewCell.swift in Headers */,\n\t\t\t\t96BCB8251CB4115200C806FE /* Color.swift in Headers */,\n\t\t\t\t96BCB8261CB4115200C806FE /* Device.swift in Headers */,\n\t\t\t\t96BCB8281CB4115200C806FE /* Material+String.swift in Headers */,\n\t\t\t\t96BCB8291CB4115200C806FE /* Material+UIFont.swift in Headers */,\n\t\t\t\t96BCB8301CB4115200C806FE /* Material+UIImage.swift in Headers */,\n\t\t\t\t96BCB8311CB4115200C806FE /* Font.swift in Headers */,\n\t\t\t\t96BCB8321CB4115200C806FE /* RobotoFont.swift in Headers */,\n\t\t\t\t96BCB8331CB4115200C806FE /* Icon.swift in Headers */,\n\t\t\t\t96BCB8341CB4115200C806FE /* Layer.swift in Headers */,\n\t\t\t\t96BCB8361CB4115200C806FE /* Grid.swift in Headers */,\n\t\t\t\t96BCB8371CB4115200C806FE /* Layout.swift in Headers */,\n\t\t\t\t96BCB83B1CB4115200C806FE /* NavigationDrawerController.swift in Headers */,\n\t\t\t\t96BCB83C1CB4115200C806FE /* Bar.swift in Headers */,\n\t\t\t\t96BCB83D1CB4115200C806FE /* TransitionController.swift in Headers */,\n\t\t\t\t96BCB8441CB4115200C806FE /* BottomNavigationController.swift in Headers */,\n\t\t\t\t96BCB8461CB4115200C806FE /* NavigationBar.swift in Headers */,\n\t\t\t\t96BCB8471CB4115200C806FE /* NavigationController.swift in Headers */,\n\t\t\t\t96BCB8481CB4115200C806FE /* NavigationItem.swift in Headers */,\n\t\t\t\t96BCB84A1CB4115200C806FE /* TextField.swift in Headers */,\n\t\t\t\t96BCB84B1CB4115200C806FE /* TextStorage.swift in Headers */,\n\t\t\t\t96BCB84C1CB4115200C806FE /* TextView.swift in Headers */,\n\t\t\t\t96BCB84D1CB4115200C806FE /* Border.swift in Headers */,\n\t\t\t\t96BCB84E1CB4115200C806FE /* InterimSpace.swift in Headers */,\n\t\t\t\t96BCB84F1CB4115200C806FE /* Depth.swift in Headers */,\n\t\t\t\t96BCB8501CB4115200C806FE /* EdgeInsets.swift in Headers */,\n\t\t\t\t96BCB8521CB4115200C806FE /* CornerRadius.swift in Headers */,\n\t\t\t\t96BCB8531CB4115200C806FE /* Shape.swift in Headers */,\n\t\t\t\t96BCB8551CB4115200C806FE /* PulseView.swift in Headers */,\n\t\t\t\t96BCB8561CB4115200C806FE /* Switch.swift in Headers */,\n\t\t\t\t96BCB8571CB4115200C806FE /* View.swift in Headers */,\n\t\t\t\t96E3C3951D3A1CC20086A024 /* IconButton.swift in Headers */,\n\t\t\t\t96E3C3961D3A1CC20086A024 /* CollectionReusableView.swift in Headers */,\n\t\t\t\t96E3C3971D3A1CC20086A024 /* Material+UIView.swift in Headers */,\n\t\t\t\t96E3C3991D3A1CC20086A024 /* StatusBarController.swift in Headers */,\n\t\t\t\t96E3C39A1D3A1CC20086A024 /* ErrorTextField.swift in Headers */,\n\t\t\t\t96E3C39C1D3A1CC20086A024 /* Offset.swift in Headers */,\n\t\t\t\t9697F7BF1D8F2572004741EC /* Divider.swift in Headers */,\n\t\t\t\t9697F7C01D8F2572004741EC /* Material+CALayer.swift in Headers */,\n\t\t\t\t9697F7C11D8F2572004741EC /* Material+Array.swift in Headers */,\n\t\t\t\t9697F7C21D8F2572004741EC /* Material+UIWindow.swift in Headers */,\n\t\t\t\t9697F7C31D8F2572004741EC /* DynamicFontType.swift in Headers */,\n\t\t\t\t9697F7CB1D8F2573004741EC /* Snackbar.swift in Headers */,\n\t\t\t\t9697F7CC1D8F2573004741EC /* SnackbarController.swift in Headers */,\n\t\t\t\t9617B07D1DFCA8CF00410F8F /* Application.swift in Headers */,\n\t\t\t\t9617B07E1DFCA8CF00410F8F /* Card.swift in Headers */,\n\t\t\t\t9617B07F1DFCA8CF00410F8F /* ImageCard.swift in Headers */,\n\t\t\t\t9617B0801DFCA8CF00410F8F /* PresenterCard.swift in Headers */,\n\t\t\t\t9617B0861DFCA8CF00410F8F /* HeightPreset.swift in Headers */,\n\t\t\t\t9617B08A1DFCA8CF00410F8F /* DisplayStyle.swift in Headers */,\n\t\t\t\t9617B08B1DFCA8CF00410F8F /* Screen.swift in Headers */,\n\t\t\t\t9617B08C1DFCA8CF00410F8F /* SearchBar.swift in Headers */,\n\t\t\t\t9617B08D1DFCA8CF00410F8F /* SearchBarController.swift in Headers */,\n\t\t\t\t9617B08E1DFCA8CF00410F8F /* TabBar.swift in Headers */,\n\t\t\t\t9617B08F1DFCA8CF00410F8F /* Material+NSMutableAttributedString.swift in Headers */,\n\t\t\t\t9617B0901DFCA8CF00410F8F /* Toolbar.swift in Headers */,\n\t\t\t\t9617B0911DFCA8CF00410F8F /* ToolbarController.swift in Headers */,\n\t\t\t\t96328B9B1E05C24E009A4C90 /* CollectionViewController.swift in Headers */,\n\t\t\t\t96328B9E1E05C24E009A4C90 /* TableView.swift in Headers */,\n\t\t\t\t96328B9F1E05C24E009A4C90 /* TableViewController.swift in Headers */,\n\t\t\t\t96BFC16F1E63C10A0075DE1F /* SpringAnimation.swift in Headers */,\n\t\t\t\t9685D5AF1F0F04CB00AFEB79 /* CardCollectionViewCell.swift in Headers */,\n\t\t\t\t9685D5B01F0F04CB00AFEB79 /* CardCollectionViewController.swift in Headers */,\n\t\t\t\t9685D5B11F0F04CB00AFEB79 /* Material+MotionAnimation.swift in Headers */,\n\t\t\t\t96F1A5531F24F17A001D8CAF /* TabsController.swift in Headers */,\n\t\t\t\t9618006E1F4D38BC00CD77A1 /* ChipBar.swift in Headers */,\n\t\t\t\t9618006F1F4D38BC00CD77A1 /* ChipBarController.swift in Headers */,\n\t\t\t\t961800701F4D38BC00CD77A1 /* Material+UIViewController.swift in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXHeadersBuildPhase section */\n\n/* Begin PBXNativeTarget section */\n\t\t963832351B88DFD80015F710 /* Material */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 9638324C1B88DFD80015F710 /* Build configuration list for PBXNativeTarget \"Material\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t963832311B88DFD80015F710 /* Sources */,\n\t\t\t\t963832331B88DFD80015F710 /* Headers */,\n\t\t\t\t963832341B88DFD80015F710 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t968BA8381F8D20530091852E /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = Material;\n\t\t\tproductName = FocusKit;\n\t\t\tproductReference = 963832361B88DFD80015F710 /* Material.framework */;\n\t\t\tproductType = \"com.apple.product-type.framework\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t9638322D1B88DFD80015F710 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastSwiftMigration = 0710;\n\t\t\t\tLastSwiftUpdateCheck = 0730;\n\t\t\t\tLastUpgradeCheck = 1100;\n\t\t\t\tORGANIZATIONNAME = \"CosmicMind, Inc.\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t963832351B88DFD80015F710 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 6.4;\n\t\t\t\t\t\tDevelopmentTeam = 9Z76XCNLGL;\n\t\t\t\t\t\tDevelopmentTeamName = \"CosmicMind Inc.\";\n\t\t\t\t\t\tLastSwiftMigration = 1020;\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 963832301B88DFD80015F710 /* Build configuration list for PBXProject \"Material\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 9638322C1B88DFD80015F710;\n\t\t\tproductRefGroup = 963832371B88DFD80015F710 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectReferences = (\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 968BA8321F8D201B0091852E /* Products */;\n\t\t\t\t\tProjectRef = 968BA8311F8D201B0091852E /* Motion.xcodeproj */;\n\t\t\t\t},\n\t\t\t);\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t963832351B88DFD80015F710 /* Material */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXReferenceProxy section */\n\t\t968BA8361F8D201B0091852E /* Motion.framework */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = wrapper.framework;\n\t\t\tpath = Motion.framework;\n\t\t\tremoteRef = 968BA8351F8D201B0091852E /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n/* End PBXReferenceProxy section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t963832341B88DFD80015F710 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t96334EF61C8B84660083986B /* Assets.xcassets in Resources */,\n\t\t\t\t96BCB7F71CB40DE900C806FE /* Roboto-Medium.ttf in Resources */,\n\t\t\t\t96BCB7F31CB40DE900C806FE /* Roboto-Bold.ttf in Resources */,\n\t\t\t\t96BCB7FB1CB40DE900C806FE /* Roboto-Thin.ttf in Resources */,\n\t\t\t\t96BCB7F91CB40DE900C806FE /* Roboto-Regular.ttf in Resources */,\n\t\t\t\t96BCB7F51CB40DE900C806FE /* Roboto-Light.ttf in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t963832311B88DFD80015F710 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t961E6BE21DDA2AF3004E6C93 /* Screen.swift in Sources */,\n\t\t\t\t9DF352441FED20ED00B2A11B /* RadioButton.swift in Sources */,\n\t\t\t\t965E81261DD4D7C800D61E4B /* Material+NSMutableAttributedString.swift in Sources */,\n\t\t\t\t965E80FF1DD4D5C800D61E4B /* BottomNavigationController.swift in Sources */,\n\t\t\t\t965E81031DD4D5C800D61E4B /* CollectionView.swift in Sources */,\n\t\t\t\t965E81041DD4D5C800D61E4B /* CollectionViewCell.swift in Sources */,\n\t\t\t\t965E81071DD4D5C800D61E4B /* CollectionViewLayout.swift in Sources */,\n\t\t\t\t965E81081DD4D5C800D61E4B /* CollectionReusableView.swift in Sources */,\n\t\t\t\t965E81091DD4D5C800D61E4B /* DataSourceItem.swift in Sources */,\n\t\t\t\t9DF352461FED210000B2A11B /* CheckButton.swift in Sources */,\n\t\t\t\t965E810A1DD4D5C800D61E4B /* Font.swift in Sources */,\n\t\t\t\t965E810B1DD4D5C800D61E4B /* RobotoFont.swift in Sources */,\n\t\t\t\t9D494A3C217F6B7D003D66F1 /* LayoutConstraint.swift in Sources */,\n\t\t\t\t965E810C1DD4D5C800D61E4B /* DynamicFontType.swift in Sources */,\n\t\t\t\t965E81101DD4D5C800D61E4B /* NavigationBar.swift in Sources */,\n\t\t\t\t965E81111DD4D5C800D61E4B /* NavigationController.swift in Sources */,\n\t\t\t\t965E81121DD4D5C800D61E4B /* NavigationItem.swift in Sources */,\n\t\t\t\t965E81131DD4D5C800D61E4B /* NavigationDrawerController.swift in Sources */,\n\t\t\t\t9656895F1F002F16001C656D /* CardCollectionViewCell.swift in Sources */,\n\t\t\t\t965E81161DD4D5C800D61E4B /* DisplayStyle.swift in Sources */,\n\t\t\t\t965E81171DD4D5C800D61E4B /* TransitionController.swift in Sources */,\n\t\t\t\t965E81181DD4D5C800D61E4B /* Snackbar.swift in Sources */,\n\t\t\t\t965E81191DD4D5C800D61E4B /* SnackbarController.swift in Sources */,\n\t\t\t\t9618006D1F4D384200CD77A1 /* Material+UIViewController.swift in Sources */,\n\t\t\t\t9DE84D741FF0252600586C8B /* CheckButtonGroup.swift in Sources */,\n\t\t\t\t965E811A1DD4D5C800D61E4B /* StatusBarController.swift in Sources */,\n\t\t\t\t965E811B1DD4D5C800D61E4B /* Switch.swift in Sources */,\n\t\t\t\t965E811C1DD4D5C800D61E4B /* TabBar.swift in Sources */,\n\t\t\t\t965E811D1DD4D5C800D61E4B /* TableViewCell.swift in Sources */,\n\t\t\t\t9D9089B92118914500605DC9 /* Editor.swift in Sources */,\n\t\t\t\t965E811E1DD4D5C800D61E4B /* TextField.swift in Sources */,\n\t\t\t\t965E811F1DD4D5C800D61E4B /* ErrorTextField.swift in Sources */,\n\t\t\t\t965E81211DD4D5C800D61E4B /* TextStorage.swift in Sources */,\n\t\t\t\t965E81221DD4D5C800D61E4B /* TextView.swift in Sources */,\n\t\t\t\t965E80E71DD4C55200D61E4B /* Material+UIView.swift in Sources */,\n\t\t\t\t9D494A38217F6B63003D66F1 /* LayoutAttribute.swift in Sources */,\n\t\t\t\t96B8D22D20CF82D5008BD149 /* FABMenu.swift in Sources */,\n\t\t\t\t965E80E81DD4C55200D61E4B /* Material+CALayer.swift in Sources */,\n\t\t\t\t965E80E91DD4C55200D61E4B /* Material+String.swift in Sources */,\n\t\t\t\t9DE84D731FF0252600586C8B /* BaseButtonGroup.swift in Sources */,\n\t\t\t\t965E80F71DD4D59500D61E4B /* Card.swift in Sources */,\n\t\t\t\t965E80EA1DD4C55200D61E4B /* Material+UIFont.swift in Sources */,\n\t\t\t\t965E80EB1DD4C55200D61E4B /* Material+UIImage.swift in Sources */,\n\t\t\t\t965E80EC1DD4C55200D61E4B /* Material+Array.swift in Sources */,\n\t\t\t\t965E80ED1DD4C55200D61E4B /* Material+UIWindow.swift in Sources */,\n\t\t\t\t961527B91F3A509900E8B2AC /* ChipBarController.swift in Sources */,\n\t\t\t\t965E80E41DD4C53300D61E4B /* PulseView.swift in Sources */,\n\t\t\t\t9DF352421FED20C900B2A11B /* BaseIconLayerButton.swift in Sources */,\n\t\t\t\t966C17731F0439F600D3E83C /* Material+MotionAnimation.swift in Sources */,\n\t\t\t\t965E80E51DD4C53300D61E4B /* PulseAnimation.swift in Sources */,\n\t\t\t\t9DE84D721FF0252600586C8B /* RadioButtonGroup.swift in Sources */,\n\t\t\t\t9D00EBB4216675FB00DBCD69 /* Theme.swift in Sources */,\n\t\t\t\t965E80FE1DD4D59500D61E4B /* ToolbarController.swift in Sources */,\n\t\t\t\t9DE25DE22170D7C0000C04DF /* DialogController.swift in Sources */,\n\t\t\t\t9DE25DE42170D7FF000C04DF /* DialogView.swift in Sources */,\n\t\t\t\t96328B971E05C0BB009A4C90 /* TableView.swift in Sources */,\n\t\t\t\t965E80F81DD4D59500D61E4B /* ImageCard.swift in Sources */,\n\t\t\t\t96328B991E05C0CE009A4C90 /* TableViewController.swift in Sources */,\n\t\t\t\t9DE25DE02170D7AF000C04DF /* Dialog.swift in Sources */,\n\t\t\t\t965E80F91DD4D59500D61E4B /* PresenterCard.swift in Sources */,\n\t\t\t\t96E09DC81F2287E50000B121 /* TabsController.swift in Sources */,\n\t\t\t\t961154CC1F32A7B100A78D74 /* ChipBar.swift in Sources */,\n\t\t\t\t965689611F002F4C001C656D /* CardCollectionViewController.swift in Sources */,\n\t\t\t\t965E80CC1DD4C50600D61E4B /* Bar.swift in Sources */,\n\t\t\t\t965E80CD1DD4C50600D61E4B /* Button.swift in Sources */,\n\t\t\t\t965E80CE1DD4C50600D61E4B /* FABButton.swift in Sources */,\n\t\t\t\t965E80CF1DD4C50600D61E4B /* FlatButton.swift in Sources */,\n\t\t\t\t9D39A81B20FE8ED100BA8FA1 /* ViewController.swift in Sources */,\n\t\t\t\t965E80D01DD4C50600D61E4B /* RaisedButton.swift in Sources */,\n\t\t\t\t9DF58CEE20C098C60098968D /* ErrorTextFieldValidator.swift in Sources */,\n\t\t\t\t9D054A6520D175AC00D0528D /* Material+UIButton.swift in Sources */,\n\t\t\t\t965E80D11DD4C50600D61E4B /* IconButton.swift in Sources */,\n\t\t\t\t965E80D21DD4C50600D61E4B /* Color.swift in Sources */,\n\t\t\t\t96BFC1541E5E486F0075DE1F /* SpringAnimation.swift in Sources */,\n\t\t\t\t9D054A6620D175AC00D0528D /* Material+UILabel.swift in Sources */,\n\t\t\t\t9D494A3A217F6B70003D66F1 /* LayoutAnchor.swift in Sources */,\n\t\t\t\t965E80D31DD4C50600D61E4B /* Device.swift in Sources */,\n\t\t\t\t965E80FD1DD4D59500D61E4B /* Toolbar.swift in Sources */,\n\t\t\t\t965E80D41DD4C50600D61E4B /* Divider.swift in Sources */,\n\t\t\t\t965E80D51DD4C50600D61E4B /* Grid.swift in Sources */,\n\t\t\t\t965E80D61DD4C50600D61E4B /* HeightPreset.swift in Sources */,\n\t\t\t\t961E6BDF1DDA2A95004E6C93 /* Application.swift in Sources */,\n\t\t\t\t965E80D71DD4C50600D61E4B /* Icon.swift in Sources */,\n\t\t\t\t965E80FC1DD4D59500D61E4B /* SearchBarController.swift in Sources */,\n\t\t\t\t965E80D81DD4C50600D61E4B /* Layer.swift in Sources */,\n\t\t\t\t965E80D91DD4C50600D61E4B /* Layout.swift in Sources */,\n\t\t\t\t965E80DA1DD4C50600D61E4B /* Border.swift in Sources */,\n\t\t\t\t965E80DB1DD4C50600D61E4B /* InterimSpace.swift in Sources */,\n\t\t\t\t965E80DC1DD4C50600D61E4B /* Depth.swift in Sources */,\n\t\t\t\t965E80DD1DD4C50600D61E4B /* EdgeInsets.swift in Sources */,\n\t\t\t\t9DF74C4E20D15D84003C1D66 /* Material+UIColor.swift in Sources */,\n\t\t\t\t965E80DF1DD4C50600D61E4B /* CornerRadius.swift in Sources */,\n\t\t\t\t965E80FB1DD4D59500D61E4B /* SearchBar.swift in Sources */,\n\t\t\t\t965E80E01DD4C50600D61E4B /* Shape.swift in Sources */,\n\t\t\t\t965E80E11DD4C50600D61E4B /* Offset.swift in Sources */,\n\t\t\t\t965E80E21DD4C50600D61E4B /* View.swift in Sources */,\n\t\t\t\t96B8D22C20CF82D2008BD149 /* FABMenuController.swift in Sources */,\n\t\t\t\t96328B7A1E020A41009A4C90 /* CollectionViewController.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t968BA8381F8D20530091852E /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\tname = \"Motion iOS\";\n\t\t\ttargetProxy = 968BA8371F8D20530091852E /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin XCBuildConfiguration section */\n\t\t9638324A1B88DFD80015F710 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.9;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tPRODUCT_NAME = Material;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_SWIFT3_OBJC_INFERENCE = Default;\n\t\t\t\tSWIFT_VERSION = 4.2;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t\tVERSION_INFO_PREFIX = \"\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t9638324B1B88DFD80015F710 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.9;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tPRODUCT_NAME = Material;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Owholemodule\";\n\t\t\t\tSWIFT_SWIFT3_OBJC_INFERENCE = Default;\n\t\t\t\tSWIFT_VERSION = 4.2;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t\tVERSION_INFO_PREFIX = \"\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t9638324D1B88DFD80015F710 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_OBJC_UNUSED_IVARS = YES;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"\";\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDYLIB_COMPATIBILITY_VERSION = 1;\n\t\t\t\tDYLIB_CURRENT_VERSION = 1;\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = \"$(SRCROOT)/**\";\n\t\t\t\tGCC_WARN_UNUSED_VALUE = YES;\n\t\t\t\tINFOPLIST_FILE = Sources/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks @rpath/Frameworks\";\n\t\t\t\tMARKETING_VERSION = 3.1.8;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.cosmicmind.Material;\n\t\t\t\tPRODUCT_NAME = Material;\n\t\t\t\tPROVISIONING_PROFILE = \"\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t9638324E1B88DFD80015F710 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_OBJC_UNUSED_IVARS = YES;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"\";\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDYLIB_COMPATIBILITY_VERSION = 1;\n\t\t\t\tDYLIB_CURRENT_VERSION = 1;\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = \"$(SRCROOT)/**\";\n\t\t\t\tGCC_WARN_UNUSED_VALUE = YES;\n\t\t\t\tINFOPLIST_FILE = Sources/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks @rpath/Frameworks\";\n\t\t\t\tMARKETING_VERSION = 3.1.8;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.cosmicmind.Material;\n\t\t\t\tPRODUCT_NAME = Material;\n\t\t\t\tPROVISIONING_PROFILE = \"\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-O\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t963832301B88DFD80015F710 /* Build configuration list for PBXProject \"Material\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t9638324A1B88DFD80015F710 /* Debug */,\n\t\t\t\t9638324B1B88DFD80015F710 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t9638324C1B88DFD80015F710 /* Build configuration list for PBXNativeTarget \"Material\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t9638324D1B88DFD80015F710 /* Debug */,\n\t\t\t\t9638324E1B88DFD80015F710 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 9638322D1B88DFD80015F710 /* Project object */;\n}\n"
  },
  {
    "path": "Material.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Material.xcodeproj/project.xcworkspace/xcshareddata/Material.xcscmblueprint",
    "content": "{\n  \"DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey\" : \"9CF35BC641478FBD765F7442D4034ED362261E0A\",\n  \"DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey\" : {\n\n  },\n  \"DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey\" : {\n    \"9CF35BC641478FBD765F7442D4034ED362261E0A\" : 9223372036854775807,\n    \"0F3E254D46E5A5B90D1542854F510B7D145A9F31\" : 9223372036854775807\n  },\n  \"DVTSourceControlWorkspaceBlueprintIdentifierKey\" : \"0F44C283-777E-4E3F-9E10-FC52C3C270CE\",\n  \"DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey\" : {\n    \"9CF35BC641478FBD765F7442D4034ED362261E0A\" : \"Material\\/\",\n    \"0F3E254D46E5A5B90D1542854F510B7D145A9F31\" : \"Material\\/Sources\\/Frameworks\\/Motion\\/\"\n  },\n  \"DVTSourceControlWorkspaceBlueprintNameKey\" : \"Material\",\n  \"DVTSourceControlWorkspaceBlueprintVersion\" : 204,\n  \"DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey\" : \"Material.xcodeproj\",\n  \"DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey\" : [\n    {\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey\" : \"https:\\/\\/github.com\\/CosmicMind\\/Motion.git\",\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey\" : \"com.apple.dt.Xcode.sourcecontrol.Git\",\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey\" : \"0F3E254D46E5A5B90D1542854F510B7D145A9F31\"\n    },\n    {\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey\" : \"https:\\/\\/github.com\\/CosmicMind\\/Material.git\",\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey\" : \"com.apple.dt.Xcode.sourcecontrol.Git\",\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey\" : \"9CF35BC641478FBD765F7442D4034ED362261E0A\"\n    }\n  ]\n}"
  },
  {
    "path": "Material.xcodeproj/xcshareddata/xcschemes/Material.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1100\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"963832351B88DFD80015F710\"\n               BuildableName = \"Material.framework\"\n               BlueprintName = \"Material\"\n               ReferencedContainer = \"container:Material.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"963832351B88DFD80015F710\"\n            BuildableName = \"Material.framework\"\n            BlueprintName = \"Material\"\n            ReferencedContainer = \"container:Material.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"963832401B88DFD80015F710\"\n               BuildableName = \"Material.xctest\"\n               BlueprintName = \"Material iOS Tests\"\n               ReferencedContainer = \"container:Material.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"963832351B88DFD80015F710\"\n            BuildableName = \"Material.framework\"\n            BlueprintName = \"Material\"\n            ReferencedContainer = \"container:Material.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"963832351B88DFD80015F710\"\n            BuildableName = \"Material.framework\"\n            BlueprintName = \"Material\"\n            ReferencedContainer = \"container:Material.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "Package.swift",
    "content": "// swift-tools-version:4.2\nimport PackageDescription\n\nlet package = Package(\n    name: \"Material\",\n    // platforms: [.iOS(\"8.0\")],\n    products: [\n        .library(name: \"Material\", targets: [\"Material\"])\n    ],\n    dependencies: [\n        .package(url: \"https://github.com/CosmicMind/Motion.git\", .upToNextMajor(from: \"3.1.0\")),\n    ],\n    targets: [\n        .target(\n            name: \"Material\",\n            dependencies: [\"Motion\"],\n            path: \"Sources\",\n            exclude: [\"Frameworks\"]\n        )\n    ]\n)\n"
  },
  {
    "path": "README.md",
    "content": "![Material](http://www.cosmicmind.com/material/github/material-logo.png)\n\n# Material\n\nWelcome to **Material,** a UI/UX framework for creating beautiful applications. Material's animation system has been completely reworked to take advantage of [Motion](https://github.com/CosmicMind/Motion), a library dedicated to animations and transitions.\n\n[![Carthage compatible](https://img.shields.io/badge/Carthage-Compatible-brightgreen.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![Accio supported](https://img.shields.io/badge/Accio-supported-0A7CF5.svg?style=flat)](https://github.com/JamitLabs/Accio)\n[![Version](https://img.shields.io/cocoapods/v/Material.svg?style=flat)](http://cocoapods.org/pods/Material)\n[![License](https://img.shields.io/cocoapods/l/Material.svg?style=flat)](https://github.com/CosmicMind/Material/blob/master/LICENSE.md)\n![Xcode 8.2+](https://img.shields.io/badge/Xcode-8.2%2B-blue.svg)\n![iOS 8.0+](https://img.shields.io/badge/iOS-8.0%2B-blue.svg)\n![Swift 4.0+](https://img.shields.io/badge/Swift-4.0%2B-orange.svg)\n[![Donate](https://img.shields.io/badge/Donate-PayPal-blue.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9D6MURMLLUNQ2)\n\n## Photos Sample\n\nTake a look at a sample [Photos](https://github.com/CosmicMind/Samples/tree/master/Projects/Programmatic/Photos) project to get started.\n\n![Photos](http://www.cosmicmind.com/motion/projects/photos.gif)\n\n## Sample Projects\n\nTake a look at [Sample Projects](https://github.com/CosmicMind/Samples) to get your projects started.\n\n## Features\n\n- [x] Completely Customizable\n- [x] [Motion Animations & Transitions](https://github.com/CosmicMind/Motion)\n- [x] Layout Tools for AutoLayout & Grid Systems\n- [x] Color Library\n- [x] Cards\n- [x] FABMenu\n- [x] Icons\n- [x] TextField\n- [x] Snackbar\n- [x] Tabs\n- [x] Chips\n- [x] SearchBar\n- [x] NavigationController\n- [x] NavigationDrawer\n- [x] BottomNavigationBar\n- [x] [Sample Projects](https://github.com/CosmicMind/Samples)\n- [x] And More...\n\n## Requirements\n\n* iOS 8.0+\n* Xcode 8.0+\n\n## Communication\n\n- If you **need help**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/cosmicmind). (Tag 'cosmicmind')\n- If you'd like to **ask a general question**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/cosmicmind).\n- If you **found a bug**, _and can provide steps to reliably reproduce it_, open an issue.\n- If you **have a feature request**, open an issue.\n- If you **want to contribute**, submit a pull request.\n\n## Installation\n\n> **Embedded frameworks require a minimum deployment target of iOS 8+.**\n> - [Download Material](https://github.com/CosmicMind/Material/archive/master.zip)\n\n## CocoaPods\n\n[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command:\n\n```bash\n$ gem install cocoapods\n```\n\nTo integrate Material's core features into your Xcode project using CocoaPods, specify it in your `Podfile`:\n\n```ruby\nsource 'https://github.com/CocoaPods/Specs.git'\nplatform :ios, '8.0'\nuse_frameworks!\n\npod 'Material', '~> 3.1.0'\n```\n\nThen, run the following command:\n\n```bash\n$ pod install\n```\n\n## Carthage\n\nCarthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.\n\nYou can install Carthage with Homebrew using the following command:\n\n```bash\n$ brew update\n$ brew install carthage\n```\nTo integrate Material into your Xcode project using Carthage, specify it in your Cartfile:\n\n```bash\ngithub \"CosmicMind/Material\"\n```\n\nRun `carthage update` to build the framework and drag the built `Material.framework` into your Xcode project.\n\n## Change Log\n\nMaterial is a growing project and will encounter changes throughout its development. It is recommended that the [Change Log](https://github.com/CosmicMind/Material/blob/master/CHANGELOG.md) be reviewed prior to updating versions.\n\n## Icons\n\nIcons is a library of Google and CosmicMind icons that are available for use within your iOS applications.\n\n![Icon](http://www.cosmicmind.com/gifs/marketplace/icons.png)\n\n[Learn More](https://github.com/CosmicMind/Material/blob/master/Sources/iOS/Icon/Icon.swift)\n\n## Colors\n\nTry the Material Colors app to see the wonderful colors available in Material, or use the online version at [MaterialColor.com](http://materialcolor.com).\n\n![MaterialColors](http://www.cosmicmind.com/gifs/shared/colors.gif)\n\n* [Material Colors iOS App](https://itunes.apple.com/app/x/id1111994400?mt=8)\n\n## TextField\n\nA TextField is an excellent way to improve UX. It allows for a placeholder and additional hint details.\n\n![TextField](http://www.cosmicmind.com/gifs/white/text-field.gif)\n\n* [TextField Sample](https://github.com/CosmicMind/Samples/tree/master/Projects/Programmatic/TextField)\n\n## Button\n\nA button is used to trigger an action through a touch event. Material comes with a foundational button, and 4 specialized buttons that can be stylized in any way.\n\n![Material Image](http://www.cosmicmind.com/material/white/button.gif)\n\n* [Button Sample](https://github.com/CosmicMind/Samples/tree/master/Projects/Programmatic/Button)\n\n## Switch\n\nA switch is a control component that toggles between on and off states.\n\n![Material Image](http://www.cosmicmind.com/material/white/switch.gif)\n\n* [Switch Sample](https://github.com/CosmicMind/Samples/tree/master/Projects/Programmatic/Switch)\n\n## Card\n\nA Card is a flexible component that may be configured in any way you like. It has a Toolbar, Bar, and content area that may utilize any UIView type.\n\n![Material Image](http://www.cosmicmind.com/gifs/white/card.gif)\n\n* [Card Sample](https://github.com/CosmicMind/Samples/tree/master/Projects/Programmatic/Card)\n\n## ImageCard\n\nAn ImageCard is an expansion of the base Card. The Toolbar overlays an image area that sits above the dynamic content area.\n\n![Image Card Sample](http://www.cosmicmind.com/gifs/white/image-card.gif)\n\n* [ImageCard Sample](https://github.com/CosmicMind/Samples/tree/master/Projects/Programmatic/ImageCard)\n\n## PresenterCard\n\nThe PresenterCard is a completely new card style. It allows for a primary presentation area that may be any UIView type in addition to the content area, Toolbar, and Bar components. The options for this card are endless.\n\n![Presenter Card Sample](http://www.cosmicmind.com/gifs/white/presenter-card.gif)\n\n* [PresenterCard Sample](https://github.com/CosmicMind/Samples/tree/master/Projects/Programmatic/PresenterCard)\n\n## FABMenu\n\nA FABMenu manages a collection of views. A new MenuItem type has been added that manages a title and button to improve UX and visual beauty.\n\n![Material Image](http://www.cosmicmind.com/material/white/menu-controller.gif)\n\n* [FABMenu Sample](https://github.com/CosmicMind/Samples/tree/master/Projects/Programmatic/FABMenuController)\n\n## Toolbar\n\nToolbars are super flexible and add excellent control to your navigation flow. They manage a set of left and right views with auto aligning title and detail labels.\n\n![Material Image](http://www.cosmicmind.com/gifs/white/toolbar-controller.gif)\n\n* [Toolbar Sample](https://github.com/CosmicMind/Samples/tree/master/Projects/Programmatic/ToolbarController)\n\n## SearchBar\n\nA SearchBar is a powerful navigation tool that allows for user's input with an instant visual response. A set of left and right views may be added to expand functionality.\n\n![SearchBarController](http://www.cosmicmind.com/gifs/shared/search-bar-controller.gif)\n\n* [SearchBar Sample](https://github.com/CosmicMind/Samples/tree/master/Projects/Programmatic/Search)\n\n## Tabs\n\nTabs is a new component that links a customizable TabBar to a stack of view controllers making a powerful and visually pleasing component to have in any application.\n\n![Tabs](http://www.cosmicmind.com/material/white/page-tab-bar-controller.gif)\n\n* [Tabs Sample](https://github.com/CosmicMind/Samples/tree/master/Projects/Programmatic/TabsController)\n\n## NavigationController\n\nA NavigationController is a specialized view controller that manages a hierarchy of content efficiently, making it easier for users to move within an application.\n\n![Material Image](http://www.cosmicmind.com/gifs/white/navigation-controller.gif)\n\n* [NavigationController Sample](https://github.com/CosmicMind/Samples/tree/master/Projects/Programmatic/NavigationController)\n\n## NavigationDrawer\n\nA NavigationDrawer slides in from the left or right and contains the navigation destinations for your application.\n\n![Material Image](http://www.cosmicmind.com/material/shared/navigation-drawer-controller.gif)\n\n* [NavigationDrawer Sample](https://github.com/CosmicMind/Samples/tree/master/Projects/Programmatic/NavigationDrawerController)\n\n## Snackbar\n\nA Snackbar is a new component that is very simple in its behavior and very powerful in its message. It can be used application wide, or isolated to specific view controllers.\n\n![Material Image](http://www.cosmicmind.com/material/white/snackbar-controller.gif)\n\n* [Snackbar Sample](https://github.com/CosmicMind/Samples/tree/master/Projects/Programmatic/SnackbarController)\n\n## Sticker Sheet\n\nTo help template your project, checkout Material Sticker Sheet.\n\n![MaterialStickerSheet](http://www.cosmicmind.com/MK/material_iso_1.png)\n\n* [Material Sticker Sheet](http://www.materialup.com/posts/material-design-sticker-sheets)\n\n## Much More...\n\nSo much more inside. Enjoy!\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\nAll rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "Sources/Assets.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_add_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_add_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_add_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_add_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_arrow_back_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_arrow_back_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_arrow_back_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_arrow_back_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_arrow_downward_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_arrow_downward_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_arrow_downward_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_arrow_downward_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_audio_library_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_audio_library_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_audio_library_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_audio_library_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_audio_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_audio_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_audio_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_audio_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_bell_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_bell_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_bell_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_bell_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_check_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_check_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_check_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_check_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_close_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_close_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_close_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_close_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_image_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_image_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_image_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_image_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_menu_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_menu_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_menu_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_menu_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_microphone_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_microphone_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_microphone_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_microphone_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_more_horiz_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_more_horiz_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_more_horiz_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_more_horiz_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_more_vert_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_more_vert_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_more_vert_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_more_vert_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_movie_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_movie_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_movie_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_movie_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_pause_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_pause_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_pause_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_pause_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_pen_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_pen_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_pen_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_pen_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_photo_camera_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_photo_camera_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_photo_camera_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_photo_camera_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_photo_library_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_photo_library_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_photo_library_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_photo_library_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_play_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_play_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_play_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_play_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_search_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_search_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_search_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_search_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_settings_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_settings_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_settings_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_settings_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_share_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_share_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_share_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_share_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_shuffle_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_shuffle_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_shuffle_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_shuffle_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_skip_backward_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_skip_backward_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_skip_backward_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_skip_backward_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_skip_forward_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_skip_forward_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_skip_forward_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_skip_forward_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_star_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_star_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_star_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_star_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_videocam_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_videocam_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_videocam_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_videocam_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_volume_high_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_volume_high_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_volume_high_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_volume_high_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_volume_medium_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_volume_medium_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_volume_medium_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_volume_medium_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/cm_volume_off_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_volume_off_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_volume_off_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"cm_volume_off_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_add_circle_outline_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_add_circle_outline_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_add_circle_outline_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_add_circle_outline_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_add_circle_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_add_circle_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_add_circle_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_add_circle_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_add_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_add_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_add_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_add_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_arrow_back_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_arrow_back_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_arrow_back_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_arrow_back_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_arrow_downward_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_arrow_downward_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_arrow_downward_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_arrow_downward_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_audiotrack_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_audiotrack_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_audiotrack_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_audiotrack_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_camera_front_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_camera_front_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_camera_front_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_camera_front_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_camera_rear_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_camera_rear_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_camera_rear_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_camera_rear_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_check_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_check_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_check_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_check_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_close_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_close_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_close_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_close_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_edit_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_edit_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_edit_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_edit_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_email_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_email_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_email_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_email_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_favorite_border_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_favorite_border_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_favorite_border_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_favorite_border_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_favorite_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_favorite_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_favorite_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_favorite_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_flash_auto_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_flash_auto_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_flash_auto_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_flash_auto_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_flash_off_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_flash_off_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_flash_off_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_flash_off_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_flash_on_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_flash_on_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_flash_on_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_flash_on_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_history_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_history_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_history_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_history_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_home_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_home_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_home_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_home_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_image_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_image_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_image_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_image_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_menu_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_menu_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_menu_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_menu_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_more_horiz_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_more_horiz_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_more_horiz_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_more_horiz_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_more_vert_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_more_vert_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_more_vert_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_more_vert_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_movie_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_movie_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_movie_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_movie_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_phone_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_phone_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_phone_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_phone_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_photo_camera_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_photo_camera_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_photo_camera_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_photo_camera_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_photo_library_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_photo_library_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_photo_library_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_photo_library_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_place_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_place_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_place_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_place_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_search_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_search_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_search_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_search_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_settings_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_settings_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_settings_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_settings_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_share_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_share_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_share_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_share_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_star_border_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_star_border_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_star_border_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_star_border_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_star_half_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_star_half_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_star_half_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_star_half_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_star_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_star_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_star_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_star_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_videocam_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_videocam_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_videocam_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_videocam_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_visibility_off_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_visibility_off_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_visibility_off_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_visibility_off_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_visibility_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_visibility_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_visibility_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_visibility_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Assets.xcassets/ic_work_white.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_work_white.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_work_white@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"ic_work_white@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Sources/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>FMWK</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(MARKETING_VERSION)</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(CURRENT_PROJECT_VERSION)</string>\n\t<key>LSApplicationCategoryType</key>\n\t<string></string>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>Copyright © 2017 CosmicMind, Inc. All rights reserved.</string>\n\t<key>NSPrincipalClass</key>\n\t<string></string>\n\t<key>UIAppFonts</key>\n\t<array>\n\t\t<string>Roboto-Thin</string>\n\t\t<string>Roboto-Light.ttf</string>\n\t\t<string>Roboto-Regular.ttf</string>\n\t\t<string>Roboto-Medium.ttf</string>\n\t\t<string>Roboto-Bold</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "Sources/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\nAll rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "Sources/Material.h",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#import <Foundation/Foundation.h>\n\n//! Project version number for Material.\nFOUNDATION_EXPORT double MaterialVersionNumber;\n\n//! Project version string for Material.\nFOUNDATION_EXPORT const unsigned char MaterialVersionString[];\n\n// In this header, you should import all the public headers of your framework using statements like #import <Material/PublicHeader.h>\n"
  },
  {
    "path": "Sources/iOS/Animation/PulseAnimation.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\n@objc(PulseAnimation)\npublic enum PulseAnimation: Int {\n  case none\n  case center\n  case centerWithBacking\n  case centerRadialBeyondBounds\n  case radialBeyondBounds\n  case backing\n  case point\n  case pointWithBacking\n}\n\npublic protocol Pulseable {\n  /// A reference to the PulseAnimation.\n  var pulseAnimation: PulseAnimation { get set }\n  \n  /// A UIColor.\n  var pulseColor: UIColor { get set }\n  \n  /// The opcaity value for the pulse animation.\n  var pulseOpacity: CGFloat { get set }\n}\n\ninternal protocol PulseableLayer {\n  /// A reference to the pulse layer.\n  var pulseLayer: CALayer? { get }\n}\n\npublic struct Pulse {\n  /// A UIView that is Pulseable.\n  fileprivate weak var pulseView: UIView?\n  \n  /// The layer the pulse layers are added to.\n  internal weak var pulseLayer: CALayer?\n  \n  /// Pulse layers.\n  fileprivate var layers = [CAShapeLayer]()\n  \n  /// A reference to the PulseAnimation.\n  public var animation = PulseAnimation.pointWithBacking\n  \n  /// A UIColor.\n  public var color = Color.grey.base\n  \n  /// The opcaity value for the pulse animation.\n  public var opacity: CGFloat = 0.18\n  \n  /**\n   An initializer that takes a given view and pulse layer.\n   - Parameter pulseView: An optional UIView.\n   - Parameter pulseLayer: An optional CALayer.\n   */\n  public init(pulseView: UIView?, pulseLayer: CALayer?) {\n    self.pulseView = pulseView\n    self.pulseLayer = pulseLayer\n  }\n  \n  /**\n   Triggers the expanding animation.\n   - Parameter point: A point to pulse from.\n   */\n  public mutating func expand(point: CGPoint) {\n    guard let view = pulseView else {\n      return\n    }\n    \n    guard let layer = pulseLayer else {\n      return\n    }\n    \n    guard .none != animation else {\n      return\n    }\n    \n    let bLayer = CAShapeLayer()\n    let pLayer = CAShapeLayer()\n    \n    bLayer.addSublayer(pLayer)\n    layer.addSublayer(bLayer)\n    bLayer.zPosition = 0\n    pLayer.zPosition = 0\n    \n    layers.insert(bLayer, at: 0)\n    \n    layer.masksToBounds = !(.centerRadialBeyondBounds == animation || .radialBeyondBounds == animation)\n    \n    let w = view.bounds.width\n    let h = view.bounds.height\n    \n    Motion.disable { [\n      n = .center == animation ? min(w, h) : max(w, h),\n      bounds = layer.bounds,\n      animation = animation,\n      color = color,\n      opacity = opacity\n      ] in\n      \n      bLayer.frame = bounds\n      pLayer.frame = CGRect(x: 0, y: 0, width: n, height: n)\n      \n      switch animation {\n      case .center, .centerWithBacking, .centerRadialBeyondBounds:\n        pLayer.position = CGPoint(x: w / 2, y: h / 2)\n      default:\n        pLayer.position = point\n      }\n      \n      pLayer.cornerRadius = n / 2\n      pLayer.backgroundColor = color.withAlphaComponent(opacity).cgColor\n      pLayer.transform = CATransform3DMakeAffineTransform(CGAffineTransform(scaleX: 0, y: 0))\n    }\n    \n    bLayer.setValue(false, forKey: \"animated\")\n    \n    let t: TimeInterval = .center == animation ? 0.16125 : 0.325\n    \n    switch animation {\n    case .centerWithBacking, .backing, .pointWithBacking:\n      bLayer.animate(.background(color: color.withAlphaComponent(opacity / 2)), .duration(t))\n    default:break\n    }\n    \n    switch animation {\n    case .center, .centerWithBacking, .centerRadialBeyondBounds, .radialBeyondBounds, .point, .pointWithBacking:\n      pLayer.animate(.scale(1), .duration(t))\n    default:break\n    }\n    \n    Motion.delay(t) {\n      bLayer.setValue(true, forKey: \"animated\")\n    }\n  }\n  \n  /// Triggers the contracting animation.\n  public mutating func contract() {\n    guard let bLayer = layers.popLast() else {\n      return\n    }\n    \n    guard let animated = bLayer.value(forKey: \"animated\") as? Bool else {\n      return\n    }\n    \n    Motion.delay(animated ? 0 : 0.15) { [animation = animation, color = color] in\n      guard let pLayer = bLayer.sublayers?.first as? CAShapeLayer else {\n        return\n      }\n      \n      let t: TimeInterval = 0.325\n      \n      switch animation {\n      case .centerWithBacking, .backing, .pointWithBacking:\n        bLayer.animate(.background(color: color.withAlphaComponent(0)), .duration(t))\n      default:break\n      }\n      \n      switch animation {\n      case .center, .centerWithBacking, .centerRadialBeyondBounds, .radialBeyondBounds, .point, .pointWithBacking:\n        pLayer.animate(.background(color: color.withAlphaComponent(0)))\n      default:break\n      }\n      \n      Motion.delay(t) {\n        pLayer.removeFromSuperlayer()\n        bLayer.removeFromSuperlayer()\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Animation/SpringAnimation.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(SpringDirection)\npublic enum SpringDirection: Int {\n  case up\n  case down\n  case left\n  case right\n}\n\nopen class SpringAnimation {\n  /// A SpringDirection value.\n  open var springDirection = SpringDirection.up\n  \n  /// A Boolean that indicates if the menu is open or not.\n  open var isOpened = false\n  \n  /// Enables the animations for the Menu.\n  open var isEnabled = true\n  \n  /// A preset wrapper around interimSpace.\n  open var interimSpacePreset = InterimSpacePreset.none {\n    didSet {\n      interimSpace = InterimSpacePresetToValue(preset: interimSpacePreset)\n    }\n  }\n  \n  /// The space between views.\n  open var interimSpace: InterimSpace = 0 {\n    didSet {\n      reload()\n    }\n  }\n  \n  /// An Array of UIViews.\n  open var views = [UIView]() {\n    didSet {\n      reload()\n    }\n  }\n  \n  /// An Optional base view size.\n  open var baseSize = CGSize(width: 48, height: 48) {\n    didSet {\n      reload()\n    }\n  }\n  \n  /// Size of views.\n  open var itemSize = CGSize(width: 48, height: 48) {\n    didSet {\n      reload()\n    }\n  }\n  \n  /// Reload the view layout.\n  open func reload() {\n    isOpened = false\n    \n    for i in 0..<views.count {\n      let v = views[i]\n      v.alpha = 0\n      v.isHidden = true\n      v.frame.size = itemSize\n      v.frame.origin.x = (baseSize.width - itemSize.width) / 2\n      v.frame.origin.y = (baseSize.height - itemSize.height) / 2\n      v.layer.zPosition = CGFloat(10000 - views.count - i)\n    }\n  }\n}\n\nextension SpringAnimation {\n  /// Disable the Menu if views exist.\n  fileprivate func disable() {\n    guard 0 < views.count else {\n      return\n    }\n    \n    isEnabled = false\n  }\n  \n  /**\n   Enable the Menu if the last view is equal to the passed in view.\n   - Parameter view: UIView that is passed in to compare.\n   */\n  fileprivate func enable(view: UIView) {\n    guard view == views.last else {\n      return\n    }\n    \n    isEnabled = true\n  }\n}\n\nextension SpringAnimation {\n  /**\n   Expands the Spring component with animation options.\n   - Parameter duration: The time for each view's animation.\n   - Parameter delay: A delay time for each view's animation.\n   - Parameter usingSpringWithDamping: A damping ratio for the animation.\n   - Parameter initialSpringVelocity: The initial velocity for the animation.\n   - Parameter options: Options to pass to the animation.\n   - Parameter animations: An animation block to execute on each view's animation.\n   - Parameter completion: A completion block to execute on each view's animation.\n   */\n  open func expand(duration: TimeInterval = 0.15, delay: TimeInterval = 0, usingSpringWithDamping: CGFloat = 0.5, initialSpringVelocity: CGFloat = 0, options: UIView.AnimationOptions = [], animations: ((UIView) -> Void)? = nil, completion: ((UIView) -> Void)? = nil) {\n    guard isEnabled else {\n      return\n    }\n    \n    disable()\n    \n    switch springDirection {\n    case .up:\n      expandUp(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)\n    case .down:\n      expandDown(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)\n    case .left:\n      expandLeft(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)\n    case .right:\n      expandRight(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)\n    }\n  }\n  \n  /**\n   Contracts the Spring component with animation options.\n   - Parameter duration: The time for each view's animation.\n   - Parameter delay: A delay time for each view's animation.\n   - Parameter usingSpringWithDamping: A damping ratio for the animation.\n   - Parameter initialSpringVelocity: The initial velocity for the animation.\n   - Parameter options: Options to pass to the animation.\n   - Parameter animations: An animation block to execute on each view's animation.\n   - Parameter completion: A completion block to execute on each view's animation.\n   */\n  open func contract(duration: TimeInterval = 0.15, delay: TimeInterval = 0, usingSpringWithDamping: CGFloat = 0.5, initialSpringVelocity: CGFloat = 0, options: UIView.AnimationOptions = [], animations: ((UIView) -> Void)? = nil, completion: ((UIView) -> Void)? = nil) {\n    guard isEnabled else {\n      return\n    }\n    \n    disable()\n    \n    switch springDirection {\n    case .up:\n      contractUp(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)\n    case .down:\n      contractDown(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)\n    case .left:\n      contractLeft(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)\n    case .right:\n      contractRight(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)\n    }\n  }\n}\n\nextension SpringAnimation {\n  /**\n   Handles the animation open completion.\n   - Parameter view: A UIView.\n   - Parameter completion: A completion handler.\n   */\n  fileprivate func handleOpenCompletion(view: UIView, completion: ((UIView) -> Void)?) {\n    enable(view: view)\n    \n    if view == views.last {\n      isOpened = true\n    }\n    \n    completion?(view)\n  }\n  \n  /**\n   Handles the animation contract completion.\n   - Parameter view: A UIView.\n   - Parameter completion: A completion handler.\n   */\n  fileprivate func handleCloseCompletion(view: UIView, completion: ((UIView) -> Void)?) {\n    view.isHidden = true\n    enable(view: view)\n    \n    if view == views.last {\n      isOpened = false\n    }\n    \n    completion?(view)\n  }\n}\n\nextension SpringAnimation {\n  /**\n   Open the Menu component with animation options in the Up direction.\n   - Parameter duration: The time for each view's animation.\n   - Parameter delay: A delay time for each view's animation.\n   - Parameter usingSpringWithDamping: A damping ratio for the animation.\n   - Parameter initialSpringVelocity: The initial velocity for the animation.\n   - Parameter options: Options to pass to the animation.\n   - Parameter animations: An animation block to execute on each view's animation.\n   - Parameter completion: A completion block to execute on each view's animation.\n   */\n  fileprivate func expandUp(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIView.AnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {\n    for i in 0..<views.count {\n      let v = views[i]\n      v.isHidden = false\n      \n      UIView.animate(withDuration: Double(i) * duration,\n                     delay: delay,\n                     usingSpringWithDamping: usingSpringWithDamping,\n                     initialSpringVelocity: initialSpringVelocity,\n                     options: options,\n                     animations: { [s = interimSpace, m = CGFloat(i + 1), v = v] in\n                      v.alpha = 1\n                      v.frame.origin.y = -m * (v.bounds.height + s)\n                      animations?(v)\n      }) { [weak self, v = v] _ in\n        self?.handleOpenCompletion(view: v, completion: completion)\n      }\n    }\n  }\n  \n  /**\n   Close the Menu component with animation options in the Up direction.\n   - Parameter duration: The time for each view's animation.\n   - Parameter delay: A delay time for each view's animation.\n   - Parameter usingSpringWithDamping: A damping ratio for the animation.\n   - Parameter initialSpringVelocity: The initial velocity for the animation.\n   - Parameter options: Options to pass to the animation.\n   - Parameter animations: An animation block to execute on each view's animation.\n   - Parameter completion: A completion block to execute on each view's animation.\n   */\n  fileprivate func contractUp(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIView.AnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {\n    for i in 0..<views.count {\n      let v = views[i]\n      \n      UIView.animate(withDuration: Double(i) * duration,\n                     delay: delay,\n                     usingSpringWithDamping: usingSpringWithDamping,\n                     initialSpringVelocity: initialSpringVelocity,\n                     options: options,\n                     animations: { [v = v] in\n                      v.alpha = 0\n                      v.frame.origin.y = 0\n                      animations?(v)\n      }) { [weak self, v = v] _ in\n        self?.handleCloseCompletion(view: v, completion: completion)\n      }\n    }\n  }\n  \n  /**\n   Open the Menu component with animation options in the Down direction.\n   - Parameter duration: The time for each view's animation.\n   - Parameter delay: A delay time for each view's animation.\n   - Parameter usingSpringWithDamping: A damping ratio for the animation.\n   - Parameter initialSpringVelocity: The initial velocity for the animation.\n   - Parameter options: Options to pass to the animation.\n   - Parameter animations: An animation block to execute on each view's animation.\n   - Parameter completion: A completion block to execute on each view's animation.\n   */\n  fileprivate func expandDown(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIView.AnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {\n    \n    for i in 0..<views.count {\n      let v = views[i]\n      v.isHidden = false\n      \n      UIView.animate(withDuration: Double(i) * duration,\n                     delay: delay,\n                     usingSpringWithDamping: usingSpringWithDamping,\n                     initialSpringVelocity: initialSpringVelocity,\n                     options: options,\n                     animations: { [s = interimSpace, m = CGFloat(i + 1), v = v] in\n                      v.alpha = 1\n                      v.frame.origin.y = m * (v.bounds.height + s)\n                      \n                      animations?(v)\n      }) { [weak self, v = v] _ in\n        self?.handleOpenCompletion(view: v, completion: completion)\n      }\n    }\n  }\n  \n  /**\n   Close the Menu component with animation options in the Down direction.\n   - Parameter duration: The time for each view's animation.\n   - Parameter delay: A delay time for each view's animation.\n   - Parameter usingSpringWithDamping: A damping ratio for the animation.\n   - Parameter initialSpringVelocity: The initial velocity for the animation.\n   - Parameter options: Options to pass to the animation.\n   - Parameter animations: An animation block to execute on each view's animation.\n   - Parameter completion: A completion block to execute on each view's animation.\n   */\n  fileprivate func contractDown(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIView.AnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {\n    guard let first = views.first else {\n      return\n    }\n    \n    for i in 0..<views.count {\n      let v = views[i]\n      \n      UIView.animate(withDuration: Double(i) * duration,\n                     delay: delay,\n                     usingSpringWithDamping: usingSpringWithDamping,\n                     initialSpringVelocity: initialSpringVelocity,\n                     options: options,\n                     animations: { [first = first, v = v] in\n                      v.alpha = 0\n                      v.frame.origin.y = first.frame.origin.y\n                      \n                      animations?(v)\n      }) { [weak self, v = v] _ in\n        self?.handleCloseCompletion(view: v, completion: completion)\n      }\n    }\n  }\n  \n  /**\n   Open the Menu component with animation options in the Left direction.\n   - Parameter duration: The time for each view's animation.\n   - Parameter delay: A delay time for each view's animation.\n   - Parameter usingSpringWithDamping: A damping ratio for the animation.\n   - Parameter initialSpringVelocity: The initial velocity for the animation.\n   - Parameter options: Options to pass to the animation.\n   - Parameter animations: An animation block to execute on each view's animation.\n   - Parameter completion: A completion block to execute on each view's animation.\n   */\n  fileprivate func expandLeft(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIView.AnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {\n    \n    for i in 0..<views.count {\n      let v = views[i]\n      v.isHidden = false\n      \n      UIView.animate(withDuration: Double(i) * duration,\n                     delay: delay,\n                     usingSpringWithDamping: usingSpringWithDamping,\n                     initialSpringVelocity: initialSpringVelocity,\n                     options: options,\n                     animations: { [s = interimSpace, m = CGFloat(i + 1), v = v] in\n                      v.alpha = 1\n                      v.frame.origin.x = -m * (v.bounds.width + s)\n                      \n                      animations?(v)\n      }) { [weak self, v = v] _ in\n        self?.handleOpenCompletion(view: v, completion: completion)\n      }\n    }\n  }\n  \n  /**\n   Close the Menu component with animation options in the Left direction.\n   - Parameter duration: The time for each view's animation.\n   - Parameter delay: A delay time for each view's animation.\n   - Parameter usingSpringWithDamping: A damping ratio for the animation.\n   - Parameter initialSpringVelocity: The initial velocity for the animation.\n   - Parameter options: Options to pass to the animation.\n   - Parameter animations: An animation block to execute on each view's animation.\n   - Parameter completion: A completion block to execute on each view's animation.\n   */\n  fileprivate func contractLeft(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIView.AnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {\n    guard let first = views.first else {\n      return\n    }\n    \n    for i in 0..<views.count {\n      let v = views[i]\n      \n      UIView.animate(withDuration: Double(i) * duration,\n                     delay: delay,\n                     usingSpringWithDamping: usingSpringWithDamping,\n                     initialSpringVelocity: initialSpringVelocity,\n                     options: options,\n                     animations: { [first = first, v = v] in\n                      v.alpha = 0\n                      v.frame.origin.x = first.frame.origin.x\n                      \n                      animations?(v)\n      }) { [weak self, v = v] _ in\n        self?.handleCloseCompletion(view: v, completion: completion)\n      }\n    }\n  }\n  \n  /**\n   Open the Menu component with animation options in the Right direction.\n   - Parameter duration: The time for each view's animation.\n   - Parameter delay: A delay time for each view's animation.\n   - Parameter usingSpringWithDamping: A damping ratio for the animation.\n   - Parameter initialSpringVelocity: The initial velocity for the animation.\n   - Parameter options: Options to pass to the animation.\n   - Parameter animations: An animation block to execute on each view's animation.\n   - Parameter completion: A completion block to execute on each view's animation.\n   */\n  fileprivate func expandRight(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIView.AnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {\n    \n    for i in 0..<views.count {\n      let v = views[i]\n      v.isHidden = false\n      \n      UIView.animate(withDuration: Double(i) * duration,\n                     delay: delay,\n                     usingSpringWithDamping: usingSpringWithDamping,\n                     initialSpringVelocity: initialSpringVelocity,\n                     options: options,\n                     animations: { [s = interimSpace, m = CGFloat(i + 1), v = v] in\n                      v.alpha = 1\n                      v.frame.origin.x = m * (v.bounds.width + s)\n                      \n                      animations?(v)\n      }) { [weak self, v = v] _ in\n        self?.handleOpenCompletion(view: v, completion: completion)\n      }\n    }\n  }\n  \n  /**\n   Close the Menu component with animation options in the Right direction.\n   - Parameter duration: The time for each view's animation.\n   - Parameter delay: A delay time for each view's animation.\n   - Parameter usingSpringWithDamping: A damping ratio for the animation.\n   - Parameter initialSpringVelocity: The initial velocity for the animation.\n   - Parameter options: Options to pass to the animation.\n   - Parameter animations: An animation block to execute on each view's animation.\n   - Parameter completion: A completion block to execute on each view's animation.\n   */\n  fileprivate func contractRight(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIView.AnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {\n    guard let first = views.first else {\n      return\n    }\n    \n    let w = baseSize.width\n    \n    for i in 0..<views.count {\n      let v = views[i]\n      \n      UIView.animate(withDuration: Double(i) * duration,\n                     delay: delay,\n                     usingSpringWithDamping: usingSpringWithDamping,\n                     initialSpringVelocity: initialSpringVelocity,\n                     options: options,\n                     animations: { [first = first, v = v] in\n                      v.alpha = 0\n                      v.frame.origin.x = first.frame.origin.x + w\n                      \n                      animations?(v)\n      }) { [weak self, v = v] _ in\n        self?.handleCloseCompletion(view: v, completion: completion)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Application/Application.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\npublic struct Application {\n  \n  /// A reference to UIApplication.shared application which doesn't trigger linker errors when Material is included in an extension\n  /// Note that this will crash if actually called from within an extension\n  public static var shared: UIApplication {\n    let sharedSelector = NSSelectorFromString(\"sharedApplication\")\n    guard UIApplication.responds(to: sharedSelector) else {\n      fatalError(\"[Material: Extensions cannot access Application]\")\n    }\n    \n    let shared = UIApplication.perform(sharedSelector)\n    return shared?.takeUnretainedValue() as! UIApplication\n  }\n  \n  /// An optional reference to the main UIWindow.\n  public static var keyWindow: UIWindow? {\n    return Application.shared.keyWindow\n  }\n  \n  /// An optional reference to the top most view controller.\n  public static var rootViewController: UIViewController? {\n    return keyWindow?.rootViewController\n  }\n  \n  /// A boolean indicating if the device is in Landscape mode.\n  public static var isLandscape: Bool {\n    return Application.shared.statusBarOrientation.isLandscape\n  }\n  \n  /// A boolean indicating if the device is in Portrait mode.\n  public static var isPortrait: Bool {\n    return !isLandscape\n  }\n  \n  /// The current UIInterfaceOrientation value.\n  public static var orientation: UIInterfaceOrientation {\n    return Application.shared.statusBarOrientation\n  }\n  \n  /// Retrieves the device status bar style.\n  public static var statusBarStyle: UIStatusBarStyle {\n    get {\n      return Application.shared.statusBarStyle\n    }\n    set(value) {\n      Application.shared.statusBarStyle = value\n    }\n  }\n  \n  /// Retrieves the device status bar hidden state.\n  public static var isStatusBarHidden: Bool {\n    get {\n      return Application.shared.isStatusBarHidden\n    }\n    set(value) {\n      Application.shared.isStatusBarHidden = value\n    }\n  }\n  \n  /**\n   A boolean that indicates based on iPhone rules if the\n   status bar should be shown.\n   */\n  public static var shouldStatusBarBeHidden: Bool {\n    return isLandscape && .phone == Device.userInterfaceIdiom\n  }\n  \n  /// A reference to the user interface layout direction.\n  public static var userInterfaceLayoutDirection: UIUserInterfaceLayoutDirection {\n    return Application.shared.userInterfaceLayoutDirection\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Bar/Bar.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(ContentViewAlignment)\npublic enum ContentViewAlignment: Int {\n  case full\n  case center\n}\n\nopen class Bar: View {\n  /// Will layout the view.\n  open var willLayout: Bool {\n    return 0 < bounds.width && 0 < bounds.height && nil != superview && !grid.isDeferred\n  }\n  \n  open override var intrinsicContentSize: CGSize {\n    return bounds.size\n  }\n  \n  /// Should center the contentView.\n  open var contentViewAlignment = ContentViewAlignment.full {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// A preset wrapper around contentEdgeInsets.\n  open var contentEdgeInsetsPreset: EdgeInsetsPreset {\n    get {\n      return grid.contentEdgeInsetsPreset\n    }\n    set(value) {\n      grid.contentEdgeInsetsPreset = value\n    }\n  }\n  \n  /// A reference to EdgeInsets.\n  @IBInspectable\n  open var contentEdgeInsets: EdgeInsets {\n    get {\n      return grid.contentEdgeInsets\n    }\n    set(value) {\n      grid.contentEdgeInsets = value\n    }\n  }\n  \n  /// A preset wrapper around interimSpace.\n  open var interimSpacePreset: InterimSpacePreset {\n    get {\n      return grid.interimSpacePreset\n    }\n    set(value) {\n      grid.interimSpacePreset = value\n    }\n  }\n  \n  /// A wrapper around grid.interimSpace.\n  @IBInspectable\n  open var interimSpace: InterimSpace {\n    get {\n      return grid.interimSpace\n    }\n    set(value) {\n      grid.interimSpace = value\n    }\n  }\n  \n  /// Grid cell factor.\n  @IBInspectable\n  open var gridFactor: CGFloat = 12 {\n    didSet {\n      assert(0 < gridFactor, \"[Material Error: gridFactor must be greater than 0.]\")\n      layoutSubviews()\n    }\n  }\n  \n  /// ContentView that holds the any desired subviews.\n  public let contentView = UIView()\n  \n  /// Left side UIViews.\n  open var leftViews = [UIView]() {\n    didSet {\n      oldValue.forEach {\n        $0.removeFromSuperview()\n      }\n      \n      layoutSubviews()\n    }\n  }\n  \n  /// Right side UIViews.\n  open var rightViews = [UIView]() {\n    didSet {\n      oldValue.forEach {\n        $0.removeFromSuperview()\n      }\n      \n      layoutSubviews()\n    }\n  }\n  \n  /// Center UIViews.\n  open var centerViews: [UIView] {\n    get {\n      return contentView.grid.views\n    }\n    set(value) {\n      contentView.grid.views = value\n    }\n  }\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n  }\n  \n  /**\n   An initializer that initializes the object with a CGRect object.\n   If AutoLayout is used, it is better to initilize the instance\n   using the init() initializer.\n   - Parameter frame: A CGRect instance.\n   */\n  public override init(frame: CGRect) {\n    super.init(frame: frame)\n  }\n  \n  /**\n   A convenience initializer with parameter settings.\n   - Parameter leftViews: An Array of UIViews that go on the left side.\n   - Parameter rightViews: An Array of UIViews that go on the right side.\n   - Parameter centerViews: An Array of UIViews that go in the center.\n   */\n  public convenience init(leftViews: [UIView]? = nil, rightViews: [UIView]? = nil, centerViews: [UIView]? = nil) {\n    self.init()\n    self.leftViews = leftViews ?? []\n    self.rightViews = rightViews ?? []\n    self.centerViews = centerViews ?? []\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    guard willLayout else {\n      return\n    }\n    \n    var lc = 0\n    var rc = 0\n    \n    grid.begin()\n    grid.views.removeAll()\n    \n    for v in leftViews {\n      if let b = v as? UIButton {\n        b.contentEdgeInsets = .zero\n        b.titleEdgeInsets = .zero\n      }\n      \n      v.frame.size.width = v.intrinsicContentSize.width\n      v.sizeToFit()\n      v.grid.columns = Int(ceil(v.bounds.width / gridFactor)) + 2\n      \n      lc += v.grid.columns\n      \n      grid.views.append(v)\n    }\n    \n    grid.views.append(contentView)\n    \n    for v in rightViews {\n      if let b = v as? UIButton {\n        b.contentEdgeInsets = .zero\n        b.titleEdgeInsets = .zero\n      }\n      \n      v.frame.size.width = v.intrinsicContentSize.width\n      v.sizeToFit()\n      v.grid.columns = Int(ceil(v.bounds.width / gridFactor)) + 2\n      \n      rc += v.grid.columns\n      \n      grid.views.append(v)\n    }\n    \n    contentView.grid.begin()\n    contentView.grid.offset.columns = 0\n    \n    var l: CGFloat = 0\n    var r: CGFloat = 0\n    \n    if .center == contentViewAlignment {\n      if leftViews.count < rightViews.count {\n        r = CGFloat(rightViews.count) * interimSpace\n        l = r\n      } else {\n        l = CGFloat(leftViews.count) * interimSpace\n        r = l\n      }\n    }\n    \n    let p = bounds.width - l - r - contentEdgeInsets.left - contentEdgeInsets.right\n    let columns = Int(ceil(p / gridFactor))\n    \n    if .center == contentViewAlignment {\n      if lc < rc {\n        contentView.grid.columns = columns - 2 * rc\n        contentView.grid.offset.columns = rc - lc\n      } else {\n        contentView.grid.columns = columns - 2 * lc\n        rightViews.first?.grid.offset.columns = lc - rc\n      }\n    } else {\n      contentView.grid.columns = columns - lc - rc\n    }\n    \n    grid.axis.columns = columns\n    grid.commit()\n    contentView.grid.commit()\n    \n    layoutDivider()\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    heightPreset = .normal\n    autoresizingMask = .flexibleWidth\n    interimSpacePreset = .interimSpace3\n    contentEdgeInsetsPreset = .square1\n    \n    prepareContentView()\n  }\n}\n\nextension Bar {\n  /// Prepares the contentView.\n  fileprivate func prepareContentView() {\n    contentView.contentScaleFactor = Screen.scale\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/BottomTabBar/BottomNavigationController.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\nextension UIViewController {\n  /**\n   A convenience property that provides access to the BottomNavigationController.\n   This is the recommended method of accessing the BottomNavigationController\n   through child UIViewControllers.\n   */\n  public var bottomNavigationController: BottomNavigationController? {\n    return traverseViewControllerHierarchyForClassType()\n  }\n}\n\nprivate class MaterialTabBar: UITabBar {\n  override func sizeThatFits(_ size: CGSize) -> CGSize {\n    var v = super.sizeThatFits(size)\n    let offset = v.height - HeightPreset.normal.rawValue\n    v.height = heightPreset.rawValue + offset\n    return v\n  }\n}\n\nopen class BottomNavigationController: UITabBarController, Themeable {\n  /// A Boolean that controls if the swipe feature is enabled.\n  open var isSwipeEnabled = true {\n    didSet {\n      guard isSwipeEnabled else {\n        removeSwipeGesture()\n        return\n      }\n      \n      prepareSwipeGesture()\n    }\n  }\n  \n  /**\n   A UIPanGestureRecognizer property internally used for the interactive\n   swipe.\n   */\n  public private(set) var interactiveSwipeGesture: UIPanGestureRecognizer?\n  \n  /**\n   A private integer for storing index of current view controller\n   during interactive transition.\n   */\n  private var currentIndex = -1\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n    setTabBarClass()\n  }\n  \n  /**\n   An initializer that initializes the object with an Optional nib and bundle.\n   - Parameter nibNameOrNil: An Optional String for the nib.\n   - Parameter bundle: An Optional NSBundle where the nib is located.\n   */\n  public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {\n    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)\n    setTabBarClass()\n  }\n  \n  /// An initializer that accepts no parameters.\n  public init() {\n    super.init(nibName: nil, bundle: nil)\n    setTabBarClass()\n  }\n  \n  /**\n   An initializer that initializes the object an Array of UIViewControllers.\n   - Parameter viewControllers: An Array of UIViewControllers.\n   */\n  public init(viewControllers: [UIViewController]) {\n    super.init(nibName: nil, bundle: nil)\n    setTabBarClass()\n    self.viewControllers = viewControllers\n  }\n  \n  open override func viewDidLoad() {\n    super.viewDidLoad()\n    prepare()\n  }\n  \n  open override func viewWillLayoutSubviews() {\n    super.viewWillLayoutSubviews()\n    layoutSubviews()\n  }\n  \n  /**\n   To execute in the order of the layout chain, override this\n   method. `layoutSubviews` should be called immediately, unless you\n   have a certain need.\n   */\n  open func layoutSubviews() {\n    tabBar.layoutDivider()\n  }\n  \n  /**\n   Prepares the view instance when intialized. When subclassing,\n   it is recommended to override the prepare method\n   to initialize property values and other setup operations.\n   The super.prepare method should always be called immediately\n   when subclassing.\n   */\n  open func prepare() {\n    view.clipsToBounds = true\n    view.backgroundColor = .white\n    view.contentScaleFactor = Screen.scale\n    \n    prepareTabBar()\n    isSwipeEnabled = true\n    isMotionEnabled = true\n    applyCurrentTheme()\n  }\n  \n  /**\n   Applies the given theme.\n   - Parameter theme: A Theme.\n   */\n  open func apply(theme: Theme) {\n    tabBar.tintColor = theme.secondary\n    tabBar.barTintColor = theme.background\n    tabBar.dividerColor = theme.onSurface.withAlphaComponent(0.12)\n    \n    if #available(iOS 10.0, *) {\n      tabBar.unselectedItemTintColor = theme.onSurface.withAlphaComponent(0.54)\n    }\n  }\n}\n\nprivate extension BottomNavigationController {\n  /**\n   A target method contolling interactive swipe transition based on\n   gesture recognizer.\n   - Parameter _ gesture: A UIPanGestureRecognizer.\n   */\n  @objc\n  func handleTransitionPan(_ gesture: UIPanGestureRecognizer) {\n    guard selectedIndex != NSNotFound else {\n      return\n    }\n    \n    let translationX = gesture.translation(in: nil).x\n    let velocityX = gesture.velocity(in: nil).x\n    \n    switch gesture.state {\n    case .began, .changed:\n      let isSlidingLeft = currentIndex == -1 ? velocityX < 0 : translationX < 0\n      \n      if currentIndex == -1 {\n        currentIndex = selectedIndex\n      }\n      \n      let nextIndex = currentIndex + (isSlidingLeft ? 1 : -1)\n      \n      if selectedIndex != nextIndex {\n        /// 5 point threshold\n        guard abs(translationX) > 5 else {\n          return\n        }\n        \n        if currentIndex != selectedIndex {\n          MotionTransition.shared.cancel(isAnimated: false)\n        }\n        \n        guard canSelect(at: nextIndex) else {\n          return\n        }\n        \n        selectedIndex = nextIndex\n        MotionTransition.shared.setCompletionCallbackForNextTransition { [weak self] isFinishing in\n          guard let `self` = self, isFinishing else {\n            return\n          }\n          \n          self.delegate?.tabBarController?(self, didSelect: self.viewControllers![nextIndex])\n        }\n      } else {\n        let progress = abs(translationX / view.bounds.width)\n        MotionTransition.shared.update(Double(progress))\n      }\n      \n    default:\n      let progress = (translationX + velocityX) / view.bounds.width\n      \n      let isUserHandDirectionLeft = progress < 0\n      let isTargetHandDirectionLeft = selectedIndex > currentIndex\n      \n      if isUserHandDirectionLeft == isTargetHandDirectionLeft && abs(progress) > 0.5 {\n        MotionTransition.shared.finish()\n      } else {\n        MotionTransition.shared.cancel()\n      }\n      \n      currentIndex = -1\n    }\n  }\n  \n  /// Prepares interactiveSwipeGesture.\n  func prepareSwipeGesture() {\n    guard nil == interactiveSwipeGesture else {\n      return\n    }\n    \n    interactiveSwipeGesture = UIPanGestureRecognizer(target: self, action: #selector(handleTransitionPan))\n    view.addGestureRecognizer(interactiveSwipeGesture!)\n  }\n  \n  /// Removes interactiveSwipeGesture.\n  func removeSwipeGesture() {\n    guard let v = interactiveSwipeGesture else {\n      return\n    }\n    \n    view.removeGestureRecognizer(v)\n    interactiveSwipeGesture = nil\n  }\n}\n\nprivate extension BottomNavigationController {\n  /// Sets tabBar class to MaterialTabBar.\n  func setTabBarClass() {\n    guard object_getClass(tabBar) === UITabBar.self else {\n      return\n    }\n    \n    object_setClass(tabBar, MaterialTabBar.self)\n  }\n}\n\nprivate extension BottomNavigationController {\n  /**\n   Checks if the view controller at a given index can be selected.\n   - Parameter at index: An Int.\n   */\n  func canSelect(at index: Int) -> Bool {\n    guard index != selectedIndex else {\n      return false\n    }\n    \n    let lastTabIndex = (tabBar.items?.count ?? 1) - 1\n    guard (0...lastTabIndex).contains(index) else {\n      return false\n    }\n    \n    guard !(index == lastTabIndex && tabBar.items?.last == moreNavigationController.tabBarItem) else {\n      return false\n    }\n    \n    let vc = viewControllers![index]\n    guard delegate?.tabBarController?(self, shouldSelect: vc) != false else {\n      return false\n    }\n    \n    return true\n  }\n}\n\nprivate extension BottomNavigationController {\n  /// Prepares the tabBar.\n  func prepareTabBar() {\n    tabBar.isTranslucent = false\n    tabBar.heightPreset = .normal\n    tabBar.dividerColor = Color.grey.lighten2\n    tabBar.dividerAlignment = .top\n    \n    let image = UIImage()\n    tabBar.shadowImage = image\n    tabBar.backgroundImage = image\n    tabBar.backgroundColor = .white\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Button/BaseIconLayerButton.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\n/// Implements common logic for CheckButton and RadioButton\nopen class BaseIconLayerButton: Button {\n  class var iconLayer: BaseIconLayer { fatalError(\"Has to be implemented by subclasses\") }\n  lazy var iconLayer: BaseIconLayer = type(of: self).iconLayer\n  \n  /// A Boolean value indicating whether the button is in the selected state\n  ///\n  /// Use `setSelected(_:, animated:)` if the state change needs to be animated\n  open override var isSelected: Bool {\n    didSet {\n      iconLayer.setSelected(isSelected, animated: false)\n      updatePulseColor()\n    }\n  }\n  \n  /// A Boolean value indicating whether the control is enabled.\n  open override var isEnabled: Bool {\n    didSet {\n      iconLayer.isEnabled = isEnabled\n    }\n  }\n  \n  \n  /// Sets the color of the icon to use for the specified state.\n  ///\n  /// - Parameters:\n  ///   - color: The color of the icon to use for the specified state.\n  ///   - state: The state that uses the specified color. Supports only (.normal, .selected, .disabled)\n  open func setIconColor(_ color: UIColor, for state: UIControl.State) {\n    switch state {\n    case .normal:\n      iconLayer.normalColor = color\n    case .selected:\n      iconLayer.selectedColor = color\n    case .disabled:\n      iconLayer.disabledColor = color\n    default:\n      fatalError(\"unsupported state\")\n    }\n  }\n  \n  /// Returns the icon color used for a state.\n  ///\n  /// - Parameter state: The state that uses the icon color. Supports only (.normal, .selected, .disabled)\n  /// - Returns: The color of the title for the specified state.\n  open func iconColor(for state: UIControl.State) -> UIColor {\n    switch state {\n    case .normal:\n      return iconLayer.normalColor\n    case .selected:\n      return iconLayer.selectedColor\n    case .disabled:\n      return iconLayer.disabledColor\n    default:\n      fatalError(\"unsupported state\")\n    }\n  }\n  \n  /// A Boolean value indicating whether the button is being animated\n  open var isAnimating: Bool { return iconLayer.isAnimating }\n  \n  \n  /// Sets the `selected` state of the button, optionally animating the transition.\n  ///\n  /// - Parameters:\n  ///   - isSelected: A Boolean value indicating new `selected` state\n  ///   - animated: true if the state change should be animated, otherwise false.\n  open func setSelected(_ isSelected: Bool, animated: Bool) {\n    guard !isAnimating else { return }\n    iconLayer.setSelected(isSelected, animated: animated)\n    self.isSelected = isSelected\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    layer.addSublayer(iconLayer)\n    iconLayer.prepare()\n    contentHorizontalAlignment = .left // default was .center\n    reloadImage()\n  }\n  \n  open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {\n    // pulse.animation set to .none so that when we call `super.touchesBegan`\n    // pulse will not expand as there is a `guard` against .none case\n    pulse.animation = .none\n    super.touchesBegan(touches, with: event)\n    pulse.animation = .point\n    \n    // expand pulse from the center of iconLayer/visualLayer (`point` is relative to self.view/self.layer)\n    pulse.expand(point: iconLayer.frame.center)\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    \n    // positioning iconLayer\n    let insets = iconEdgeInsets\n    iconLayer.frame.size = CGSize(width: iconSize, height: iconSize)\n    iconLayer.frame.origin = CGPoint(x: imageView!.frame.minX + insets.left, y: imageView!.frame.minY + insets.top)\n    \n    // visualLayer is the layer where pulse layer is expanding.\n    // So we position it at the center of iconLayer, and make it\n    // small circle, so that the expansion of pulse layer is clipped off\n    let w = iconSize + insets.left + insets.right\n    let h = iconSize + insets.top + insets.bottom\n    let pulseSize = min(w, h)\n    visualLayer.bounds.size = CGSize(width: pulseSize, height: pulseSize)\n    visualLayer.frame.center = iconLayer.frame.center\n    visualLayer.cornerRadius = pulseSize / 2\n  }\n  \n  /// Size of the icon\n  ///\n  /// This property affects `intrinsicContentSize` and `sizeThatFits(_:)`\n  /// Use `iconEdgeInsets` to set margins.\n  open var iconSize: CGFloat = 18 {\n    didSet {\n      reloadImage()\n    }\n  }\n  \n  /// The *outset* margins for the rectangle around the button’s icon.\n  ///\n  /// You can specify a different value for each of the four margins (top, left, bottom, right)\n  /// This property affects `intrinsicContentSize` and `sizeThatFits(_:)` and position of the icon\n  /// within the rectangle.\n  ///\n  /// You can use `iconSize` and this property, or `titleEdgeInsets` and `contentEdgeInsets` to position\n  /// the icon however you want.\n  /// For negative values, behavior is undefined. Default is `8.0` for all four margins\n  open var iconEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8) {\n    didSet {\n      reloadImage()\n    }\n  }\n  \n  open override func apply(theme: Theme) {\n    super.apply(theme: theme)\n    \n    setIconColor(theme.secondary, for: .selected)\n    setIconColor(theme.onSurface.withAlphaComponent(0.38), for: .normal)\n    titleColor = theme.onSurface.withAlphaComponent(0.60)\n    \n    selectedPulseColor = theme.secondary\n    normalPulseColor = theme.onSurface\n    updatePulseColor()\n  }\n  \n  \n  /// This might be considered as a hackish way, but it's just manipulation\n  /// UIButton considers size of the `currentImage` to determine `intrinsicContentSize`\n  /// and `sizeThatFits(_:)`, and to position `titleLabel`.\n  /// So, we make use of this property (by setting transparent image) to make room for our icon\n  /// without making much effort (like playing with `titleEdgeInsets` and `contentEdgeInsets`)\n  /// Size of the image equals to `iconSize` plus corresponsing `iconEdgeInsets` values\n  private func reloadImage() {\n    let insets = iconEdgeInsets\n    let w = iconSize + insets.left + insets.right\n    let h = iconSize + insets.top + insets.bottom\n    UIGraphicsBeginImageContext(CGSize(width: w, height: h))\n    let image = UIGraphicsGetImageFromCurrentImageContext()\n    UIGraphicsEndImageContext()\n    self.image = image\n  }\n  \n  /// Pulse color for selected state.\n  open var selectedPulseColor = Color.white\n  \n  /// Pulse color for normal state.\n  open var normalPulseColor = Color.white\n}\n\nprivate extension BaseIconLayerButton {\n  func updatePulseColor() {\n    pulseColor = isSelected ? selectedPulseColor : normalPulseColor\n  }\n}\n\n// MARK: - BaseIconLayer\n\ninternal class BaseIconLayer: CALayer {\n  var selectedColor = Color.blue.base\n  var normalColor = Color.lightGray\n  var disabledColor = Color.gray\n  \n  \n  func prepareForFirstAnimation() {}\n  func firstAnimation() {}\n  \n  func prepareForSecondAnimation() {}\n  func secondAnimation() {}\n  \n  private(set) var isAnimating = false\n  private(set) var isSelected = false\n  var isEnabled = true {\n    didSet {\n      selectedColor = { selectedColor }()\n      normalColor = { normalColor }()\n      disabledColor = { disabledColor }()\n    }\n  }\n  \n  func prepare() {\n    normalColor = { normalColor }() // calling didSet\n    selectedColor = { selectedColor }() // calling didSet\n  }\n  \n  func setSelected(_ isSelected: Bool, animated: Bool) {\n    guard self.isSelected != isSelected, !isAnimating else { return }\n    self.isSelected = isSelected\n    \n    if animated {\n      animate()\n    } else {\n      Motion.disable {\n        prepareForFirstAnimation()\n        firstAnimation()\n        prepareForSecondAnimation()\n        secondAnimation()\n      }\n    }\n  }\n  \n  private func animate() {\n    guard !isAnimating else { return }\n    \n    prepareForFirstAnimation()\n    Motion.animate(duration: Constants.partialDuration, timingFunction: .easeInOut, animations: {\n      self.isAnimating = true\n      self.firstAnimation()\n    }, completion: {\n      Motion.disable {\n        self.prepareForSecondAnimation()\n      }\n      Motion.delay(Constants.partialDuration * Constants.delayFactor) {\n        Motion.animate(duration: Constants.partialDuration, timingFunction: .easeInOut, animations: {\n          self.secondAnimation()\n        }, completion: { self.isAnimating = false })\n      }\n    })\n  }\n  \n  var sideLength: CGFloat { return frame.height }\n  \n  struct Constants {\n    static let totalDuration = 0.5\n    static let delayFactor = 0.33\n    static let partialDuration = totalDuration / (1.0 + delayFactor + 1.0)\n  }\n}\n\n// MARK: - Helper extension\n\nprivate extension CGRect {\n  var center: CGPoint {\n    get {\n      return CGPoint(x: minX + width / 2 , y: minY + height / 2)\n    }\n    set {\n      origin = CGPoint(x: newValue.x - width / 2, y: newValue.y - height / 2)\n    }\n  }\n}\n\n\ninternal extension CALayer {\n  /// Animates the propery of CALayer from current value to the specified value\n  /// and does not reset to the initial value after the animation finishes\n  ///\n  /// - Parameters:\n  ///   - keyPath: Keypath to the animatable property of the layer\n  ///   - to: Final value of the property\n  ///   - dur: Duration of the animation in seconds. Defaults to 0, which results in taking the duration from enclosing CATransaction, or .25 seconds\n  func animate(_ keyPath: String, to: CGFloat, dur: TimeInterval = 0) {\n    let animation = CABasicAnimation(keyPath: keyPath)\n    animation.timingFunction = .easeIn\n    animation.fromValue = self.value(forKeyPath: keyPath) // from current value\n    animation.duration = dur\n    \n    setValue(to, forKeyPath: keyPath)\n    self.add(animation, forKey: nil)\n  }\n}\n\ninternal extension CATransform3D {\n  static var identity: CATransform3D {\n    return CATransform3DIdentity\n  }\n}\n\n"
  },
  {
    "path": "Sources/iOS/Button/Button.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\nopen class Button: UIButton, Pulseable, PulseableLayer, Themeable {\n  /**\n   A CAShapeLayer used to manage elements that would be affected by\n   the clipToBounds property of the backing layer. For example, this\n   allows the dropshadow effect on the backing layer, while clipping\n   the image to a desired shape within the visualLayer.\n   */\n  public let visualLayer = CAShapeLayer()\n  \n  /// A Pulse reference.\n  internal var pulse: Pulse!\n  \n  /// A reference to the pulse layer.\n  internal var pulseLayer: CALayer? {\n    return pulse.pulseLayer\n  }\n  \n  /// PulseAnimation value.\n  open var pulseAnimation: PulseAnimation {\n    get {\n      return pulse.animation\n    }\n    set(value) {\n      pulse.animation = value\n    }\n  }\n  \n  /// PulseAnimation color.\n  @IBInspectable\n  open var pulseColor: UIColor {\n    get {\n      return pulse.color\n    }\n    set(value) {\n      pulse.color = value\n    }\n  }\n  \n  /// Pulse opacity.\n  @IBInspectable\n  open var pulseOpacity: CGFloat {\n    get {\n      return pulse.opacity\n    }\n    set(value) {\n      pulse.opacity = value\n    }\n  }\n  \n  /// A property that accesses the backing layer's background\n  @IBInspectable\n  open override var backgroundColor: UIColor? {\n    didSet {\n      layer.backgroundColor = backgroundColor?.cgColor\n    }\n  }\n  \n  /// A preset property for updated contentEdgeInsets.\n  open var contentEdgeInsetsPreset = EdgeInsetsPreset.none {\n    didSet {\n      contentEdgeInsets = EdgeInsetsPresetToValue(preset: contentEdgeInsetsPreset)\n    }\n  }\n  \n  /// Sets the normal and highlighted image for the button.\n  @IBInspectable\n  open var image: UIImage? {\n    didSet {\n      setImage(image, for: .normal)\n      setImage(image, for: .selected)\n      setImage(image, for: .highlighted)\n      setImage(image, for: .disabled)\n      \n      if #available(iOS 9, *) {\n        setImage(image, for: .application)\n        setImage(image, for: .focused)\n        setImage(image, for: .reserved)\n      }\n    }\n  }\n  \n  /// Sets the normal and highlighted title for the button.\n  @IBInspectable\n  open var title: String? {\n    didSet {\n      setTitle(title, for: .normal)\n      setTitle(title, for: .selected)\n      setTitle(title, for: .highlighted)\n      setTitle(title, for: .disabled)\n      \n      if #available(iOS 9, *) {\n        setTitle(title, for: .application)\n        setTitle(title, for: .focused)\n        setTitle(title, for: .reserved)\n      }\n      \n      guard nil != title else {\n        return\n      }\n      \n      guard nil == titleColor else {\n        return\n      }\n      \n      titleColor = Color.blue.base\n    }\n  }\n  \n  /// Sets the normal and highlighted titleColor for the button.\n  @IBInspectable\n  open var titleColor: UIColor? {\n    didSet {\n      setTitleColor(titleColor, for: .normal)\n      setTitleColor(titleColor, for: .highlighted)\n      setTitleColor(titleColor, for: .disabled)\n      \n      if nil == selectedTitleColor {\n        setTitleColor(titleColor, for: .selected)\n      }\n      \n      if #available(iOS 9, *) {\n        setTitleColor(titleColor, for: .application)\n        setTitleColor(titleColor, for: .focused)\n        setTitleColor(titleColor, for: .reserved)\n      }\n    }\n  }\n  \n  /// Sets the selected titleColor for the button.\n  @IBInspectable\n  open var selectedTitleColor: UIColor? {\n    didSet {\n      setTitleColor(selectedTitleColor, for: .selected)\n    }\n  }\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n    prepare()\n  }\n  \n  /**\n   An initializer that initializes the object with a CGRect object.\n   If AutoLayout is used, it is better to initilize the instance\n   using the init() initializer.\n   - Parameter frame: A CGRect instance.\n   */\n  public override init(frame: CGRect) {\n    super.init(frame: frame)\n    /// Set these here to avoid overriding storyboard values\n    tintColor = Color.blue.base\n    titleLabel?.font = Theme.font.regular(with: fontSize)\n    prepare()\n  }\n  \n  /**\n   A convenience initializer that acceps an image and tint\n   - Parameter image: A UIImage.\n   - Parameter tintColor: A UIColor.\n   */\n  public init(image: UIImage?, tintColor: UIColor? = nil) {\n    super.init(frame: .zero)\n    prepare()\n    prepare(with: image, tintColor: tintColor)\n  }\n  \n  /**\n   A convenience initializer that acceps a title and title\n   - Parameter title: A String.\n   - Parameter titleColor: A UIColor.\n   */\n  public init(title: String?, titleColor: UIColor? = nil) {\n    super.init(frame: .zero)\n    prepare()\n    prepare(with: title, titleColor: titleColor)\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    layoutShape()\n    layoutVisualLayer()\n    layoutShadowPath()\n  }\n  \n  /**\n   Triggers the pulse animation.\n   - Parameter point: A Optional point to pulse from, otherwise pulses\n   from the center.\n   */\n  open func pulse(point: CGPoint? = nil) {\n    pulse.expand(point: point ?? center)\n    Motion.delay(0.35) { [weak self] in\n      self?.pulse.contract()\n    }\n  }\n  \n  /**\n   A delegation method that is executed when the view has began a\n   touch event.\n   - Parameter touches: A set of UITouch objects.\n   - Parameter event: A UIEvent object.\n   */\n  open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {\n    super.touchesBegan(touches, with: event)\n    pulse.expand(point: layer.convert(touches.first!.location(in: self), from: layer))\n  }\n  \n  /**\n   A delegation method that is executed when the view touch event has\n   ended.\n   - Parameter touches: A set of UITouch objects.\n   - Parameter event: A UIEvent object.\n   */\n  open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {\n    super.touchesEnded(touches, with: event)\n    pulse.contract()\n  }\n  \n  /**\n   A delegation method that is executed when the view touch event has\n   been cancelled.\n   - Parameter touches: A set of UITouch objects.\n   - Parameter event: A UIEvent object.\n   */\n  open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {\n    super.touchesCancelled(touches, with: event)\n    pulse.contract()\n  }\n  \n  open func bringImageViewToFront() {\n    guard let v = imageView else {\n      return\n    }\n    \n    bringSubviewToFront(v)\n  }\n  \n  /**\n   Prepares the view instance when intialized. When subclassing,\n   it is recommended to override the prepare method\n   to initialize property values and other setup operations.\n   The super.prepare method should always be called immediately\n   when subclassing.\n   */\n  open func prepare() {\n    contentScaleFactor = Screen.scale\n    prepareVisualLayer()\n    preparePulse()\n    applyCurrentTheme()\n  }\n  \n  /**\n   Applies the given theme.\n   - Parameter theme: A Theme.\n   */\n  open func apply(theme: Theme) { }\n}\n\nextension Button {\n  /// Prepares the visualLayer property.\n  fileprivate func prepareVisualLayer() {\n    visualLayer.zPosition = 0\n    visualLayer.masksToBounds = true\n    layer.addSublayer(visualLayer)\n  }\n  \n  /// Prepares the pulse motion.\n  fileprivate func preparePulse() {\n    pulse = Pulse(pulseView: self, pulseLayer: visualLayer)\n  }\n  \n  /**\n   Prepares the Button with an image and tint\n   - Parameter image: A UIImage.\n   - Parameter tintColor: A UI\n   */\n  fileprivate func prepare(with image: UIImage?, tintColor: UIColor?) {\n    self.image = image\n    self.tintColor = tintColor ?? self.tintColor\n  }\n  \n  /**\n   Prepares the Button with a title and title\n   - Parameter title: A String.\n   - Parameter titleColor: A UI\n   */\n  fileprivate func prepare(with title: String?, titleColor: UIColor?) {\n    self.title = title\n    self.titleColor = titleColor ?? self.titleColor\n  }\n}\n\nextension Button {\n  /// Manages the layout for the visualLayer property.\n  fileprivate func layoutVisualLayer() {\n    visualLayer.frame = bounds\n    visualLayer.cornerRadius = layer.cornerRadius\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Button/CheckButton.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class CheckButton: BaseIconLayerButton {\n  class override var iconLayer: BaseIconLayer { return CheckBoxLayer() }\n  \n  /// Color of the checkmark (✓)\n  open var checkmarkColor: UIColor {\n    get {\n      return (iconLayer as! CheckBoxLayer).checkmarkColor\n    }\n    set {\n      (iconLayer as! CheckBoxLayer).checkmarkColor = newValue\n    }\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    addTarget(self, action: #selector(didTap), for: .touchUpInside)\n  }\n  \n  @objc\n  private func didTap() {\n    guard !isAnimating else { return }\n    setSelected(!isSelected, animated: true)\n  }\n  \n  open override func apply(theme: Theme) {\n    super.apply(theme: theme)\n    \n    checkmarkColor = theme.onSecondary\n  }\n}\n\ninternal class CheckBoxLayer: BaseIconLayer {\n  var checkmarkColor: UIColor = .white {\n    didSet {\n      checkMarkLeftLayer.strokeColor = checkmarkColor.cgColor\n      checkMarkRightLayer.strokeColor = checkmarkColor.cgColor\n    }\n  }\n  let borderLayer = CALayer()\n  let checkMarkLeftLayer = CAShapeLayer()\n  let checkMarkRightLayer = CAShapeLayer()\n  let checkMarkLayer = CALayer()\n  \n  override var selectedColor: UIColor {\n    didSet {\n      guard isSelected, isEnabled else { return }\n      borderLayer.borderColor = selectedColor.cgColor\n      borderLayer.backgroundColor = selectedColor.cgColor\n    }\n  }\n  \n  override var normalColor: UIColor {\n    didSet {\n      guard !isSelected, isEnabled else { return }\n      borderLayer.borderColor = normalColor.cgColor\n    }\n  }\n  \n  override var disabledColor: UIColor {\n    didSet {\n      guard !isEnabled else { return }\n      borderLayer.borderColor =  disabledColor.cgColor\n      if isSelected { borderLayer.backgroundColor = disabledColor.cgColor }\n    }\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    addSublayer(borderLayer)\n    addSublayer(checkMarkLayer)\n    checkMarkLayer.addSublayer(checkMarkLeftLayer)\n    checkMarkLayer.addSublayer(checkMarkRightLayer)\n    checkMarkLeftLayer.lineCap = CAShapeLayerLineCap.square\n    checkMarkRightLayer.lineCap = CAShapeLayerLineCap.square\n    checkMarkLeftLayer.strokeEnd = 0\n    checkMarkRightLayer.strokeEnd = 0\n    checkmarkColor = { checkmarkColor }() // calling didSet\n  }\n  \n  override func prepareForFirstAnimation() {\n    borderLayer.borderColor = (isEnabled ? (isSelected ? selectedColor : normalColor) : disabledColor).cgColor\n    if isSelected {\n      borderLayer.borderWidth = borderLayerNormalBorderWidth\n    } else {\n      borderLayer.borderWidth = 0\n      borderLayer.backgroundColor = (isEnabled ? normalColor : disabledColor).cgColor\n      checkMarkLeftLayer.strokeEnd = 1\n      checkMarkRightLayer.strokeEnd = 1\n    }\n    checkMarkLayer.transform = .identity\n  }\n  \n  override func firstAnimation() {\n    borderLayer.transform = borderLayerScaleToShrink\n    checkMarkLayer.transform = borderLayerScaleToShrink\n    if isSelected {\n      borderLayer.animate(#keyPath(CALayer.borderWidth), to: borderLayerFullBorderWidth)\n    } else {\n      checkMarkLeftLayer.animate(#keyPath(CAShapeLayer.strokeEnd), to: 0)\n      checkMarkRightLayer.animate(#keyPath(CAShapeLayer.strokeEnd), to: 0)\n      \n      checkMarkLayer.transform = CATransform3DMakeTranslation(sideLength / 2 - checkMarkStartPoint.x, -(checkMarkStartPoint.y - sideLength / 2), 0)\n    }\n  }\n  \n  override func prepareForSecondAnimation() {\n    borderLayer.backgroundColor = (isSelected ? (isEnabled ? selectedColor : disabledColor) : .clear).cgColor\n    \n    if isSelected {\n      borderLayer.borderWidth = borderLayerNormalBorderWidth\n      checkMarkLeftLayer.strokeEnd = 0.0001\n      checkMarkRightLayer.strokeEnd = 0.0001\n      \n      checkMarkLayer.opacity = 0\n      checkMarkLayer.animate(#keyPath(CALayer.opacity), to: 1, dur: Constants.totalDuration * 0.1)\n    } else {\n      borderLayer.borderWidth = borderLayerCenterDotBorderWidth\n    }\n  }\n  \n  override func secondAnimation() {\n    borderLayer.transform = .identity\n    checkMarkLayer.transform = .identity\n    if isSelected {\n      checkMarkLeftLayer.animate(#keyPath(CAShapeLayer.strokeEnd), to: 1)\n      checkMarkRightLayer.animate(#keyPath(CAShapeLayer.strokeEnd), to: 1)\n    } else {\n      borderLayer.animate(#keyPath(CALayer.borderWidth), to: borderLayerNormalBorderWidth)\n    }\n  }\n  \n  override func layoutSublayers() {\n    super.layoutSublayers()\n    guard !isAnimating else { return }\n    \n    let s = CGSize(width: sideLength, height: sideLength)\n    borderLayer.frame.size = s\n    checkMarkLayer.frame.size = s\n    checkMarkLeftLayer.frame.size = s\n    checkMarkRightLayer.frame.size = s\n    \n    checkMarkLeftLayer.path = checkMarkPathLeft.cgPath\n    checkMarkRightLayer.path = checkMarkPathRigth.cgPath\n    checkMarkLeftLayer.lineWidth = lineWidth\n    checkMarkRightLayer.lineWidth = lineWidth\n    \n    borderLayer.borderWidth = borderLayerNormalBorderWidth\n    borderLayer.cornerRadius = borderLayerCornerRadius\n  }\n}\n\nprivate extension CheckBoxLayer {\n  var borderLayerFullBorderWidth: CGFloat { return sideLength / 2 * 1.1 } //without multipling 1.1 a weird plus sign (+) appears sometimes.\n  var borderLayerCenterDotBorderWidth: CGFloat { return sideLength / 2 * 0.87 }\n  var borderLayerNormalBorderWidth: CGFloat { return sideLength * 0.1 }\n  var borderLayerCornerRadius: CGFloat { return sideLength * 0.1 }\n  var borderLayerScalePercentageToShrink: CGFloat { return 0.9 }\n  var borderLayerScaleToShrink: CATransform3D {\n    return CATransform3DMakeScale(borderLayerScalePercentageToShrink, borderLayerScalePercentageToShrink, 1)\n  }\n  \n  \n  var checkMarkStartPoint: CGPoint {\n    return CGPoint(x: sideLength * 14 / 36, y: sideLength * 25 / 36)\n  }\n  \n  var checkMarkRightEndPoint: CGPoint {\n    return CGPoint(x: sideLength - (sideLength * 6 / 36), y: sideLength * 9 / 36)\n  }\n  \n  var checkMarkLeftEndPoint: CGPoint {\n    return CGPoint(x: sideLength * 6 / 36, y: sideLength * 18 / 36)\n  }\n  \n  var checkMarkPathRigth: UIBezierPath {\n    let path = UIBezierPath()\n    path.move(to: checkMarkStartPoint)\n    path.addLine(to: checkMarkRightEndPoint)\n    return path\n  }\n  \n  var checkMarkPathLeft: UIBezierPath {\n    let path = UIBezierPath()\n    path.move(to: checkMarkStartPoint)\n    path.addLine(to: checkMarkLeftEndPoint)\n    return path\n  }\n  \n  var lineWidth: CGFloat { return sideLength * 0.1 }\n}\n"
  },
  {
    "path": "Sources/iOS/Button/FABButton.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class FABButton: Button {\n  open override func prepare() {\n    super.prepare()\n    depthPreset = .depth1\n    shapePreset = .circle\n    pulseAnimation = .centerWithBacking\n  }\n  \n  open override func apply(theme: Theme) {\n    super.apply(theme: theme)\n    \n    backgroundColor = theme.secondary\n    titleColor = theme.onSecondary\n    tintColor = theme.onSecondary\n    pulseColor = theme.onSecondary\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Button/FlatButton.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class FlatButton: Button {\n  open override func prepare() {\n    super.prepare()\n    cornerRadiusPreset = .cornerRadius1\n  }\n  \n  open override func apply(theme: Theme) {\n    super.apply(theme: theme)\n    \n    backgroundColor = .clear\n    titleColor = theme.secondary\n    tintColor = theme.secondary\n    pulseColor = theme.secondary\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Button/IconButton.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\npublic enum IconButtonThemingStyle {\n  /// Theming when background content is in background color.\n  case onBackground\n  \n  /// Theming when background content is in primary color.\n  case onPrimary\n}\n\nopen class IconButton: Button {\n  /// A reference to IconButtonThemingStyle.\n  open var themingStyle = IconButtonThemingStyle.onBackground\n  \n  open override func prepare() {\n    super.prepare()\n    pulseAnimation = .center\n  }\n  \n  open override func apply(theme: Theme) {\n    super.apply(theme: theme)\n    \n    switch themingStyle {\n    case .onBackground:\n      tintColor = theme.secondary\n      pulseColor = theme.secondary\n    case .onPrimary:\n      tintColor = theme.onPrimary\n      pulseColor = theme.onPrimary\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Button/RadioButton.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class RadioButton: BaseIconLayerButton {\n  class override var iconLayer: BaseIconLayer { return RadioBoxLayer() }\n  \n  open override func prepare() {\n    super.prepare()\n    \n    addTarget(self, action: #selector(didTap), for: .touchUpInside)\n  }\n  \n  @objc\n  private func didTap() {\n    setSelected(true, animated: true)\n  }\n}\n\ninternal class RadioBoxLayer: BaseIconLayer {\n  private let centerDot = CALayer()\n  private let outerCircle = CALayer()\n  \n  override var selectedColor: UIColor {\n    didSet {\n      guard isSelected, isEnabled else { return }\n      outerCircle.borderColor = selectedColor.cgColor\n      centerDot.backgroundColor = selectedColor.cgColor\n    }\n  }\n  \n  override var normalColor: UIColor {\n    didSet {\n      guard !isSelected, isEnabled else { return }\n      outerCircle.borderColor = normalColor.cgColor\n    }\n  }\n  \n  override var disabledColor: UIColor {\n    didSet {\n      guard !isEnabled else { return }\n      outerCircle.borderColor = disabledColor.cgColor\n      if isSelected { centerDot.backgroundColor = disabledColor.cgColor }\n    }\n  }\n  \n  override func prepare() {\n    super.prepare()\n    addSublayer(centerDot)\n    addSublayer(outerCircle)\n  }\n  \n  override func prepareForFirstAnimation() {\n    outerCircle.borderColor = (isEnabled ? (isSelected ? selectedColor : normalColor) : disabledColor).cgColor\n    if !isSelected {\n      centerDot.backgroundColor = (isEnabled ? normalColor : disabledColor).cgColor\n    }\n    outerCircle.borderWidth = outerCircleBorderWidth\n  }\n  \n  override func firstAnimation() {\n    outerCircle.transform = outerCircleScaleToShrink\n    let to = isSelected ? sideLength / 2.0 : outerCircleBorderWidth * percentageOfOuterCircleWidthToStart\n    outerCircle.animate(#keyPath(CALayer.borderWidth), to: to)\n    if !isSelected {\n      centerDot.transform = centerDotScaleForMeeting\n    }\n  }\n  \n  override func prepareForSecondAnimation() {\n    centerDot.transform = isSelected ? centerDotScaleForMeeting : .identity\n    centerDot.backgroundColor = (isSelected ? (isEnabled ? selectedColor : disabledColor) : .clear).cgColor\n    outerCircle.borderWidth = isSelected ? outerCircleBorderWidth * percentageOfOuterCircleWidthToStart : outerCircleFullBorderWidth\n  }\n  \n  override func secondAnimation() {\n    outerCircle.transform = .identity\n    outerCircle.animate(#keyPath(CALayer.borderWidth), to: outerCircleBorderWidth)\n    if isSelected {\n      centerDot.transform = .identity\n    }\n  }\n  \n  override func layoutSublayers() {\n    super.layoutSublayers()\n    guard !isAnimating else { return }\n    \n    centerDot.frame = CGRect(x: centerDotDiameter / 2.0, y: centerDotDiameter / 2.0, width: centerDotDiameter, height: centerDotDiameter)\n    outerCircle.frame.size = CGSize(width: sideLength, height: sideLength)\n    centerDot.cornerRadius = centerDot.bounds.width / 2\n    outerCircle.cornerRadius = sideLength / 2\n    outerCircle.borderWidth = outerCircleBorderWidth\n  }\n}\n\nprivate extension RadioBoxLayer {\n  var percentageOfOuterCircleSizeToShrinkTo: CGFloat { return 0.9 }\n  var percentageOfOuterCircleWidthToStart: CGFloat { return 1 }\n  \n  var outerCircleScaleToShrink: CATransform3D {\n    let s = percentageOfOuterCircleSizeToShrinkTo\n    return CATransform3DMakeScale(s, s, 1)\n  }\n  var centerDotScaleForMeeting: CATransform3D {\n    let s = ((sideLength - 2 * percentageOfOuterCircleWidthToStart * outerCircleBorderWidth) * percentageOfOuterCircleSizeToShrinkTo) / centerDotDiameter\n    return CATransform3DMakeScale(s, s, 1)\n  }\n  \n  var outerCircleFullBorderWidth: CGFloat {\n    return (self.sideLength / 2.0) * 1.1 //without multipling 1.1 a weird plus sign (+) appears sometimes.\n  }\n  \n  var centerDotDiameter: CGFloat { return sideLength / 2.0 }\n  var outerCircleBorderWidth: CGFloat { return sideLength * 0.11 }\n}\n"
  },
  {
    "path": "Sources/iOS/Button/RaisedButton.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class RaisedButton: Button {\n  open override func prepare() {\n    super.prepare()\n    depthPreset = .depth1\n    cornerRadiusPreset = .cornerRadius1\n  }\n  \n  open override func apply(theme: Theme) {\n    super.apply(theme: theme)\n    \n    backgroundColor = theme.secondary\n    titleColor = theme.onSecondary\n    pulseColor = theme.onSecondary\n    tintColor = theme.onSecondary\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/ButtonGroup/BaseButtonGroup.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class BaseButtonGroup<T: Button>: View {\n  \n  /// Holds reference to buttons within the group.\n  open var buttons: [T] = [] {\n    didSet {\n      oldValue.forEach {\n        $0.removeFromSuperview()\n        $0.removeTarget(self, action: #selector(didTap(_:)), for: .touchUpInside)\n      }\n      prepareButtons()\n      grid.views = buttons\n      grid.axis.rows = buttons.count\n    }\n  }\n  \n  /// Initializes group with the provided buttons.\n  ///\n  /// - Parameter buttons: Array of buttons.\n  public convenience init(buttons: [T]) {\n    self.init(frame: .zero)\n    defer { self.buttons = buttons } // defer allows didSet to be called\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    grid.axis.direction = .vertical\n    grid.axis.columns = 1\n  }\n  \n  \n  open override var intrinsicContentSize: CGSize { return sizeThatFits(bounds.size) }\n  \n  open override func sizeThatFits(_ size: CGSize) -> CGSize {\n    let size = CGSize(width: size.width == 0 ? .greatestFiniteMagnitude : size.width, height: size.height == 0 ? .greatestFiniteMagnitude : size.height)\n    let availableW = size.width - grid.contentEdgeInsets.left - grid.contentEdgeInsets.right - grid.layoutEdgeInsets.left - grid.layoutEdgeInsets.right\n    let maxW = buttons.reduce(0) { max($0, $1.sizeThatFits(.init(width: availableW, height: .greatestFiniteMagnitude)).width) }\n    \n    let h = buttons.reduce(0) { $0 + $1.sizeThatFits(.init(width: maxW, height: .greatestFiniteMagnitude)).height }\n      + grid.contentEdgeInsets.top + grid.contentEdgeInsets.bottom\n      + grid.layoutEdgeInsets.top + grid.layoutEdgeInsets.bottom\n      + CGFloat(buttons.count - 1) * grid.interimSpace\n    \n    return CGSize(width: maxW + grid.contentEdgeInsets.left + grid.contentEdgeInsets.right + grid.layoutEdgeInsets.left + grid.layoutEdgeInsets.right, height: min(h, size.height))\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    grid.reload()\n  }\n  \n  open func didTap(button: T, at index: Int) { }\n  \n  @objc\n  private func didTap(_ sender: Button) {\n    guard let sender = sender as? T,\n      let index = buttons.firstIndex(of: sender)\n      else { return }\n    \n    didTap(button: sender, at: index)\n  }\n}\n\nprivate extension BaseButtonGroup {\n  func prepareButtons() {\n    buttons.forEach {\n      addSubview($0)\n      $0.removeTarget(nil, action: nil, for: .allEvents)\n      $0.addTarget(self, action: #selector(didTap(_:)), for: .touchUpInside)\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/ButtonGroup/CheckButtonGroup.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n/// Lays out provided check buttons within itself.\n///\n/// Unlike RadioButtonGroup, checking one check button that belongs to a check group *does not* unchecks any previously checked\n/// check button within the same group. Intially, all of the check buttons are unchecked.\n///\n/// The buttons are laid out by `Grid` system, so that changing properites of grid instance\n/// (e.g interimSpace) are reflected.\nopen class CheckButtonGroup: BaseButtonGroup<CheckButton> {\n  \n  /// Initializes CheckButtonGroup with an array of check buttons each having\n  /// title equal to corresponding string in the `titles` parameter.\n  ///\n  /// - Parameter titles: An array of title strings\n  public convenience init(titles: [String]) {\n    let buttons = titles.map { CheckButton(title: $0) }\n    self.init(buttons: buttons)\n  }\n  \n  /// Returns all selected check buttons within the group\n  /// or empty array if none is seleceted.\n  open var selecetedButtons: [CheckButton] {\n    return buttons.filter { $0.isSelected }\n  }\n  \n  /// Returns indexes of all selected check buttons within the group\n  /// or empty array if none is seleceted.\n  open var selectedIndices: [Int] {\n    return selecetedButtons.map { buttons.firstIndex(of: $0)! }\n  }\n  \n  open override func didTap(button: CheckButton, at index: Int) {\n    button.setSelected(!button.isSelected, animated: true)\n  }\n}\n\n"
  },
  {
    "path": "Sources/iOS/ButtonGroup/RadioButtonGroup.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n/// Lays out provided radio buttons within itself.\n///\n/// Checking one radio button that belongs to a radio group unchecks any previously checked\n/// radio button within the same group. Intially, all of the radio buttons are unchecked.\n///\n/// The buttons are laid out by `Grid` system, so that changing properites of grid instance\n/// (e.g interimSpace) are reflected.\nopen class RadioButtonGroup: BaseButtonGroup<RadioButton> {\n  \n  /// Initializes RadioButtonGroup with an array of radio buttons each having\n  /// title equal to corresponding string in the `titles` parameter.\n  ///\n  /// - Parameter titles: An array of title strings.\n  public convenience init(titles: [String]) {\n    let buttons = titles.map { RadioButton(title: $0) }\n    self.init(buttons: buttons)\n  }\n  \n  /// Returns selected radio button within the group.\n  /// If none is selected (e.g in initial state), nil is returned.\n  open var selectedButton: RadioButton? {\n    return buttons.first { $0.isSelected }\n  }\n  \n  /// Returns index of selected radio button within the group.\n  /// If none is selected (e.g in initial state), -1 is returned.\n  open var selectedIndex: Int {\n    guard let b = selectedButton else { return -1 }\n    return buttons.firstIndex(of: b)!\n  }\n  \n  open override func didTap(button: RadioButton, at index: Int) {\n    let isAnimating = buttons.reduce(false) { $0 || $1.isAnimating }\n    guard !isAnimating else { return }\n    \n    buttons.forEach { $0.setSelected($0 == button, animated: true) }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Card/Card.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class Card: PulseView {\n  /// A container view for subviews.\n  public let container = UIView()\n  \n  @IBInspectable\n  open override var cornerRadiusPreset: CornerRadiusPreset {\n    didSet {\n      container.cornerRadiusPreset = cornerRadiusPreset\n    }\n  }\n  \n  @IBInspectable\n  open var cornerRadius: CGFloat {\n    get {\n      return container.layer.cornerRadius\n    }\n    set(value) {\n      container.layer.cornerRadius = value\n    }\n  }\n  \n  open override var shapePreset: ShapePreset {\n    didSet {\n      container.shapePreset = shapePreset\n    }\n  }\n  \n  @IBInspectable\n  open override var backgroundColor: UIColor? {\n    didSet {\n      container.backgroundColor = backgroundColor\n    }\n  }\n  \n  /// A reference to the toolbar.\n  @IBInspectable\n  open var toolbar: Toolbar? {\n    didSet {\n      oldValue?.removeFromSuperview()\n      \n      if let v = toolbar {\n        container.addSubview(v)\n      }\n      \n      layoutSubviews()\n    }\n  }\n  \n  /// A preset wrapper around toolbarEdgeInsets.\n  open var toolbarEdgeInsetsPreset = EdgeInsetsPreset.none {\n    didSet {\n      toolbarEdgeInsets = EdgeInsetsPresetToValue(preset: toolbarEdgeInsetsPreset)\n    }\n  }\n  \n  /// A reference to toolbarEdgeInsets.\n  @IBInspectable\n  open var toolbarEdgeInsets = EdgeInsets.zero {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// A reference to the contentView.\n  @IBInspectable\n  open var contentView: UIView? {\n    didSet {\n      oldValue?.removeFromSuperview()\n      \n      if let v = contentView {\n        v.clipsToBounds = true\n        container.addSubview(v)\n      }\n      \n      layoutSubviews()\n    }\n  }\n  \n  /// A preset wrapper around contentViewEdgeInsets.\n  open var contentViewEdgeInsetsPreset = EdgeInsetsPreset.none {\n    didSet {\n      contentViewEdgeInsets = EdgeInsetsPresetToValue(preset: contentViewEdgeInsetsPreset)\n    }\n  }\n  \n  /// A reference to contentViewEdgeInsets.\n  @IBInspectable\n  open var contentViewEdgeInsets = EdgeInsets.zero {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// A reference to the bottomBar.\n  @IBInspectable\n  open var bottomBar: Bar? {\n    didSet {\n      oldValue?.removeFromSuperview()\n      \n      if let v = bottomBar {\n        container.addSubview(v)\n      }\n      \n      layoutSubviews()\n    }\n  }\n  \n  /// A preset wrapper around bottomBarEdgeInsets.\n  open var bottomBarEdgeInsetsPreset = EdgeInsetsPreset.none {\n    didSet {\n      bottomBarEdgeInsets = EdgeInsetsPresetToValue(preset: bottomBarEdgeInsetsPreset)\n    }\n  }\n  \n  /// A reference to bottomBarEdgeInsets.\n  @IBInspectable\n  open var bottomBarEdgeInsets = EdgeInsets.zero {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /**\n   An initializer that accepts a NSCoder.\n   - Parameter coder aDecoder: A NSCoder.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n  }\n  \n  /**\n   An initializer that accepts a CGRect.\n   - Parameter frame: A CGRect.\n   */\n  public override init(frame: CGRect) {\n    super.init(frame: frame)\n  }\n  \n  /**\n   A convenience initiazlier.\n   - Parameter toolbar: An optional Toolbar.\n   - Parameter contentView: An optional UIView.\n   - Parameter bottomBar: An optional Bar.\n   */\n  public convenience init?(toolbar: Toolbar?, contentView: UIView?, bottomBar: Bar?) {\n    self.init(frame: .zero)\n    prepareProperties(toolbar: toolbar, contentView: contentView, bottomBar: bottomBar)\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    container.frame.size.width = bounds.width\n    reload()\n  }\n  \n  /// Reloads the layout.\n  open func reload() {\n    var h: CGFloat = 0\n    \n    if let v = toolbar {\n      h = prepare(view: v, with: toolbarEdgeInsets, from: h)\n    }\n    \n    if let v = contentView {\n      h = prepare(view: v, with: contentViewEdgeInsets, from: h)\n    }\n    \n    if let v = bottomBar {\n      h = prepare(view: v, with: bottomBarEdgeInsets, from: h)\n    }\n    \n    container.frame.size.height = h\n    bounds.size.height = h\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    pulseAnimation = .none\n    cornerRadiusPreset = .cornerRadius1\n    \n    prepareContainer()\n  }\n  \n  /**\n   Prepare the view size from a given top position.\n   - Parameter view: A UIView.\n   - Parameter edge insets: An EdgeInsets.\n   - Parameter from top: A CGFloat.\n   - Returns: A CGFloat.\n   */\n  @discardableResult\n  open func prepare(view: UIView, with insets: EdgeInsets, from top: CGFloat) -> CGFloat {\n    let y = insets.top + top\n    \n    view.frame.origin.y = y\n    view.frame.origin.x = insets.left\n    \n    let w = container.bounds.width - insets.left - insets.right\n    var h = view.bounds.height\n    \n    if 0 == h || nil != view as? UILabel {\n      (view as? UILabel)?.sizeToFit()\n      h = view.sizeThatFits(CGSize(width: w, height: .greatestFiniteMagnitude)).height\n    }\n    \n    view.frame.size.width = w\n    view.frame.size.height = h\n    \n    return y + h + insets.bottom\n  }\n  \n  /**\n   A preparation method that sets the base UI elements.\n   - Parameter toolbar: An optional Toolbar.\n   - Parameter contentView: An optional UIView.\n   - Parameter bottomBar: An optional Bar.\n   */\n  internal func prepareProperties(toolbar: Toolbar?, contentView: UIView?, bottomBar: Bar?) {\n    self.toolbar = toolbar\n    self.contentView = contentView\n    self.bottomBar = bottomBar\n  }\n}\n\nextension Card {\n  /// Prepares the container.\n  fileprivate func prepareContainer() {\n    container.clipsToBounds = true\n    addSubview(container)\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Card/ImageCard.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class ImageCard: Card {\n  /**\n   A Display value to indicate whether or not to\n   display the imageView to the full view\n   bounds.\n   */\n  open var displayStyle = DisplayStyle.partial {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// A preset wrapper around imageViewEdgeInsets.\n  open var imageViewEdgeInsetsPreset = EdgeInsetsPreset.none {\n    didSet {\n      imageViewEdgeInsets = EdgeInsetsPresetToValue(preset: imageViewEdgeInsetsPreset)\n    }\n  }\n  \n  /// A reference to imageViewEdgeInsets.\n  @IBInspectable\n  open var imageViewEdgeInsets = EdgeInsets.zero {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// A reference to the imageView.\n  @IBInspectable\n  open var imageView: UIImageView? {\n    didSet {\n      oldValue?.removeFromSuperview()\n      \n      if let v = imageView {\n        container.addSubview(v)\n      }\n      \n      layoutSubviews()\n    }\n  }\n  \n  /// An ImageCardToolbarAlignment value.\n  open var toolbarAlignment = ToolbarAlignment.bottom {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// Reloads the view.\n  open override func reload() {\n    var h: CGFloat = 0\n    \n    if let v = imageView {\n      h = prepare(view: v, with: imageViewEdgeInsets, from: h)\n      container.sendSubviewToBack(v)\n    }\n    \n    if let v = toolbar {\n      prepare(view: v, with: toolbarEdgeInsets, from: h)\n      v.frame.origin.y = .top == toolbarAlignment ? toolbarEdgeInsets.top : h - v.bounds.height - toolbarEdgeInsets.bottom\n      container.bringSubviewToFront(v)\n    }\n    \n    if let v = contentView {\n      h = prepare(view: v, with: contentViewEdgeInsets, from: h)\n    }\n    \n    if let v = bottomBar {\n      h = prepare(view: v, with: bottomBarEdgeInsets, from: h)\n    }\n    \n    container.frame.size.height = h\n    bounds.size.height = h\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Card/PresenterCard.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class PresenterCard: Card {\n  /// A preset wrapper around presenterViewEdgeInsets.\n  open var presenterViewEdgeInsetsPreset = EdgeInsetsPreset.none {\n    didSet {\n      presenterViewEdgeInsets = EdgeInsetsPresetToValue(preset: presenterViewEdgeInsetsPreset)\n    }\n  }\n  \n  /// A reference to presenterViewEdgeInsets.\n  @IBInspectable\n  open var presenterViewEdgeInsets = EdgeInsets.zero {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// A reference to the presenterView.\n  @IBInspectable\n  open var presenterView: UIView? {\n    didSet {\n      oldValue?.removeFromSuperview()\n      \n      if let v = presenterView {\n        v.clipsToBounds = true\n        container.addSubview(v)\n      }\n      \n      layoutSubviews()\n    }\n  }\n  \n  open override func reload() {\n    var h: CGFloat = 0\n    \n    if let v = toolbar {\n      h = prepare(view: v, with: toolbarEdgeInsets, from: h)\n    }\n    \n    if let v = presenterView {\n      h = prepare(view: v, with: presenterViewEdgeInsets, from: h)\n    }\n    \n    if let v = contentView {\n      h = prepare(view: v, with: contentViewEdgeInsets, from: h)\n    }\n    \n    if let v = bottomBar {\n      h = prepare(view: v, with: bottomBarEdgeInsets, from: h)\n    }\n    \n    container.frame.size.height = h\n    bounds.size.height = h\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Chip/ChipBar.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\n@objc(ChipItemStyle)\npublic enum ChipItemStyle: Int {\n  case pill\n}\n\nopen class ChipItem: FlatButton {\n  /// Configures the visual display of the chip.\n  var chipItemStyle: ChipItemStyle {\n    get {\n      return associatedInstance.chipItemStyle\n    }\n    set(value) {\n      associatedInstance.chipItemStyle = value\n      layoutSubviews()\n    }\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    layoutChipItemStyle()\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    pulseAnimation = .none\n  }\n}\n\nfileprivate extension ChipItem {\n  /// Lays out the chipItem based on its style.\n  func layoutChipItemStyle() {\n    if .pill == chipItemStyle {\n      layer.cornerRadius = bounds.height / 2\n    }\n  }\n}\n\nfileprivate struct AssociatedInstance {\n  /// A ChipItemStyle value.\n  var chipItemStyle: ChipItemStyle\n}\n\n/// A memory reference to the ChipItemStyle instance for ChipItem extensions.\nfileprivate var ChipKey: UInt8 = 0\n\nfileprivate extension ChipItem {\n  /// AssociatedInstance reference.\n  var associatedInstance: AssociatedInstance {\n    get {\n      return AssociatedObject.get(base: self, key: &ChipKey) {\n        return AssociatedInstance(chipItemStyle: .pill)\n      }\n    }\n    set(value) {\n      AssociatedObject.set(base: self, key: &ChipKey, value: value)\n    }\n  }\n}\n\n@objc(ChipBarDelegate)\npublic protocol ChipBarDelegate {\n  /**\n   A delegation method that is executed when the chipItem will trigger the\n   animation to the next chip.\n   - Parameter chipBar: A ChipBar.\n   - Parameter chipItem: A ChipItem.\n   */\n  @objc\n  optional func chipBar(chipBar: ChipBar, willSelect chipItem: ChipItem)\n  \n  /**\n   A delegation method that is executed when the chipItem did complete the\n   animation to the next chip.\n   - Parameter chipBar: A ChipBar.\n   - Parameter chipItem: A ChipItem.\n   */\n  @objc\n  optional func chipBar(chipBar: ChipBar, didSelect chipItem: ChipItem)\n}\n\n@objc(ChipBarStyle)\npublic enum ChipBarStyle: Int {\n  case auto\n  case nonScrollable\n  case scrollable\n}\n\nopen class ChipBar: Bar {\n  /// The total width of the chipItems.\n  fileprivate var chipItemsTotalWidth: CGFloat {\n    var w: CGFloat = 0\n    let q = 2 * chipItemsInterimSpace\n    let p = q + chipItemsInterimSpace\n    \n    for v in chipItems {\n      let x = v.sizeThatFits(CGSize(width: .greatestFiniteMagnitude, height: scrollView.bounds.height)).width\n      w += x\n      w += p\n    }\n    \n    w -= chipItemsInterimSpace\n    \n    return w\n  }\n  \n  /// An enum that determines the chip bar style.\n  open var chipBarStyle = ChipBarStyle.auto {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// A reference to the scroll view when the chip bar style is scrollable.\n  public let scrollView = UIScrollView()\n  \n  /// Enables and disables bouncing when swiping.\n  open var isScrollBounceEnabled: Bool {\n    get {\n      return scrollView.bounces\n    }\n    set(value) {\n      scrollView.bounces = value\n    }\n  }\n  \n  /// A delegation reference.\n  open weak var delegate: ChipBarDelegate?\n  \n  /// The currently selected chipItem.\n  open fileprivate(set) var selectedChipItem: ChipItem?\n  \n  /// A preset wrapper around chipItems contentEdgeInsets.\n  open var chipItemsContentEdgeInsetsPreset: EdgeInsetsPreset {\n    get {\n      return contentView.grid.contentEdgeInsetsPreset\n    }\n    set(value) {\n      contentView.grid.contentEdgeInsetsPreset = value\n    }\n  }\n  \n  /// A reference to EdgeInsets.\n  @IBInspectable\n  open var chipItemsContentEdgeInsets: EdgeInsets {\n    get {\n      return contentView.grid.contentEdgeInsets\n    }\n    set(value) {\n      contentView.grid.contentEdgeInsets = value\n    }\n  }\n  \n  /// A preset wrapper around chipItems interimSpace.\n  open var chipItemsInterimSpacePreset: InterimSpacePreset {\n    get {\n      return contentView.grid.interimSpacePreset\n    }\n    set(value) {\n      contentView.grid.interimSpacePreset = value\n    }\n  }\n  \n  /// A wrapper around chipItems interimSpace.\n  @IBInspectable\n  open var chipItemsInterimSpace: InterimSpace {\n    get {\n      return contentView.grid.interimSpace\n    }\n    set(value) {\n      contentView.grid.interimSpace = value\n    }\n  }\n  \n  /// Buttons.\n  open var chipItems = [ChipItem]() {\n    didSet {\n      oldValue.forEach {\n        $0.removeFromSuperview()\n      }\n      \n      prepareChipItems()\n      layoutSubviews()\n    }\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    guard willLayout else {\n      return\n    }\n    \n    layoutScrollView()\n    \n    updateScrollView()\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    interimSpacePreset = .interimSpace3\n    contentEdgeInsetsPreset = .square1\n    chipItemsInterimSpacePreset = .interimSpace4\n    chipItemsContentEdgeInsetsPreset = .square2\n    chipItemsContentEdgeInsets.left = 0\n    chipItemsContentEdgeInsets.right = 0\n    \n    prepareContentView()\n    prepareScrollView()\n    prepareDivider()\n  }\n}\n\nfileprivate extension ChipBar {\n  /// Prepares the divider.\n  func prepareDivider() {\n    dividerColor = Color.grey.lighten2\n  }\n  \n  /// Prepares the chipItems.\n  func prepareChipItems() {\n    for v in chipItems {\n      v.grid.columns = 0\n      v.layer.cornerRadius = 0\n      v.contentEdgeInsets = .zero\n      \n      v.removeTarget(self, action: #selector(handle(chipItem:)), for: .touchUpInside)\n      v.addTarget(self, action: #selector(handle(chipItem:)), for: .touchUpInside)\n    }\n  }\n  \n  /// Prepares the contentView.\n  func prepareContentView() {\n    contentView.layer.zPosition = 6000\n  }\n  \n  /// Prepares the scroll view.\n  func prepareScrollView() {\n    scrollView.showsVerticalScrollIndicator = false\n    scrollView.showsHorizontalScrollIndicator = false\n    centerViews = [scrollView]\n  }\n}\n\nfileprivate extension ChipBar {\n  /// Layout the scrollView.\n  func layoutScrollView() {\n    contentView.grid.reload()\n    \n    if .scrollable == chipBarStyle || (.auto == chipBarStyle && chipItemsTotalWidth > scrollView.bounds.width) {\n      var w: CGFloat = 0\n      let q = 2 * chipItemsInterimSpace\n      let p = q + chipItemsInterimSpace\n      \n      for v in chipItems {\n        let x = v.sizeThatFits(CGSize(width: .greatestFiniteMagnitude, height: scrollView.bounds.height)).width\n        v.frame.size.height = scrollView.bounds.height\n        v.frame.size.width = x + q\n        v.frame.origin.x = w\n        w += x\n        w += p\n        \n        if scrollView != v.superview {\n          scrollView.addSubview(v)\n        }\n      }\n      \n      w -= chipItemsInterimSpace\n      \n      scrollView.contentSize = CGSize(width: w, height: scrollView.bounds.height)\n      \n    } else {\n      scrollView.grid.begin()\n      scrollView.grid.views = chipItems\n      scrollView.grid.axis.columns = chipItems.count\n      scrollView.grid.contentEdgeInsets = chipItemsContentEdgeInsets\n      scrollView.grid.interimSpace = chipItemsInterimSpace\n      scrollView.grid.commit()\n      scrollView.contentSize = scrollView.frame.size\n    }\n  }\n}\n\nfileprivate extension ChipBar {\n  /// Handles the chipItem touch event.\n  @objc\n  func handle(chipItem: ChipItem) {\n    animate(to: chipItem, isTriggeredByUserInteraction: true)\n  }\n}\n\nextension ChipBar {\n  /**\n   Selects a given index from the chipItems array.\n   - Parameter at index: An Int.\n   - Paramater completion: An optional completion block.\n   */\n  open func select(at index: Int, completion: ((ChipItem) -> Void)? = nil) {\n    guard -1 < index, index < chipItems.count else {\n      return\n    }\n    \n    animate(to: chipItems[index], isTriggeredByUserInteraction: false, completion: completion)\n  }\n  \n  /**\n   Animates to a given chipItem.\n   - Parameter to chipItem: A ChipItem.\n   - Parameter completion: An optional completion block.\n   */\n  open func animate(to chipItem: ChipItem, completion: ((ChipItem) -> Void)? = nil) {\n    animate(to: chipItem, isTriggeredByUserInteraction: false, completion: completion)\n  }\n}\n\nfileprivate extension ChipBar {\n  /**\n   Animates to a given chipItem.\n   - Parameter to chipItem: A ChipItem.\n   - Parameter isTriggeredByUserInteraction: A boolean indicating whether the\n   state was changed by a user interaction, true if yes, false otherwise.\n   - Parameter completion: An optional completion block.\n   */\n  func animate(to chipItem: ChipItem, isTriggeredByUserInteraction: Bool, completion: ((ChipItem) -> Void)? = nil) {\n    if isTriggeredByUserInteraction {\n      delegate?.chipBar?(chipBar: self, willSelect: chipItem)\n    }\n    \n    selectedChipItem = chipItem\n    updateScrollView()\n  }\n}\n\nfileprivate extension ChipBar {\n  /// Updates the scrollView.\n  func updateScrollView() {\n    guard let v = selectedChipItem else {\n      return\n    }\n    \n    if !scrollView.bounds.contains(v.frame) {\n      let contentOffsetX = (v.frame.origin.x < scrollView.bounds.minX) ? v.frame.origin.x : v.frame.maxX - scrollView.bounds.width\n      let normalizedOffsetX = min(max(contentOffsetX, 0), scrollView.contentSize.width - scrollView.bounds.width)\n      scrollView.setContentOffset(CGPoint(x: normalizedOffsetX, y: 0), animated: true)\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Chip/ChipBarController.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nfileprivate var ChipItemKey: UInt8 = 0\n\n@objc(ChipBarAlignment)\npublic enum ChipBarAlignment: Int {\n  case top\n  case bottom\n  case hidden\n}\n\nextension UIViewController {\n  /**\n   A convenience property that provides access to the ChipBarController.\n   This is the recommended method of accessing the ChipBarController\n   through child UIViewControllers.\n   */\n  public var chipBarController: ChipBarController? {\n    return traverseViewControllerHierarchyForClassType()\n  }\n}\n\nopen class ChipBarController: TransitionController {\n  /**\n   A Display value to indicate whether or not to\n   display the rootViewController to the full view\n   bounds, or up to the toolbar height.\n   */\n  open var displayStyle = DisplayStyle.partial {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// The ChipBar used to switch between view controllers.\n  @IBInspectable\n  public let chipBar = ChipBar()\n  \n  /// The chipBar alignment.\n  open var chipBarAlignment = ChipBarAlignment.bottom {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    layoutChipBar()\n    layoutContainer()\n    layoutRootViewController()\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    prepareChipBar()\n  }\n}\n\nfileprivate extension ChipBarController {\n  /// Prepares the ChipBar.\n  func prepareChipBar() {\n    chipBar.depthPreset = .depth1\n    view.addSubview(chipBar)\n  }\n}\n\nfileprivate extension ChipBarController {\n  /// Layout the container.\n  func layoutContainer() {\n    chipBar.frame.size.width = view.bounds.width\n    \n    switch displayStyle {\n    case .partial:\n      let p = chipBar.bounds.height\n      let y = view.bounds.height - p\n      \n      switch chipBarAlignment {\n      case .top:\n        container.frame.origin.y = p\n        container.frame.size.height = y\n        \n      case .bottom:\n        container.frame.origin.y = 0\n        container.frame.size.height = y\n        \n      case .hidden:\n        container.frame.origin.y = 0\n        container.frame.size.height = view.bounds.height\n      }\n      \n      container.frame.size.width = view.bounds.width\n      \n    case .full:\n      container.frame = view.bounds\n    }\n  }\n  \n  /// Layout the chipBar.\n  func layoutChipBar() {\n    chipBar.frame.size.width = view.bounds.width\n    \n    switch chipBarAlignment {\n    case .top:\n      chipBar.isHidden = false\n      chipBar.frame.origin.y = 0\n      \n    case .bottom:\n      chipBar.isHidden = false\n      chipBar.frame.origin.y = view.bounds.height - chipBar.bounds.height\n      \n    case .hidden:\n      chipBar.isHidden = true\n    }\n  }\n  \n  /// Layout the rootViewController.\n  func layoutRootViewController() {\n    rootViewController.view.frame = container.bounds\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Collection/CardCollectionView/CardCollectionViewCell.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class CardCollectionViewCell: CollectionViewCell {\n  /// An optional reference to the card being displayed in the cell.\n  open var card: Card? {\n    didSet {\n      oldValue?.removeFromSuperview()\n      \n      guard let v = card else {\n        return\n      }\n      \n      contentView.addSubview(v)\n    }\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    pulseAnimation = .none\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Collection/CardCollectionView/CardCollectionViewController.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nextension UIViewController {\n  /**\n   A convenience property that provides access to the CardCollectionViewController.\n   This is the recommended method of accessing the CardCollectionViewController\n   through child UIViewControllers.\n   */\n  public var cardCollectionViewController: CardCollectionViewController? {\n    return traverseViewControllerHierarchyForClassType()\n  }\n}\n\nopen class CardCollectionViewController: ViewController {\n  /// A reference to a Reminder.\n  public let collectionView = CollectionView()\n  \n  open var dataSourceItems = [DataSourceItem]()\n  \n  /// An index of IndexPath to DataSourceItem.\n  open var dataSourceItemsIndexPaths = [IndexPath: Any]()\n  \n  open override func prepare() {\n    super.prepare()\n    prepareCollectionView()\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    layoutCollectionView()\n  }\n}\n\nextension CardCollectionViewController {\n  /// Prepares the collectionView.\n  fileprivate func prepareCollectionView() {\n    collectionView.delegate = self\n    collectionView.dataSource = self\n    collectionView.register(CardCollectionViewCell.self, forCellWithReuseIdentifier: \"CardCollectionViewCell\")\n    view.addSubview(collectionView)\n    layoutCollectionView()\n  }\n}\n\nextension CardCollectionViewController {\n  /// Sets the frame for the collectionView.\n  fileprivate func layoutCollectionView() {\n    collectionView.frame = view.bounds\n  }\n}\n\nextension CardCollectionViewController: CollectionViewDelegate {}\n\nextension CardCollectionViewController: CollectionViewDataSource {\n  @objc\n  open func numberOfSections(in collectionView: UICollectionView) -> Int {\n    return 1\n  }\n  \n  @objc\n  open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {\n    return dataSourceItems.count\n  }\n  \n  @objc\n  open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {\n    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: \"CardCollectionViewCell\", for: indexPath) as! CardCollectionViewCell\n    \n    guard let card = dataSourceItems[indexPath.item].data as? Card else {\n      return cell\n    }\n    \n    dataSourceItemsIndexPaths[indexPath] = card\n    \n    card.frame = cell.bounds\n    \n    cell.card = card\n    \n    return cell\n  }\n}\n\n"
  },
  {
    "path": "Sources/iOS/Collection/CollectionReusableView.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\n@objc(CollectionReusableView)\nopen class CollectionReusableView: UICollectionReusableView, Pulseable, PulseableLayer {\n  /**\n   A CAShapeLayer used to manage elements that would be affected by\n   the clipToBounds property of the backing layer. For example, this\n   allows the dropshadow effect on the backing layer, while clipping\n   the image to a desired shape within the visualLayer.\n   */\n  public let visualLayer = CAShapeLayer()\n  \n  /// A Pulse reference.\n  internal var pulse: Pulse!\n  \n  /// A reference to the pulse layer.\n  internal var pulseLayer: CALayer? {\n    return pulse.pulseLayer\n  }\n  \n  /// PulseAnimation value.\n  open var pulseAnimation: PulseAnimation {\n    get {\n      return pulse.animation\n    }\n    set(value) {\n      pulse.animation = value\n    }\n  }\n  \n  /// PulseAnimation color.\n  @IBInspectable\n  open var pulseColor: UIColor {\n    get {\n      return pulse.color\n    }\n    set(value) {\n      pulse.color = value\n    }\n  }\n  \n  /// Pulse opacity.\n  @IBInspectable\n  open var pulseOpacity: CGFloat {\n    get {\n      return pulse.opacity\n    }\n    set(value) {\n      pulse.opacity = value\n    }\n  }\n  \n  /**\n   A property that manages an image for the visualLayer's contents\n   property. Images should not be set to the backing layer's contents\n   property to avoid conflicts when using clipsToBounds.\n   */\n  @IBInspectable\n  open var image: UIImage? {\n    didSet {\n      visualLayer.contents = image?.cgImage\n    }\n  }\n  \n  /**\n   Allows a relative subrectangle within the range of 0 to 1 to be\n   specified for the visualLayer's contents property. This allows\n   much greater flexibility than the contentsGravity property in\n   terms of how the image is cropped and stretched.\n   */\n  @IBInspectable\n  open var contentsRect: CGRect {\n    get {\n      return visualLayer.contentsRect\n    }\n    set(value) {\n      visualLayer.contentsRect = value\n    }\n  }\n  \n  /**\n   A CGRect that defines a stretchable region inside the visualLayer\n   with a fixed border around the edge.\n   */\n  @IBInspectable\n  open var contentsCenter: CGRect {\n    get {\n      return visualLayer.contentsCenter\n    }\n    set(value) {\n      visualLayer.contentsCenter = value\n    }\n  }\n  \n  /**\n   A floating point value that defines a ratio between the pixel\n   dimensions of the visualLayer's contents property and the size\n   of the view. By default, this value is set to the Screen.scale.\n   */\n  @IBInspectable\n  open var contentsScale: CGFloat {\n    get {\n      return visualLayer.contentsScale\n    }\n    set(value) {\n      visualLayer.contentsScale = value\n    }\n  }\n  \n  /// Determines how content should be aligned within the visualLayer's bounds.\n  @IBInspectable\n  open var contentsGravity: CALayerContentsGravity {\n    get {\n      return visualLayer.contentsGravity\n    }\n    set(value) {\n      visualLayer.contentsGravity = value\n    }\n  }\n  \n  /// A preset wrapper around contentEdgeInsets.\n  open var contentEdgeInsetsPreset: EdgeInsetsPreset {\n    get {\n      return grid.contentEdgeInsetsPreset\n    }\n    set(value) {\n      grid.contentEdgeInsetsPreset = value\n    }\n  }\n  \n  /// A reference to EdgeInsets.\n  @IBInspectable\n  open var contentEdgeInsets: UIEdgeInsets {\n    get {\n      return grid.contentEdgeInsets\n    }\n    set(value) {\n      grid.contentEdgeInsets = value\n    }\n  }\n  \n  /// A preset wrapper around interimSpace.\n  open var interimSpacePreset: InterimSpacePreset {\n    get {\n      return grid.interimSpacePreset\n    }\n    set(value) {\n      grid.interimSpacePreset = value\n    }\n  }\n  \n  /// A wrapper around grid.interimSpace.\n  @IBInspectable\n  open var interimSpace: InterimSpace {\n    get {\n      return grid.interimSpace\n    }\n    set(value) {\n      grid.interimSpace = value\n    }\n  }\n  \n  /// A property that accesses the backing layer's background\n  @IBInspectable\n  open override var backgroundColor: UIColor? {\n    didSet {\n      layer.backgroundColor = backgroundColor?.cgColor\n    }\n  }\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n    prepare()\n  }\n  \n  /**\n   An initializer that initializes the object with a CGRect object.\n   If AutoLayout is used, it is better to initilize the instance\n   using the init() initializer.\n   - Parameter frame: A CGRect instance.\n   */\n  public override init(frame: CGRect) {\n    super.init(frame: frame)\n    prepare()\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    layoutShape()\n    layoutVisualLayer()\n    layoutShadowPath()\n  }\n  \n  /**\n   Triggers the pulse animation.\n   - Parameter point: A Optional point to pulse from, otherwise pulses\n   from the center.\n   */\n  open func pulse(point: CGPoint? = nil) {\n    pulse.expand(point: point ?? center)\n    Motion.delay(0.35) { [weak self] in\n      self?.pulse.contract()\n    }\n  }\n  \n  /**\n   A delegation method that is executed when the view has began a\n   touch event.\n   - Parameter touches: A set of UITouch objects.\n   - Parameter event: A UIEvent object.\n   */\n  open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {\n    super.touchesBegan(touches, with: event)\n    pulse.expand(point: layer.convert(touches.first!.location(in: self), from: layer))\n  }\n  \n  /**\n   A delegation method that is executed when the view touch event has\n   ended.\n   - Parameter touches: A set of UITouch objects.\n   - Parameter event: A UIEvent object.\n   */\n  open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {\n    super.touchesEnded(touches, with: event)\n    pulse.contract()\n  }\n  \n  /**\n   A delegation method that is executed when the view touch event has\n   been cancelled.\n   - Parameter touches: A set of UITouch objects.\n   - Parameter event: A UIEvent object.\n   */\n  open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {\n    super.touchesCancelled(touches, with: event)\n    pulse.contract()\n  }\n  \n  /**\n   Prepares the view instance when intialized. When subclassing,\n   it is recommended to override the prepare method\n   to initialize property values and other setup operations.\n   The super.prepare method should always be called immediately\n   when subclassing.\n   */\n  open func prepare() {\n    contentsGravity = .resizeAspectFill\n    contentScaleFactor = Screen.scale\n    prepareVisualLayer()\n    preparePulse()\n  }\n}\n\nextension CollectionReusableView {\n  /// Prepares the pulse motion.\n  fileprivate func preparePulse() {\n    pulse = Pulse(pulseView: self, pulseLayer: visualLayer)\n    pulseAnimation = .none\n  }\n  \n  /// Prepares the visualLayer property.\n  fileprivate func prepareVisualLayer() {\n    visualLayer.zPosition = 0\n    visualLayer.masksToBounds = true\n    layer.addSublayer(visualLayer)\n  }\n}\n\nextension CollectionReusableView {\n  /// Manages the layout for the visualLayer property.\n  fileprivate func layoutVisualLayer() {\n    visualLayer.frame = bounds\n    visualLayer.cornerRadius = layer.cornerRadius\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Collection/CollectionView.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class CollectionView: UICollectionView {\n  /// A preset wrapper around contentEdgeInsets.\n  open var contentEdgeInsetsPreset: EdgeInsetsPreset {\n    get {\n      return (collectionViewLayout as? CollectionViewLayout)!.contentEdgeInsetsPreset\n    }\n    set(value) {\n      (collectionViewLayout as? CollectionViewLayout)!.contentEdgeInsetsPreset = value\n    }\n  }\n  \n  open var contentEdgeInsets: EdgeInsets {\n    get {\n      return (collectionViewLayout as? CollectionViewLayout)!.contentEdgeInsets\n    }\n    set(value) {\n      (collectionViewLayout as? CollectionViewLayout)!.contentEdgeInsets = value\n    }\n  }\n  \n  /// Scroll direction.\n  open var scrollDirection: UICollectionView.ScrollDirection {\n    get {\n      return (collectionViewLayout as? CollectionViewLayout)!.scrollDirection\n    }\n    set(value) {\n      (collectionViewLayout as? CollectionViewLayout)!.scrollDirection = value\n    }\n  }\n  \n  /// A preset wrapper around interimSpace.\n  open var interimSpacePreset: InterimSpacePreset {\n    get {\n      return (collectionViewLayout as? CollectionViewLayout)!.interimSpacePreset\n    }\n    set(value) {\n      (collectionViewLayout as? CollectionViewLayout)!.interimSpacePreset = value\n    }\n  }\n  \n  /// Spacing between items.\n  @IBInspectable\n  open var interimSpace: InterimSpace {\n    get {\n      return (collectionViewLayout as? CollectionViewLayout)!.interimSpace\n    }\n    set(value) {\n      (collectionViewLayout as? CollectionViewLayout)!.interimSpace = value\n    }\n  }\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n    prepare()\n  }\n  \n  /**\n   An initializer that initializes the object.\n   - Parameter frame: A CGRect defining the view's frame.\n   - Parameter collectionViewLayout: A UICollectionViewLayout reference.\n   */\n  public override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {\n    super.init(frame: frame, collectionViewLayout: layout)\n    prepare()\n  }\n  \n  /**\n   An initializer that initializes the object.\n   - Parameter collectionViewLayout: A UICollectionViewLayout reference.\n   */\n  public init(collectionViewLayout layout: UICollectionViewLayout) {\n    super.init(frame: .zero, collectionViewLayout: layout)\n    prepare()\n  }\n  \n  /**\n   An initializer that initializes the object.\n   - Parameter frame: A CGRect defining the view's frame.\n   */\n  public init(frame: CGRect) {\n    let layout = CollectionViewLayout()\n    super.init(frame: frame, collectionViewLayout: layout)\n    prepare()\n  }\n  \n  /// A convenience initializer that initializes the object.\n  public init() {\n    let layout = CollectionViewLayout()\n    super.init(frame: .zero, collectionViewLayout: layout)\n    prepare()\n  }\n  \n  /**\n   Prepares the view instance when intialized. When subclassing,\n   it is recommended to override the prepare method\n   to initialize property values and other setup operations.\n   The super.prepare method should always be called immediately\n   when subclassing.\n   */\n  open func prepare() {\n    backgroundColor = .white\n    contentScaleFactor = Screen.scale\n    register(CollectionViewCell.self, forCellWithReuseIdentifier: \"CollectionViewCell\")\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Collection/CollectionViewCell.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\n@objc(CollectionViewCell)\nopen class CollectionViewCell: UICollectionViewCell, Pulseable, PulseableLayer {\n  /**\n   A CAShapeLayer used to manage elements that would be affected by\n   the clipToBounds property of the backing layer. For example, this\n   allows the dropshadow effect on the backing layer, while clipping\n   the image to a desired shape within the visualLayer.\n   */\n  public let visualLayer = CAShapeLayer()\n  \n  /// A Pulse reference.\n  internal var pulse: Pulse!\n  \n  /// A reference to the pulse layer.\n  internal var pulseLayer: CALayer? {\n    return pulse.pulseLayer\n  }\n  \n  /// PulseAnimation value.\n  open var pulseAnimation: PulseAnimation {\n    get {\n      return pulse.animation\n    }\n    set(value) {\n      pulse.animation = value\n    }\n  }\n  \n  /// PulseAnimation color.\n  @IBInspectable\n  open var pulseColor: UIColor {\n    get {\n      return pulse.color\n    }\n    set(value) {\n      pulse.color = value\n    }\n  }\n  \n  /// Pulse opacity.\n  @IBInspectable\n  open var pulseOpacity: CGFloat {\n    get {\n      return pulse.opacity\n    }\n    set(value) {\n      pulse.opacity = value\n    }\n  }\n  \n  /**\n   A property that manages an image for the visualLayer's contents\n   property. Images should not be set to the backing layer's contents\n   property to avoid conflicts when using clipsToBounds.\n   */\n  @IBInspectable\n  open var image: UIImage? {\n    didSet {\n      visualLayer.contents = image?.cgImage\n    }\n  }\n  \n  /**\n   Allows a relative subrectangle within the range of 0 to 1 to be\n   specified for the visualLayer's contents property. This allows\n   much greater flexibility than the contentsGravity property in\n   terms of how the image is cropped and stretched.\n   */\n  @IBInspectable\n  open var contentsRect: CGRect {\n    get {\n      return visualLayer.contentsRect\n    }\n    set(value) {\n      visualLayer.contentsRect = value\n    }\n  }\n  \n  /**\n   A CGRect that defines a stretchable region inside the visualLayer\n   with a fixed border around the edge.\n   */\n  @IBInspectable\n  open var contentsCenter: CGRect {\n    get {\n      return visualLayer.contentsCenter\n    }\n    set(value) {\n      visualLayer.contentsCenter = value\n    }\n  }\n  \n  /**\n   A floating point value that defines a ratio between the pixel\n   dimensions of the visualLayer's contents property and the size\n   of the view. By default, this value is set to the Screen.scale.\n   */\n  @IBInspectable\n  open var contentsScale: CGFloat {\n    get {\n      return visualLayer.contentsScale\n    }\n    set(value) {\n      visualLayer.contentsScale = value\n    }\n  }\n  \n  /// Determines how content should be aligned within the visualLayer's bounds.\n  @IBInspectable\n  open var contentsGravity: CALayerContentsGravity {\n    get {\n      return visualLayer.contentsGravity\n    }\n    set(value) {\n      visualLayer.contentsGravity = value\n    }\n  }\n  \n  /// A property that accesses the backing layer's background\n  @IBInspectable\n  open override var backgroundColor: UIColor? {\n    didSet {\n      layer.backgroundColor = backgroundColor?.cgColor\n    }\n  }\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n    prepare()\n  }\n  \n  /**\n   An initializer that initializes the object with a CGRect object.\n   If AutoLayout is used, it is better to initilize the instance\n   using the init() initializer.\n   - Parameter frame: A CGRect instance.\n   */\n  public override init(frame: CGRect) {\n    super.init(frame: frame)\n    prepare()\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    layoutShape()\n    layoutVisualLayer()\n    layoutShadowPath()\n  }\n  \n  /**\n   Triggers the pulse animation.\n   - Parameter point: A Optional point to pulse from, otherwise pulses\n   from the center.\n   */\n  open func pulse(point: CGPoint? = nil) {\n    pulse.expand(point: point ?? center)\n    Motion.delay(0.35) { [weak self] in\n      self?.pulse.contract()\n    }\n  }\n  \n  /**\n   A delegation method that is executed when the view has began a\n   touch event.\n   - Parameter touches: A set of UITouch objects.\n   - Parameter event: A UIEvent object.\n   */\n  open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {\n    super.touchesBegan(touches, with: event)\n    pulse.expand(point: layer.convert(touches.first!.location(in: self), from: layer))\n  }\n  \n  /**\n   A delegation method that is executed when the view touch event has\n   ended.\n   - Parameter touches: A set of UITouch objects.\n   - Parameter event: A UIEvent object.\n   */\n  open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {\n    super.touchesEnded(touches, with: event)\n    pulse.contract()\n  }\n  \n  /**\n   A delegation method that is executed when the view touch event has\n   been cancelled.\n   - Parameter touches: A set of UITouch objects.\n   - Parameter event: A UIEvent object.\n   */\n  open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {\n    super.touchesCancelled(touches, with: event)\n    pulse.contract()\n  }\n  \n  /**\n   Prepares the view instance when intialized. When subclassing,\n   it is recommended to override the prepare method\n   to initialize property values and other setup operations.\n   The super.prepare method should always be called immediately\n   when subclassing.\n   */\n  open func prepare() {\n    contentsGravity = .resizeAspectFill\n    contentScaleFactor = Screen.scale\n    backgroundColor = .white\n    \n    prepareVisualLayer()\n    preparePulse()\n  }\n}\n\nfileprivate extension CollectionViewCell {\n  /// Prepares the pulse motion.\n  func preparePulse() {\n    pulse = Pulse(pulseView: self, pulseLayer: visualLayer)\n  }\n  \n  /// Prepares the visualLayer property.\n  func prepareVisualLayer() {\n    visualLayer.zPosition = 0\n    visualLayer.masksToBounds = true\n    layer.addSublayer(visualLayer)\n  }\n}\n\nfileprivate extension CollectionViewCell {\n  /// Manages the layout for the visualLayer property.\n  func layoutVisualLayer() {\n    visualLayer.frame = bounds\n    visualLayer.cornerRadius = layer.cornerRadius\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Collection/CollectionViewController.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\npublic protocol CollectionViewDelegate: UICollectionViewDelegate {}\n\npublic protocol CollectionViewDataSource: UICollectionViewDataSource {\n  /**\n   Retrieves the data source items for the collectionView.\n   - Returns: An Array of DataSourceItem objects.\n   */\n  var dataSourceItems: [DataSourceItem] { get }\n}\n\nextension UIViewController {\n  /**\n   A convenience property that provides access to the CollectionViewController.\n   This is the recommended method of accessing the CollectionViewController\n   through child UIViewControllers.\n   */\n  public var collectionViewController: CollectionViewController? {\n    return traverseViewControllerHierarchyForClassType()\n  }\n}\n\nopen class CollectionViewController: ViewController {\n  /// A reference to a Reminder.\n  public let collectionView = CollectionView()\n  \n  open var dataSourceItems = [DataSourceItem]()\n  \n  open override func prepare() {\n    super.prepare()\n    prepareCollectionView()\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    layoutCollectionView()\n  }\n}\n\nextension CollectionViewController {\n  /// Prepares the collectionView.\n  fileprivate func prepareCollectionView() {\n    collectionView.delegate = self\n    collectionView.dataSource = self\n    view.layout(collectionView).edges()\n  }\n}\n\nextension CollectionViewController {\n  /// Sets the frame for the collectionView.\n  fileprivate func layoutCollectionView() {\n    collectionView.frame = view.bounds\n  }\n}\n\nextension CollectionViewController: CollectionViewDelegate {}\n\nextension CollectionViewController: CollectionViewDataSource {\n  @objc\n  open func numberOfSections(in collectionView: UICollectionView) -> Int {\n    return 1\n  }\n  \n  @objc\n  open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {\n    return dataSourceItems.count\n  }\n  \n  @objc\n  open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {\n    return collectionView.dequeueReusableCell(withReuseIdentifier: \"CollectionViewCell\", for: indexPath)\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Collection/CollectionViewLayout.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class CollectionViewLayout: UICollectionViewLayout {\n  /// Used to calculate the dimensions of the cells.\n  public var offset = CGPoint.zero\n  \n  /// The size of items.\n  public var itemSize = CGSize.zero\n  \n  /// A preset wrapper around contentEdgeInsets.\n  public var contentEdgeInsetsPreset = EdgeInsetsPreset.none {\n    didSet {\n      contentEdgeInsets = EdgeInsetsPresetToValue(preset: contentEdgeInsetsPreset)\n    }\n  }\n  \n  /// A wrapper around grid.contentEdgeInsets.\n  public var contentEdgeInsets = EdgeInsets.zero\n  \n  /// Size of the content.\n  public fileprivate(set) var contentSize = CGSize.zero\n  \n  /// Layout attribute items.\n  public fileprivate(set) lazy var layoutItems = [(UICollectionViewLayoutAttributes, NSIndexPath)]()\n  \n  /// Cell data source items.\n  public fileprivate(set) var dataSourceItems: [DataSourceItem]?\n  \n  /// Scroll direction.\n  public var scrollDirection = UICollectionView.ScrollDirection.vertical\n  \n  /// A preset wrapper around interimSpace.\n  public var interimSpacePreset = InterimSpacePreset.none {\n    didSet {\n      interimSpace = InterimSpacePresetToValue(preset: interimSpacePreset)\n    }\n  }\n  \n  /// Spacing between items.\n  public var interimSpace: InterimSpace = 0\n  \n  open override var collectionViewContentSize: CGSize {\n    return contentSize\n  }\n}\n\nextension CollectionViewLayout {\n  /**\n   Retrieves the index paths for the items within the passed in CGRect.\n   - Parameter rect: A CGRect that acts as the bounds to find the items within.\n   - Returns: An Array of NSIndexPath objects.\n   */\n  public func indexPathsOfItems(in rect: CGRect) -> [NSIndexPath] {\n    var paths = [NSIndexPath]()\n    \n    for (attribute, indexPath) in layoutItems {\n      guard rect.intersects(attribute.frame) else {\n        continue\n      }\n      \n      paths.append(indexPath)\n    }\n    \n    return paths\n  }\n}\n\nextension CollectionViewLayout {\n  /**\n   Prepares the layout for the given data source items.\n   - Parameter for dataSourceItems: An Array of DataSourceItems.\n   */\n  fileprivate func prepareLayout(for dataSourceItems: [DataSourceItem]) {\n    self.dataSourceItems = dataSourceItems\n    layoutItems.removeAll()\n    \n    offset.x = contentEdgeInsets.left\n    offset.y = contentEdgeInsets.top\n    \n    for i in 0..<dataSourceItems.count {\n      let item = dataSourceItems[i]\n      let indexPath = IndexPath(item: i, section: 0)\n      layoutItems.append((layoutAttributesForItem(at: indexPath)!, indexPath as NSIndexPath))\n      \n      offset.x += interimSpace\n      offset.y += interimSpace\n      \n      if nil != item.width {\n        offset.x += item.width!\n      } else if let v = item.data as? UIView, 0 < v.bounds.width {\n        offset.x += v.bounds.width\n      } else {\n        offset.x += itemSize.width\n      }\n      \n      if nil != item.height {\n        offset.y += item.height!\n      } else if let v = item.data as? UIView, 0 < v.bounds.height {\n        offset.y += v.bounds.height\n      } else {\n        offset.y += itemSize.height\n      }\n    }\n    \n    offset.x += contentEdgeInsets.right - interimSpace\n    offset.y += contentEdgeInsets.bottom - interimSpace\n    \n    if 0 < itemSize.width && 0 < itemSize.height {\n      contentSize = CGSize(width: offset.x, height: offset.y)\n    } else if .vertical == scrollDirection {\n      contentSize = CGSize(width: collectionView!.bounds.width, height: offset.y)\n    } else {\n      contentSize = CGSize(width: offset.x, height: collectionView!.bounds.height)\n    }\n  }\n}\n\nextension CollectionViewLayout {\n  open override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {\n    let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)\n    let dataSourceItem = dataSourceItems![indexPath.item]\n    \n    if 0 < itemSize.width && 0 < itemSize.height {\n      attributes.frame = CGRect(x: offset.x, y: offset.y, width: itemSize.width - contentEdgeInsets.left - contentEdgeInsets.right, height: itemSize.height - contentEdgeInsets.top - contentEdgeInsets.bottom)\n    } else if .vertical == scrollDirection {\n      if let h = dataSourceItem.height {\n        attributes.frame = CGRect(x: contentEdgeInsets.left, y: offset.y, width: collectionView!.bounds.width - contentEdgeInsets.left - contentEdgeInsets.right, height: h)\n        \n      } else if let v = dataSourceItem.data as? UIView, 0 < v.bounds.height {\n        v.updateConstraintsIfNeeded()\n        v.updateConstraints()\n        v.setNeedsLayout()\n        v.layoutIfNeeded()\n        \n        attributes.frame = CGRect(x: contentEdgeInsets.left, y: offset.y, width: collectionView!.bounds.width - contentEdgeInsets.left - contentEdgeInsets.right, height: v.bounds.height)\n        \n      } else {\n        attributes.frame = CGRect(x: contentEdgeInsets.left, y: offset.y, width: collectionView!.bounds.width - contentEdgeInsets.left - contentEdgeInsets.right, height: collectionView!.bounds.height)\n      }\n    } else {\n      if let w = dataSourceItem.width {\n        attributes.frame = CGRect(x: offset.x, y: contentEdgeInsets.top, width: w, height: collectionView!.bounds.height - contentEdgeInsets.top - contentEdgeInsets.bottom)\n        \n      } else if let v = dataSourceItem.data as? UIView, 0 < v.bounds.width {\n        v.updateConstraintsIfNeeded()\n        v.updateConstraints()\n        v.setNeedsLayout()\n        v.layoutIfNeeded()\n        \n        attributes.frame = CGRect(x: offset.x, y: contentEdgeInsets.top, width: v.bounds.width, height: collectionView!.bounds.height - contentEdgeInsets.top - contentEdgeInsets.bottom)\n        \n      } else {\n        attributes.frame = CGRect(x: offset.x, y: contentEdgeInsets.top, width: collectionView!.bounds.width, height: collectionView!.bounds.height - contentEdgeInsets.top - contentEdgeInsets.bottom)\n      }\n    }\n    \n    return attributes\n  }\n  \n  open override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {\n    var layoutAttributes = [UICollectionViewLayoutAttributes]()\n    for (attribute, _) in layoutItems {\n      if rect.intersects(attribute.frame) {\n        layoutAttributes.append(attribute)\n      }\n    }\n    return layoutAttributes\n  }\n  \n  open override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {\n    return .vertical == scrollDirection ? newBounds.width != collectionView!.bounds.width : newBounds.height != collectionView!.bounds.height\n  }\n  \n  open override func prepare() {\n    guard let dataSource = collectionView?.dataSource as? CollectionViewDataSource else {\n      return\n    }\n    \n    prepareLayout(for: dataSource.dataSourceItems)\n  }\n  \n  open override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {\n    return proposedContentOffset\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Color/Color.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(ColorPalette)\npublic protocol ColorPalette {\n  /// Material color code: 50\n  static var lighten5: UIColor { get }\n  /// Material color code: 100\n  static var lighten4: UIColor { get }\n  /// Material color code: 200\n  static var lighten3: UIColor { get }\n  /// Material color code: 300\n  static var lighten2: UIColor { get }\n  /// Material color code: 400\n  static var lighten1: UIColor { get }\n  /// Material color code: 500\n  static var base: UIColor { get }\n  /// Material color code: 600\n  static var darken1: UIColor { get }\n  /// Material color code: 700\n  static var darken2: UIColor { get }\n  /// Material color code: 800\n  static var darken3: UIColor { get }\n  /// Material color code: 900\n  static var darken4: UIColor { get }\n  \n  /// Material color code: A100\n  @objc\n  optional static var accent1: UIColor { get }\n  \n  /// Material color code: A200\n  @objc\n  optional static var accent2: UIColor { get }\n  \n  /// Material color code: A400\n  @objc\n  optional static var accent3: UIColor { get }\n  \n  /// Material color code: A700\n  @objc\n  optional static var accent4: UIColor { get }\n}\n\nopen class Color: UIColor {\n  // dark text\n  open class darkText {\n    public static let primary = Color.black.withAlphaComponent(0.87)\n    public static let secondary = Color.black.withAlphaComponent(0.54)\n    public static let others = Color.black.withAlphaComponent(0.38)\n    public static let dividers = Color.black.withAlphaComponent(0.12)\n  }\n  \n  // light text\n  open class lightText {\n    public static let primary = Color.white\n    public static let secondary = Color.white.withAlphaComponent(0.7)\n    public static let others = Color.white.withAlphaComponent(0.5)\n    public static let dividers = Color.white.withAlphaComponent(0.12)\n  }\n  \n  // red\n  open class red: ColorPalette {\n    public static let lighten5 = UIColor(red: 255/255, green: 235/255, blue: 238/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 255/255, green: 205/255, blue: 210/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 239/255, green: 154/255, blue: 154/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 229/255, green: 115/255, blue: 115/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 229/255, green: 83/255, blue: 80/255, alpha: 1)\n    public static let base = UIColor(red: 244/255, green: 67/255, blue: 54/255, alpha: 1)\n    public static let darken1 = UIColor(red: 229/255, green: 57/255, blue: 53/255, alpha: 1)\n    public static let darken2 = UIColor(red: 211/255, green: 47/255, blue: 47/255, alpha: 1)\n    public static let darken3 = UIColor(red: 198/255, green: 40/255, blue: 40/255, alpha: 1)\n    public static let darken4 = UIColor(red: 183/255, green: 28/255, blue: 28/255, alpha: 1)\n    public static let accent1 = UIColor(red: 255/255, green: 138/255, blue: 128/255, alpha: 1)\n    public static let accent2 = UIColor(red: 255/255, green: 82/255, blue: 82/255, alpha: 1)\n    public static let accent3 = UIColor(red: 255/255, green: 23/255, blue: 68/255, alpha: 1)\n    public static let accent4 = UIColor(red: 213/255, green: 0/255, blue: 0/255, alpha: 1)\n  }\n  \n  // pink\n  open class pink: ColorPalette {\n    public static let lighten5 = UIColor(red: 252/255, green: 228/255, blue: 236/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 248/255, green: 187/255, blue: 208/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 244/255, green: 143/255, blue: 177/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 240/255, green: 98/255, blue: 146/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 236/255, green: 64/255, blue: 122/255, alpha: 1)\n    public static let base = UIColor(red: 233/255, green: 30/255, blue: 99/255, alpha: 1)\n    public static let darken1 = UIColor(red: 216/255, green: 27/255, blue: 96/255, alpha: 1)\n    public static let darken2 = UIColor(red: 194/255, green: 24/255, blue: 91/255, alpha: 1)\n    public static let darken3 = UIColor(red: 173/255, green: 20/255, blue: 87/255, alpha: 1)\n    public static let darken4 = UIColor(red: 136/255, green: 14/255, blue: 79/255, alpha: 1)\n    public static let accent1 = UIColor(red: 255/255, green: 128/255, blue: 171/255, alpha: 1)\n    public static let accent2 = UIColor(red: 255/255, green: 64/255, blue: 129/255, alpha: 1)\n    public static let accent3 = UIColor(red: 245/255, green: 0/255, blue: 87/255, alpha: 1)\n    public static let accent4 = UIColor(red: 197/255, green: 17/255, blue: 98/255, alpha: 1)\n  }\n  \n  // purple\n  open class purple: ColorPalette {\n    public static let lighten5 = UIColor(red: 243/255, green: 229/255, blue: 245/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 225/255, green: 190/255, blue: 231/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 206/255, green: 147/255, blue: 216/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 186/255, green: 104/255, blue: 200/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 171/255, green: 71/255, blue: 188/255, alpha: 1)\n    public static let base = UIColor(red: 156/255, green: 39/255, blue: 176/255, alpha: 1)\n    public static let darken1 = UIColor(red: 142/255, green: 36/255, blue: 170/255, alpha: 1)\n    public static let darken2 = UIColor(red: 123/255, green: 31/255, blue: 162/255, alpha: 1)\n    public static let darken3 = UIColor(red: 106/255, green: 27/255, blue: 154/255, alpha: 1)\n    public static let darken4 = UIColor(red: 74/255, green: 20/255, blue: 140/255, alpha: 1)\n    public static let accent1 = UIColor(red: 234/255, green: 128/255, blue: 252/255, alpha: 1)\n    public static let accent2 = UIColor(red: 224/255, green: 64/255, blue: 251/255, alpha: 1)\n    public static let accent3 = UIColor(red: 213/255, green: 0/255, blue: 249/255, alpha: 1)\n    public static let accent4 = UIColor(red: 170/255, green: 0/255, blue: 255/255, alpha: 1)\n  }\n  \n  // deepPurple\n  open class deepPurple: ColorPalette {\n    public static let lighten5 = UIColor(red: 237/255, green: 231/255, blue: 246/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 209/255, green: 196/255, blue: 233/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 179/255, green: 157/255, blue: 219/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 149/255, green: 117/255, blue: 205/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 126/255, green: 87/255, blue: 194/255, alpha: 1)\n    public static let base = UIColor(red: 103/255, green: 58/255, blue: 183/255, alpha: 1)\n    public static let darken1 = UIColor(red: 94/255, green: 53/255, blue: 177/255, alpha: 1)\n    public static let darken2 = UIColor(red: 81/255, green: 45/255, blue: 168/255, alpha: 1)\n    public static let darken3 = UIColor(red: 69/255, green: 39/255, blue: 160/255, alpha: 1)\n    public static let darken4 = UIColor(red: 49/255, green: 27/255, blue: 146/255, alpha: 1)\n    public static let accent1 = UIColor(red: 179/255, green: 136/255, blue: 255/255, alpha: 1)\n    public static let accent2 = UIColor(red: 124/255, green: 77/255, blue: 255/255, alpha: 1)\n    public static let accent3 = UIColor(red: 101/255, green: 31/255, blue: 255/255, alpha: 1)\n    public static let accent4 = UIColor(red: 98/255, green: 0/255, blue: 234/255, alpha: 1)\n  }\n  \n  // indigo\n  open class indigo: ColorPalette {\n    public static let lighten5 = UIColor(red: 232/255, green: 234/255, blue: 246/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 197/255, green: 202/255, blue: 233/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 159/255, green: 168/255, blue: 218/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 121/255, green: 134/255, blue: 203/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 92/255, green: 107/255, blue: 192/255, alpha: 1)\n    public static let base = UIColor(red: 63/255, green: 81/255, blue: 181/255, alpha: 1)\n    public static let darken1 = UIColor(red: 57/255, green: 73/255, blue: 171/255, alpha: 1)\n    public static let darken2 = UIColor(red: 48/255, green: 63/255, blue: 159/255, alpha: 1)\n    public static let darken3 = UIColor(red: 40/255, green: 53/255, blue: 147/255, alpha: 1)\n    public static let darken4 = UIColor(red: 26/255, green: 35/255, blue: 126/255, alpha: 1)\n    public static let accent1 = UIColor(red: 140/255, green: 158/255, blue: 255/255, alpha: 1)\n    public static let accent2 = UIColor(red: 83/255, green: 109/255, blue: 254/255, alpha: 1)\n    public static let accent3 = UIColor(red: 61/255, green: 90/255, blue: 254/255, alpha: 1)\n    public static let accent4 = UIColor(red: 48/255, green: 79/255, blue: 254/255, alpha: 1)\n  }\n  \n  // blue\n  open class blue: ColorPalette {\n    public static let lighten5 = UIColor(red: 227/255, green: 242/255, blue: 253/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 187/255, green: 222/255, blue: 251/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 144/255, green: 202/255, blue: 249/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 100/255, green: 181/255, blue: 246/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 66/255, green: 165/255, blue: 245/255, alpha: 1)\n    public static let base = UIColor(red: 33/255, green: 150/255, blue: 243/255, alpha: 1)\n    public static let darken1 = UIColor(red: 30/255, green: 136/255, blue: 229/255, alpha: 1)\n    public static let darken2 = UIColor(red: 25/255, green: 118/255, blue: 210/255, alpha: 1)\n    public static let darken3 = UIColor(red: 21/255, green: 101/255, blue: 192/255, alpha: 1)\n    public static let darken4 = UIColor(red: 13/255, green: 71/255, blue: 161/255, alpha: 1)\n    public static let accent1 = UIColor(red: 130/255, green: 177/255, blue: 255/255, alpha: 1)\n    public static let accent2 = UIColor(red: 68/255, green: 138/255, blue: 255/255, alpha: 1)\n    public static let accent3 = UIColor(red: 41/255, green: 121/255, blue: 255/255, alpha: 1)\n    public static let accent4 = UIColor(red: 41/255, green: 98/255, blue: 255/255, alpha: 1)\n  }\n  \n  // light blue\n  open class lightBlue: ColorPalette {\n    public static let lighten5 = UIColor(red: 225/255, green: 245/255, blue: 254/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 179/255, green: 229/255, blue: 252/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 129/255, green: 212/255, blue: 250/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 79/255, green: 195/255, blue: 247/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 41/255, green: 182/255, blue: 246/255, alpha: 1)\n    public static let base = UIColor(red: 3/255, green: 169/255, blue: 244/255, alpha: 1)\n    public static let darken1 = UIColor(red: 3/255, green: 155/255, blue: 229/255, alpha: 1)\n    public static let darken2 = UIColor(red: 2/255, green: 136/255, blue: 209/255, alpha: 1)\n    public static let darken3 = UIColor(red: 2/255, green: 119/255, blue: 189/255, alpha: 1)\n    public static let darken4 = UIColor(red: 1/255, green: 87/255, blue: 155/255, alpha: 1)\n    public static let accent1 = UIColor(red: 128/255, green: 216/255, blue: 255/255, alpha: 1)\n    public static let accent2 = UIColor(red: 64/255, green: 196/255, blue: 255/255, alpha: 1)\n    public static let accent3 = UIColor(red: 0/255, green: 176/255, blue: 255/255, alpha: 1)\n    public static let accent4 = UIColor(red: 0/255, green: 145/255, blue: 234/255, alpha: 1)\n  }\n  \n  // cyan\n  open class cyan: ColorPalette {\n    public static let lighten5 = UIColor(red: 224/255, green: 247/255, blue: 250/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 178/255, green: 235/255, blue: 242/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 128/255, green: 222/255, blue: 234/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 77/255, green: 208/255, blue: 225/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 38/255, green: 198/255, blue: 218/255, alpha: 1)\n    public static let base = UIColor(red: 0/255, green: 188/255, blue: 212/255, alpha: 1)\n    public static let darken1 = UIColor(red: 0/255, green: 172/255, blue: 193/255, alpha: 1)\n    public static let darken2 = UIColor(red: 0/255, green: 151/255, blue: 167/255, alpha: 1)\n    public static let darken3 = UIColor(red: 0/255, green: 131/255, blue: 143/255, alpha: 1)\n    public static let darken4 = UIColor(red: 0/255, green: 96/255, blue: 100/255, alpha: 1)\n    public static let accent1 = UIColor(red: 132/255, green: 255/255, blue: 255/255, alpha: 1)\n    public static let accent2 = UIColor(red: 24/255, green: 255/255, blue: 255/255, alpha: 1)\n    public static let accent3 = UIColor(red: 0/255, green: 229/255, blue: 255/255, alpha: 1)\n    public static let accent4 = UIColor(red: 0/255, green: 184/255, blue: 212/255, alpha: 1)\n  }\n  \n  // teal\n  open class teal: ColorPalette {\n    public static let lighten5 = UIColor(red: 224/255, green: 242/255, blue: 241/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 178/255, green: 223/255, blue: 219/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 128/255, green: 203/255, blue: 196/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 77/255, green: 182/255, blue: 172/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 38/255, green: 166/255, blue: 154/255, alpha: 1)\n    public static let base = UIColor(red: 0/255, green: 150/255, blue: 136/255, alpha: 1)\n    public static let darken1 = UIColor(red: 0/255, green: 137/255, blue: 123/255, alpha: 1)\n    public static let darken2 = UIColor(red: 0/255, green: 121/255, blue: 107/255, alpha: 1)\n    public static let darken3 = UIColor(red: 0/255, green: 105/255, blue: 92/255, alpha: 1)\n    public static let darken4 = UIColor(red: 0/255, green: 77/255, blue: 64/255, alpha: 1)\n    public static let accent1 = UIColor(red: 167/255, green: 255/255, blue: 235/255, alpha: 1)\n    public static let accent2 = UIColor(red: 100/255, green: 255/255, blue: 218/255, alpha: 1)\n    public static let accent3 = UIColor(red: 29/255, green: 233/255, blue: 182/255, alpha: 1)\n    public static let accent4 = UIColor(red: 0/255, green: 191/255, blue: 165/255, alpha: 1)\n  }\n  \n  // green\n  open class green: ColorPalette {\n    public static let lighten5 = UIColor(red: 232/255, green: 245/255, blue: 233/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 200/255, green: 230/255, blue: 201/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 165/255, green: 214/255, blue: 167/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 129/255, green: 199/255, blue: 132/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 102/255, green: 187/255, blue: 106/255, alpha: 1)\n    public static let base = UIColor(red: 76/255, green: 175/255, blue: 80/255, alpha: 1)\n    public static let darken1 = UIColor(red: 67/255, green: 160/255, blue: 71/255, alpha: 1)\n    public static let darken2 = UIColor(red: 56/255, green: 142/255, blue: 60/255, alpha: 1)\n    public static let darken3 = UIColor(red: 46/255, green: 125/255, blue: 50/255, alpha: 1)\n    public static let darken4 = UIColor(red: 27/255, green: 94/255, blue: 32/255, alpha: 1)\n    public static let accent1 = UIColor(red: 185/255, green: 246/255, blue: 202/255, alpha: 1)\n    public static let accent2 = UIColor(red: 105/255, green: 240/255, blue: 174/255, alpha: 1)\n    public static let accent3 = UIColor(red: 0/255, green: 230/255, blue: 118/255, alpha: 1)\n    public static let accent4 = UIColor(red: 0/255, green: 200/255, blue: 83/255, alpha: 1)\n  }\n  \n  // light green\n  open class lightGreen: ColorPalette {\n    public static let lighten5 = UIColor(red: 241/255, green: 248/255, blue: 233/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 220/255, green: 237/255, blue: 200/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 197/255, green: 225/255, blue: 165/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 174/255, green: 213/255, blue: 129/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 156/255, green: 204/255, blue: 101/255, alpha: 1)\n    public static let base = UIColor(red: 139/255, green: 195/255, blue: 74/255, alpha: 1)\n    public static let darken1 = UIColor(red: 124/255, green: 179/255, blue: 66/255, alpha: 1)\n    public static let darken2 = UIColor(red: 104/255, green: 159/255, blue: 56/255, alpha: 1)\n    public static let darken3 = UIColor(red: 85/255, green: 139/255, blue: 47/255, alpha: 1)\n    public static let darken4 = UIColor(red: 51/255, green: 105/255, blue: 30/255, alpha: 1)\n    public static let accent1 = UIColor(red: 204/255, green: 255/255, blue: 144/255, alpha: 1)\n    public static let accent2 = UIColor(red: 178/255, green: 255/255, blue: 89/255, alpha: 1)\n    public static let accent3 = UIColor(red: 118/255, green: 255/255, blue: 3/255, alpha: 1)\n    public static let accent4 = UIColor(red: 100/255, green: 221/255, blue: 23/255, alpha: 1)\n  }\n  \n  // lime\n  open class lime: ColorPalette {\n    public static let lighten5 = UIColor(red: 249/255, green: 251/255, blue: 231/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 240/255, green: 244/255, blue: 195/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 230/255, green: 238/255, blue: 156/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 220/255, green: 231/255, blue: 117/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 212/255, green: 225/255, blue: 87/255, alpha: 1)\n    public static let base = UIColor(red: 205/255, green: 220/255, blue: 57/255, alpha: 1)\n    public static let darken1 = UIColor(red: 192/255, green: 202/255, blue: 51/255, alpha: 1)\n    public static let darken2 = UIColor(red: 175/255, green: 180/255, blue: 43/255, alpha: 1)\n    public static let darken3 = UIColor(red: 158/255, green: 157/255, blue: 36/255, alpha: 1)\n    public static let darken4 = UIColor(red: 130/255, green: 119/255, blue: 23/255, alpha: 1)\n    public static let accent1 = UIColor(red: 244/255, green: 255/255, blue: 129/255, alpha: 1)\n    public static let accent2 = UIColor(red: 238/255, green: 255/255, blue: 65/255, alpha: 1)\n    public static let accent3 = UIColor(red: 198/255, green: 255/255, blue: 0/255, alpha: 1)\n    public static let accent4 = UIColor(red: 174/255, green: 234/255, blue: 0/255, alpha: 1)\n  }\n  \n  // yellow\n  open class yellow: ColorPalette {\n    public static let lighten5 = UIColor(red: 255/255, green: 253/255, blue: 231/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 255/255, green: 249/255, blue: 196/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 255/255, green: 245/255, blue: 157/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 255/255, green: 241/255, blue: 118/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 255/255, green: 238/255, blue: 88/255, alpha: 1)\n    public static let base = UIColor(red: 255/255, green: 235/255, blue: 59/255, alpha: 1)\n    public static let darken1 = UIColor(red: 253/255, green: 216/255, blue: 53/255, alpha: 1)\n    public static let darken2 = UIColor(red: 251/255, green: 192/255, blue: 45/255, alpha: 1)\n    public static let darken3 = UIColor(red: 249/255, green: 168/255, blue: 37/255, alpha: 1)\n    public static let darken4 = UIColor(red: 245/255, green: 127/255, blue: 23/255, alpha: 1)\n    public static let accent1 = UIColor(red: 255/255, green: 255/255, blue: 141/255, alpha: 1)\n    public static let accent2 = UIColor(red: 255/255, green: 255/255, blue: 0/255, alpha: 1)\n    public static let accent3 = UIColor(red: 255/255, green: 234/255, blue: 0/255, alpha: 1)\n    public static let accent4 = UIColor(red: 255/255, green: 214/255, blue: 0/255, alpha: 1)\n  }\n  \n  // amber\n  open class amber: ColorPalette {\n    public static let lighten5 = UIColor(red: 255/255, green: 248/255, blue: 225/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 255/255, green: 236/255, blue: 179/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 255/255, green: 224/255, blue: 130/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 255/255, green: 213/255, blue: 79/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 255/255, green: 202/255, blue: 40/255, alpha: 1)\n    public static let base = UIColor(red: 255/255, green: 193/255, blue: 7/255, alpha: 1)\n    public static let darken1 = UIColor(red: 255/255, green: 179/255, blue: 0/255, alpha: 1)\n    public static let darken2 = UIColor(red: 255/255, green: 160/255, blue: 0/255, alpha: 1)\n    public static let darken3 = UIColor(red: 255/255, green: 143/255, blue: 0/255, alpha: 1)\n    public static let darken4 = UIColor(red: 255/255, green: 111/255, blue: 0/255, alpha: 1)\n    public static let accent1 = UIColor(red: 255/255, green: 229/255, blue: 127/255, alpha: 1)\n    public static let accent2 = UIColor(red: 255/255, green: 215/255, blue: 64/255, alpha: 1)\n    public static let accent3 = UIColor(red: 255/255, green: 196/255, blue: 0/255, alpha: 1)\n    public static let accent4 = UIColor(red: 255/255, green: 171/255, blue: 0/255, alpha: 1)\n  }\n  \n  // orange\n  open class orange: ColorPalette {\n    public static let lighten5 = UIColor(red: 255/255, green: 243/255, blue: 224/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 255/255, green: 224/255, blue: 178/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 255/255, green: 204/255, blue: 128/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 255/255, green: 183/255, blue: 77/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 255/255, green: 167/255, blue: 38/255, alpha: 1)\n    public static let base = UIColor(red: 255/255, green: 152/255, blue: 0/255, alpha: 1)\n    public static let darken1 = UIColor(red: 251/255, green: 140/255, blue: 0/255, alpha: 1)\n    public static let darken2 = UIColor(red: 245/255, green: 124/255, blue: 0/255, alpha: 1)\n    public static let darken3 = UIColor(red: 239/255, green: 108/255, blue: 0/255, alpha: 1)\n    public static let darken4 = UIColor(red: 230/255, green: 81/255, blue: 0/255, alpha: 1)\n    public static let accent1 = UIColor(red: 255/255, green: 209/255, blue: 128/255, alpha: 1)\n    public static let accent2 = UIColor(red: 255/255, green: 171/255, blue: 64/255, alpha: 1)\n    public static let accent3 = UIColor(red: 255/255, green: 145/255, blue: 0/255, alpha: 1)\n    public static let accent4 = UIColor(red: 255/255, green: 109/255, blue: 0/255, alpha: 1)\n  }\n  \n  \n  // deep orange\n  open class deepOrange: ColorPalette {\n    public static let lighten5 = UIColor(red: 251/255, green: 233/255, blue: 231/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 255/255, green: 204/255, blue: 188/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 255/255, green: 171/255, blue: 145/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 255/255, green: 138/255, blue: 101/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 255/255, green: 112/255, blue: 67/255, alpha: 1)\n    public static let base = UIColor(red: 255/255, green: 87/255, blue: 34/255, alpha: 1)\n    public static let darken1 = UIColor(red: 244/255, green: 81/255, blue: 30/255, alpha: 1)\n    public static let darken2 = UIColor(red: 230/255, green: 74/255, blue: 25/255, alpha: 1)\n    public static let darken3 = UIColor(red: 216/255, green: 67/255, blue: 21/255, alpha: 1)\n    public static let darken4 = UIColor(red: 191/255, green: 54/255, blue: 12/255, alpha: 1)\n    public static let accent1 = UIColor(red: 255/255, green: 158/255, blue: 128/255, alpha: 1)\n    public static let accent2 = UIColor(red: 255/255, green: 110/255, blue: 64/255, alpha: 1)\n    public static let accent3 = UIColor(red: 255/255, green: 61/255, blue: 0/255, alpha: 1)\n    public static let accent4 = UIColor(red: 221/255, green: 44/255, blue: 0/255, alpha: 1)\n  }\n  \n  \n  // brown\n  open class brown: ColorPalette {\n    public static let lighten5 = UIColor(red: 239/255, green: 235/255, blue: 233/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 215/255, green: 204/255, blue: 200/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 188/255, green: 170/255, blue: 164/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 161/255, green: 136/255, blue: 127/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 141/255, green: 110/255, blue: 99/255, alpha: 1)\n    public static let base = UIColor(red: 121/255, green: 85/255, blue: 72/255, alpha: 1)\n    public static let darken1 = UIColor(red: 109/255, green: 76/255, blue: 65/255, alpha: 1)\n    public static let darken2 = UIColor(red: 93/255, green: 64/255, blue: 55/255, alpha: 1)\n    public static let darken3 = UIColor(red: 78/255, green: 52/255, blue: 46/255, alpha: 1)\n    public static let darken4 = UIColor(red: 62/255, green: 39/255, blue: 35/255, alpha: 1)\n  }\n  \n  // grey\n  open class grey: ColorPalette {\n    public static let lighten5 = UIColor(red: 250/255, green: 250/255, blue: 250/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 245/255, green: 245/255, blue: 245/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 238/255, green: 238/255, blue: 238/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 224/255, green: 224/255, blue: 224/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 189/255, green: 189/255, blue: 189/255, alpha: 1)\n    public static let base = UIColor(red: 158/255, green: 158/255, blue: 158/255, alpha: 1)\n    public static let darken1 = UIColor(red: 117/255, green: 117/255, blue: 117/255, alpha: 1)\n    public static let darken2 = UIColor(red: 97/255, green: 97/255, blue: 97/255, alpha: 1)\n    public static let darken3 = UIColor(red: 66/255, green: 66/255, blue: 66/255, alpha: 1)\n    public static let darken4 = UIColor(red: 33/255, green: 33/255, blue: 33/255, alpha: 1)\n  }\n  \n  // blue grey\n  open class blueGrey: ColorPalette {\n    public static let lighten5 = UIColor(red: 236/255, green: 239/255, blue: 241/255, alpha: 1)\n    public static let lighten4 = UIColor(red: 207/255, green: 216/255, blue: 220/255, alpha: 1)\n    public static let lighten3 = UIColor(red: 176/255, green: 190/255, blue: 197/255, alpha: 1)\n    public static let lighten2 = UIColor(red: 144/255, green: 164/255, blue: 174/255, alpha: 1)\n    public static let lighten1 = UIColor(red: 120/255, green: 144/255, blue: 156/255, alpha: 1)\n    public static let base = UIColor(red: 96/255, green: 125/255, blue: 139/255, alpha: 1)\n    public static let darken1 = UIColor(red: 84/255, green: 110/255, blue: 122/255, alpha: 1)\n    public static let darken2 = UIColor(red: 69/255, green: 90/255, blue: 100/255, alpha: 1)\n    public static let darken3 = UIColor(red: 55/255, green: 71/255, blue: 79/255, alpha: 1)\n    public static let darken4 = UIColor(red: 38/255, green: 50/255, blue: 56/255, alpha: 1)\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Data/DataSourceItem.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\npublic struct DataSourceItem {\n  /// Stores an the data for the item.\n  public var data: Any?\n  \n  /// Width for horizontal scroll direction.\n  public var width: CGFloat?\n  \n  /// Height for vertical scroll direction.\n  public var height: CGFloat?\n  \n  /**\n   Initializer.\n   - Parameter data: A reference to an Any that is associated\n   with a width or height.\n   - Parameter width: The width for the horizontal scroll direction.\n   - Parameter height: The height for the vertical scroll direction.\n   */\n  public init(data: Any? = nil, width: CGFloat? = nil, height: CGFloat? = nil) {\n    self.data = data\n    self.width = width\n    self.height = height\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Device/Device.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(DeviceModel)\npublic enum DeviceModel: Int {\n  case iPodTouch5\n  case iPodTouch6\n  case iPhone4\n  case iPhone4s\n  case iPhone5\n  case iPhone5c\n  case iPhone5s\n  case iPhone6\n  case iPhone6Plus\n  case iPhone6s\n  case iPhone6sPlus\n  case iPhone7\n  case iPhone7Plus\n  case iPhone8\n  case iPhone8Plus\n  case iPhoneX\n  case iPhoneXS\n  case iPhoneXSMax\n  case iPhoneXR\n  case iPhoneSE\n  case iPad2\n  case iPad3\n  case iPad4\n  case iPadAir\n  case iPadAir2\n  case iPadMini\n  case iPadMini2\n  case iPadMini3\n  case iPadMini4\n  case iPadPro\n  case iPadProLarge\n  case iPad5\n  case iPadPro2\n  case iPadProLarge2\n  case iPad6\n  case iPadPro3       //iPad Pro (11-inch)\n  case iPadProLarge3  //iPad Pro (12.9-inch) (3rd generation)\n  case appleTv\n  case appleTv4k\n  case homePod\n  case simulator\n  case unknown\n}\n\npublic struct Device {\n  /// Gets the Device identifier String.\n  public static var identifier: String {\n    var systemInfo = utsname()\n    uname(&systemInfo)\n    \n    let machineMirror = Mirror(reflecting: systemInfo.machine)\n    let identifier = machineMirror.children.reduce(\"\") { (identifier, element) in\n      guard let value = element.value as? Int8, value != 0 else {\n        return identifier\n      }\n      return identifier + String(UnicodeScalar(UInt8(value)))\n    }\n    return identifier\n  }\n  \n  /// Gets the model name for the device.\n  public static var model: DeviceModel {\n    switch identifier {\n    case \"iPod5,1\":                                     return .iPodTouch5\n    case \"iPod7,1\":                                     return .iPodTouch6\n    case \"iPhone4,1\":                                   return .iPhone4s\n    case \"iPhone5,1\", \"iPhone5,2\":                      return .iPhone5\n    case \"iPhone5,3\", \"iPhone5,4\":                      return .iPhone5c\n    case \"iPhone6,1\", \"iPhone6,2\":                      return .iPhone5s\n    case \"iPhone7,2\":                                   return .iPhone6\n    case \"iPhone7,1\":                                   return .iPhone6Plus\n    case \"iPhone8,1\":                                   return .iPhone6s\n    case \"iPhone8,2\":                                   return .iPhone6sPlus\n    case \"iPhone8,3\", \"iPhone8,4\":                      return .iPhoneSE\n    case \"iPhone9,1\", \"iPhone9,3\":                      return .iPhone7\n    case \"iPhone9,2\", \"iPhone9,4\":                      return .iPhone7Plus\n    case \"iPhone10,1\", \"iPhone10,4\":                    return .iPhone8\n    case \"iPhone10,2\", \"iPhone10,5\":                    return .iPhone8Plus\n    case \"iPhone10,3\",\"iPhone10,6\":                     return .iPhoneX\n    case \"iPad2,1\", \"iPad2,2\", \"iPad2,3\", \"iPad2,4\":    return .iPad2\n    case \"iPad3,1\", \"iPad3,2\", \"iPad3,3\":               return .iPad3\n    case \"iPad3,4\", \"iPad3,5\", \"iPad3,6\":               return .iPad4\n    case \"iPad4,1\", \"iPad4,2\", \"iPad4,3\":               return .iPadAir\n    case \"iPad5,3\", \"iPad5,4\":                          return .iPadAir2\n    case \"iPad2,5\", \"iPad2,6\", \"iPad2,7\":               return .iPadMini\n    case \"iPad4,4\", \"iPad4,5\", \"iPad4,6\":               return .iPadMini2\n    case \"iPad4,7\", \"iPad4,8\", \"iPad4,9\":               return .iPadMini3\n    case \"iPad5,1\", \"iPad5,2\":                          return .iPadMini4\n    case \"iPad6,3\", \"iPad6,4\":                          return .iPadPro\n    case \"iPad6,7\", \"iPad6,8\":                          return .iPadProLarge\n    case \"iPad6,11\", \"iPad6,12\":                        return .iPad5\n    case \"iPad7,3\", \"iPad7,4\":                          return .iPadPro2\n    case \"iPad7,1\", \"iPad7,2\":                          return .iPadProLarge2\n    case \"iPad7,5\", \"iPad7,6\":                          return .iPad6\n    case \"i386\", \"x86_64\":                              return .simulator\n    case \"iPhone3,1\", \"iPhone3,2\", \"iPhone3,3\":         return .iPhone4\n    case \"iPhone11,2\":                                  return .iPhoneXS\n    case \"iPhone11,4\", \"iPhone11,6\":                    return .iPhoneXSMax\n    case \"iPhone11,8\":                                  return .iPhoneXR\n    case \"iPad8,1\", \"iPad8,2\", \"iPad8,3\", \"iPad8,4\":   return .iPadPro3\n    case \"iPad8,5\", \"iPad8,6\", \"iPad8,7\", \"iPad8,8\":   return .iPadProLarge3\n    case \"AppleTV5,3\":                                  return .appleTv\n    case \"AppleTV6,2\":                                  return .appleTv4k\n    case \"AudioAccessory1,1\":                           return .homePod\n    default:                                            return .unknown\n    }\n  }\n  \n  /// Retrieves the current device type.\n  public static var userInterfaceIdiom: UIUserInterfaceIdiom {\n    return UIDevice.current.userInterfaceIdiom\n  }\n}\n\n\npublic func ==(lhs: DeviceModel, rhs: DeviceModel) -> Bool {\n  return lhs.rawValue == rhs.rawValue\n}\n\npublic func !=(lhs: DeviceModel, rhs: DeviceModel) -> Bool {\n  return lhs.rawValue != rhs.rawValue\n}\n\n"
  },
  {
    "path": "Sources/iOS/Dialogs/Dialog.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\n@objc\npublic protocol DialogDelegate {\n  /**\n   A delegation method that is executed when the Dialog is cancelled through tapping background.\n   - Parameter _ dialog: A Dialog.\n   */\n  @objc\n  optional func dialogDidCancel(_ dialog: Dialog)\n  \n  /**\n   A delegation method that is executed when the Dialog will appear.\n   - Parameter _ dialog: A Dialog.\n   */\n  @objc\n  optional func dialogWillAppear(_ dialog: Dialog)\n  \n  /**\n   A delegation method that is executed when the Dialog did disappear.\n   - Parameter _ dialog: A Dialog.\n   */\n  @objc\n  optional func dialogDidDisappear(_ dialog: Dialog)\n  \n  /**\n   A delegation method that is executed to determine if the Dialog should be dismissed.\n   - Parameter _ dialog: A Dialog.\n   - Parameter shouldDismiss button: The tapped button. nil if dialog is being\n   cancelled through tapping background.\n   - Returns: A Boolean.\n   */\n  @objc\n  optional func dialog(_ dialog: Dialog, shouldDismiss button: Button?) -> Bool\n  \n  /**\n   A delegation method that is executed when the positive button of Dialog is tapped.\n   - Parameter _ dialog: A Dialog.\n   - Parameter didTapPositive button: A Button.\n   */\n  @objc\n  optional func dialog(_ dialog: Dialog, didTapPositive button: Button)\n  \n  /**\n   A delegation method that is executed when the negative button of Dialog is tapped.\n   - Parameter _ dialog: A Dialog.\n   - Parameter didTapNegative button: A Button.\n   */\n  @objc\n  optional func dialog(_ dialog: Dialog, didTapNegative button: Button)\n  \n  /**\n   A delegation method that is executed when the neutral button of Dialog is tapped.\n   - Parameter _ dialog: A Dialog.\n   - Parameter didTapNeutral button: A Button.\n   */\n  @objc\n  optional func dialog(_ dialog: Dialog, didTapNeutral button: Button)\n}\n\n/// A builder for DialogController.\nopen class Dialog: NSObject {\n  /// A reference to dialog controller.\n  public let controller = DialogController<DialogView>()\n  \n  /// A weak reference to DialogDelegate.\n  open weak var delegate: DialogDelegate?\n  \n  /// An empty initializer.\n  public override init() {\n    super.init()\n    \n    /// Set callbacks for delegate.\n    shouldDismiss(handler: nil)\n      .positive(nil, handler: nil)\n      .negative(nil, handler: nil)\n      .neutral(nil, handler: nil)\n      .isCancelable(controller.isCancelable, handler: nil)\n      .willAppear(handler: nil)\n      .didDisappear(handler: nil)\n  }\n  \n  /**\n   Sets title of the dialog.\n   - Parameter _ text: A string.\n   - Returns: Dialog itself to allow chaining.\n   */\n  @discardableResult\n  open func title(_ text: String?) -> Dialog {\n    dialogView.titleLabel.text = text\n    return self\n  }\n  \n  /**\n   Sets details of the dialog.\n   - Parameter _ text: A string.\n   - Returns: Dialog itself to allow chaining.\n   */\n  @discardableResult\n  open func details(_ text: String?) -> Dialog {\n    dialogView.detailsLabel.text = text\n    return self\n  }\n  \n  /**\n   Sets title and handler for positive button of dialog.\n   - Parameter _ title: A string.\n   - Parameter handler: A closure handling tap.\n   - Returns: Dialog itself to allow chaining.\n   */\n  @discardableResult\n  open func positive(_ title: String?, handler: (() -> Void)?) -> Dialog {\n    dialogView.positiveButton.title = title\n    controller.didTapPositiveButtonHandler = { [weak self] in\n      guard let strongSelf = self else { return }\n      strongSelf.delegate?.dialog?(strongSelf, didTapPositive: strongSelf.controller.dialogView.positiveButton)\n      handler?()\n    }\n    return self\n  }\n  \n  /**\n   Sets title and handler for negative button of dialog.\n   - Parameter _ title: A string.\n   - Parameter handler: A closure handling tap.\n   - Returns: Dialog itself to allow chaining.\n   */\n  @discardableResult\n  open func negative(_ title: String?, handler: (() -> Void)?) -> Dialog {\n    dialogView.negativeButton.title = title\n    controller.didTapNegativeButtonHandler = { [weak self] in\n      guard let strongSelf = self else { return }\n      strongSelf.delegate?.dialog?(strongSelf, didTapNegative: strongSelf.controller.dialogView.negativeButton)\n      handler?()\n    }\n    return self\n  }\n  \n  /**\n   Sets title and handler for neutral button of dialog.\n   - Parameter _ title: A string.\n   - Parameter handler: A closure handling tap.\n   - Returns: Dialog itself to allow chaining.\n   */\n  @discardableResult\n  open func neutral(_ title: String?, handler: (() -> Void)?) -> Dialog {\n    dialogView.neutralButton.title = title\n    controller.didTapNeutralButtonHandler = { [weak self] in\n      guard let strongSelf = self else { return }\n      strongSelf.delegate?.dialog?(strongSelf, didTapNeutral: strongSelf.controller.dialogView.neutralButton)\n      handler?()\n    }\n    return self\n  }\n  \n  /**\n   Sets cancelability of dialog and handler for when it's cancelled.\n   - Parameter _ value: A Bool.\n   - Parameter handler: A closure handling cancellation.\n   - Returns: Dialog itself to allow chaining.\n   */\n  @discardableResult\n  open func isCancelable(_ value: Bool, handler: (() -> Void)? = nil) -> Dialog {\n    controller.isCancelable = value\n    controller.didCancelHandler = { [weak self] in\n      guard let strongSelf = self else { return }\n      strongSelf.delegate?.dialogDidCancel?(strongSelf)\n      handler?()\n    }\n    return self\n  }\n  \n  /**\n   Sets should-dismiss handler of dialog which takes dialogView and tapped\n   button and returns a boolean indicating if dialog should be dismissed.\n   - Parameter handler: A closure handling if dialog can be dismissed.\n   - Returns: Dialog itself to allow chaining.\n   */\n  @discardableResult\n  open func shouldDismiss(handler: ((DialogView, Button?) -> Bool)?) -> Dialog {\n    controller.shouldDismissHandler = { [weak self] dialogView, button in\n      guard let strongSelf = self else { return true }\n      let d = strongSelf.delegate?.dialog?(strongSelf, shouldDismiss: button) ?? true\n      let h = handler?(dialogView, button) ?? true\n      return d && h\n    }\n    return self\n  }\n  \n  /**\n   Sets handler for when view controller will appear.\n   - Parameter handler: A closure handling the event.\n   - Returns: Dialog itself to allow chaining.\n   */\n  @discardableResult\n  open func willAppear(handler: (() -> Void)?) -> Dialog {\n    controller.willAppear = { [weak self] in\n      guard let strongSelf = self else { return }\n      strongSelf.delegate?.dialogWillAppear?(strongSelf)\n      handler?()\n    }\n    return self\n  }\n  \n  /**\n   Sets handler for when view controller did disappear.\n   - Parameter handler: A closure handling the event.\n   - Returns: Dialog itself to allow chaining.\n   */\n  @discardableResult\n  open func didDisappear(handler: (() -> Void)?) -> Dialog {\n    controller.didDisappear = { [weak self] in\n      guard let strongSelf = self else { return }\n      strongSelf.delegate?.dialogDidDisappear?(strongSelf)\n      handler?()\n      strongSelf.controller.dialog = nil\n    }\n    return self\n  }\n  \n  /**\n   Sets dialog delegate.\n   - Parameter delegate: A DialogDelegate.\n   - Returns: Dialog itself to allow chaining.\n   */\n  @discardableResult\n  open func delegate(_ delegate: DialogDelegate) -> Dialog {\n    self.delegate = delegate\n    return self\n  }\n  \n  /**\n   Presents dialog modally from given viewController.\n   - Parameter _ viewController: A UIViewController.\n   - Returns: Dialog itself to allow chaining.\n   */\n  @discardableResult\n  open func show(_ viewController: UIViewController) -> Dialog {\n    controller.dialog = self\n    viewController.present(controller, animated: true, completion: nil)\n    return self\n  }\n}\n\nprivate extension Dialog {\n  /// Returns dialogView of controller.\n  var dialogView: DialogView {\n    return controller.dialogView\n  }\n}\n\n/// A memory reference to companion Dialog instance.\nprivate var DialogKey: UInt8 = 0\n\nprivate extension DialogController {\n  /**\n   A Dialog instance attached to the dialog controller.\n   This is used to keep Dialog alive throughout the lifespan\n   of the controller.\n   */\n  var dialog: Dialog? {\n    get {\n      return AssociatedObject.get(base: self, key: &DialogKey) {\n        return nil\n      }\n    }\n    set(value) {\n      AssociatedObject.set(base: self, key: &DialogKey, value: value)\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Dialogs/DialogController.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n/// A UIViewController managing DialogView.\nopen class DialogController<T: DialogView>: UIViewController {\n  /// A reference to dialogView.\n  public let dialogView = T()\n  \n  /// A boolean indicating cancelability of dialog when user taps on background.\n  open var isCancelable = false\n  \n  /// A reference to did-cancel handler.\n  open var didCancelHandler: (() -> Void)?\n  \n  /**\n   A reference to should-dismiss handler which takes dialogView\n   and tapped button and returns Boolean indicating if dialog should be dismissed.\n   */\n  open var shouldDismissHandler: ((T, Button?) -> Bool)?\n  \n  /// A reference to handler for when positiveButton is tapped.\n  open var didTapPositiveButtonHandler: (() -> Void)?\n  \n  /// A reference to handler for when negativeButton is tapped.\n  open var didTapNegativeButtonHandler: (() -> Void)?\n  \n  /// A reference to handler for when neutralButton is tapped.\n  open var didTapNeutralButtonHandler: (() -> Void)?\n  \n  /// A reference to handler for when controller will appear.\n  open var willAppear: (() -> Void)?\n  \n  /// A reference to handler for when controller did disappear.\n  open var didDisappear: (() -> Void)?\n  \n  public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {\n    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)\n    prepare()\n  }\n  \n  required public init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n    prepare()\n  }\n  \n  /// Prepares controller for presentation.\n  open func prepare() {\n    isMotionEnabled = true\n    motionTransitionType = .fade\n    modalPresentationStyle = .overFullScreen\n  }\n  \n  open override func viewDidLoad() {\n    super.viewDidLoad()\n    prepareView()\n    prepareDialogView()\n  }\n  \n  open override func viewWillAppear(_ animated: Bool) {\n    super.viewWillAppear(animated)\n    willAppear?()\n  }\n  \n  open override func viewDidDisappear(_ animated: Bool) {\n    super.viewDidDisappear(animated)\n    didDisappear?()\n  }\n  \n  open override func viewWillLayoutSubviews() {\n    super.viewWillLayoutSubviews()\n    dialogView.maxSize = CGSize(width: Screen.width * 0.8, height: Screen.height * 0.9)\n  }\n  \n  /**\n   Dismisses dialog.\n   - Parameter isAnimated: A boolean.\n   */\n  open func dismiss(isAnimated: Bool = true) {\n    dismiss(isTriggeredByUserInteraction: false, isAnimated: isAnimated)\n  }\n  \n  /// Handler for when background scrim is tapped.\n  @objc\n  private func didTapBackgroundView() {\n    guard isCancelable else {\n      return\n    }\n    \n    dismiss(isTriggeredByUserInteraction: true, isAnimated: true)\n  }\n  \n  /// Handler for when one of 3 dialog buttons is tapped.\n  @objc\n  private func didTapButton(_ sender: Button) {\n    switch sender {\n    case dialogView.positiveButton:\n      didTapPositiveButtonHandler?()\n      \n    case dialogView.negativeButton:\n      didTapNegativeButtonHandler?()\n      \n    case dialogView.neutralButton:\n      didTapNeutralButtonHandler?()\n      \n    default:\n      break\n    }\n    \n    dismiss(isTriggeredByUserInteraction: true, isAnimated: true, using: sender)\n  }\n}\n\nprivate extension DialogController {\n  /// Prepares view.\n  func prepareView() {\n    let v = UIControl()\n    v.backgroundColor = Color.black.withAlphaComponent(0.33)\n    v.addTarget(self, action: #selector(didTapBackgroundView), for: .touchUpInside)\n    view = v\n  }\n  \n  /// Prepares dialogView.\n  func prepareDialogView() {\n    view.layout(dialogView).center()\n    dialogView.buttonArea.subviews.forEach {\n      ($0 as? Button)?.addTarget(self, action: #selector(didTapButton), for: .touchUpInside)\n    }\n  }\n}\n\nprivate extension DialogController {\n  /**\n   Dismisses dialog.\n   - Parameter isTriggeredByUserInteraction: A boolean indicating whether the action is\n   triggered by a user interaction\n   - Parameter isAnimated: A boolean indicating if the dismissal should be animated.\n   - Parameter using button: A button triggering the dismissal.\n   */\n  func dismiss(isTriggeredByUserInteraction: Bool, isAnimated: Bool, using button: Button? = nil) {\n    if isTriggeredByUserInteraction {\n      guard shouldDismissHandler?(dialogView, button) ?? true else {\n        return\n      }\n    }\n    \n    presentingViewController?.dismiss(animated: isAnimated, completion: nil)\n    \n    guard isTriggeredByUserInteraction, nil == button else {\n      return\n    }\n    \n    didCancelHandler?()\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Dialogs/DialogView.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nprivate struct Constants {\n  struct titleArea {\n    static let insets = UIEdgeInsets(top: 24, left: 24, bottom: 20, right: 24)\n  }\n  \n  struct contentArea {\n    static let insets = UIEdgeInsets(top: 0, left: 24, bottom: 24, right: 24)\n    static let insetsNoTitle = UIEdgeInsets(top: 20, left: 24, bottom: 24, right: 24)\n  }\n  \n  struct buttonArea {\n    static let insets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)\n    static let insetsStacked = UIEdgeInsets(top: 6, left: 8, bottom: 14, right: 8)\n  }\n  \n  struct button {\n    static let insets = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 8)\n    static let minWidth: CGFloat = 64\n    static let height: CGFloat = 36\n    static let interimStacked: CGFloat = 12\n    static let interim: CGFloat = 8\n  }\n}\n\nprivate class DialogScrollView: UIScrollView {\n  /// A weak reference to DialogView.\n  weak var dialogView: DialogView?\n  \n  override func layoutSubviews() {\n    super.layoutSubviews()\n    dialogView?.layoutDividers()\n  }\n}\n\nopen class DialogView: View, Themeable {\n  /// A container view for title area.\n  public let titleArea = UIView()\n  \n  /// A container view for button area.\n  public let buttonArea = UIView()\n  \n  /// A container view for content area.\n  public let contentArea = UIView()\n  \n  /// A scroll view containing contentArea.\n  public let scrollView: UIScrollView = DialogScrollView()\n  \n  /// A UILabel.\n  public let titleLabel = UILabel()\n  \n  /// A UILabel.\n  public let detailsLabel = UILabel()\n  \n  /// A Button.\n  public let neutralButton = FlatButton()\n  \n  /// A Button.\n  public let positiveButton = FlatButton()\n  \n  /// A Button.\n  public let negativeButton = FlatButton()\n  \n  /// Maximum size of the dialog.\n  open var maxSize = CGSize(width: 200, height: 300) {\n    didSet {\n      invalidateIntrinsicContentSize()\n    }\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    \n    depthPreset = .depth5\n    cornerRadiusPreset = .cornerRadius2\n    prepareTitleArea()\n    prepareTitleLabel()\n    prepareScrollView()\n    prepareContentArea()\n    prepareDetailsLabel()\n    prepareButtonArea()\n    prepareButtons()\n    applyCurrentTheme()\n  }\n  \n  open override var intrinsicContentSize: CGSize {\n    return sizeThatFits(maxSize)\n  }\n  \n  open override func sizeThatFits(_ size: CGSize) -> CGSize {\n    var w: CGFloat = 0\n    func setMaxWidth(_ width: CGFloat) {\n      w = max(w, width)\n      w = min(w, size.width)\n    }\n    \n    setMaxWidth(titleAreaSizeThatFits(width: size.width).width)\n    setMaxWidth(buttonAreaSizeThatFits(width: size.width).width)\n    setMaxWidth(contentAreaSizeThatFits(width: size.width).width)\n    \n    var h: CGFloat = 0\n    h += titleAreaSizeThatFits(width: w).height\n    h += buttonAreaSizeThatFits(width: w).height\n    h += contentAreaSizeThatFits(width: w).height\n    h = min(h, size.height)\n    \n    return CGSize(width: w, height: h)\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    \n    layoutTitleArea()\n    layoutButtonArea()\n    layoutContentArea()\n    layoutScrollView()\n    layoutDividers()\n    \n    /// Position button area after having correct sizes.\n    buttonArea.frame.origin.y = scrollView.frame.maxY\n  }\n  \n  /**\n   Calculates the size for title area that best fits the specified width.\n   - Parameter width: A CGFloat.\n   - Returns: Calculated CGSize.\n   */\n  open func titleAreaSizeThatFits(width: CGFloat) -> CGSize {\n    guard !titleLabel.isEmpty else {\n      return .zero\n    }\n    \n    let insets = Constants.titleArea.insets\n    var size = titleLabel.sizeThatFits(CGSize(width: width - insets.left - insets.right, height: .greatestFiniteMagnitude))\n    size.width += insets.left + insets.right\n    size.height += insets.top + insets.bottom\n    return size\n  }\n  \n  /**\n   Calculates the size for button area that best fits the specified width.\n   - Parameter width: A CGFloat.\n   - Returns: Calculated CGSize.\n   */\n  open func buttonAreaSizeThatFits(width: CGFloat) -> CGSize {\n    guard !nonHiddenButtons.isEmpty else {\n      return .zero\n    }\n    \n    let isStacked = requiredButtonAreaWidth > width\n    let buttonsHeight = Constants.button.height * CGFloat(isStacked ? nonHiddenButtons.count : 1)\n    let buttonsInterim = isStacked ? CGFloat(nonHiddenButtons.count - 1) * Constants.button.interimStacked : 0\n    let insets = isStacked ? Constants.buttonArea.insetsStacked : Constants.buttonArea.insets\n    let h = buttonsInterim + buttonsHeight + insets.bottom + insets.top\n    let w = min(width, isStacked ? requiredButtonAreaWidthForStacked : requiredButtonAreaWidth)\n    return CGSize(width: w, height: h)\n  }\n  \n  /**\n   Calculates the size for content area that best fits the specified width.\n   - Parameter width: A CGFloat.\n   - Returns: Calculated CGSize.\n   */\n  open func contentAreaSizeThatFits(width: CGFloat) -> CGSize {\n    guard !detailsLabel.isEmpty else {\n      return .zero\n    }\n    \n    let insets = titleLabel.isEmpty ? Constants.contentArea.insetsNoTitle : Constants.contentArea.insets\n    var size = detailsLabel.sizeThatFits(CGSize(width: width - insets.left - insets.right, height: .greatestFiniteMagnitude))\n    size.width += insets.left + insets.right\n    size.height += insets.top + insets.bottom\n    return size\n  }\n  \n  /**\n   Applies the given theme.\n   - Parameter theme: A Theme.\n   */\n  open func apply(theme: Theme) {\n    backgroundColor = theme.surface\n    titleLabel.textColor = theme.onSurface.withAlphaComponent(0.87)\n    detailsLabel.textColor = theme.onSurface.withAlphaComponent(0.60)\n    \n    titleArea.dividerColor = theme.onSurface.withAlphaComponent(0.12)\n    buttonArea.dividerColor = theme.onSurface.withAlphaComponent(0.12)\n  }\n}\n\nprivate extension DialogView {\n  /// Prepares titleArea.\n  func prepareTitleArea() {\n    addSubview(titleArea)\n    titleArea.dividerColor = Color.darkText.dividers\n    titleArea.dividerThickness = 1\n    titleArea.dividerAlignment = .bottom\n  }\n  \n  /// Prepares titleTitle.\n  func prepareTitleLabel() {\n    titleArea.addSubview(titleLabel)\n    titleLabel.font = Theme.font.bold(with: 20)\n    titleLabel.textColor = Color.darkText.primary\n    titleLabel.numberOfLines = 0\n  }\n  \n  /// Prepares buttonArea.\n  func prepareButtonArea() {\n    addSubview(buttonArea)\n    buttonArea.dividerColor = Color.darkText.dividers\n    buttonArea.dividerThickness = 1\n    buttonArea.dividerAlignment = .top\n  }\n  \n  /// Prepares buttons.\n  func prepareButtons() {\n    [positiveButton, negativeButton, neutralButton].forEach {\n      buttonArea.addSubview($0)\n      $0.titleLabel?.font = Theme.font.medium(with: 14)\n      $0.contentEdgeInsets = Constants.button.insets\n      $0.cornerRadiusPreset = .cornerRadius1\n    }\n  }\n  \n  /// Prepares scrollView.\n  func prepareScrollView() {\n    (scrollView as! DialogScrollView).dialogView = self\n    addSubview(scrollView)\n  }\n  \n  /// Prepares contentArea.\n  func prepareContentArea() {\n    scrollView.addSubview(contentArea)\n  }\n  \n  /// Prepares detailsLabel.\n  func prepareDetailsLabel() {\n    contentArea.addSubview(detailsLabel)\n    detailsLabel.font = Theme.font.regular(with: detailsLabel.fontSize)\n    detailsLabel.numberOfLines = 0\n    detailsLabel.textColor = Color.darkText.secondary\n  }\n}\n\nprivate extension DialogView {\n  /// Layout the titleArea.\n  func layoutTitleArea() {\n    let size = CGSize(width: frame.width, height: titleAreaSizeThatFits(width: frame.width).height)\n    titleArea.frame.size = size\n    \n    guard !titleLabel.isEmpty else {\n      return\n    }\n    \n    let rect = CGRect(origin: .zero, size: size)\n    titleLabel.frame = rect.inset(by: Constants.titleArea.insets)\n  }\n  \n  /// Layout the buttonArea.\n  func layoutButtonArea() {\n    let width = frame.width\n    buttonArea.frame.size.width = width\n    buttonArea.frame.size.height = buttonAreaSizeThatFits(width: width).height\n    \n    let buttons = nonHiddenButtons\n    guard !buttons.isEmpty else {\n      return\n    }\n    \n    let isStacked = requiredButtonAreaWidth > width\n    if isStacked {\n      let insets = Constants.buttonArea.insetsStacked\n      buttons.forEach {\n        let w = min($0.optimalWidth, width - insets.left - insets.right)\n        $0.frame.size = CGSize(width: w, height: Constants.button.height)\n        $0.frame.origin.x = width - insets.right - w\n      }\n      \n      positiveButton.frame.origin.y = insets.top\n      let belowPositive = positiveButton.isHidden ? insets.top : positiveButton.frame.maxY + Constants.button.interimStacked\n      negativeButton.frame.origin.y = belowPositive\n      neutralButton.frame.origin.y = negativeButton.isHidden ? belowPositive : negativeButton.frame.maxY + Constants.button.interimStacked\n    } else {\n      let insets = Constants.buttonArea.insets\n      buttons.forEach {\n        $0.frame.size = CGSize(width: $0.optimalWidth, height: Constants.button.height)\n        $0.frame.origin.y = insets.top\n      }\n      \n      neutralButton.frame.origin.x = insets.left\n      positiveButton.frame.origin.x = width - insets.right - positiveButton.frame.width\n      \n      let maxX = positiveButton.isHidden ? width - insets.right : positiveButton.frame.minX - Constants.button.interim\n      negativeButton.frame.origin.x = maxX - negativeButton.frame.width\n    }\n  }\n  \n  /// Layout the contentArea.\n  func layoutContentArea() {\n    let size = CGSize(width: frame.width, height: contentAreaSizeThatFits(width: frame.width).height)\n    contentArea.frame.size = size\n    guard !detailsLabel.isEmpty else {\n      return\n    }\n    \n    let rect = CGRect(origin: .zero, size: size)\n    let insets = titleArea.frame.height == 0 ? Constants.contentArea.insetsNoTitle : Constants.contentArea.insets\n    detailsLabel.frame = rect.inset(by: insets)\n  }\n  \n  /// Layout the scrollView.\n  func layoutScrollView() {\n    let h = titleArea.frame.height + buttonArea.frame.height\n    let allowed = min(frame.height - h, contentArea.frame.height)\n    \n    scrollView.frame.size = CGSize(width: frame.width, height: max(allowed, 0))\n    scrollView.frame.origin.y = titleArea.frame.maxY\n    \n    scrollView.contentSize = contentArea.frame.size\n  }\n  \n  /**\n   Layout the dividers.\n   This method is also called (by scrollView) when scrolling happens\n   */\n  func layoutDividers() {\n    let isScrollable = contentArea.frame.height > scrollView.frame.height\n    \n    titleArea.isDividerHidden = titleArea.frame.height == 0 || !isScrollable || scrollView.isAtTop\n    buttonArea.isDividerHidden =  buttonArea.frame.height == 0 || !isScrollable || scrollView.isAtBottom\n    \n    titleArea.layoutDivider()\n    buttonArea.layoutDivider()\n  }\n}\n\nprivate extension DialogView {\n  /// Required width to fit content of buttonArea.\n  var requiredButtonAreaWidth: CGFloat {\n    let buttons = nonHiddenButtons\n    guard !buttons.isEmpty else {\n      return 0\n    }\n    \n    let buttonsWidth: CGFloat = buttons.reduce(0) { $0 + $1.optimalWidth }\n    let additional: CGFloat = neutralButton.isHidden ? 0 : 8 // additional spacing for neutral button\n    let insets = Constants.buttonArea.insets\n    return buttonsWidth + insets.left + insets.right + CGFloat((buttons.count - 1)) * Constants.button.interim + additional\n  }\n  \n  /// Required width to fit statcked content of buttonArea.\n  var requiredButtonAreaWidthForStacked: CGFloat {\n    let insets = Constants.buttonArea.insetsStacked\n    return insets.left + insets.right + nonHiddenButtons.reduce(0) {\n      max($0, $1.optimalWidth)\n    }\n  }\n  \n  /// Non-hidden buttons within buttonArea.\n  var nonHiddenButtons: [Button] {\n    positiveButton.isHidden = positiveButton.title(for: .normal)?.isEmpty ?? true\n    negativeButton.isHidden = negativeButton.title(for: .normal)?.isEmpty ?? true\n    neutralButton.isHidden = neutralButton.title(for: .normal)?.isEmpty ?? true\n    return [positiveButton, negativeButton, neutralButton].filter { !$0.isHidden }\n  }\n}\n\nprivate extension UIScrollView {\n  /// Checks if scroll view is at the top.\n  var isAtTop: Bool {\n    return contentOffset.y <= 0\n  }\n  \n  /// Checks if scroll view is at the bottom.\n  var isAtBottom: Bool {\n    /// -1 is used to get rid of precision errors\n    /// make divider appear even when scroll is at the bottom.\n    return contentOffset.y >= (contentSize.height - frame.height - 1)\n  }\n}\n\nprivate extension Button {\n  /// Optimal width for dialog button.\n  var optimalWidth: CGFloat {\n    let size = CGSize(width: .greatestFiniteMagnitude, height: Constants.button.height)\n    return max(Constants.button.minWidth, sizeThatFits(size).width)\n  }\n}\n\nprivate extension UILabel {\n  /// Checks if label is empty.\n  var isEmpty: Bool {\n    let empty = text?.isEmpty ?? true\n    isHidden = empty\n    return empty\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Divider/Divider.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\n@objc(DividerAlignment)\npublic enum DividerAlignment: Int {\n  case top\n  case left\n  case bottom\n  case right\n}\n\npublic struct Divider {\n  /// A reference to the UIView.\n  internal weak var view: UIView?\n  \n  /// A reference to the divider UIView.\n  internal var line: UIView?\n  \n  /// A reference to the height.\n  public var thickness: CGFloat {\n    didSet {\n      reload()\n    }\n  }\n  \n  /// A preset wrapper around contentEdgeInsets.\n  public var contentEdgeInsetsPreset = EdgeInsetsPreset.none {\n    didSet {\n      contentEdgeInsets = EdgeInsetsPresetToValue(preset: contentEdgeInsetsPreset)\n    }\n  }\n  \n  /// A reference to EdgeInsets.\n  public var contentEdgeInsets = EdgeInsets.zero {\n    didSet {\n      reload()\n    }\n  }\n  \n  /// A UIColor.\n  public var color: UIColor? {\n    get {\n      return line?.backgroundColor\n    }\n    set(value) {\n      guard let v = value else {\n        line?.removeFromSuperview()\n        line = nil\n        return\n      }\n      if nil == line {\n        line = UIView()\n        line?.layer.zPosition = 5000\n        view?.addSubview(line!)\n        reload()\n      }\n      line?.backgroundColor = v\n    }\n  }\n  \n  /// A reference to the dividerAlignment.\n  public var alignment = DividerAlignment.bottom {\n    didSet {\n      reload()\n    }\n  }\n  \n  /**\n   Initializer that takes in a UIView.\n   - Parameter view: A UIView reference.\n   - Parameter thickness: A CGFloat value.\n   */\n  internal init(view: UIView?, thickness: CGFloat = 1) {\n    self.view = view\n    self.thickness = thickness\n  }\n  \n  /**\n   Hides the divier line.\n   */\n  internal var isHidden = false {\n    didSet {\n      line?.isHidden = isHidden\n    }\n  }\n  \n  /// Lays out the divider.\n  public func reload() {\n    guard let l = line, let v = view else {\n      return\n    }\n    \n    let c = contentEdgeInsets\n    \n    switch alignment {\n    case .top:\n      l.frame = CGRect(x: c.left, y: c.top, width: v.bounds.width - c.left - c.right, height: thickness)\n    case .bottom:\n      l.frame = CGRect(x: c.left, y: v.bounds.height - thickness - c.bottom, width: v.bounds.width - c.left - c.right, height: thickness)\n    case .left:\n      l.frame = CGRect(x: c.left, y: c.top, width: thickness, height: v.bounds.height - c.top - c.bottom)\n    case .right:\n      l.frame = CGRect(x: v.bounds.width - thickness - c.right, y: c.top, width: thickness, height: v.bounds.height - c.top - c.bottom)\n    }\n  }\n}\n\n/// A memory reference to the Divider instance.\nfileprivate var DividerKey: UInt8 = 0\n\nextension UIView {\n  /// TabBarItem reference.\n  public private(set) var divider: Divider {\n    get {\n      return AssociatedObject.get(base: self, key: &DividerKey) {\n        return Divider(view: self)\n      }\n    }\n    set(value) {\n      AssociatedObject.set(base: self, key: &DividerKey, value: value)\n    }\n  }\n  \n  /// A preset wrapper around divider.contentEdgeInsets.\n  open var dividerContentEdgeInsetsPreset: EdgeInsetsPreset {\n    get {\n      return divider.contentEdgeInsetsPreset\n    }\n    set(value) {\n      divider.contentEdgeInsetsPreset = value\n    }\n  }\n  \n  /// A reference to divider.contentEdgeInsets.\n  open var dividerContentEdgeInsets: EdgeInsets {\n    get {\n      return divider.contentEdgeInsets\n    }\n    set(value) {\n      divider.contentEdgeInsets = value\n    }\n  }\n  \n  /// Divider color.\n  @IBInspectable\n  open var dividerColor: UIColor? {\n    get {\n      return divider.color\n    }\n    set(value) {\n      divider.color = value\n    }\n  }\n  \n  /// Divider visibility.\n  @IBInspectable\n  open var isDividerHidden: Bool {\n    get {\n      return divider.isHidden\n    }\n    set(value) {\n      divider.isHidden = value\n    }\n  }\n  \n  /// Divider animation.\n  open var dividerAlignment: DividerAlignment {\n    get {\n      return divider.alignment\n    }\n    set(value) {\n      divider.alignment = value\n    }\n  }\n  \n  /// Divider thickness.\n  @IBInspectable\n  open var dividerThickness: CGFloat {\n    get {\n      return divider.thickness\n    }\n    set(value) {\n      divider.thickness = value\n    }\n  }\n  \n  /// Sets the divider frame.\n  open func layoutDivider() {\n    divider.reload()\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Extension/Material+Array.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nextension Array where Element: Equatable {\n  /**\n   Slices a out a segment of an array based on the start\n   and end positions.\n   - Parameter start: A start index.\n   - Parameter end: An end index.\n   - Returns: A segmented array based on the start and end\n   indices.\n   */\n  public func slice(start: Int, end: Int?) -> [Element] {\n    var e = end ?? count - 1\n    if e >= count {\n      e = count - 1\n    }\n    \n    guard -1 < start else {\n      fatalError(\"Range out of bounds for \\(start) - \\(end ?? 0), should be 0 - \\(count).\")\n    }\n    \n    var diff = abs(e - start)\n    guard count > diff else {\n      return self\n    }\n    \n    var ret = [Element]()\n    while -1 < diff {\n      ret.insert(self[start + diff], at: 0)\n      diff -= 1\n    }\n    \n    return ret\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Extension/Material+CALayer.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\nfileprivate class MaterialLayer {\n  /// A reference to the CALayer.\n  fileprivate weak var layer: CALayer?\n  \n  /// A property that sets the height of the layer's frame.\n  fileprivate var heightPreset = HeightPreset.default {\n    didSet {\n      layer?.height = heightPreset.rawValue\n    }\n  }\n  \n  /// A property that sets the cornerRadius of the backing layer.\n  fileprivate var cornerRadiusPreset = CornerRadiusPreset.none {\n    didSet {\n      layer?.cornerRadius = CornerRadiusPresetToValue(preset: cornerRadiusPreset)\n    }\n  }\n  \n  /// A preset property to set the borderWidth.\n  fileprivate var borderWidthPreset = BorderWidthPreset.none {\n    didSet {\n      layer?.borderWidth = borderWidthPreset.cgFloatValue\n    }\n  }\n  \n  /// A preset property to set the shape.\n  fileprivate var shapePreset = ShapePreset.none {\n    didSet {\n      layer?.layoutShape()\n    }\n  }\n  \n  /// A preset value for Depth.\n  fileprivate var depthPreset: DepthPreset {\n    get {\n      return depth.preset\n    }\n    set(value) {\n      depth.preset = value\n    }\n  }\n  \n  /// Grid reference.\n  fileprivate var depth = Depth.zero {\n    didSet {\n      guard let v = layer else {\n        return\n      }\n      \n      v.shadowOffset = depth.offset.asSize\n      v.shadowOpacity = depth.opacity\n      v.shadowRadius = depth.radius\n      v.layoutShadowPath()\n    }\n  }\n  \n  /// Enables automatic shadowPath sizing.\n  fileprivate var isShadowPathAutoSizing = false\n  \n  /**\n   Initializer that takes in a CALayer.\n   - Parameter view: A CALayer reference.\n   */\n  fileprivate init(layer: CALayer?) {\n    self.layer = layer\n  }\n}\n\nfileprivate var MaterialLayerKey: UInt8 = 0\n\nextension CALayer {\n  /// MaterialLayer Reference.\n  fileprivate var materialLayer: MaterialLayer {\n    get {\n      return AssociatedObject.get(base: self, key: &MaterialLayerKey) {\n        return MaterialLayer(layer: self)\n      }\n    }\n    set(value) {\n      AssociatedObject.set(base: self, key: &MaterialLayerKey, value: value)\n    }\n  }\n  \n  /// A property that accesses the frame.origin.x property.\n  @IBInspectable\n  open var x: CGFloat {\n    get {\n      return frame.origin.x\n    }\n    set(value) {\n      frame.origin.x = value\n      \n      layoutShadowPath()\n    }\n  }\n  \n  /// A property that accesses the frame.origin.y property.\n  @IBInspectable\n  open var y: CGFloat {\n    get {\n      return frame.origin.y\n    }\n    set(value) {\n      frame.origin.y = value\n      \n      layoutShadowPath()\n    }\n  }\n  \n  /// A property that accesses the frame.size.width property.\n  @IBInspectable\n  open var width: CGFloat {\n    get {\n      return frame.size.width\n    }\n    set(value) {\n      frame.size.width = value\n      \n      if .none != shapePreset {\n        frame.size.height = value\n        layoutShape()\n      }\n      \n      layoutShadowPath()\n    }\n  }\n  \n  /// A property that accesses the frame.size.height property.\n  @IBInspectable\n  open var height: CGFloat {\n    get {\n      return frame.size.height\n    }\n    set(value) {\n      frame.size.height = value\n      \n      if .none != shapePreset {\n        frame.size.width = value\n        layoutShape()\n      }\n      \n      layoutShadowPath()\n    }\n  }\n  \n  /// HeightPreset value.\n  open var heightPreset: HeightPreset {\n    get {\n      return materialLayer.heightPreset\n    }\n    set(value) {\n      materialLayer.heightPreset = value\n    }\n  }\n  \n  /**\n   A property that manages the overall shape for the object. If either the\n   width or height property is set, the other will be automatically adjusted\n   to maintain the shape of the object.\n   */\n  open var shapePreset: ShapePreset {\n    get {\n      return materialLayer.shapePreset\n    }\n    set(value) {\n      materialLayer.shapePreset = value\n    }\n  }\n  \n  /// A preset value for Depth.\n  open var depthPreset: DepthPreset {\n    get {\n      return depth.preset\n    }\n    set(value) {\n      depth.preset = value\n    }\n  }\n  \n  /// Grid reference.\n  open var depth: Depth {\n    get {\n      return materialLayer.depth\n    }\n    set(value) {\n      materialLayer.depth = value\n    }\n  }\n  \n  /// Enables automatic shadowPath sizing.\n  @IBInspectable\n  open var isShadowPathAutoSizing: Bool {\n    get {\n      return materialLayer.isShadowPathAutoSizing\n    }\n    set(value) {\n      materialLayer.isShadowPathAutoSizing = value\n    }\n  }\n  \n  /// A property that sets the cornerRadius of the backing layer.\n  open var cornerRadiusPreset: CornerRadiusPreset {\n    get {\n      return materialLayer.cornerRadiusPreset\n    }\n    set(value) {\n      materialLayer.cornerRadiusPreset = value\n    }\n  }\n  \n  /// A preset property to set the borderWidth.\n  open var borderWidthPreset: BorderWidthPreset {\n    get {\n      return materialLayer.borderWidthPreset\n    }\n    set(value) {\n      materialLayer.borderWidthPreset = value\n    }\n  }\n}\n\nextension CALayer {\n  /// Manages the layout for the shape of the view instance.\n  open func layoutShape() {\n    guard .none != shapePreset else {\n      return\n    }\n    \n    if 0 == bounds.width {\n      bounds.size.width = bounds.height\n    }\n    \n    if 0 == bounds.height {\n      bounds.size.height = bounds.width\n    }\n    \n    guard .circle == shapePreset else {\n      cornerRadius = 0\n      return\n    }\n    \n    cornerRadius = bounds.width / 2\n  }\n  \n  /// Sets the shadow path.\n  open func layoutShadowPath() {\n    guard isShadowPathAutoSizing else {\n      return\n    }\n    \n    if case .none = depthPreset.rawValue {\n      shadowPath = nil\n    } else if nil == shadowPath {\n      shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius).cgPath\n    } else {\n      animate(.shadow(path: UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius).cgPath))\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Extension/Material+MotionAnimation.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\npublic extension MotionAnimation {\n  /**\n   Animates the view's current shadow offset to the given one.\n   - Parameter offset: A CGSize.\n   - Returns: A MotionAnimation.\n   */\n  static func shadow(offset: Offset) -> MotionAnimation {\n    return .shadow(offset: offset.asSize)\n  }\n  \n  /**\n   Animates the views shadow offset, opacity, and radius using a DepthPreset.\n   - Parameter _ preset: A DepthPreset.\n   */\n  static func depth(_ preset: DepthPreset) -> MotionAnimation {\n    return .depth(DepthPresetToValue(preset: preset).rawValue)\n  }\n  \n  /**\n   Animates the views shadow offset, opacity, and radius using a given Depth.\n   - Parameter _ preset: A Depth.\n   */\n  static func depth(_ depth: Depth) -> MotionAnimation {\n    return .depth(depth.rawValue)\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Extension/Material+NSMutableAttributedString.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nextension NSMutableAttributedString {\n  /**\n   Updates a NSAttributedStringKey for a given range.\n   - Parameter _ name: A NSAttributedStringKey.\n   - Parameter value: Any type.\n   - Parameter range: A NSRange.\n   */\n  open func updateAttribute(_ name: NSAttributedString.Key, value: Any, range: NSRange) {\n    removeAttribute(name, range: range)\n    addAttribute(name, value: value, range: range)\n  }\n  \n  /**\n   Updates a Dictionary of NSAttributedStringKeys for a given range.\n   - Parameter _ attrs: A Dictionary of NSAttributedStringKey type keys and Any type values.\n   - Parameter range: A NSRange.\n   */\n  open func updateAttributes(_ attrs: [NSAttributedString.Key: Any], range: NSRange) {\n    for (k, v) in attrs {\n      updateAttribute(k, value: v, range: range)\n    }\n  }\n  \n  /**\n   Removes a Dictionary of NSAttributedStringKeys for a given range.\n   - Parameter _ attrs: An Array of attributedStringKeys.\n   - Parameter range: A NSRange.\n   */\n  open func removeAttributes(_ attrs: [NSAttributedString.Key], range: NSRange) {\n    for k in attrs {\n      removeAttribute(k, range: range)\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Extension/Material+String.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nextension String {\n  /**\n   :name:\ttrim\n   */\n  public var trimmed: String {\n    return trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)\n  }\n  \n  /**\n   :name:\tlines\n   */\n  public var lines: [String] {\n    return components(separatedBy: CharacterSet.newlines)\n  }\n  \n  /**\n   :name:\tfirstLine\n   */\n  public var firstLine: String? {\n    return lines.first?.trimmed\n  }\n  \n  /**\n   :name:\tlastLine\n   */\n  public var lastLine: String? {\n    return lines.last?.trimmed\n  }\n  \n  /**\n   :name:\treplaceNewLineCharater\n   */\n  public func replaceNewLineCharater(separator: String = \" \") -> String {\n    return components(separatedBy: CharacterSet.whitespaces).joined(separator: separator).trimmed\n  }\n  \n  /**\n   :name:\treplacePunctuationCharacters\n   */\n  public func replacePunctuationCharacters(separator: String = \"\") -> String {\n    return components(separatedBy: CharacterSet.punctuationCharacters).joined(separator: separator).trimmed\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Extension/Material+UIButton.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\npublic extension UIButton {\n  /// Convenience way to change titleLabel font size.\n  var fontSize: CGFloat {\n    get {\n      return titleLabel?.font?.pointSize ?? UIFont.buttonFontSize\n    }\n    set(value) {\n      titleLabel?.font = titleLabel?.font?.withSize(value) ?? UIFont.systemFont(ofSize: value)\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Extension/Material+UIColor.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\npublic extension UIColor {\n  /**\n   A convenience initializer that creates color from\n   argb(alpha red green blue) hexadecimal representation.\n   - Parameter argb: An unsigned 32 bit integer. E.g 0xFFAA44CC.\n   */\n  convenience init(argb: UInt32) {\n    let a = argb >> 24\n    let r = argb >> 16\n    let g = argb >> 8\n    let b = argb >> 0\n    \n    func f(_ v: UInt32) -> CGFloat {\n      return CGFloat(v & 0xff) / 255\n    }\n    \n    self.init(red: f(r), green: f(g), blue: f(b), alpha: f(a))\n  }\n  \n  \n  /**\n   A convenience initializer that creates color from\n   rgb(red green blue) hexadecimal representation with alpha value 1.\n   - Parameter rgb: An unsigned 32 bit integer. E.g 0xAA44CC.\n   */\n  convenience init(rgb: UInt32) {\n    self.init(argb: (0xff000000 as UInt32) | rgb)\n  }\n}\n\ninternal extension UIColor {\n  /// A tuple of the rgba components.\n  var components: (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat) {\n    var r: CGFloat = 0\n    var g: CGFloat = 0\n    var b: CGFloat = 0\n    var a: CGFloat = 0\n    \n    getRed(&r, green: &g, blue: &b, alpha: &a)\n    \n    return (r, g, b, a)\n  }\n  \n  /**\n   Blends given coverColor over this color.\n   - Parameter with coverColor: A UIColor.\n   - Returns: Resultant color of blending.\n   */\n  func blend(with coverColor: UIColor) -> UIColor {\n    \n    /// Blends channels according to https://en.wikipedia.org/wiki/Alpha_compositing (see `over` operator).\n    func blendChannel(value: CGFloat, bValue: CGFloat, alpha: CGFloat, bAlpha: CGFloat) -> CGFloat {\n      return ((1 - alpha) * bValue * bAlpha + alpha * value) / (alpha + bAlpha * (1 - alpha))\n    }\n    \n    let (r, g, b, a) = coverColor.components\n    let (bR, bG, bB, bA) = components\n    \n    let newR = blendChannel(value: r, bValue: bR, alpha: a, bAlpha: bA)\n    let newG = blendChannel(value: g, bValue: bG, alpha: a, bAlpha: bA)\n    let newB = blendChannel(value: b, bValue: bB, alpha: a, bAlpha: bA)\n    let newA = a + bA * (1 - a)\n    \n    return UIColor(red: newR, green: newG, blue: newB, alpha: newA)\n  }\n  \n  /**\n   Adjusts brightness of the color by given value.\n   - Parameter by value: A CGFloat value.\n   - Returns: Adjusted color.\n   */\n  func adjustingBrightness(by value: CGFloat) -> UIColor {\n    var h: CGFloat = 0\n    var s: CGFloat = 0\n    var b: CGFloat = 0\n    var a: CGFloat = 0\n    \n    getHue(&h, saturation: &s, brightness: &b, alpha: &a)\n    \n    return UIColor(hue: h, saturation: s, brightness: (b + value).clamp(0, 1), alpha: 1)\n  }\n  \n  /// A lighter version of the color.\n  var lighter: UIColor {\n    return adjustingBrightness(by: 0.1)\n  }\n  \n  /// A darker version of the color.\n  var darker: UIColor {\n    return adjustingBrightness(by: -0.1)\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Extension/Material+UIFont.swift",
    "content": "/*\n * Copyright (C) 2015 - 2019 and CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Authors:\n * Daniel Dahan <daniel@cosmcimind.com>,\n * Orkhan Alikhanov <orkhan.alikhanov@cosmicmind.com>\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *  *  Redistributions of source code must retain the above copyright notice, this\n *    list of conditions and the following disclaimer.\n *\n *  *  Redistributions in binary form must reproduce the above copyright notice,\n *    this list of conditions and the following disclaimer in the documentation\n *    and/or other materials provided with the distribution.\n *\n *  *  Neither the name of CosmicMind nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport UIKit\n\nextension UIFont {\n  /**\n   Calculates a CGSize value based on a width and length of a string with a\n   given UIFont.\n   - Parameter string: A String.\n   - Parameter constrainedTo width: A CGFloat.\n   - Returns a CGSize.\n   */\n  open func stringSize(string: String, constrainedTo width: CGFloat) -> CGSize {\n    return string.boundingRect(with: CGSize(width: width, height: CGFloat(Double.greatestFiniteMagnitude)),\n                               options: .usesLineFragmentOrigin,\n                               attributes: [.font: self],\n                               context: nil).size\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Extension/Material+UIImage.swift",
    "content": "/*\n * Copyright (C) 2015 - 2019 and CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Authors:\n * Daniel Dahan <daniel@cosmcimind.com>,\n * Orkhan Alikhanov <orkhan.alikhanov@cosmicmind.com>\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *  *  Redistributions of source code must retain the above copyright notice, this\n *    list of conditions and the following disclaimer.\n *\n *  *  Redistributions in binary form must reproduce the above copyright notice,\n *    this list of conditions and the following disclaimer in the documentation\n *    and/or other materials provided with the distribution.\n *\n *  *  Neither the name of CosmicMind nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport UIKit\nimport Accelerate\nimport Motion\n\n@objc(ImageFormat)\npublic enum ImageFormat: Int {\n  case png\n  case jpeg\n}\n\nextension UIImage {\n  /// Width of the UIImage.\n  open var width: CGFloat {\n    return size.width\n  }\n  \n  /// Height of the UIImage.\n  open var height: CGFloat {\n    return size.height\n  }\n}\n\nextension UIImage {\n  /**\n   Resizes an image based on a given width.\n   - Parameter toWidth w: A width value.\n   - Returns: An optional UIImage.\n   */\n  open func resize(toWidth w: CGFloat) -> UIImage? {\n    return internalResize(toWidth: w)\n  }\n  \n  /**\n   Resizes an image based on a given height.\n   - Parameter toHeight h: A height value.\n   - Returns: An optional UIImage.\n   */\n  open func resize(toHeight h: CGFloat) -> UIImage? {\n    return internalResize(toHeight: h)\n  }\n  \n  /**\n   Internally resizes the image.\n   - Parameter toWidth tw: A width.\n   - Parameter toHeight th: A height.\n   - Returns: An optional UIImage.\n   */\n  private func internalResize(toWidth tw: CGFloat = 0, toHeight th: CGFloat = 0) -> UIImage? {\n    var w: CGFloat?\n    var h: CGFloat?\n    \n    if 0 < tw {\n      h = height * tw / width\n    } else if 0 < th {\n      w = width * th / height\n    }\n    \n    let g: UIImage?\n    let t: CGRect = CGRect(x: 0, y: 0, width: w ?? tw, height: h ?? th)\n    UIGraphicsBeginImageContextWithOptions(t.size, false, Screen.scale)\n    draw(in: t, blendMode: .normal, alpha: 1)\n    g = UIGraphicsGetImageFromCurrentImageContext()\n    UIGraphicsEndImageContext()\n    \n    return g\n  }\n}\n\nextension UIImage {\n  /**\n   Creates a new image with the passed in color.\n   - Parameter color: The UIColor to create the image from.\n   - Returns: A UIImage that is the color passed in.\n   */\n  open func tint(with color: UIColor) -> UIImage? {\n    UIGraphicsBeginImageContextWithOptions(size, false, Screen.scale)\n    guard let context = UIGraphicsGetCurrentContext() else {\n      return nil\n    }\n    \n    context.scaleBy(x: 1.0, y: -1.0)\n    context.translateBy(x: 0.0, y: -size.height)\n    \n    context.setBlendMode(.multiply)\n    \n    let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)\n    context.clip(to: rect, mask: cgImage!)\n    color.setFill()\n    context.fill(rect)\n    \n    let image = UIGraphicsGetImageFromCurrentImageContext()\n    UIGraphicsEndImageContext()\n    return image?.withRenderingMode(.alwaysOriginal)\n  }\n}\n\nextension UIImage {\n  /**\n   Creates an Image that is a color.\n   - Parameter color: The UIColor to create the image from.\n   - Parameter size: The size of the image to create.\n   - Returns: A UIImage that is the color passed in.\n   */\n  open class func image(with color: UIColor, size: CGSize) -> UIImage? {\n    UIGraphicsBeginImageContextWithOptions(size, false, Screen.scale)\n    guard let context = UIGraphicsGetCurrentContext() else {\n      return nil\n    }\n    \n    context.scaleBy(x: 1.0, y: -1.0)\n    context.translateBy(x: 0.0, y: -size.height)\n    \n    context.setBlendMode(.multiply)\n    \n    let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)\n    color.setFill()\n    context.fill(rect)\n    \n    let image = UIGraphicsGetImageFromCurrentImageContext()\n    UIGraphicsEndImageContext()\n    return image?.withRenderingMode(.alwaysOriginal)\n  }\n}\n\nextension UIImage {\n  /**\n   Crops an image to a specified width and height.\n   - Parameter toWidth tw: A specified width.\n   - Parameter toHeight th: A specified height.\n   - Returns: An optional UIImage.\n   */\n  open func crop(toWidth tw: CGFloat, toHeight th: CGFloat) -> UIImage? {\n    let g: UIImage?\n    let b = width > height\n    let s: CGFloat = b ? th / height : tw / width\n    let t: CGSize = CGSize(width: tw, height: th)\n    \n    let w = width * s\n    let h = height * s\n    \n    UIGraphicsBeginImageContext(t)\n    draw(in: b ? CGRect(x: -1 * (w - t.width) / 2, y: 0, width: w, height: h) : CGRect(x: 0, y: -1 * (h - t.height) / 2, width: w, height: h), blendMode: .normal, alpha: 1)\n    g = UIGraphicsGetImageFromCurrentImageContext()\n    UIGraphicsEndImageContext()\n    \n    return g\n  }\n}\n\nextension UIImage {\n  /**\n   Creates a clear image.\n   - Returns: A UIImage that is clear.\n   */\n  open class func clear(size: CGSize = CGSize(width: 16, height: 16)) -> UIImage? {\n    UIGraphicsBeginImageContextWithOptions(size, false, 0)\n    let image = UIGraphicsGetImageFromCurrentImageContext()\n    UIGraphicsEndImageContext()\n    return image\n  }\n}\n\nextension UIImage {\n  /**\n   Asynchronously load images with a completion block.\n   - Parameter URL: A URL destination to fetch the image from.\n   - Parameter completion: A completion block that is executed once the image\n   has been retrieved.\n   */\n  open class func contentsOfURL(url: URL, completion: @escaping ((UIImage?, Error?) -> Void)) {\n    URLSession.shared.dataTask(with: URLRequest(url: url)) { [completion = completion] (data: Data?, response: URLResponse?, error: Error?) in\n      Motion.async {\n        if let v = error {\n          completion(nil, v)\n        } else if let v = data {\n          completion(UIImage(data: v), nil)\n        }\n      }\n      }.resume()\n  }\n}\n\nextension UIImage {\n  /**\n   Adjusts the orientation of the image from the capture orientation.\n   This is an issue when taking images, the capture orientation is not set correctly\n   when using Portrait.\n   - Returns: An optional UIImage if successful.\n   */\n  open func adjustOrientation() -> UIImage? {\n    guard .up != imageOrientation else {\n      return self\n    }\n    \n    var transform: CGAffineTransform = .identity\n    \n    // Rotate if Left, Right, or Down.\n    switch imageOrientation {\n    case .down, .downMirrored:\n      transform = transform.translatedBy(x: size.width, y: size.height)\n      transform = transform.rotated(by: CGFloat(Double.pi))\n    case .left, .leftMirrored:\n      transform = transform.translatedBy(x: size.width, y: 0)\n      transform = transform.rotated(by: CGFloat(Double.pi / 2))\n    case .right, .rightMirrored:\n      transform = transform.translatedBy(x: 0, y: size.height)\n      transform = transform.rotated(by: -CGFloat(Double.pi / 2))\n    default:break\n    }\n    \n    // Flip if mirrored.\n    switch imageOrientation {\n    case .upMirrored, .downMirrored:\n      transform = transform.translatedBy(x: size.width, y: 0)\n      transform = transform.scaledBy(x: -1, y: 1)\n    case .leftMirrored, .rightMirrored:\n      transform = transform.translatedBy(x: size.height, y: 0)\n      transform = transform.scaledBy(x: -1, y: 1)\n    default:break\n    }\n    \n    // Draw the underlying cgImage with the calculated transform.\n    guard let context = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: cgImage!.bitsPerComponent, bytesPerRow: 0, space: cgImage!.colorSpace!, bitmapInfo: cgImage!.bitmapInfo.rawValue) else {\n      return nil\n    }\n    \n    context.concatenate(transform)\n    \n    switch imageOrientation {\n    case .left, .leftMirrored, .right, .rightMirrored:\n      context.draw(cgImage!, in: CGRect(x: 0, y: 0, width: size.height, height: size.width))\n    default:\n      context.draw(cgImage!, in: CGRect(origin: .zero, size: size))\n    }\n    \n    guard let cgImage = context.makeImage() else {\n      return nil\n    }\n    \n    return UIImage(cgImage: cgImage)\n  }\n}\n\n/**\n Creates an effect buffer for images that already have effects.\n - Parameter context: A CGContext.\n - Returns: vImage_Buffer.\n */\nfileprivate func createEffectBuffer(context: CGContext) -> vImage_Buffer {\n  let data = context.data\n  let width = vImagePixelCount(context.width)\n  let height = vImagePixelCount(context.height)\n  let rowBytes = context.bytesPerRow\n  return vImage_Buffer(data: data, height: height, width: width, rowBytes: rowBytes)\n}\n\nextension UIImage {\n  /**\n   Applies a blur effect to a UIImage.\n   - Parameter radius: The radius of the blur effect.\n   - Parameter tintColor: The color used for the blur effect (optional).\n   - Parameter saturationDeltaFactor: The delta factor for the saturation of the blur effect.\n   - Returns: a UIImage.\n   */\n  open func blur(radius: CGFloat = 0, tintColor: UIColor? = nil, saturationDeltaFactor: CGFloat = 0) -> UIImage? {\n    var effectImage = self\n    \n    let screenScale = Screen.scale\n    let imageRect = CGRect(origin: .zero, size: size)\n    let hasBlur = radius > CGFloat(Float.ulpOfOne)\n    let hasSaturationChange = abs(saturationDeltaFactor - 1.0) > CGFloat(Float.ulpOfOne)\n    \n    if hasBlur || hasSaturationChange {\n      UIGraphicsBeginImageContextWithOptions(size, false, screenScale)\n      let inContext = UIGraphicsGetCurrentContext()!\n      inContext.scaleBy(x: 1.0, y: -1.0)\n      inContext.translateBy(x: 0, y: -size.height)\n      \n      inContext.draw(cgImage!, in: imageRect)\n      \n      var inBuffer = createEffectBuffer(context: inContext)\n      \n      UIGraphicsBeginImageContextWithOptions(size, false, screenScale)\n      \n      let outContext = UIGraphicsGetCurrentContext()!\n      var outBuffer = createEffectBuffer(context: outContext)\n      \n      if hasBlur {\n        let a = sqrt(2 * .pi)\n        let b = CGFloat(a) / 4\n        let c = radius * screenScale\n        let d = c * 3.0 * b\n        \n        var e = UInt32(floor(d + 0.5))\n        \n        if 1 != e % 2 {\n          e += 1 // force radius to be odd so that the three box-blur methodology works.\n        }\n        \n        let imageEdgeExtendFlags = vImage_Flags(kvImageEdgeExtend)\n        \n        vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, nil, 0, 0, e, e, nil, imageEdgeExtendFlags)\n        vImageBoxConvolve_ARGB8888(&outBuffer, &inBuffer, nil, 0, 0, e, e, nil, imageEdgeExtendFlags)\n        vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, nil, 0, 0, e, e, nil, imageEdgeExtendFlags)\n      }\n      \n      var effectImageBuffersAreSwapped = false\n      \n      if hasSaturationChange {\n        let s = saturationDeltaFactor\n        \n        let floatingPointSaturationMatrix: [CGFloat] = [\n          0.0722 + 0.9278 * s,  0.0722 - 0.0722 * s,  0.0722 - 0.0722 * s,  0,\n          0.7152 - 0.7152 * s,  0.7152 + 0.2848 * s,  0.7152 - 0.7152 * s,  0,\n          0.2126 - 0.2126 * s,  0.2126 - 0.2126 * s,  0.2126 + 0.7873 * s,  0,\n          0,                    0,                    0,                    1\n        ]\n        \n        let divisor: CGFloat = 256\n        let matrixSize = floatingPointSaturationMatrix.count\n        var saturationMatrix = [Int16](repeating: 0, count: matrixSize)\n        \n        for i in 0..<matrixSize {\n          saturationMatrix[i] = Int16(round(floatingPointSaturationMatrix[i] * divisor))\n        }\n        \n        if hasBlur {\n          vImageMatrixMultiply_ARGB8888(&outBuffer, &inBuffer, saturationMatrix, Int32(divisor), nil, nil, vImage_Flags(kvImageNoFlags))\n          effectImageBuffersAreSwapped = true\n        } else {\n          vImageMatrixMultiply_ARGB8888(&inBuffer, &outBuffer, saturationMatrix, Int32(divisor), nil, nil, vImage_Flags(kvImageNoFlags))\n        }\n      }\n      \n      if !effectImageBuffersAreSwapped {\n        effectImage = UIGraphicsGetImageFromCurrentImageContext()!\n      }\n      \n      UIGraphicsEndImageContext()\n      \n      if effectImageBuffersAreSwapped {\n        effectImage = UIGraphicsGetImageFromCurrentImageContext()!\n      }\n      \n      UIGraphicsEndImageContext()\n    }\n    \n    // Set up output context.\n    UIGraphicsBeginImageContextWithOptions(size, false, screenScale)\n    let outputContext = UIGraphicsGetCurrentContext()!\n    outputContext.scaleBy(x: 1.0, y: -1.0)\n    outputContext.translateBy(x: 0, y: -size.height)\n    \n    // Draw base image.\n    outputContext.draw(cgImage!, in: imageRect)\n    \n    // Draw effect image.\n    if hasBlur {\n      outputContext.saveGState()\n      outputContext.draw(effectImage.cgImage!, in: imageRect)\n      outputContext.restoreGState()\n    }\n    \n    // Add in color tint.\n    if let v = tintColor {\n      outputContext.saveGState()\n      outputContext.setFillColor(v.cgColor)\n      outputContext.fill(imageRect)\n      outputContext.restoreGState()\n    }\n    \n    // Output image is ready.\n    let outputImage = UIGraphicsGetImageFromCurrentImageContext()!\n    UIGraphicsEndImageContext()\n    \n    return outputImage\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Extension/Material+UILabel.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\npublic extension UILabel {\n  /// Convenience way to change font size.\n  var fontSize: CGFloat {\n    get {\n      return font?.pointSize ?? UIFont.labelFontSize\n    }\n    set(value) {\n      font = font?.withSize(value) ?? UIFont.systemFont(ofSize: value)\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Extension/Material+UIView.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nextension UIView {\n  /// A property that accesses the backing layer's shadow\n  @objc\n  open var shadowColor: UIColor? {\n    get {\n      guard let v = layer.shadowColor else {\n        return nil\n      }\n      \n      return UIColor(cgColor: v)\n    }\n    set(value) {\n      layer.shadowColor = value?.cgColor\n    }\n  }\n  \n  /// A property that accesses the layer.borderColor property.\n  @objc\n  open var borderColor: UIColor? {\n    get {\n      guard let v = layer.borderColor else {\n        return nil\n      }\n      return UIColor(cgColor: v)\n    }\n    set(value) {\n      layer.borderColor = value?.cgColor\n    }\n  }\n  \n  /// HeightPreset value.\n  open var heightPreset: HeightPreset {\n    get {\n      return layer.heightPreset\n    }\n    set(value) {\n      layer.heightPreset = value\n    }\n  }\n  \n  /**\n   A property that manages the overall shape for the object. If either the\n   width or height property is set, the other will be automatically adjusted\n   to maintain the shape of the object.\n   */\n  @objc\n  open var shapePreset: ShapePreset {\n    get {\n      return layer.shapePreset\n    }\n    set(value) {\n      layer.shapePreset = value\n    }\n  }\n  \n  /// A preset value for Depth.\n  open var depthPreset: DepthPreset {\n    get {\n      return layer.depthPreset\n    }\n    set(value) {\n      layer.depthPreset = value\n    }\n  }\n  \n  /// Depth reference.\n  open var depth: Depth {\n    get {\n      return layer.depth\n    }\n    set(value) {\n      layer.depth = value\n    }\n  }\n  \n  /// Enables automatic shadowPath sizing.\n  @IBInspectable\n  @objc\n  open var isShadowPathAutoSizing: Bool {\n    get {\n      return layer.isShadowPathAutoSizing\n    }\n    set(value) {\n      layer.isShadowPathAutoSizing = value\n    }\n  }\n  \n  /// A property that sets the cornerRadius of the backing layer.\n  @objc\n  open var cornerRadiusPreset: CornerRadiusPreset {\n    get {\n      return layer.cornerRadiusPreset\n    }\n    set(value) {\n      layer.cornerRadiusPreset = value\n    }\n  }\n  \n  /// A preset property to set the borderWidth.\n  @objc\n  open var borderWidthPreset: BorderWidthPreset {\n    get {\n      return layer.borderWidthPreset\n    }\n    set(value) {\n      layer.borderWidthPreset = value\n    }\n  }\n}\n\ninternal extension UIView {\n  /// Manages the layout for the shape of the view instance.\n  func layoutShape() {\n    layer.layoutShape()\n  }\n  \n  /// Sets the shadow path.\n  func layoutShadowPath() {\n    layer.layoutShadowPath()\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Extension/Material+UIViewController.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\ninternal extension UIViewController {\n  /**\n   Finds a view controller with a given type based on\n   the view controller subclass.\n   - Returns: An optional of type T.\n   */\n  func traverseViewControllerHierarchyForClassType<T: UIViewController>() -> T? {\n    var v: UIViewController? = self\n    while nil != v {\n      if v is T {\n        return v as? T\n      }\n      \n      v = v?.parent\n    }\n    \n    return Application.rootViewController?.traverseTransitionViewControllerHierarchyForClassType()\n  }\n  \n  /**\n   Traverses the child view controllers to find the correct view controller type T.\n   - Returns: An optional of type T.\n   */\n  func traverseTransitionViewControllerHierarchyForClassType<T: UIViewController>() -> T? {\n    if let v = self as? T {\n      return v\n      \n    } else if let v = self as? TransitionController {\n      return v.rootViewController.traverseTransitionViewControllerHierarchyForClassType()\n    }\n    \n    return nil\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Extension/Material+UIWindow.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nextension UIWindow {\n  /**\n   Captures a screenshot of the contents in the apps keyWindow.\n   - Returns: An optional UIImage.\n   */\n  open func capture() -> UIImage? {\n    UIGraphicsBeginImageContextWithOptions(frame.size, isOpaque, Screen.scale)\n    layer.render(in: UIGraphicsGetCurrentContext()!)\n    let image = UIGraphicsGetImageFromCurrentImageContext()\n    UIGraphicsEndImageContext()\n    return image\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/FABMenu/FABMenu.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(FABMenuItemTitleLabelPosition)\npublic enum FABMenuItemTitleLabelPosition: Int {\n  case left\n  case right\n}\n\n@objc(FABMenuDirection)\npublic enum FABMenuDirection: Int {\n  case up\n  case down\n  case left\n  case right\n}\n\nopen class FABMenuItem: View {\n  /// A reference to the titleLabel.\n  public let titleLabel = UILabel()\n  \n  /// The titleLabel side.\n  open var titleLabelPosition = FABMenuItemTitleLabelPosition.left\n  \n  /// A reference to the fabButton.\n  public let fabButton = FABButton()\n  \n  open override func prepare() {\n    super.prepare()\n    backgroundColor = nil\n    \n    prepareFABButton()\n    prepareTitleLabel()\n  }\n  \n  /// A reference to the titleLabel text.\n  open var title: String? {\n    get {\n      return titleLabel.text\n    }\n    set(value) {\n      titleLabel.text = value\n      layoutSubviews()\n    }\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    guard let t = title, 0 < t.utf16.count else {\n      titleLabel.removeFromSuperview()\n      return\n    }\n    \n    if nil == titleLabel.superview {\n      addSubview(titleLabel)\n    }\n  }\n}\n\nextension FABMenuItem {\n  /// Shows the titleLabel.\n  open func showTitleLabel() {\n    let interimSpace = InterimSpacePresetToValue(preset: .interimSpace6)\n    \n    titleLabel.sizeToFit()\n    titleLabel.frame.size.width += 1.5 * interimSpace\n    titleLabel.frame.size.height += interimSpace / 2\n    titleLabel.frame.origin.y = (bounds.height - titleLabel.bounds.height) / 2\n    \n    switch titleLabelPosition {\n    case .left:\n      titleLabel.frame.origin.x = -titleLabel.bounds.width - interimSpace\n    case .right:\n      titleLabel.frame.origin.x = frame.bounds.width + interimSpace\n    }\n    \n    titleLabel.alpha = 0\n    titleLabel.isHidden = false\n    \n    UIView.animate(withDuration: 0.25, animations: { [weak self] in\n      guard let `self` = self else {\n        return\n      }\n      \n      `self`.titleLabel.alpha = 1\n    })\n  }\n  \n  /// Hides the titleLabel.\n  open func hideTitleLabel() {\n    titleLabel.isHidden = true\n  }\n}\n\nextension FABMenuItem {\n  /// Prepares the fabButton.\n  fileprivate func prepareFABButton() {\n    layout(fabButton).edges()\n  }\n  \n  /// Prepares the titleLabel.\n  fileprivate func prepareTitleLabel() {\n    titleLabel.font = Theme.font.regular(with: 14)\n    titleLabel.textAlignment = .center\n    titleLabel.backgroundColor = .white\n    titleLabel.depthPreset = fabButton.depthPreset\n    titleLabel.cornerRadiusPreset = .cornerRadius1\n  }\n}\n\n@objc(FABMenuDelegate)\npublic protocol FABMenuDelegate {\n  /**\n   A delegation method that is executed to determine whether fabMenu should open.\n   - Parameter fabMenu: A FABMenu.\n   */\n  @objc\n  optional func fabMenuShouldOpen(fabMenu: FABMenu) -> Bool\n  \n  /**\n   A delegation method that is execited when the fabMenu will open.\n   - Parameter fabMenu: A FABMenu.\n   */\n  @objc\n  optional func fabMenuWillOpen(fabMenu: FABMenu)\n  \n  /**\n   A delegation method that is execited when the fabMenu did open.\n   - Parameter fabMenu: A FABMenu.\n   */\n  @objc\n  optional func fabMenuDidOpen(fabMenu: FABMenu)\n  \n  /**\n   A delegation method that is executed to determine whether fabMenu should close.\n   - Parameter fabMenu: A FABMenu.\n   */\n  @objc\n  optional func fabMenuShouldClose(fabMenu: FABMenu) -> Bool\n  \n  /**\n   A delegation method that is execited when the fabMenu will close.\n   - Parameter fabMenu: A FABMenu.\n   */\n  @objc\n  optional func fabMenuWillClose(fabMenu: FABMenu)\n  \n  /**\n   A delegation method that is execited when the fabMenu did close.\n   - Parameter fabMenu: A FABMenu.\n   */\n  @objc\n  optional func fabMenuDidClose(fabMenu: FABMenu)\n  \n  /**\n   A delegation method that is executed when the user taps while\n   the menu is opened.\n   - Parameter fabMenu: A FABMenu.\n   - Parameter tappedAt point: A CGPoint.\n   - Parameter isOutside: A boolean indicating whether the tap\n   was outside the menu button area.\n   */\n  @objc\n  optional func fabMenu(fabMenu: FABMenu, tappedAt point: CGPoint, isOutside: Bool)\n}\n\n@objc(FABMenu)\nopen class FABMenu: View {\n  /// A flag to avoid the double tap.\n  fileprivate var shouldAvoidHitTest = false\n  \n  \n  /// A reference to the SpringAnimation object.\n  let spring = SpringAnimation()\n  \n  open var fabMenuDirection: FABMenuDirection {\n    get {\n      switch spring.springDirection {\n      case .up:\n        return .up\n      case .down:\n        return .down\n      case .left:\n        return .left\n      case .right:\n        return .right\n      }\n    }\n    set(value) {\n      switch value {\n      case .up:\n        spring.springDirection = .up\n      case .down:\n        spring.springDirection = .down\n      case .left:\n        spring.springDirection = .left\n      case .right:\n        spring.springDirection = .right\n      }\n      \n      layoutSubviews()\n    }\n  }\n  \n  /// A reference to the base FABButton.\n  open var fabButton: FABButton? {\n    didSet {\n      oldValue?.removeFromSuperview()\n      \n      guard let v = fabButton else {\n        return\n      }\n      \n      addSubview(v)\n      \n      v.addTarget(self, action: #selector(handleFABButton(button:)), for: .touchUpInside)\n    }\n  }\n  \n  /// An open handler for the FABButton.\n  open var handleFABButtonCallback: ((UIButton) -> Void)?\n  \n  /// An internal handler for the open function.\n  internal var handleOpenCallback: (() -> Void)?\n  \n  /// An internal handler for the close function.\n  internal var handleCloseCallback: (() -> Void)?\n  \n  /// An internal handler for the completion function.\n  internal var handleCompletionCallback: ((UIView) -> Void)?\n  \n  /// Size of FABMenuItems.\n  open var fabMenuItemSize: CGSize {\n    get {\n      return spring.itemSize\n    }\n    set(value) {\n      spring.itemSize = value\n    }\n  }\n  \n  /// A preset wrapper around interimSpace.\n  open var interimSpacePreset: InterimSpacePreset {\n    get {\n      return spring.interimSpacePreset\n    }\n    set(value) {\n      spring.interimSpacePreset = value\n    }\n  }\n  \n  /// The space between views.\n  open var interimSpace: InterimSpace {\n    get {\n      return spring.interimSpace\n    }\n    set(value) {\n      spring.interimSpace = value\n    }\n  }\n  \n  /// A boolean indicating if the menu is open or not.\n  open var isOpened: Bool {\n    get {\n      return spring.isOpened\n    }\n    set(value) {\n      spring.isOpened = value\n    }\n  }\n  \n  /// A boolean indicating if the menu is enabled.\n  open var isEnabled: Bool {\n    get {\n      return spring.isEnabled\n    }\n    set(value) {\n      spring.isEnabled = value\n    }\n  }\n  \n  /// An optional delegation handler.\n  open weak var delegate: FABMenuDelegate?\n  \n  /// A reference to the FABMenuItems\n  open var fabMenuItems: [FABMenuItem] {\n    get {\n      return spring.views as! [FABMenuItem]\n    }\n    set(value) {\n      for v in spring.views {\n        v.removeFromSuperview()\n      }\n      \n      for v in value {\n        addSubview(v)\n      }\n      \n      spring.views = value\n    }\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    fabButton?.frame = bounds\n    fabButton?.setNeedsLayout()\n    fabButton?.layoutIfNeeded()\n    spring.baseSize = bounds.size\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    backgroundColor = nil\n    interimSpacePreset = .interimSpace6\n  }\n}\n\nextension FABMenu {\n  /**\n   Open the Menu component with animation options.\n   - Parameter duration: The time for each view's animation.\n   - Parameter delay: A delay time for each view's animation.\n   - Parameter usingSpringWithDamping: A damping ratio for the animation.\n   - Parameter initialSpringVelocity: The initial velocity for the animation.\n   - Parameter options: Options to pass to the animation.\n   - Parameter animations: An animation block to execute on each view's animation.\n   - Parameter completion: A completion block to execute on each view's animation.\n   */\n  open func open(duration: TimeInterval = 0.15, delay: TimeInterval = 0, usingSpringWithDamping: CGFloat = 0.5, initialSpringVelocity: CGFloat = 0, options: UIView.AnimationOptions = [], animations: ((UIView) -> Void)? = nil, completion: ((UIView) -> Void)? = nil) {\n    open(isTriggeredByUserInteraction: false, duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)\n  }\n  \n  /**\n   Open the Menu component with animation options.\n   - Parameter isTriggeredByUserInteraction: A boolean indicating whether the\n   state was changed by a user interaction, true if yes, false otherwise.\n   - Parameter duration: The time for each view's animation.\n   - Parameter delay: A delay time for each view's animation.\n   - Parameter usingSpringWithDamping: A damping ratio for the animation.\n   - Parameter initialSpringVelocity: The initial velocity for the animation.\n   - Parameter options: Options to pass to the animation.\n   - Parameter animations: An animation block to execute on each view's animation.\n   - Parameter completion: A completion block to execute on each view's animation.\n   */\n  open func open(isTriggeredByUserInteraction: Bool, duration: TimeInterval = 0.15, delay: TimeInterval = 0, usingSpringWithDamping: CGFloat = 0.5, initialSpringVelocity: CGFloat = 0, options: UIView.AnimationOptions = [], animations: ((UIView) -> Void)? = nil, completion: ((UIView) -> Void)? = nil) {\n    \n    if isTriggeredByUserInteraction && false == delegate?.fabMenuShouldOpen?(fabMenu: self) {\n      return\n    }\n    \n    handleOpenCallback?()\n    \n    if isTriggeredByUserInteraction {\n      delegate?.fabMenuWillOpen?(fabMenu: self)\n    }\n    \n    spring.expand(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations) { [weak self, isTriggeredByUserInteraction = isTriggeredByUserInteraction, completion = completion] (view) in\n      guard let `self` = self else {\n        return\n      }\n      \n      (view as? FABMenuItem)?.showTitleLabel()\n      \n      if isTriggeredByUserInteraction && view == self.fabMenuItems.last {\n        self.delegate?.fabMenuDidOpen?(fabMenu: self)\n      }\n      \n      completion?(view)\n      self.handleCompletionCallback?(view)\n    }\n  }\n  \n  /**\n   Close the Menu component with animation options.\n   - Parameter duration: The time for each view's animation.\n   - Parameter delay: A delay time for each view's animation.\n   - Parameter usingSpringWithDamping: A damping ratio for the animation.\n   - Parameter initialSpringVelocity: The initial velocity for the animation.\n   - Parameter options: Options to pass to the animation.\n   - Parameter animations: An animation block to execute on each view's animation.\n   - Parameter completion: A completion block to execute on each view's animation.\n   */\n  open func close(duration: TimeInterval = 0.15, delay: TimeInterval = 0, usingSpringWithDamping: CGFloat = 0.5, initialSpringVelocity: CGFloat = 0, options: UIView.AnimationOptions = [], animations: ((UIView) -> Void)? = nil, completion: ((UIView) -> Void)? = nil) {\n    close(isTriggeredByUserInteraction: false, duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)\n  }\n  \n  /**\n   Close the Menu component with animation options.\n   - Parameter isTriggeredByUserInteraction: A boolean indicating whether the\n   state was changed by a user interaction, true if yes, false otherwise.\n   - Parameter duration: The time for each view's animation.\n   - Parameter delay: A delay time for each view's animation.\n   - Parameter usingSpringWithDamping: A damping ratio for the animation.\n   - Parameter initialSpringVelocity: The initial velocity for the animation.\n   - Parameter options: Options to pass to the animation.\n   - Parameter animations: An animation block to execute on each view's animation.\n   - Parameter completion: A completion block to execute on each view's animation.\n   */\n  open func close(isTriggeredByUserInteraction: Bool, duration: TimeInterval = 0.15, delay: TimeInterval = 0, usingSpringWithDamping: CGFloat = 0.5, initialSpringVelocity: CGFloat = 0, options: UIView.AnimationOptions = [], animations: ((UIView) -> Void)? = nil, completion: ((UIView) -> Void)? = nil) {\n    \n    if isTriggeredByUserInteraction && false == delegate?.fabMenuShouldClose?(fabMenu: self) {\n      return\n    }\n    \n    handleCloseCallback?()\n    \n    if isTriggeredByUserInteraction {\n      delegate?.fabMenuWillClose?(fabMenu: self)\n    }\n    \n    spring.contract(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations) { [weak self, isTriggeredByUserInteraction = isTriggeredByUserInteraction, completion = completion] (view) in\n      guard let `self` = self else {\n        return\n      }\n      \n      (view as? FABMenuItem)?.hideTitleLabel()\n      \n      if isTriggeredByUserInteraction && view == self.fabMenuItems.last {\n        self.delegate?.fabMenuDidClose?(fabMenu: self)\n      }\n      \n      completion?(view)\n      self.handleCompletionCallback?(view)\n    }\n  }\n}\n\nextension FABMenu {\n  /**\n   Handles the hit test for the Menu and views outside of the Menu bounds.\n   - Parameter _ point: A CGPoint.\n   - Parameter with event: An optional UIEvent.\n   - Returns: An optional UIView.\n   */\n  open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {\n    guard isOpened, isEnabled else {\n      return super.hitTest(point, with: event)\n    }\n    \n    for v in subviews {\n      let p = v.convert(point, from: self)\n      if v.bounds.contains(p) {\n        if !shouldAvoidHitTest {\n          delegate?.fabMenu?(fabMenu: self, tappedAt: point, isOutside: false)\n        }\n        shouldAvoidHitTest = !shouldAvoidHitTest\n        return v.hitTest(p, with: event)\n      }\n    }\n    \n    delegate?.fabMenu?(fabMenu: self, tappedAt: point, isOutside: true)\n    \n    close(isTriggeredByUserInteraction: true)\n    \n    return super.hitTest(point, with: event)\n  }\n}\n\nextension FABMenu {\n  /**\n   Handler to toggle the FABMenu opened or closed. \n   - Parameter button: A UIButton.\n   */\n  @objc\n  fileprivate func handleFABButton(button: UIButton) {\n    guard nil == handleFABButtonCallback else {\n      handleFABButtonCallback?(button)\n      return\n    }\n    \n    guard isOpened else {\n      open(isTriggeredByUserInteraction: true)\n      return\n    }\n    \n    close(isTriggeredByUserInteraction: true)\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/FABMenu/FABMenuController.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\npublic enum FABMenuBacking {\n  case none\n  case fade\n  case blur\n}\n\nextension UIViewController {\n  /**\n   A convenience property that provides access to the FABMenuController.\n   This is the recommended method of accessing the FABMenuController\n   through child UIViewControllers.\n   */\n  public var fabMenuController: FABMenuController? {\n    return traverseViewControllerHierarchyForClassType()\n  }\n}\n\nopen class FABMenuController: TransitionController {\n  /// Reference to the MenuView.\n  @IBInspectable\n  open var fabMenu = FABMenu()\n  \n  /// A FABMenuBacking value type.\n  open var fabMenuBacking = FABMenuBacking.blur\n  \n  /// The fabMenuBacking UIBlurEffectStyle.\n  open var fabMenuBackingBlurEffectStyle = UIBlurEffect.Style.light\n  \n  /// A reference to the blurView.\n  open fileprivate(set) var blurView: UIView?\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    rootViewController.view.frame = view.bounds\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    prepareFABMenu()\n  }\n}\n\nextension FABMenuController: FABMenuDelegate {}\n\nfileprivate extension FABMenuController {\n  /// Prepares the fabMenu.\n  func prepareFABMenu() {\n    fabMenu.delegate = self\n    fabMenu.layer.zPosition = 1000\n    \n    fabMenu.handleFABButtonCallback = { [weak self] in\n      self?.handleFABButtonCallback(button: $0)\n    }\n    \n    fabMenu.handleOpenCallback = { [weak self] in\n      self?.handleOpenCallback()\n    }\n    \n    fabMenu.handleCloseCallback = { [weak self] in\n      self?.handleCloseCallback()\n    }\n    \n    fabMenu.handleCompletionCallback = { [weak self] in\n      self?.handleCompletionCallback(view: $0)\n    }\n    \n    view.addSubview(fabMenu)\n  }\n}\n\nfileprivate extension FABMenuController {\n  /// Shows the fabMenuBacking.\n  func showFabMenuBacking() {\n    showFade()\n    showBlurView()\n  }\n  \n  /// Hides the fabMenuBacking.\n  func hideFabMenuBacking() {\n    hideFade()\n    hideBlurView()\n  }\n  \n  /// Shows the blurView.\n  func showBlurView() {\n    guard .blur == fabMenuBacking else {\n      return\n    }\n    \n    guard !fabMenu.isOpened, fabMenu.isEnabled else {\n      return\n    }\n    \n    guard nil == blurView else {\n      return\n    }\n    \n    let blur = UIVisualEffectView(effect: UIBlurEffect(style: fabMenuBackingBlurEffectStyle))\n    blurView = UIView()\n    blurView?.layout(blur).edges()\n    view.layout(blurView!).edges()\n    view.bringSubviewToFront(fabMenu)\n  }\n  \n  /// Hides the blurView.\n  func hideBlurView() {\n    guard .blur == fabMenuBacking else {\n      return\n    }\n    \n    guard fabMenu.isOpened, fabMenu.isEnabled else {\n      return\n    }\n    \n    blurView?.removeFromSuperview()\n    blurView = nil\n  }\n  \n  /// Shows the fade.\n  func showFade() {\n    guard .fade == fabMenuBacking else {\n      return\n    }\n    \n    guard !fabMenu.isOpened, fabMenu.isEnabled else {\n      return\n    }\n    \n    UIView.animate(withDuration: 0.15, animations: { [weak self] in\n      self?.rootViewController.view.alpha = 0.15\n    })\n  }\n  \n  /// Hides the fade.\n  func hideFade() {\n    guard .fade == fabMenuBacking else {\n      return\n    }\n    \n    guard fabMenu.isOpened, fabMenu.isEnabled else {\n      return\n    }\n    \n    UIView.animate(withDuration: 0.15, animations: { [weak self] in\n      self?.rootViewController.view.alpha = 1\n    })\n  }\n}\n\nfileprivate extension FABMenuController {\n  /**\n   Handler to toggle the FABMenu opened or closed.\n   - Parameter button: A UIButton.\n   */\n  func handleFABButtonCallback(button: UIButton) {\n    guard fabMenu.isOpened else {\n      fabMenu.open(isTriggeredByUserInteraction: true)\n      return\n    }\n    \n    fabMenu.close(isTriggeredByUserInteraction: true)\n  }\n  \n  /// Handler for when the FABMenu.open function is called.\n  func handleOpenCallback() {\n    isUserInteractionEnabled = false\n    showFabMenuBacking()\n  }\n  \n  /// Handler for when the FABMenu.close function is called.\n  func handleCloseCallback() {\n    isUserInteractionEnabled = false\n    hideFabMenuBacking()\n  }\n  \n  /**\n   Completion handler for FABMenu open and close calls.\n   - Parameter view: A UIView.\n   */\n  func handleCompletionCallback(view: UIView) {\n    if view == fabMenu.fabMenuItems.last {\n      isUserInteractionEnabled = true\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Font/DynamicFontType.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(DynamicFontTypeDelegate)\npublic protocol DynamicFontTypeDelegate {\n  /**\n   A delegation method that is executed when the dynamic type\n   is changed.\n   - Parameter dynamicFontType: A DynamicFontType.\n   */\n  func dynamicFontType(dynamicFontType: DynamicFontType)\n}\n\n@objc(DynamicFontType)\nopen class DynamicFontType: NSObject {\n  /// A weak reference to a DynamicFontTypeDelegate.\n  open weak var delegate: DynamicFontTypeDelegate?\n  \n  /// Initializer.\n  public override init() {\n    super.init()\n    prepare()\n  }\n  \n  @objc\n  internal func handleContentSizeChange() {\n    delegate?.dynamicFontType(dynamicFontType: self)\n  }\n  \n  /// Prepare the instance object.\n  private func prepare() {\n    prepareContentSizeObservation()\n  }\n  \n  /// Prepares observation for content size changes.\n  private func prepareContentSizeObservation() {\n    NotificationCenter.default.addObserver(self, selector: #selector(handleContentSizeChange), name: UIContentSizeCategory.didChangeNotification, object: nil)\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Font/Font.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\npublic protocol FontType {\n  /**\n   Regular with size font.\n   - Parameter with size: A CGFLoat for the font size.\n   - Returns: A UIFont.\n   */\n  static func regular(with size: CGFloat) -> UIFont\n  \n  /**\n   Medium with size font.\n   - Parameter with size: A CGFLoat for the font size.\n   - Returns: A UIFont.\n   */\n  static func medium(with size: CGFloat) -> UIFont\n  \n  /**\n   Bold with size font.\n   - Parameter with size: A CGFLoat for the font size.\n   - Returns: A UIFont.\n   */\n  static func bold(with size: CGFloat) -> UIFont\n}\n\npublic struct Font {\n  /// Size of font.\n  public static let pointSize: CGFloat = 16\n  \n  /** \n   Retrieves the system font with a specified size.\n   - Parameter ofSize size: A CGFloat.\n   */\n  public static func systemFont(ofSize size: CGFloat) -> UIFont {\n    return UIFont.systemFont(ofSize: size)\n  }\n  \n  /**\n   Retrieves the bold system font with a specified size..\n   - Parameter ofSize size: A CGFloat.\n   */\n  public static func boldSystemFont(ofSize size: CGFloat) -> UIFont {\n    return UIFont.boldSystemFont(ofSize: size)\n  }\n  \n  /**\n   Retrieves the italic system font with a specified size.\n   - Parameter ofSize size: A CGFloat.\n   */\n  public static func italicSystemFont(ofSize size: CGFloat) -> UIFont {\n    return UIFont.italicSystemFont(ofSize: size)\n  }\n  \n  /**\n   Loads a given font if needed.\n   - Parameter name: A String font name.\n   */\n  public static func loadFontIfNeeded(name: String) {\n    FontLoader.loadFontIfNeeded(name: name)\n  }\n}\n\n/// Loads fonts packaged with Material.\nprivate class FontLoader {\n  /// A Dictionary of the fonts already loaded.\n  static var loadedFonts: Dictionary<String, String> = Dictionary<String, String>()\n  \n  /**\n   Loads a given font if needed.\n   - Parameter fontName: A String font name.\n   */\n  static func loadFontIfNeeded(name: String) {\n    let loadedFont: String? = FontLoader.loadedFonts[name]\n    \n    if nil == loadedFont && nil == UIFont(name: name, size: 1) {\n      FontLoader.loadedFonts[name] = name\n      \n      let bundle = Bundle(for: FontLoader.self)\n      let identifier = bundle.bundleIdentifier\n      let fontURL = true == identifier?.hasPrefix(\"org.cocoapods\") ? bundle.url(forResource: name, withExtension: \"ttf\", subdirectory: \"com.cosmicmind.material.fonts.bundle\") : bundle.url(forResource: name, withExtension: \"ttf\")\n      \n      if let v = fontURL {\n        let data = NSData(contentsOf: v as URL)!\n        let provider = CGDataProvider(data: data)!\n        let font = CGFont(provider)\n        \n        var error: Unmanaged<CFError>?\n        if !CTFontManagerRegisterGraphicsFont(font!, &error) {\n          let errorDescription = CFErrorCopyDescription(error!.takeUnretainedValue())\n          let nsError = error!.takeUnretainedValue() as Any as! Error\n          NSException(name: .internalInconsistencyException, reason: errorDescription as String?, userInfo: [NSUnderlyingErrorKey: nsError as Any]).raise()\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Font/RobotoFont.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\npublic struct RobotoFont: FontType {\n  /// Size of font.\n  public static var pointSize: CGFloat {\n    return Font.pointSize\n  }\n  \n  /// Thin font.\n  public static var thin: UIFont {\n    return thin(with: Font.pointSize)\n  }\n  \n  /// Light font.\n  public static var light: UIFont {\n    return light(with: Font.pointSize)\n  }\n  \n  /// Regular font.\n  public static var regular: UIFont {\n    return regular(with: Font.pointSize)\n  }\n  \n  /// Medium font.\n  public static var medium: UIFont {\n    return medium(with: Font.pointSize)\n  }\n  \n  /// Bold font.\n  public static var bold: UIFont {\n    return bold(with: Font.pointSize)\n  }\n  \n  /**\n   Thin with size font.\n   - Parameter with size: A CGFLoat for the font size.\n   - Returns: A UIFont.\n   */\n  public static func thin(with size: CGFloat) -> UIFont {\n    Font.loadFontIfNeeded(name: \"Roboto-Thin\")\n    \n    if let f = UIFont(name: \"Roboto-Thin\", size: size) {\n      return f\n    }\n    \n    return Font.systemFont(ofSize: size)\n  }\n  \n  /**\n   Light with size font.\n   - Parameter with size: A CGFLoat for the font size.\n   - Returns: A UIFont.\n   */\n  public static func light(with size: CGFloat) -> UIFont {\n    Font.loadFontIfNeeded(name: \"Roboto-Light\")\n    \n    if let f = UIFont(name: \"Roboto-Light\", size: size) {\n      return f\n    }\n    \n    return Font.systemFont(ofSize: size)\n  }\n  \n  /**\n   Regular with size font.\n   - Parameter with size: A CGFLoat for the font size.\n   - Returns: A UIFont.\n   */\n  public static func regular(with size: CGFloat) -> UIFont {\n    Font.loadFontIfNeeded(name: \"Roboto-Regular\")\n    \n    if let f = UIFont(name: \"Roboto-Regular\", size: size) {\n      return f\n    }\n    \n    return Font.systemFont(ofSize: size)\n  }\n  \n  /**\n   Medium with size font.\n   - Parameter with size: A CGFLoat for the font size.\n   - Returns: A UIFont.\n   */\n  public static func medium(with size: CGFloat) -> UIFont {\n    Font.loadFontIfNeeded(name: \"Roboto-Medium\")\n    \n    if let f = UIFont(name: \"Roboto-Medium\", size: size) {\n      return f\n    }\n    \n    return Font.boldSystemFont(ofSize: size)\n  }\n  \n  /**\n   Bold with size font.\n   - Parameter with size: A CGFLoat for the font size.\n   - Returns: A UIFont.\n   */\n  public static func bold(with size: CGFloat) -> UIFont {\n    Font.loadFontIfNeeded(name: \"Roboto-Bold\")\n    \n    if let f = UIFont(name: \"Roboto-Bold\", size: size) {\n      return f\n    }\n    \n    return Font.boldSystemFont(ofSize: size)\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Grid/Grid.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\n@objc(GridAxisDirection)\npublic enum GridAxisDirection: Int {\n  case any\n  case horizontal\n  case vertical\n}\n\npublic struct GridAxis {\n  /// The direction the grid lays its views out.\n  public var direction = GridAxisDirection.horizontal\n  \n  /// The rows size.\n  public var rows: Int\n  \n  /// The columns size.\n  public var columns: Int\n  \n  /**\n   Initializer.\n   - Parameter rows: The number of rows, vertical axis the grid will use.\n   - Parameter columns: The number of columns, horizontal axis the grid will use.\n   */\n  internal init(rows: Int = 12, columns: Int = 12) {\n    self.rows = rows\n    self.columns = columns\n  }\n}\n\npublic struct GridOffset {\n  /// The rows size.\n  public var rows: Int\n  \n  /// The columns size.\n  public var columns: Int\n  \n  /**\n   Initializer.\n   - Parameter rows: The number of rows, vertical axis the grid will use.\n   - Parameter columns: The number of columns, horizontal axis the grid will use.\n   */\n  internal init(rows: Int = 0, columns: Int = 0) {\n    self.rows = rows\n    self.columns = columns\n  }\n}\n\npublic struct Grid {\n  /// Context view.\n  internal weak var context: UIView?\n  \n  /// Defer the calculation.\n  public var isDeferred = false\n  \n  /// Number of rows.\n  public var rows: Int {\n    didSet {\n      reload()\n    }\n  }\n  \n  /// Number of columns.\n  public var columns: Int {\n    didSet {\n      reload()\n    }\n  }\n  \n  /// Offsets for rows and columns.\n  public var offset = GridOffset() {\n    didSet {\n      reload()\n    }\n  }\n  \n  /// The axis in which the Grid is laying out its views.\n  public var axis = GridAxis() {\n    didSet {\n      reload()\n    }\n  }\n  \n  /// Preset inset value for grid.\n  public var layoutEdgeInsetsPreset = EdgeInsetsPreset.none {\n    didSet {\n      layoutEdgeInsets = EdgeInsetsPresetToValue(preset: contentEdgeInsetsPreset)\n    }\n  }\n  \n  /// Insets value for grid.\n  public var layoutEdgeInsets = EdgeInsets.zero {\n    didSet {\n      reload()\n    }\n  }\n  \n  /// Preset inset value for grid.\n  public var contentEdgeInsetsPreset = EdgeInsetsPreset.none {\n    didSet {\n      contentEdgeInsets = EdgeInsetsPresetToValue(preset: contentEdgeInsetsPreset)\n    }\n  }\n  \n  /// Insets value for grid.\n  public var contentEdgeInsets = EdgeInsets.zero {\n    didSet {\n      reload()\n    }\n  }\n  \n  /// A preset wrapper for interim space.\n  public var interimSpacePreset = InterimSpacePreset.none {\n    didSet {\n      interimSpace = InterimSpacePresetToValue(preset: interimSpacePreset)\n    }\n  }\n  \n  /// The space between grid rows and columnss.\n  public var interimSpace: InterimSpace {\n    didSet {\n      reload()\n    }\n  }\n  \n  /// An Array of UIButtons.\n  public var views = [UIView]() {\n    didSet {\n      oldValue.forEach {\n        $0.removeFromSuperview()\n      }\n      \n      reload()\n    }\n  }\n  \n  /**\n   Initializer.\n   - Parameter rows: The number of rows, vertical axis the grid will use.\n   - Parameter columns: The number of columns, horizontal axis the grid will use.\n   - Parameter interimSpace: The interim space between rows or columns.\n   */\n  internal init(context: UIView?, rows: Int = 0, columns: Int = 0, interimSpace: InterimSpace = 0) {\n    self.context = context\n    self.rows = rows\n    self.columns = columns\n    self.interimSpace = interimSpace\n  }\n  \n  /// Begins a deferred block.\n  public mutating func begin() {\n    isDeferred = true\n  }\n  \n  /// Completes a deferred block.\n  public mutating func commit() {\n    isDeferred = false\n    reload()\n  }\n  \n  /**\n   Update grid in a deferred block.\n   - Parameter _ block: An update code block.\n   */\n  public mutating func update(_ block: (Grid) -> Void) {\n    begin()\n    block(self)\n    commit()\n  }\n  \n  /// Reload the button layout.\n  public func reload() {\n    guard !isDeferred else {\n      return\n    }\n    \n    guard let canvas = context else {\n      return\n    }\n    \n    for v in views {\n      if canvas != v.superview {\n        canvas.addSubview(v)\n      }\n    }\n    \n    let count = views.count\n    \n    guard 0 < count else {\n      return\n    }\n    \n    /// It is important to call `setNeedsLayout` and `layoutIfNeeded`\n    /// in order to have the parent view's `frame` calculation be set\n    /// for `Grid` to be able to then calculate the correct dimenions\n    /// of its `child` views.\n    canvas.setNeedsLayout()\n    canvas.layoutIfNeeded()\n    \n    guard 0 < canvas.bounds.width && 0 < canvas.bounds.height else {\n      return\n    }\n    \n    var n = 0\n    var i = 0\n    \n    for v in views {\n      // Forces the view to adjust accordingly to size changes, ie: UILabel.\n      (v as? UILabel)?.sizeToFit()\n      \n      switch axis.direction {\n      case .horizontal:\n        let c = 0 == v.grid.columns ? axis.columns / count : v.grid.columns\n        let co = v.grid.offset.columns\n        let w = (canvas.bounds.width - contentEdgeInsets.left - contentEdgeInsets.right - layoutEdgeInsets.left - layoutEdgeInsets.right + interimSpace) / CGFloat(axis.columns)\n        \n        v.frame.origin.x = CGFloat(i + n + co) * w + contentEdgeInsets.left + layoutEdgeInsets.left\n        v.frame.origin.y = contentEdgeInsets.top + layoutEdgeInsets.top\n        v.frame.size.width = w * CGFloat(c) - interimSpace\n        v.frame.size.height = canvas.bounds.height - contentEdgeInsets.top - contentEdgeInsets.bottom - layoutEdgeInsets.top - layoutEdgeInsets.bottom\n        \n        n += c + co - 1\n        \n      case .vertical:\n        let r = 0 == v.grid.rows ? axis.rows / count : v.grid.rows\n        let ro = v.grid.offset.rows\n        let h = (canvas.bounds.height - contentEdgeInsets.top - contentEdgeInsets.bottom - layoutEdgeInsets.top - layoutEdgeInsets.bottom + interimSpace) / CGFloat(axis.rows)\n        \n        v.frame.origin.x = contentEdgeInsets.left + layoutEdgeInsets.left\n        v.frame.origin.y = CGFloat(i + n + ro) * h + contentEdgeInsets.top + layoutEdgeInsets.top\n        v.frame.size.width = canvas.bounds.width - contentEdgeInsets.left - contentEdgeInsets.right - layoutEdgeInsets.left - layoutEdgeInsets.right\n        v.frame.size.height = h * CGFloat(r) - interimSpace\n        \n        n += r + ro - 1\n        \n      case .any:\n        let r = 0 == v.grid.rows ? axis.rows / count : v.grid.rows\n        let ro = v.grid.offset.rows\n        let c = 0 == v.grid.columns ? axis.columns / count : v.grid.columns\n        let co = v.grid.offset.columns\n        let w = (canvas.bounds.width - contentEdgeInsets.left - contentEdgeInsets.right - layoutEdgeInsets.left - layoutEdgeInsets.right + interimSpace) / CGFloat(axis.columns)\n        let h = (canvas.bounds.height - contentEdgeInsets.top - contentEdgeInsets.bottom - layoutEdgeInsets.top - layoutEdgeInsets.bottom + interimSpace) / CGFloat(axis.rows)\n        \n        v.frame.origin.x = CGFloat(co) * w + contentEdgeInsets.left + layoutEdgeInsets.left\n        v.frame.origin.y = CGFloat(ro) * h + contentEdgeInsets.top + layoutEdgeInsets.top\n        v.frame.size.width = w * CGFloat(c) - interimSpace\n        v.frame.size.height = h * CGFloat(r) - interimSpace\n      }\n      \n      i += 1\n      \n      /// reload the grid layout for each view on\n      /// each iteration, in order to ensure that\n      /// subviews are recalculated correctly.\n      if (isDeferred) { continue }\n      v.grid.reload()\n    }\n  }\n}\n\nfileprivate var AssociatedInstanceKey: UInt8 = 0\n\nextension UIView {\n  /// Grid reference.\n  public var grid: Grid {\n    get {\n      return AssociatedObject.get(base: self, key: &AssociatedInstanceKey) {\n        return Grid(context: self)\n      }\n    }\n    set(value) {\n      AssociatedObject.set(base: self, key: &AssociatedInstanceKey, value: value)\n    }\n  }\n  \n  /// A reference to grid's layoutEdgeInsetsPreset.\n  open var layoutEdgeInsetsPreset: EdgeInsetsPreset {\n    get {\n      return grid.layoutEdgeInsetsPreset\n    }\n    set(value) {\n      grid.layoutEdgeInsetsPreset = value\n    }\n  }\n  \n  /// A reference to grid's layoutEdgeInsets.\n  @IBInspectable\n  open var layoutEdgeInsets: EdgeInsets {\n    get {\n      return grid.layoutEdgeInsets\n    }\n    set(value) {\n      grid.layoutEdgeInsets = value\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Height/HeightPreset.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\npublic enum HeightPreset {\n  case none\n  case tiny\n  case xsmall\n  case small\n  case `default`\n  case normal\n  case medium\n  case large\n  case xlarge\n  case xxlarge\n  case custom(CGFloat)\n  \n  public var rawValue: CGFloat {\n    switch self {\n    case .none:\n      return 0\n    case .tiny:\n      return 20\n    case .xsmall:\n      return 28\n    case .small:\n      return 36\n    case .`default`:\n      return 44\n    case .normal:\n      return 49\n    case .medium:\n      return 52\n    case .large:\n      return 60\n    case .xlarge:\n      return 68\n    case .xxlarge:\n      return 104\n    case .custom(let v):\n      return v\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Icon/Icon.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\npublic struct Icon {\n  /// An internal reference to the icons bundle.\n  private static var internalBundle: Bundle?\n  \n  /**\n   A public reference to the icons bundle, that aims to detect\n   the correct bundle to use.\n   */\n  public static var bundle: Bundle {\n    if nil == Icon.internalBundle {\n      Icon.internalBundle = Bundle(for: View.self)\n      let url = Icon.internalBundle!.resourceURL!\n      let b = Bundle(url: url.appendingPathComponent(\"com.cosmicmind.material.icons.bundle\"))\n      if let v = b {\n        Icon.internalBundle = v\n      }\n    }\n    return Icon.internalBundle!\n  }\n  \n  /// Get the icon by the file name.\n  public static func icon(_ name: String) -> UIImage? {\n    return UIImage(named: name, in: bundle, compatibleWith: nil)?.withRenderingMode(.alwaysTemplate)\n  }\n  \n  /// Google icons.\n  public static var add = Icon.icon(\"ic_add_white\")\n  public static var addCircle = Icon.icon(\"ic_add_circle_white\")\n  public static var addCircleOutline = Icon.icon(\"ic_add_circle_outline_white\")\n  public static var arrowBack = Icon.icon(\"ic_arrow_back_white\")\n  public static var arrowDownward = Icon.icon(\"ic_arrow_downward_white\")\n  public static var audio = Icon.icon(\"ic_audiotrack_white\")\n  public static var bell = Icon.icon(\"cm_bell_white\")\n  public static var cameraFront = Icon.icon(\"ic_camera_front_white\")\n  public static var cameraRear = Icon.icon(\"ic_camera_rear_white\")\n  public static var check = Icon.icon(\"ic_check_white\")\n  public static var clear = Icon.icon(\"ic_close_white\")\n  public static var close = Icon.icon(\"ic_close_white\")\n  public static var edit = Icon.icon(\"ic_edit_white\")\n  public static var email = Icon.icon(\"ic_email_white\")\n  public static var favorite = Icon.icon(\"ic_favorite_white\")\n  public static var favoriteBorder = Icon.icon(\"ic_favorite_border_white\")\n  public static var flashAuto = Icon.icon(\"ic_flash_auto_white\")\n  public static var flashOff = Icon.icon(\"ic_flash_off_white\")\n  public static var flashOn = Icon.icon(\"ic_flash_on_white\")\n  public static var history = Icon.icon(\"ic_history_white\")\n  public static var home = Icon.icon(\"ic_home_white\")\n  public static var image = Icon.icon(\"ic_image_white\")\n  public static var menu = Icon.icon(\"ic_menu_white\")\n  public static var moreHorizontal = Icon.icon(\"ic_more_horiz_white\")\n  public static var moreVertical = Icon.icon(\"ic_more_vert_white\")\n  public static var movie = Icon.icon(\"ic_movie_white\")\n  public static var pen = Icon.icon(\"ic_edit_white\")\n  public static var place = Icon.icon(\"ic_place_white\")\n  public static var phone = Icon.icon(\"ic_phone_white\")\n  public static var photoCamera = Icon.icon(\"ic_photo_camera_white\")\n  public static var photoLibrary = Icon.icon(\"ic_photo_library_white\")\n  public static var search = Icon.icon(\"ic_search_white\")\n  public static var settings = Icon.icon(\"ic_settings_white\")\n  public static var share = Icon.icon(\"ic_share_white\")\n  public static var star = Icon.icon(\"ic_star_white\")\n  public static var starBorder = Icon.icon(\"ic_star_border_white\")\n  public static var starHalf = Icon.icon(\"ic_star_half_white\")\n  public static var videocam = Icon.icon(\"ic_videocam_white\")\n  public static var visibility = Icon.icon(\"ic_visibility_white\")\n  public static var visibilityOff = Icon.icon(\"ic_visibility_off_white\")\n  public static var work = Icon.icon(\"ic_work_white\")\n  \n  /// CosmicMind icons.\n  public struct cm {\n    public static var add = Icon.icon(\"cm_add_white\")\n    public static var arrowBack = Icon.icon(\"cm_arrow_back_white\")\n    public static var arrowDownward = Icon.icon(\"cm_arrow_downward_white\")\n    public static var audio = Icon.icon(\"cm_audio_white\")\n    public static var audioLibrary = Icon.icon(\"cm_audio_library_white\")\n    public static var bell = Icon.icon(\"cm_bell_white\")\n    public static var check = Icon.icon(\"cm_check_white\")\n    public static var clear = Icon.icon(\"cm_close_white\")\n    public static var close = Icon.icon(\"cm_close_white\")\n    public static var edit = Icon.icon(\"cm_pen_white\")\n    public static var image = Icon.icon(\"cm_image_white\")\n    public static var menu = Icon.icon(\"cm_menu_white\")\n    public static var microphone = Icon.icon(\"cm_microphone_white\")\n    public static var moreHorizontal = Icon.icon(\"cm_more_horiz_white\")\n    public static var moreVertical = Icon.icon(\"cm_more_vert_white\")\n    public static var movie = Icon.icon(\"cm_movie_white\")\n    public static var pause = Icon.icon(\"cm_pause_white\")\n    public static var pen = Icon.icon(\"cm_pen_white\")\n    public static var photoCamera = Icon.icon(\"cm_photo_camera_white\")\n    public static var photoLibrary = Icon.icon(\"cm_photo_library_white\")\n    public static var play = Icon.icon(\"cm_play_white\")\n    public static var search = Icon.icon(\"cm_search_white\")\n    public static var settings = Icon.icon(\"cm_settings_white\")\n    public static var share = Icon.icon(\"cm_share_white\")\n    public static var shuffle = Icon.icon(\"cm_shuffle_white\")\n    public static var skipBackward = Icon.icon(\"cm_skip_backward_white\")\n    public static var skipForward = Icon.icon(\"cm_skip_forward_white\")\n    public static var star = Icon.icon(\"cm_star_white\")\n    public static var videocam = Icon.icon(\"cm_videocam_white\")\n    public static var volumeHigh = Icon.icon(\"cm_volume_high_white\")\n    public static var volumeMedium = Icon.icon(\"cm_volume_medium_white\")\n    public static var volumeOff = Icon.icon(\"cm_volume_off_white\")\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Layer/Layer.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(Layer)\nopen class Layer: CAShapeLayer {\n  /**\n   A CAShapeLayer used to manage elements that would be affected by\n   the clipToBounds property of the backing layer. For example, this\n   allows the dropshadow effect on the backing layer, while clipping\n   the image to a desired shape within the visualLayer.\n   */\n  public let visualLayer = CAShapeLayer()\n  \n  /**\n   A property that manages an image for the visualLayer's contents\n   property. Images should not be set to the backing layer's contents\n   property to avoid conflicts when using clipsToBounds.\n   */\n  @IBInspectable\n  open var image: UIImage? {\n    didSet {\n      visualLayer.contents = image?.cgImage\n    }\n  }\n  \n  /**\n   Allows a relative subrectangle within the range of 0 to 1 to be\n   specified for the visualLayer's contents property. This allows\n   much greater flexibility than the contentsGravity property in\n   terms of how the image is cropped and stretched.\n   */\n  open override var contentsRect: CGRect {\n    didSet {\n      visualLayer.contentsRect = contentsRect\n    }\n  }\n  \n  /**\n   A CGRect that defines a stretchable region inside the visualLayer\n   with a fixed border around the edge.\n   */\n  open override var contentsCenter: CGRect {\n    didSet {\n      visualLayer.contentsCenter = contentsCenter\n    }\n  }\n  \n  /**\n   A floating point value that defines a ratio between the pixel\n   dimensions of the visualLayer's contents property and the size\n   of the layer. By default, this value is set to the Screen.scale.\n   */\n  @IBInspectable\n  open override var contentsScale: CGFloat {\n    didSet {\n      visualLayer.contentsScale = contentsScale\n    }\n  }\n  \n  /// Determines how content should be aligned within the visualLayer's bounds.\n  @IBInspectable\n  open override var contentsGravity: CALayerContentsGravity {\n    get {\n      return visualLayer.contentsGravity\n    }\n    set(value) {\n      visualLayer.contentsGravity = value\n    }\n  }\n  \n  /**\n   A property that sets the cornerRadius of the backing layer. If the shape\n   property has a value of .circle when the cornerRadius is set, it will\n   become .none, as it no longer maintains its circle shape.\n   */\n  @IBInspectable\n  open override var cornerRadius: CGFloat {\n    didSet {\n      layoutShadowPath()\n      shapePreset = .none\n    }\n  }\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n    prepareVisualLayer()\n  }\n  \n  /**\n   An initializer the same as init(). The layer parameter is ignored\n   to avoid crashes on certain architectures.\n   - Parameter layer: Any.\n   */\n  public override init(layer: Any) {\n    super.init(layer: layer)\n    prepareVisualLayer()\n  }\n  \n  /// A convenience initializer.\n  public override init() {\n    super.init()\n    prepareVisualLayer()\n  }\n  \n  /**\n   An initializer that initializes the object with a CGRect object.\n   - Parameter frame: A CGRect instance.\n   */\n  public convenience init(frame: CGRect) {\n    self.init()\n    self.frame = frame\n  }\n  \n  open override func layoutSublayers() {\n    super.layoutSublayers()\n    layoutShape()\n    layoutVisualLayer()\n    layoutShadowPath()\n  }\n}\n\nfileprivate extension Layer {\n  /// Prepares the visualLayer property.\n  func prepareVisualLayer() {\n    contentsGravity = .resizeAspectFill\n    visualLayer.zPosition = 0\n    visualLayer.masksToBounds = true\n    addSublayer(visualLayer)\n  }\n  \n  /// Manages the layout for the visualLayer property.\n  func layoutVisualLayer() {\n    visualLayer.frame = bounds\n    visualLayer.cornerRadius = cornerRadius\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Layout/Layout.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\n/// A protocol that's conformed by UIView and UILayoutGuide.\npublic protocol Constraintable: class { }\n\n@available(iOS 9.0, *)\nextension UILayoutGuide: Constraintable { }\nextension UIView: Constraintable { }\n\n/// Layout extension for UIView.\npublic extension UIView {\n  /**\n   Used to chain layout constraints on a child context.\n   - Parameter child: A child UIView to layout.\n   - Returns: A Layout instance.\n   */\n  func layout(_ child: UIView) -> Layout {\n    if self != child.superview {\n      addSubview(child)\n    }\n    \n    child.translatesAutoresizingMaskIntoConstraints = false\n    return child.layout\n  }\n  \n  /// Layout instance for the view.\n  var layout: Layout {\n    return Layout(constraintable: self)\n  }\n  \n  /// Anchor instance for the view.\n  var anchor: LayoutAnchor {\n    return LayoutAnchor(constraintable: self)\n  }\n  \n  /**\n   Anchor instance for safeAreaLayoutGuide.\n   Below iOS 11, it will be same as view.anchor.\n   */\n  var safeAnchor: LayoutAnchor {\n    if #available(iOS 11.0, *) {\n      return LayoutAnchor(constraintable: safeAreaLayoutGuide)\n    } else {\n      return anchor\n    }\n  }\n}\n\nprivate extension NSLayoutConstraint {\n  /**\n   Checks if the constraint is equal to given constraint.\n   - Parameter _ other: An NSLayoutConstraint.\n   - Returns: A Bool indicating whether constraints are equal.\n   */\n  func equalTo(_ other: NSLayoutConstraint) -> Bool {\n    return firstItem === other.firstItem\n      && secondItem === other.secondItem\n      && firstAttribute == other.firstAttribute\n      && secondAttribute == other.secondAttribute\n      && relation == other.relation\n  }\n}\n\n/// A memory reference to the lastConstraint of UIView.\nprivate var LastConstraintKey: UInt8 = 0\n\nprivate extension UIView {\n  /**\n   The last consntraint that's created by Layout system.\n   Used to set multiplier/priority on the last constraint.\n   */\n  var lastConstraint: NSLayoutConstraint? {\n    get {\n      return AssociatedObject.get(base: self, key: &LastConstraintKey) {\n        nil\n      }\n    }\n    set(value) {\n      AssociatedObject.set(base: self, key: &LastConstraintKey, value: value)\n    }\n  }\n}\n\npublic struct Layout {\n  /// A weak reference to the constraintable.\n  public weak var constraintable: Constraintable?\n  \n  /// Parent view of the view.\n  var parent: UIView? {\n    return (constraintable as? UIView)?.superview\n  }\n  \n  /// Returns the view that is being laied out.\n  public var view: UIView? {\n    var  v = constraintable as? UIView\n    if #available(iOS 9.0, *), v == nil {\n      v = (constraintable as? UILayoutGuide)?.owningView\n    }\n    \n    return v\n  }\n  \n  /**\n   An initializer taking Constraintable.\n   - Parameter view: A Constraintable.\n   */\n  init(constraintable: Constraintable) {\n    self.constraintable = constraintable\n  }\n}\n\npublic extension Layout {\n  /**\n   Sets multiplier of the last created constraint.\n   Not meant for updating the multiplier as it will re-create the constraint.\n   - Parameter _ multiplier: A CGFloat multiplier.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func multiply(_ multiplier: CGFloat) -> Layout {\n    return resetLastConstraint(multiplier: multiplier)\n  }\n  \n  /**\n   Sets priority of the last created constraint.\n   Not meant for updating the multiplier as it will re-create the constraint.\n   - Parameter _ value: A Float priority.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func priority(_ value: Float) -> Layout {\n    return priority(.init(rawValue: value))\n  }\n  \n  /**\n   Sets priority of the last created constraint.\n   Not meant for updating the priority as it will re-create the constraint.\n   - Parameter _ priority: A UILayoutPriority.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func priority(_ priority: UILayoutPriority) -> Layout {\n    return resetLastConstraint(priority: priority)\n  }\n  \n  /**\n   Removes the last created constraint and creates new one with the new multiplier and/or priority (if provided).\n   - Parameter multiplier: An optional CGFloat.\n   - Parameter priority: An optional UILayoutPriority.\n   - Returns: A Layout instance to allow chaining.\n   */\n  private func resetLastConstraint(multiplier: CGFloat? = nil, priority: UILayoutPriority? = nil) -> Layout {\n    guard let v = view?.lastConstraint, v.isActive else {\n      return self\n    }\n    v.isActive = false\n    let newV = NSLayoutConstraint(item: v.firstItem as Any,\n                                  attribute: v.firstAttribute,\n                                  relatedBy: v.relation,\n                                  toItem: v.secondItem,\n                                  attribute: v.secondAttribute,\n                                  multiplier: multiplier ?? v.multiplier,\n                                  constant: v.constant)\n    newV.priority = priority ?? v.priority\n    newV.isActive = true\n    view?.lastConstraint = newV\n    return self\n  }\n}\n\npublic extension Layout {\n  /**\n   Constraints top of the view to its parent's.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func top(_ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.top, relationer: relationer, constant: offset)\n  }\n  \n  /**\n   Constraints left of the view to its parent's.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func left(_ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.left, relationer: relationer, constant: offset)\n  }\n  \n  /**\n   Constraints right of the view to its parent.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func right(_ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.right, relationer: relationer, constant: -offset)\n  }\n  \n  /**\n   Constraints leading of the view to its parent's.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func leading(_ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.leading, relationer: relationer, constant: offset)\n  }\n  \n  /**\n   Constraints trailing of the view to its parent.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func trailing(_ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.trailing, relationer: relationer, constant: -offset)\n  }\n  \n  /**\n   Constraints bottom of the view to its parent's.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func bottom(_ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.bottom, relationer: relationer, constant: -offset)\n  }\n  \n  /**\n   Constraints top-left of the view to its parent's.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter left: A CGFloat offset for left.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func topLeft(top: CGFloat = 0, left: CGFloat = 0) -> Layout {\n    return constraint(.topLeft, constants: top, left)\n  }\n  \n  /**\n   Constraints top-right of the view to its parent's.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter right: A CGFloat offset for right.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func topRight(top: CGFloat = 0, right: CGFloat = 0) -> Layout {\n    return constraint(.topRight, constants: top, -right)\n  }\n  \n  /**\n   Constraints bottom-left of the view to its parent's.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Parameter left: A CGFloat offset for left.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func bottomLeft(bottom: CGFloat = 0, left: CGFloat = 0) -> Layout {\n    return constraint(.bottomLeft, constants: -bottom, left)\n  }\n  \n  /**\n   Constraints bottom-right of the view to its parent's.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Parameter right: A CGFloat offset for right.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func bottomRight(bottom: CGFloat = 0, right: CGFloat = 0) -> Layout {\n    return constraint(.bottomRight, constants: -bottom, -right)\n  }\n  \n  /**\n   Constraints left and right of the view to its parent's.\n   - Parameter left: A CGFloat offset for left.\n   - Parameter right: A CGFloat offset for right.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func leftRight(left: CGFloat = 0, right: CGFloat = 0) -> Layout {\n    return constraint(.leftRight, constants: left, -right)\n  }\n  \n  /**\n   Constraints top-leading of the view to its parent's.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter leading: A CGFloat offset for leading.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func topLeading(top: CGFloat = 0, leading: CGFloat = 0) -> Layout {\n    return constraint(.topLeading, constants: top, leading)\n  }\n  \n  /**\n   Constraints top-trailing of the view to its parent's.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter trailing: A CGFloat offset for trailing.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func topTrailing(top: CGFloat = 0, trailing: CGFloat = 0) -> Layout {\n    return constraint(.topTrailing, constants: top, -trailing)\n  }\n  \n  /**\n   Constraints bottom-leading of the view to its parent's.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Parameter leading: A CGFloat offset for leading.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func bottomLeading(bottom: CGFloat = 0, leading: CGFloat = 0) -> Layout {\n    return constraint(.bottomLeading, constants: -bottom, leading)\n  }\n  \n  /**\n   Constraints bottom-trailing of the view to its parent's.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Parameter trailing: A CGFloat offset for trailing.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func bottomTrailing(bottom: CGFloat = 0, trailing: CGFloat = 0) -> Layout {\n    return constraint(.bottomTrailing, constants: -bottom, -trailing)\n  }\n  \n  /**\n   Constraints leading and trailing of the view to its parent's.\n   - Parameter leading: A CGFloat offset for leading.\n   - Parameter trailing: A CGFloat offset for trailing.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func leadingTrailing(leading: CGFloat = 0, trailing: CGFloat = 0) -> Layout {\n    return constraint(.leadingTrailing, constants: leading, -trailing)\n  }\n  \n  /**\n   Constraints top and bottom of the view to its parent's.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func topBottom(top: CGFloat = 0, bottom: CGFloat = 0) -> Layout {\n    return constraint(.topBottom, constants: top, -bottom)\n  }\n  \n  /**\n   Constraints center of the view to its parent's.\n   - Parameter offsetX: A CGFloat offset for horizontal center.\n   - Parameter offsetY: A CGFloat offset for vertical center.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func center(offsetX: CGFloat = 0, offsetY: CGFloat = 0) -> Layout {\n    return constraint(.center, constants: offsetX, offsetY)\n  }\n  \n  /**\n   Constraints horizontal center of the view to its parent's.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func centerX(_ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.centerX, relationer: relationer, constant: offset)\n  }\n  \n  /**\n   Constraints vertical center of the view to its parent's.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func centerY(_ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.centerY, relationer: relationer, constant: offset)\n  }\n  \n  /**\n   Constraints width of the view to its parent's.\n   - Parameter offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func width(offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.width, relationer: relationer, constant: offset)\n  }\n  \n  /**\n   Constraints height of the view to its parent's.\n   - Parameter offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func height(offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.height, relationer: relationer, constant: offset)\n  }\n  \n  /**\n   Constraints edges of the view to its parent's.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter left: A CGFloat offset for left.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Parameter right: A CGFloat offset for right.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func edges(top: CGFloat = 0, left: CGFloat = 0, bottom: CGFloat = 0, right: CGFloat = 0) -> Layout {\n    return constraint(.edges, constants: top, left, -bottom, -right)\n  }\n}\n\npublic extension Layout {\n  /**\n   Constraints top of the view to its parent's safeArea.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func topSafe(_ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.top, relationer: relationer, constant: offset, useSafeArea: true)\n  }\n  \n  /**\n   Constraints left of the view to its parent's safeArea.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func leftSafe(_ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.left, relationer: relationer, constant: offset, useSafeArea: true)\n  }\n  \n  /**\n   Constraints right of the view to its parent.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func rightSafe(_ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.right, relationer: relationer, constant: -offset, useSafeArea: true)\n  }\n  \n  /**\n   Constraints leading of the view to its parent's safeArea.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func leadingSafe(_ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.leading, relationer: relationer, constant: offset, useSafeArea: true)\n  }\n  \n  /**\n   Constraints trailing of the view to its parent.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func trailingSafe(_ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.trailing, relationer: relationer, constant: -offset, useSafeArea: true)\n  }\n  \n  /**\n   Constraints bottom of the view to its parent's safeArea.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func bottomSafe(_ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.bottom, relationer: relationer, constant: -offset, useSafeArea: true)\n  }\n  \n  /**\n   Constraints top-left of the view to its parent's safeArea.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter left: A CGFloat offset for left.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func topLeftSafe(top: CGFloat = 0, left: CGFloat = 0) -> Layout {\n    return constraint(.topLeft, constants: top, left, useSafeArea: true)\n  }\n  \n  /**\n   Constraints top-right of the view to its parent's safeArea.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter right: A CGFloat offset for right.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func topRightSafe(top: CGFloat = 0, right: CGFloat = 0) -> Layout {\n    return constraint(.topRight, constants: top, -right, useSafeArea: true)\n  }\n  \n  /**\n   Constraints bottom-left of the view to its parent's safeArea.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Parameter left: A CGFloat offset for left.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func bottomLeftSafe(bottom: CGFloat = 0, left: CGFloat = 0) -> Layout {\n    return constraint(.bottomLeft, constants: -bottom, left, useSafeArea: true)\n  }\n  \n  /**\n   Constraints bottom-right of the view to its parent's safeArea.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Parameter right: A CGFloat offset for right.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func bottomRightSafe(bottom: CGFloat = 0, right: CGFloat = 0) -> Layout {\n    return constraint(.bottomRight, constants: -bottom, -right, useSafeArea: true)\n  }\n  \n  /**\n   Constraints left and right of the view to its parent's safeArea.\n   - Parameter left: A CGFloat offset for left.\n   - Parameter right: A CGFloat offset for right.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func leftRightSafe(left: CGFloat = 0, right: CGFloat = 0) -> Layout {\n    return constraint(.leftRight, constants: left, -right, useSafeArea: true)\n  }\n  \n  /**\n   Constraints top-leading of the view to its parent's safeArea.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter leading: A CGFloat offset for leading.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func topLeadingSafe(top: CGFloat = 0, leading: CGFloat = 0) -> Layout {\n    return constraint(.topLeading, constants: top, leading, useSafeArea: true)\n  }\n  \n  /**\n   Constraints top-trailing of the view to its parent's safeArea.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter trailing: A CGFloat offset for trailing.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func topTrailingSafe(top: CGFloat = 0, trailing: CGFloat = 0) -> Layout {\n    return constraint(.topTrailing, constants: top, -trailing, useSafeArea: true)\n  }\n  \n  /**\n   Constraints bottom-leading of the view to its parent's safeArea.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Parameter leading: A CGFloat offset for leading.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func bottomLeadingSafe(bottom: CGFloat = 0, leading: CGFloat = 0) -> Layout {\n    return constraint(.bottomLeading, constants: -bottom, leading, useSafeArea: true)\n  }\n  \n  /**\n   Constraints bottom-trailing of the view to its parent's safeArea.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Parameter trailing: A CGFloat offset for trailing.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func bottomTrailingSafe(bottom: CGFloat = 0, trailing: CGFloat = 0) -> Layout {\n    return constraint(.bottomTrailing, constants: -bottom, -trailing, useSafeArea: true)\n  }\n  \n  /**\n   Constraints leading and trailing of the view to its parent's safeArea.\n   - Parameter leading: A CGFloat offset for leading.\n   - Parameter trailing: A CGFloat offset for trailing.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func leadingTrailingSafe(leading: CGFloat = 0, trailing: CGFloat = 0) -> Layout {\n    return constraint(.leadingTrailing, constants: leading, -trailing, useSafeArea: true)\n  }\n  \n  /**\n   Constraints top and bottom of the view to its parent's safeArea.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func topBottomSafe(top: CGFloat = 0, bottom: CGFloat = 0) -> Layout {\n    return constraint(.topBottom, constants: top, -bottom, useSafeArea: true)\n  }\n  \n  /**\n   Constraints center of the view to its parent's safeArea.\n   - Parameter offsetX: A CGFloat offset for horizontal center.\n   - Parameter offsetY: A CGFloat offset for vertical center.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func centerSafe(offsetX: CGFloat = 0, offsetY: CGFloat = 0) -> Layout {\n    return constraint(.center, constants: offsetX, offsetY, useSafeArea: true)\n  }\n  \n  /**\n   Constraints horizontal center of the view to its parent's safeArea.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func centerXSafe(_ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.centerX, relationer: relationer, constant: offset, useSafeArea: true)\n  }\n  \n  /**\n   Constraints vertical center of the view to its parent's safeArea.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func centerYSafe(_ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.centerY, relationer: relationer, constant: offset, useSafeArea: true)\n  }\n  \n  /**\n   Constraints width of the view to its parent's safeArea.\n   - Parameter offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func widthSafe(offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.width, relationer: relationer, constant: offset, useSafeArea: true)\n  }\n  \n  /**\n   Constraints height of the view to its parent's safeArea.\n   - Parameter offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func heightSafe(offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.height, relationer: relationer, constant: offset, useSafeArea: true)\n  }\n  \n  /**\n   Constraints edges of the view to its parent's safeArea.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter left: A CGFloat offset for left.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Parameter right: A CGFloat offset for right.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func edgesSafe(top: CGFloat = 0, left: CGFloat = 0, bottom: CGFloat = 0, right: CGFloat = 0) -> Layout {\n    return constraint(.edges, constants: top, left, -bottom, -right, useSafeArea: true)\n  }\n}\n\npublic extension Layout {\n  /**\n   Constraints width of the view to a constant value.\n   - Parameter _ width: A CGFloat value.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func width(_ width: CGFloat, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.constantWidth, relationer: relationer, constants: width)\n  }\n  \n  /**\n   Constraints height of the view to a constant value.\n   - Parameter _ height: A CGFloat value.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func height(_ height: CGFloat, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.constantHeight, relationer: relationer, constants: height)\n  }\n  \n  /**\n   The width and height of the view to its parent's.\n   - Parameter _ size: A CGSize offset.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func size(_ size: CGSize) -> Layout {\n    return width(size.width).height(size.height)\n  }\n}\n\npublic extension Layout {\n  /**\n   Constraints top of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func top(_ anchor: LayoutAnchorable, _ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.top, to: anchor, relationer: relationer, constant: offset)\n  }\n  \n  /**\n   Constraints left of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func left(_ anchor: LayoutAnchorable, _ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.left, to: anchor, relationer: relationer, constant: offset)\n  }\n  \n  /**\n   Constraints right of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func right(_ anchor: LayoutAnchorable, _ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.right, to: anchor, relationer: relationer, constant: -offset)\n  }\n  \n  /**\n   Constraints leading of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func leading(_ anchor: LayoutAnchorable, _ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.leading, to: anchor, relationer: relationer, constant: offset)\n  }\n  \n  /**\n   Constraints trailing of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func trailing(_ anchor: LayoutAnchorable, _ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.trailing, to: anchor, relationer: relationer, constant: -offset)\n  }\n  \n  /**\n   Constraints bottom of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func bottom(_ anchor: LayoutAnchorable, _ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.bottom, to: anchor, relationer: relationer, constant: -offset)\n  }\n  \n  /**\n   Constraints top-leading of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter leading: A CGFloat offset for leading.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func topLeading(_ anchor: LayoutAnchorable, top: CGFloat = 0, leading: CGFloat = 0) -> Layout {\n    return constraint(.topLeading, to: anchor, constants: top, leading)\n  }\n  \n  /**\n   Constraints top-trailing of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter trailing: A CGFloat offset for trailing.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func topTrailing(_ anchor: LayoutAnchorable, top: CGFloat = 0, trailing: CGFloat = 0) -> Layout {\n    return constraint(.topTrailing, to: anchor, constants: top, -trailing)\n  }\n  \n  /**\n   Constraints bottom-leading of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Parameter leading: A CGFloat offset for leading.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func bottomLeading(_ anchor: LayoutAnchorable, bottom: CGFloat = 0, leading: CGFloat = 0) -> Layout {\n    return constraint(.bottomLeading, to: anchor, constants: -bottom, leading)\n  }\n  \n  /**\n   Constraints bottom-trailing of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Parameter trailing: A CGFloat offset for trailing.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func bottomTrailing(_ anchor: LayoutAnchorable, bottom: CGFloat = 0, trailing: CGFloat = 0) -> Layout {\n    return constraint(.bottomTrailing, to: anchor, constants: -bottom, -trailing)\n  }\n  \n  /**\n   Constraints leading and trailing of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter leading: A CGFloat offset for leading.\n   - Parameter trailing: A CGFloat offset for trailing.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func leadingTrailing(_ anchor: LayoutAnchorable, leading: CGFloat = 0, trailing: CGFloat = 0) -> Layout {\n    return constraint(.leadingTrailing, to: anchor, constants: leading, -trailing)\n  }\n  \n  /**\n   Constraints top-left of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter left: A CGFloat offset for left.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func topLeft(_ anchor: LayoutAnchorable, top: CGFloat = 0, left: CGFloat = 0) -> Layout {\n    return constraint(.topLeft, to: anchor, constants: top, left)\n  }\n  \n  /**\n   Constraints top-right of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter right: A CGFloat offset for right.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func topRight(_ anchor: LayoutAnchorable, top: CGFloat = 0, right: CGFloat = 0) -> Layout {\n    return constraint(.topRight, to: anchor, constants: top, -right)\n  }\n  \n  /**\n   Constraints bottom-left of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Parameter left: A CGFloat offset for left.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func bottomLeft(_ anchor: LayoutAnchorable, bottom: CGFloat = 0, left: CGFloat = 0) -> Layout {\n    return constraint(.bottomLeft, to: anchor, constants: -bottom, left)\n  }\n  \n  /**\n   Constraints bottom-right of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Parameter right: A CGFloat offset for right.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func bottomRight(_ anchor: LayoutAnchorable, bottom: CGFloat = 0, right: CGFloat = 0) -> Layout {\n    return constraint(.bottomRight, to: anchor, constants: -bottom, -right)\n  }\n  \n  /**\n   Constraints left and right of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter left: A CGFloat offset for left.\n   - Parameter right: A CGFloat offset for right.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func leftRight(_ anchor: LayoutAnchorable, left: CGFloat = 0, right: CGFloat = 0) -> Layout {\n    return constraint(.leftRight, to: anchor, constants: left, -right)\n  }\n  \n  /**\n   Constraints top and bottom of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func topBottom(_ anchor: LayoutAnchorable, top: CGFloat = 0, bottom: CGFloat = 0) -> Layout {\n    return constraint(.topBottom, to: anchor, constants: top, -bottom)\n  }\n  \n  /**\n   Constraints center of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter offsetX: A CGFloat offset for horizontal center.\n   - Parameter offsetY: A CGFloat offset for vertical center.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func center(_ anchor: LayoutAnchorable, offsetX: CGFloat = 0, offsetY: CGFloat = 0) -> Layout {\n    return constraint(.center, to: anchor, constants: offsetX, offsetY)\n  }\n  \n  /**\n   Constraints horizontal center of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func centerX(_ anchor: LayoutAnchorable, _ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.centerX, to: anchor, relationer: relationer, constant: offset)\n  }\n  \n  /**\n   Constraints vertical center of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func centerY(_ anchor: LayoutAnchorable, _ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.centerY, to: anchor, relationer: relationer, constant: offset)\n  }\n  \n  /**\n   Constraints width of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func width(_ anchor: LayoutAnchorable, _ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.width, to: anchor, relationer: relationer, constant: offset)\n  }\n  \n  /**\n   Constraints height of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter _ offset: A CGFloat offset.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func height(_ anchor: LayoutAnchorable, _ offset: CGFloat = 0, _ relationer: LayoutRelationer = LayoutRelationerStruct.equal) -> Layout {\n    return constraint(.height, to: anchor, relationer: relationer, constant: offset)\n  }\n  \n  /**\n   Constraints edges of the view to the given anchor.\n   - Parameter _ anchor: A LayoutAnchorable.\n   - Parameter top: A CGFloat offset for top.\n   - Parameter left: A CGFloat offset for left.\n   - Parameter bottom: A CGFloat offset for bottom.\n   - Parameter right: A CGFloat offset for right.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func edges(_ anchor: LayoutAnchorable, top: CGFloat = 0, left: CGFloat = 0, bottom: CGFloat = 0, right: CGFloat = 0) -> Layout {\n    return constraint(.edges, to: anchor, constants: top, left, -bottom, -right)\n  }\n}\n\npublic extension Layout {\n  /**\n   Constraints the object and sets it's anchor to `bottom`.\n   - Parameter _ view: A UIView.\n   - Parameter offset: A CGFloat offset for top.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func below(_ view: UIView, _ offset: CGFloat = 0) -> Layout {\n    return top(view.anchor.bottom, offset)\n  }\n  \n  /**\n   Constraints the object and sets it's anchor to `top`.\n   - Parameter _ view: A UIView.\n   - Parameter offset: A CGFloat offset for bottom.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func above(_ view: UIView, _ offset: CGFloat = 0) -> Layout {\n    return bottom(view.anchor.top, offset)\n  }\n  \n  /**\n   Constraints the object and sets it's anchor to `before/left`.\n   - Parameter _ view: A UIView.\n   - Parameter offset: A CGFloat offset for right.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func before(_ view: UIView, _ offset: CGFloat = 0) -> Layout {\n    return right(view.anchor.left, offset)\n  }\n  \n  /**\n   Constraints the object and sets it's anchor to `after/right`.\n   - Parameter _ view: A UIView.\n   - Parameter offset: A CGFloat offset for left.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func after(_ view: UIView, _ offset: CGFloat = 0) -> Layout {\n    return left(view.anchor.right, offset)\n  }\n  \n  /**\n   Constraints the object and sets it's aspect.\n   - Parameter ratio: A CGFloat ratio multiplier.\n   - Returns: A Layout instance to allow chaining.\n   */\n  @discardableResult\n  func aspect(_ ratio: CGFloat = 1) -> Layout {\n    return height(view!.anchor.width).multiply(ratio)\n  }\n}\n\nprivate extension Layout {\n  /**\n   Constraints the view to its parent according to the provided attribute.\n   If the constraint already exists, will update its constant.\n   - Parameter _ attribute: A LayoutAttribute.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Parameter constant: A CGFloat.\n   - Returns: A Layout instance to allow chaining.\n   */\n  func constraint(_ attribute: LayoutAttribute, relationer: LayoutRelationer = LayoutRelationerStruct.equal, constant: CGFloat, useSafeArea: Bool = false) -> Layout {\n    return constraint([attribute], relationer: relationer, constants: constant, useSafeArea: useSafeArea)\n  }\n  \n  /**\n   Constraints the view to its parent according to the provided attributes.\n   If any of the constraints already exists, will update its constant.\n   - Parameter _ attributes: An array of LayoutAttribute.\n   - Parameter _ relationer: A LayoutRelationer.\n   - Parameter constants: A list of CGFloat.\n   - Returns: A Layout instance to allow chaining.\n   */\n  func constraint(_ attributes: [LayoutAttribute], relationer: LayoutRelationer = LayoutRelationerStruct.equal, constants: CGFloat..., useSafeArea: Bool = false) -> Layout {\n    var attributes = attributes\n    var anchor: LayoutAnchor!\n    \n    if attributes == .constantHeight || attributes == .constantWidth {\n      attributes.removeLast()\n      anchor = LayoutAnchor(constraintable: nil, attributes: [.notAnAttribute])\n    } else {\n      \n      guard parent != nil else {\n        fatalError(\"[Material Error: Constraint requires view to have parent.\")\n      }\n      \n      anchor = LayoutAnchor(constraintable: useSafeArea ? parent?.safeAnchor.constraintable : parent, attributes: attributes)\n    }\n    return constraint(attributes, to: anchor, relationer: relationer, constants: constants)\n  }\n  \n  /**\n   Constraints the view to the given anchor according to the provided attribute.\n   If the constraint already exists, will update its constant.\n   - Parameter _ attribute: A LayoutAttribute.\n   - Parameter to anchor: A LayoutAnchorable.\n   - Parameter relation: A LayoutRelation between anchors.\n   - Parameter constant: A CGFloat.\n   - Returns: A Layout instance to allow chaining.\n   */\n  func constraint(_ attribute: LayoutAttribute, to anchor: LayoutAnchorable, relationer: LayoutRelationer = LayoutRelationerStruct.equal, constant: CGFloat) -> Layout {\n    return constraint([attribute], to: anchor, relationer: relationer, constants: constant)\n  }\n  \n  /**\n   Constraints the view to the given anchor according to the provided attributes.\n   If any of the constraints already exists, will update its constant.\n   - Parameter _ attributes: An array of LayoutAttribute.\n   - Parameter to anchor: A LayoutAnchorable.\n   - Parameter relation: A LayoutRelation between anchors.\n   - Parameter constants: A list of CGFloat.\n   - Returns: A Layout instance to allow chaining.\n   */\n  func constraint(_ attributes: [LayoutAttribute], to anchor: LayoutAnchorable, relationer: LayoutRelationer = LayoutRelationerStruct.equal, constants: CGFloat...) -> Layout {\n    return constraint(attributes, to: anchor, relationer: relationer, constants: constants)\n  }\n  \n  /**\n   Constraints the view to the given anchor according to the provided attributes.\n   If any of the constraints already exists, will update its constant.\n   - Parameter _ attributes: An array of LayoutAttribute.\n   - Parameter to anchor: A LayoutAnchorable.\n   - Parameter relation: A LayoutRelation between anchors.\n   - Parameter constants: An array of CGFloat.\n   - Returns: A Layout instance to allow chaining.\n   */\n  func constraint(_ attributes: [LayoutAttribute], to anchor: LayoutAnchorable, relationer: LayoutRelationer, constants: [CGFloat]) -> Layout {\n    let from = LayoutAnchor(constraintable: constraintable, attributes: attributes)\n    var to = anchor as? LayoutAnchor\n    if to?.attributes.isEmpty ?? true {\n      let v = (anchor as? UIView) ?? (anchor as? LayoutAnchor)?.constraintable\n      to = LayoutAnchor(constraintable: v, attributes: attributes)\n    }\n    let constraint = LayoutConstraint(fromAnchor: from, toAnchor: to!, relation: relationer(.nil, .nil), constants: constants)\n    \n    \n    let constraints = (view?.constraints ?? []) + (view?.superview?.constraints ?? [])\n    let newConstraints = constraint.constraints\n    for newConstraint in newConstraints {\n      guard let activeConstraint = constraints.first(where: { $0.equalTo(newConstraint) }) else {\n        newConstraint.isActive = true\n        view?.lastConstraint = newConstraint\n        continue\n      }\n      \n      activeConstraint.constant = newConstraint.constant\n    }\n    \n    return self\n  }\n}\n\n/// A closure typealias for relation operators.\npublic typealias LayoutRelationer = (LayoutRelationerStruct, LayoutRelationerStruct) -> LayoutRelation\n\n/// A dummy struct used in creating relation operators (==, >=, <=).\npublic struct LayoutRelationerStruct {\n  /// Passed as an unused argument to the LayoutRelationer closures.\n  static let `nil` = LayoutRelationerStruct()\n  \n  /**\n   A method used as a default parameter for LayoutRelationer closures.\n   Swift does not allow using == operator directly, so we had to create this.\n   */\n  public static func equal(left: LayoutRelationerStruct, right: LayoutRelationerStruct) -> LayoutRelation {\n    return .equal\n  }\n}\n\n/// A method returning `LayoutRelation.equal`\npublic func ==(left: LayoutRelationerStruct, right: LayoutRelationerStruct) -> LayoutRelation {\n  return .equal\n}\n\n/// A method returning `LayoutRelation.greaterThanOrEqual`\npublic func >=(left: LayoutRelationerStruct, right: LayoutRelationerStruct) -> LayoutRelation {\n  return .greaterThanOrEqual\n}\n\n/// A method returning `LayoutRelation.lessThanOrEqual`\npublic func <=(left: LayoutRelationerStruct, right: LayoutRelationerStruct) -> LayoutRelation {\n  return .lessThanOrEqual\n}\n\n"
  },
  {
    "path": "Sources/iOS/Layout/LayoutAnchor.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n/// A protocol that's conformed by UIView, LayoutAnchor, and Layout.\npublic protocol LayoutAnchorable { }\n\nextension UIView: LayoutAnchorable { }\nextension Layout: LayoutAnchorable { }\nextension LayoutAnchor: LayoutAnchorable { }\n\npublic struct LayoutAnchor {\n  /// A weak reference to the constraintable.\n  public weak var constraintable: Constraintable?\n  \n  /// An array of LayoutAttribute for the view.\n  public let attributes: [LayoutAttribute]\n  \n  /**\n   An initializer taking constraintable and anchor attributes.\n   - Parameter view: A Constraintable.\n   - Parameter attributes: An array of LayoutAtrribute.\n   */\n  public init(constraintable: Constraintable?, attributes: [LayoutAttribute] = []) {\n    self.constraintable = constraintable\n    self.attributes = attributes\n  }\n}\n\npublic extension LayoutAnchor {\n  /// A layout anchor representing top of the view.\n  var top: LayoutAnchor {\n    return anchor(.top)\n  }\n  \n  /// A layout anchor representing bottom of the view.\n  var bottom: LayoutAnchor {\n    return anchor(.bottom)\n  }\n  \n  /// A layout anchor representing left of the view.\n  var left: LayoutAnchor {\n    return anchor(.left)\n  }\n  \n  /// A layout anchor representing right of the view.\n  var right: LayoutAnchor {\n    return anchor(.right)\n  }\n  \n  /// A layout anchor representing leading of the view.\n  var leading: LayoutAnchor {\n    return anchor(.leading)\n  }\n  \n  /// A layout anchor representing trailing of the view.\n  var trailing: LayoutAnchor {\n    return anchor(.trailing)\n  }\n  \n  /// A layout anchor representing top-left of the view.\n  var topLeft: LayoutAnchor {\n    return acnhor(.topLeft)\n  }\n  \n  /// A layout anchor representing top-right of the view.\n  var topRight: LayoutAnchor {\n    return acnhor(.topRight)\n  }\n  \n  /// A layout anchor representing bottom-left of the view.\n  var bottomLeft: LayoutAnchor {\n    return acnhor(.bottomLeft)\n  }\n  \n  /// A layout anchor representing bottom-right of the view.\n  var bottomRight: LayoutAnchor {\n    return acnhor(.bottomRight)\n  }\n  \n  /// A layout anchor representing top-leading of the view.\n  var topLeading: LayoutAnchor {\n    return acnhor(.topLeading)\n  }\n  \n  /// A layout anchor representing top-trailing of the view.\n  var topTrailing: LayoutAnchor {\n    return acnhor(.topTrailing)\n  }\n  \n  /// A layout anchor representing bottom-leading of the view.\n  var bottomLeading: LayoutAnchor {\n    return acnhor(.bottomLeading)\n  }\n  \n  /// A layout anchor representing bottom-trailing of the view.\n  var bottomTrailing: LayoutAnchor {\n    return acnhor(.bottomTrailing)\n  }\n  \n  /// A layout anchor representing top and bottom of the view.\n  var topBottom: LayoutAnchor {\n    return acnhor(.topBottom)\n  }\n  \n  /// A layout anchor representing left and right of the view.\n  var leftRight: LayoutAnchor {\n    return acnhor(.leftRight)\n  }\n  \n  /// A layout anchor representing leading and trailing of the view.\n  var leadingTrailing: LayoutAnchor {\n    return acnhor(.leadingTrailing)\n  }\n  \n  /// A layout anchor representing center of the view.\n  var center: LayoutAnchor {\n    return acnhor(.center)\n  }\n  \n  /// A layout anchor representing horizontal center of the view.\n  var centerX: LayoutAnchor {\n    return anchor(.centerX)\n  }\n  \n  /// A layout anchor representing vertical center of the view.\n  var centerY: LayoutAnchor {\n    return anchor(.centerY)\n  }\n  \n  /// A layout anchor representing top, left, bottom and right of the view.\n  var edges: LayoutAnchor {\n    return acnhor(.edges)\n  }\n  \n  /// A layout anchor representing width of the view.\n  var width: LayoutAnchor {\n    return anchor(.width)\n  }\n  /// A layout anchor representing height of the view.\n  var height: LayoutAnchor {\n    return anchor(.height)\n  }\n}\n\nprivate extension LayoutAnchor {\n  /**\n   Creates LayoutAnchor with the given attribute.\n   - Parameter attribute: A LayoutAttribute.\n   - Returns: A LayoutAnchor.\n   */\n  func anchor(_ attribute: LayoutAttribute) -> LayoutAnchor {\n    return LayoutAnchor(constraintable: constraintable, attributes: [attribute])\n  }\n  \n  /**\n   Creates LayoutAnchor with the given attributes.\n   - Parameter attributes: An array of LayoutAttribute.\n   - Returns: A LayoutAnchor.\n   */\n  func acnhor(_ attributes: [LayoutAttribute]) -> LayoutAnchor {\n    return LayoutAnchor(constraintable: constraintable, attributes: attributes)\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Layout/LayoutAttribute.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n/// A typealias for NSLayoutConstraint.Attribute\npublic typealias LayoutAttribute = NSLayoutConstraint.Attribute\n\ninternal extension Array where Element == LayoutAttribute {\n  /// A LayoutAttribute array containing top and left.\n  static var topLeft: [LayoutAttribute] {\n    return [.top, .left]\n  }\n  \n  /// A LayoutAttribute array containing top and right.\n  static var topRight: [LayoutAttribute] {\n    return [.top, .right]\n  }\n  \n  /// A LayoutAttribute array containing bottom and left.\n  static var bottomLeft: [LayoutAttribute] {\n    return [.bottom, .left]\n  }\n  \n  /// A LayoutAttribute array containing bottom and right.\n  static var bottomRight: [LayoutAttribute] {\n    return [.bottom, .right]\n  }\n  \n  /// A LayoutAttribute array containing left and right.\n  static var leftRight: [LayoutAttribute] {\n    return [.left, .right]\n  }\n  \n  /// A LayoutAttribute array containing top and leading.\n  static var topLeading: [LayoutAttribute] {\n    return [.top, .leading]\n  }\n  \n  /// A LayoutAttribute array containing top and trailing.\n  static var topTrailing: [LayoutAttribute] {\n    return [.top, .trailing]\n  }\n  \n  /// A LayoutAttribute array containing bottom and leading.\n  static var bottomLeading: [LayoutAttribute] {\n    return [.bottom, .leading]\n  }\n  \n  /// A LayoutAttribute array containing bottom and trailing.\n  static var bottomTrailing: [LayoutAttribute] {\n    return [.bottom, .trailing]\n  }\n  \n  /// A LayoutAttribute array containing left and trailing.\n  static var leadingTrailing: [LayoutAttribute] {\n    return [.leading, .trailing]\n  }\n  \n  /// A LayoutAttribute array containing top and bottom.\n  static var topBottom: [LayoutAttribute] {\n    return [.top, .bottom]\n  }\n  \n  /// A LayoutAttribute array containing centerX and centerY.\n  static var center: [LayoutAttribute] {\n    return [.centerX, .centerY]\n  }\n  \n  /// A LayoutAttribute array containing top, left, bottom and right.\n  static var edges: [LayoutAttribute] {\n    return [.top, .left, .bottom, .right]\n  }\n  \n  /// A LayoutAttribute array for constant height.\n  static var constantHeight: [LayoutAttribute] {\n    return [.height, .notAnAttribute]\n  }\n  \n  /// A LayoutAttribute array for constant width.\n  static var constantWidth: [LayoutAttribute] {\n    return [.width, .notAnAttribute]\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Layout/LayoutConstraint.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n/// A typealias for NSLayoutConstraint.Relation\npublic typealias LayoutRelation = NSLayoutConstraint.Relation\n\ninternal struct LayoutConstraint {\n  /// `From` anchor for the constraint.\n  private let fromAnchor: LayoutAnchor\n  \n  /// `To` anchor for the constraint.\n  private let toAnchor: LayoutAnchor\n  \n  /// An array of constants for the constraint.\n  private let constants: [CGFloat]\n  \n  /// A LayoutRelation between anchors.\n  private let relation: LayoutRelation\n  \n  \n  /**\n   An initializer taking `from` and `to` anchors, their `relation` and constants for the constraint.\n   - Parameter fromAnchor: A LayoutAnchor.\n   - Parameter toAnchor: A LayoutAnchor.\n   - Parameter relation: A LayoutRelation between anchors.\n   - Parameter constants: An array of CGFloat.\n   */\n  init(fromAnchor: LayoutAnchor, toAnchor: LayoutAnchor, relation: LayoutRelation, constants: [CGFloat]) {\n    self.fromAnchor = fromAnchor\n    self.toAnchor = toAnchor\n    self.relation = relation\n    self.constants = constants\n  }\n}\n\ninternal extension LayoutConstraint {\n  /// Creates an array of NSLayoutConstraint from a LayoutConstraint.\n  var constraints: [NSLayoutConstraint] {\n    guard fromAnchor.attributes.count == toAnchor.attributes.count else {\n      fatalError(\"[Material Error: The number of attributes of anchors does not match.]\")\n    }\n    \n    guard fromAnchor.attributes.count == constants.count else {\n      fatalError(\"[Material Error: The number of constants does not match the number of constraints.]\")\n    }\n    \n    var v: [NSLayoutConstraint] = []\n    \n    zip(zip(fromAnchor.attributes, toAnchor.attributes), constants).forEach {\n      v.append(NSLayoutConstraint(item: fromAnchor.constraintable as Any,\n                                  attribute: $0.0,\n                                  relatedBy: relation,\n                                  toItem: toAnchor.constraintable,\n                                  attribute: $0.1,\n                                  multiplier: 1,\n                                  constant: $1))\n    }\n    \n    \n    return v\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Navigation/NavigationBar.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class NavigationBar: UINavigationBar, Themeable {\n  /// Will layout the view.\n  open var willLayout: Bool {\n    return 0 < bounds.width && 0 < bounds.height && nil != superview\n  }\n  \n  /// Detail UILabel when in landscape for iOS 11.\n  fileprivate var toolbarToText: [Toolbar: String?]?\n  \n  open override var intrinsicContentSize: CGSize {\n    return CGSize(width: bounds.width, height: bounds.height)\n  }\n  \n  /// A preset wrapper around contentEdgeInsets.\n  open var contentEdgeInsetsPreset = EdgeInsetsPreset.square1 {\n    didSet {\n      contentEdgeInsets = EdgeInsetsPresetToValue(preset: contentEdgeInsetsPreset)\n    }\n  }\n  \n  /// A reference to EdgeInsets.\n  @IBInspectable\n  open var contentEdgeInsets = EdgeInsetsPresetToValue(preset: .square1) {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// A preset wrapper around interimSpace.\n  open var interimSpacePreset = InterimSpacePreset.interimSpace3 {\n    didSet {\n      interimSpace = InterimSpacePresetToValue(preset: interimSpacePreset)\n    }\n  }\n  \n  /// A wrapper around grid.interimSpace.\n  @IBInspectable\n  open var interimSpace = InterimSpacePresetToValue(preset: .interimSpace3) {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /**\n   The back button image writes to the backIndicatorImage property and\n   backIndicatorTransitionMaskImage property.\n   */\n  @IBInspectable\n  open var backButtonImage: UIImage? {\n    get {\n      return backIndicatorImage\n    }\n    set(value) {\n      let image: UIImage? = value\n      backIndicatorImage = image\n      backIndicatorTransitionMaskImage = image\n    }\n  }\n  \n  /// A property that accesses the backing layer's background\n  @IBInspectable\n  open override var backgroundColor: UIColor? {\n    get {\n      return barTintColor\n    }\n    set(value) {\n      barTintColor = value\n    }\n  }\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n    prepare()\n  }\n  \n  /**\n   An initializer that initializes the object with a CGRect object.\n   If AutoLayout is used, it is better to initilize the instance\n   using the init() initializer.\n   - Parameter frame: A CGRect instance.\n   */\n  public override init(frame: CGRect) {\n    super.init(frame: frame)\n    prepare()\n  }\n  \n  open override func sizeThatFits(_ size: CGSize) -> CGSize {\n    return intrinsicContentSize\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    layoutShape()\n    layoutShadowPath()\n    \n    //iOS 11 added left/right layout margin in subviews of UINavigationBar\n    //since we do not want to unsafely access private views directly, we\n    //iterate through the subviews to set `layoutMargins` to zero\n    for v in subviews {\n      if #available(iOS 13.0, *) {\n        let margins = v.layoutMargins\n        v.frame.origin.x = -margins.left\n        v.frame.size.width += margins.left + margins.right\n      } else {\n        v.layoutMargins = .zero\n      }\n    }\n    \n    if let v = topItem {\n      layoutNavigationItem(item: v)\n    }\n    \n    if let v = backItem {\n      layoutNavigationItem(item: v)\n    }\n    \n    layoutDivider()\n  }\n  \n  /**\n   Prepares the view instance when intialized. When subclassing,\n   it is recommended to override the prepare method\n   to initialize property values and other setup operations.\n   The super.prepare method should always be called immediately\n   when subclassing.\n   */\n  open func prepare() {\n    barStyle = .black\n    isTranslucent = false\n    depthPreset = .none\n    contentScaleFactor = Screen.scale\n    backButtonImage = Icon.cm.arrowBack\n    \n    if #available(iOS 11, *) {\n      toolbarToText = [:]\n    }\n    \n    let image = UIImage()\n    shadowImage = image\n    setBackgroundImage(image, for: .default)\n    backgroundColor = .white\n    applyCurrentTheme()\n  }\n  \n  /**\n   Applies the given theme.\n   - Parameter theme: A Theme.\n   */\n  open func apply(theme: Theme) {\n    backgroundColor = theme.primary\n    items?.forEach {\n      apply(theme: theme, to: $0)\n    }\n  }\n  \n  /**\n   Applies the given theme to the navigation item.\n   - Parameter theme: A Theme.\n   - Parameter to item: A UINavigationItem.\n   */\n  private func apply(theme: Theme, to item: UINavigationItem) {\n    Theme.apply(theme: theme, to: item.toolbar)\n  }\n}\n\ninternal extension NavigationBar {\n  /**\n   Lays out the UINavigationItem.\n   - Parameter item: A UINavigationItem to layout.\n   */\n  func layoutNavigationItem(item: UINavigationItem) {\n    guard willLayout else {\n      return\n    }\n    \n    if isThemingEnabled {\n      apply(theme: .current, to: item)\n    }\n    \n    let toolbar = item.toolbar\n    toolbar.backgroundColor = .clear\n    toolbar.interimSpace = interimSpace\n    toolbar.contentEdgeInsets = contentEdgeInsets\n    \n    if #available(iOS 11, *) {\n      if Application.shouldStatusBarBeHidden {\n        toolbar.contentEdgeInsetsPreset = .none\n        \n        if nil != toolbar.detailLabel.text {\n          toolbarToText?[toolbar] = toolbar.detailLabel.text\n          toolbar.detailLabel.text = nil\n        }\n      } else if nil != toolbarToText?[toolbar] {\n        toolbar.detailLabel.text = toolbarToText?[toolbar] ?? nil\n        toolbarToText?[toolbar] = nil\n      }\n    }\n    \n    item.titleView = toolbar\n    item.titleView!.frame = bounds\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Navigation/NavigationController.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\nextension NavigationController {\n  /// Device status bar style.\n  open var statusBarStyle: UIStatusBarStyle {\n    get {\n      return Application.statusBarStyle\n    }\n    set(value) {\n      Application.statusBarStyle = value\n    }\n  }\n}\n\nopen class NavigationController: UINavigationController {\n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n  }\n  \n  /**\n   An initializer that initializes the object with an Optional nib and bundle.\n   - Parameter nibNameOrNil: An Optional String for the nib.\n   - Parameter bundle: An Optional NSBundle where the nib is located.\n   */\n  public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {\n    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)\n  }\n  \n  /**\n   An initializer that initializes the object with a rootViewController.\n   - Parameter rootViewController: A UIViewController for the rootViewController.\n   */\n  public override init(rootViewController: UIViewController) {\n    super.init(navigationBarClass: NavigationBar.self, toolbarClass: nil)\n    setViewControllers([rootViewController], animated: false)\n  }\n  \n  public init(rootViewController: UIViewController, navigationBarClass: Swift.AnyClass?) {\n    super.init(navigationBarClass: navigationBarClass, toolbarClass: nil)\n    setViewControllers([rootViewController], animated: false)\n  }\n  \n  open override func viewWillAppear(_ animated: Bool) {\n    super.viewWillAppear(animated)\n    guard let v = interactivePopGestureRecognizer else {\n      return\n    }\n    \n    guard let x = navigationDrawerController else {\n      return\n    }\n    \n    if let l = x.leftPanGesture {\n      l.require(toFail: v)\n    }\n    \n    if let r = x.rightPanGesture {\n      r.require(toFail: v)\n    }\n  }\n  \n  open override func viewDidLoad() {\n    super.viewDidLoad()\n    prepare()\n  }\n  \n  open override func viewDidAppear(_ animated: Bool) {\n    super.viewDidAppear(animated)\n    guard let v = navigationBar as? NavigationBar else {\n      return\n    }\n    \n    guard let item = v.topItem else {\n      return\n    }\n    \n    v.layoutNavigationItem(item: item)\n  }\n  \n  open override func viewWillLayoutSubviews() {\n    super.viewWillLayoutSubviews()\n    layoutSubviews()\n  }\n  \n  /**\n   Prepares the view instance when intialized. When subclassing,\n   it is recommended to override the prepare method\n   to initialize property values and other setup operations.\n   The super.prepare method should always be called immediately\n   when subclassing.\n   */\n  open func prepare() {\n    navigationBar.frame.size.width = view.bounds.width\n    navigationBar.heightPreset = .normal\n    \n    view.clipsToBounds = true\n    view.backgroundColor = .white\n    view.contentScaleFactor = Screen.scale\n    \n    // This ensures the panning gesture is available when going back between views.\n    if let v = interactivePopGestureRecognizer {\n      v.isEnabled = true\n      v.delegate = self\n    }\n  }\n  \n  /// Calls the layout functions for the view heirarchy.\n  open func layoutSubviews() {\n    navigationBar.setNeedsUpdateConstraints()\n    navigationBar.updateConstraintsIfNeeded()\n    navigationBar.setNeedsLayout()\n    navigationBar.layoutIfNeeded()\n  }\n  \n  /**\n   Sets whether the navigation bar is hidden.\n   - Parameter _ hidden: Specify true to hide the navigation bar or false to show it.\n   - Parameter animated: Specify true if you want to animate the change in visibility or false if you want the navigation bar to appear immediately.\n   */\n  open override func setNavigationBarHidden(_ hidden: Bool, animated: Bool) {\n    super.setNavigationBarHidden(hidden, animated: animated)\n    guard let items = navigationBar.items, items.count > 1 else {\n      return\n    }\n    \n    items.forEach {\n      prepareBackButton(for: $0, in: navigationBar)\n    }\n  }\n}\n\nextension NavigationController: UINavigationBarDelegate {\n  /**\n   Delegation method that is called when a new UINavigationItem is about to be pushed.\n   This is used to prepare the transitions between UIViewControllers on the stack.\n   - Parameter navigationBar: A UINavigationBar that is used in the NavigationController.\n   - Parameter item: The UINavigationItem that will be pushed on the stack.\n   - Returns: A Boolean value that indicates whether to push the item on to the stack or not.\n   True is yes, false is no.\n   */\n  public func navigationBar(_ navigationBar: UINavigationBar, shouldPush item: UINavigationItem) -> Bool {\n    prepareBackButton(for: item, in: navigationBar)\n    return true\n  }\n  \n  public func navigationBar(_ navigationBar: UINavigationBar, didPop item: UINavigationItem) {\n    removeBackButton(from: item)\n  }\n}\n\ninternal extension NavigationController {\n  /// Handler for the backbutton.\n  @objc\n  func handle(backButton: UIButton) {\n    popViewController(animated: true)\n  }\n  \n  /**\n   Prepares back button of the navigation item in navigation bar.\n   - Parameter for item: A UINavigationItem.\n   - Parameter in navigationBar: A UINavigationBar.\n   */\n  func prepareBackButton(for item: UINavigationItem, in navigationBar: UINavigationBar) {\n    guard let v = navigationBar as? NavigationBar else {\n      return\n    }\n    \n    if nil == item.backButton.image && nil == item.backButton.title {\n      item.backButton.image = v.backButtonImage\n    }\n    \n    if !item.backButton.isHidden && !item.leftViews.contains(item.backButton) {\n      item.leftViews.insert(item.backButton, at: 0)\n    }\n    \n    item.backButton.addTarget(self, action: #selector(handle(backButton:)), for: .touchUpInside)\n    \n    item.hidesBackButton = false\n    item.setHidesBackButton(true, animated: false)\n    \n    v.layoutNavigationItem(item: item)\n  }\n  \n  /**\n   Removes back button of the navigation item.\n   - Parameter from item: A UINavigationItem.\n   */\n  func removeBackButton(from item: UINavigationItem) {\n    if let index = item.leftViews.firstIndex(of: item.backButton) {\n      item.leftViews.remove(at: index)\n    }\n    \n    item.backButton.removeTarget(self, action: #selector(handle(backButton:)), for: .touchUpInside)\n  }\n}\n\nextension NavigationController: UIGestureRecognizerDelegate {\n  /**\n   Detects the gesture recognizer being used. This is necessary when using\n   NavigationDrawerController. It eliminates the conflict in panning.\n   - Parameter gestureRecognizer: A UIGestureRecognizer to detect.\n   - Parameter touch: The UITouch event.\n   - Returns: A Boolean of whether to continue the gesture or not, true yes, false no.\n   */\n  public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {\n    return interactivePopGestureRecognizer == gestureRecognizer && nil != navigationBar.backItem\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Navigation/NavigationItem.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\n/// A memory reference to the NavigationItem instance.\nfileprivate var NavigationItemKey: UInt8 = 0\nfileprivate var NavigationItemContext: UInt8 = 0\n\nfileprivate class NavigationItem: NSObject {\n  /// A reference to the toolbar.\n  @objc\n  let toolbar = Toolbar()\n  \n  /// Back Button.\n  lazy var backButton = IconButton()\n  \n  /// An optional reference to the NavigationBar.\n  var navigationBar: NavigationBar? {\n    var v = toolbar.contentView.superview\n    while nil != v {\n      if let navigationBar = v as? NavigationBar {\n        return navigationBar\n      }\n      v = v?.superview\n    }\n    return nil\n  }\n}\n\nfileprivate extension UINavigationItem {\n  /// NavigationItem reference.\n  var navigationItem: NavigationItem {\n    get {\n      return AssociatedObject.get(base: self, key: &NavigationItemKey) {\n        return NavigationItem()\n      }\n    }\n    set(value) {\n      AssociatedObject.set(base: self, key: &NavigationItemKey, value: value)\n    }\n  }\n}\n\ninternal extension UINavigationItem {\n  /// A reference to the NavigationItem Toolbar.\n  var toolbar: Toolbar {\n    return navigationItem.toolbar\n  }\n}\n\nextension UINavigationItem {\n  /// Should center the contentView.\n  open var contentViewAlignment: ContentViewAlignment {\n    get {\n      return toolbar.contentViewAlignment\n    }\n    set(value) {\n      toolbar.contentViewAlignment = value\n    }\n  }\n  \n  /// Content View.\n  open var contentView: UIView {\n    return toolbar.contentView\n  }\n  \n  /// Back Button.\n  open var backButton: IconButton {\n    return navigationItem.backButton\n  }\n  \n  /// Title Label.\n  open var titleLabel: UILabel {\n    return toolbar.titleLabel\n  }\n  \n  /// Detail Label.\n  open var detailLabel: UILabel {\n    return toolbar.detailLabel\n  }\n  \n  /// Left side UIViews.\n  open var leftViews: [UIView] {\n    get {\n      return toolbar.leftViews\n    }\n    set(value) {\n      toolbar.leftViews = value\n    }\n  }\n  \n  /// Right side UIViews.\n  open var rightViews: [UIView] {\n    get {\n      return toolbar.rightViews\n    }\n    set(value) {\n      toolbar.rightViews = value\n    }\n  }\n  \n  /// Center UIViews.\n  open var centerViews: [UIView] {\n    get {\n      return toolbar.centerViews\n    }\n    set(value) {\n      toolbar.centerViews = value\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/NavigationDrawer/NavigationDrawerController.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\n@objc(NavigationDrawerPosition)\npublic enum NavigationDrawerPosition: Int {\n  case left\n  case right\n}\n\nextension UIViewController {\n  /**\n   A convenience property that provides access to the NavigationDrawerController.\n   This is the recommended method of accessing the NavigationDrawerController\n   through child UIViewControllers.\n   */\n  public var navigationDrawerController: NavigationDrawerController? {\n    return traverseViewControllerHierarchyForClassType()\n  }\n}\n\n@objc(NavigationDrawerControllerDelegate)\npublic protocol NavigationDrawerControllerDelegate {\n  /**\n   An optional delegation method that is fired before the\n   NavigationDrawerController opens.\n   - Parameter navigationDrawerController: A NavigationDrawerController.\n   - Parameter position: The NavigationDrawerPosition.\n   */\n  @objc\n  optional func navigationDrawerController(navigationDrawerController: NavigationDrawerController, willOpen position: NavigationDrawerPosition)\n  \n  /**\n   An optional delegation method that is fired after the\n   NavigationDrawerController opened.\n   - Parameter navigationDrawerController: A NavigationDrawerController.\n   - Parameter position: The NavigationDrawerPosition.\n   */\n  @objc\n  optional func navigationDrawerController(navigationDrawerController: NavigationDrawerController, didOpen position: NavigationDrawerPosition)\n  \n  /**\n   An optional delegation method that is fired before the\n   NavigationDrawerController closes.\n   - Parameter navigationDrawerController: A NavigationDrawerController.\n   - Parameter position: The NavigationDrawerPosition.\n   */\n  @objc\n  optional func navigationDrawerController(navigationDrawerController: NavigationDrawerController, willClose position: NavigationDrawerPosition)\n  \n  /**\n   An optional delegation method that is fired after the\n   NavigationDrawerController closed.\n   - Parameter navigationDrawerController: A NavigationDrawerController.\n   - Parameter position: The NavigationDrawerPosition.\n   */\n  @objc\n  optional func navigationDrawerController(navigationDrawerController: NavigationDrawerController, didClose position: NavigationDrawerPosition)\n  \n  /**\n   An optional delegation method that is fired when the\n   NavigationDrawerController pan gesture begins.\n   - Parameter navigationDrawerController: A NavigationDrawerController.\n   - Parameter didBeginPanAt point: A CGPoint.\n   - Parameter position: The NavigationDrawerPosition.\n   */\n  @objc\n  optional func navigationDrawerController(navigationDrawerController: NavigationDrawerController, didBeginPanAt point: CGPoint, position: NavigationDrawerPosition)\n  \n  /**\n   An optional delegation method that is fired when the\n   NavigationDrawerController pan gesture changes position.\n   - Parameter navigationDrawerController: A NavigationDrawerController.\n   - Parameter didChangePanAt point: A CGPoint.\n   - Parameter position: The NavigationDrawerPosition.\n   */\n  @objc\n  optional func navigationDrawerController(navigationDrawerController: NavigationDrawerController, didChangePanAt point: CGPoint, position: NavigationDrawerPosition)\n  \n  /**\n   An optional delegation method that is fired when the\n   NavigationDrawerController pan gesture ends.\n   - Parameter navigationDrawerController: A NavigationDrawerController.\n   - Parameter didEndPanAt point: A CGPoint.\n   - Parameter position: The NavigationDrawerPosition.\n   */\n  @objc\n  optional func navigationDrawerController(navigationDrawerController: NavigationDrawerController, didEndPanAt point: CGPoint, position: NavigationDrawerPosition)\n  \n  /**\n   An optional delegation method that is fired when the\n   NavigationDrawerController tap gesture executes.\n   - Parameter navigationDrawerController: A NavigationDrawerController.\n   - Parameter didTapAt point: A CGPoint.\n   - Parameter position: The NavigationDrawerPosition.\n   */\n  @objc\n  optional func navigationDrawerController(navigationDrawerController: NavigationDrawerController, didTapAt point: CGPoint, position: NavigationDrawerPosition)\n  \n  /**\n   An optional delegation method that is fired when the\n   status bar is about to change display, isHidden or not.\n   - Parameter navigationDrawerController: A NavigationDrawerController.\n   - Parameter statusBar isHidden: A boolean.\n   */\n  @objc\n  optional func navigationDrawerController(navigationDrawerController: NavigationDrawerController, statusBar isHidden: Bool)\n}\n\n@objc(NavigationDrawerController)\n@objcMembers\nopen class NavigationDrawerController: TransitionController {\n  /// A boolean indicating if the panel is animating.\n  fileprivate var isAnimating = false\n  \n  /**\n   A CGFloat property that is used internally to track\n   the original (x) position of the container view when panning.\n   */\n  fileprivate var originalX: CGFloat = 0\n  \n  /**\n   A UIPanGestureRecognizer property internally used for the\n   leftView pan gesture.\n   */\n  internal fileprivate(set) var leftPanGesture: UIPanGestureRecognizer?\n  \n  /**\n   A UITapGestureRecognizer property internally used for the\n   leftView tap gesture.\n   */\n  internal fileprivate(set) var leftTapGesture: UITapGestureRecognizer?\n  \n  /**\n   A UIPanGestureRecognizer property internally used for the\n   rightView pan gesture.\n   */\n  internal fileprivate(set) var rightPanGesture: UIPanGestureRecognizer?\n  \n  /**\n   A UITapGestureRecognizer property internally used for the\n   rightView tap gesture.\n   */\n  internal fileprivate(set) var rightTapGesture: UITapGestureRecognizer?\n  \n  /**\n   A CGFloat property that accesses the leftView threshold of\n   the NavigationDrawerController. When the panning gesture has\n   ended, if the position is beyond the threshold,\n   the leftView is opened, if it is below the threshold, the\n   leftView is closed.\n   */\n  @IBInspectable\n  open var leftThreshold: CGFloat = 64\n  fileprivate var leftViewThreshold: CGFloat = 0\n  \n  /**\n   A CGFloat property that accesses the rightView threshold of\n   the NavigationDrawerController. When the panning gesture has\n   ended, if the position is beyond the threshold,\n   the rightView is closed, if it is below the threshold, the\n   rightView is opened.\n   */\n  @IBInspectable\n  open var rightThreshold: CGFloat = 64\n  fileprivate var rightViewThreshold: CGFloat = 0\n  \n  /**\n   A NavigationDrawerControllerDelegate property used to bind\n   the delegation object.\n   */\n  open weak var delegate: NavigationDrawerControllerDelegate?\n  \n  /**\n   A CGFloat property that sets the animation duration of the\n   leftView when closing and opening. Defaults to 0.25.\n   */\n  @IBInspectable\n  open var animationDuration: TimeInterval = 0.25\n  \n  /**\n   A Boolean property that enables and disables the leftView from\n   opening and closing. Defaults to true.\n   */\n  @IBInspectable\n  open var isEnabled: Bool {\n    get {\n      return isLeftViewEnabled || isRightViewEnabled\n    }\n    set(value) {\n      if nil != leftView {\n        isLeftViewEnabled = value\n      }\n      \n      if nil != rightView {\n        isRightViewEnabled = value\n      }\n    }\n  }\n  \n  /**\n   A Boolean property that enables and disables the leftView from\n   opening and closing. Defaults to true.\n   */\n  @IBInspectable\n  open var isLeftViewEnabled = false {\n    didSet {\n      isLeftPanGestureEnabled = isLeftViewEnabled\n      isLeftTapGestureEnabled = isLeftViewEnabled\n    }\n  }\n  \n  /// Enables the left pan gesture.\n  @IBInspectable\n  open var isLeftPanGestureEnabled = false {\n    didSet {\n      if isLeftPanGestureEnabled {\n        prepareLeftPanGesture()\n      } else {\n        removeLeftPanGesture()\n      }\n    }\n  }\n  \n  /// Enables the left tap gesture.\n  @IBInspectable\n  open var isLeftTapGestureEnabled = false {\n    didSet {\n      if isLeftTapGestureEnabled {\n        prepareLeftTapGesture()\n      } else {\n        removeLeftTapGesture()\n      }\n    }\n  }\n  \n  /**\n   A Boolean property that enables and disables the rightView from\n   opening and closing. Defaults to true.\n   */\n  @IBInspectable\n  open var isRightViewEnabled = false {\n    didSet {\n      isRightPanGestureEnabled = isRightViewEnabled\n      isRightTapGestureEnabled = isRightViewEnabled\n    }\n  }\n  \n  /// Enables the right pan gesture.\n  @IBInspectable\n  open var isRightPanGestureEnabled = false {\n    didSet {\n      if isRightPanGestureEnabled {\n        prepareRightPanGesture()\n      } else {\n        removeRightPanGesture()\n      }\n    }\n  }\n  \n  /// Enables the right tap gesture.\n  @IBInspectable\n  open var isRightTapGestureEnabled = false {\n    didSet {\n      if isRightTapGestureEnabled {\n        prepareRightTapGesture()\n      } else {\n        removeRightTapGesture()\n      }\n    }\n  }\n  \n  /**\n   A Boolean property that triggers the status bar to be isHidden\n   when the leftView is opened. Defaults to true.\n   */\n  @IBInspectable\n  open var isHiddenStatusBarEnabled = true\n  \n  /**\n   A DepthPreset property that is used to set the depth of the\n   leftView when opened.\n   */\n  open var depthPreset = DepthPreset.depth1\n  \n  /**\n   A UIView property that is used to hide and reveal the\n   leftViewController. It is very rare that this property will\n   need to be accessed externally.\n   */\n  open fileprivate(set) var leftView: UIView?\n  \n  /**\n   A UIView property that is used to hide and reveal the\n   rightViewController. It is very rare that this property will\n   need to be accessed externally.\n   */\n  open fileprivate(set) var rightView: UIView?\n  \n  /// Indicates whether the leftView or rightView is opened.\n  open var isOpened: Bool {\n    return isLeftViewOpened || isRightViewOpened\n  }\n  \n  /// indicates if the leftView is opened.\n  open var isLeftViewOpened: Bool {\n    guard let v = leftView else {\n      return false\n    }\n    return v.frame.origin.x != -leftViewWidth\n  }\n  \n  /// Indicates if the rightView is opened.\n  open var isRightViewOpened: Bool {\n    guard let v = rightView else {\n      return false\n    }\n    return v.frame.origin.x != Screen.width\n  }\n  \n  /**\n   Content view controller to encompase the entire component. This is\n   primarily used when the StatusBar is being isHidden. The alpha value of\n   the rootViewController decreases, and shows the StatusBar. To avoid\n   this, and to add a isHidden transition viewController for complex\n   situations, the contentViewController was added.\n   */\n  open fileprivate(set) lazy var contentViewController = UIViewController()\n  \n  /**\n   A UIViewController property that references the\n   active left UIViewController.\n   */\n  open fileprivate(set) var leftViewController: UIViewController?\n  \n  /**\n   A UIViewController property that references the\n   active right UIViewController.\n   */\n  open fileprivate(set) var rightViewController: UIViewController?\n  \n  /**\n   A CGFloat property to access the width that the leftView\n   opens up to.\n   */\n  @IBInspectable\n  open fileprivate(set) var leftViewWidth: CGFloat = 0\n  \n  /**\n   A CGFloat property to access the width that the rightView\n   opens up to.\n   */\n  @IBInspectable\n  open fileprivate(set) var rightViewWidth: CGFloat = 0\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n  }\n  \n  /**\n   An initializer that initializes the object with an Optional nib and bundle.\n   - Parameter nibNameOrNil: An Optional String for the nib.\n   - Parameter bundle: An Optional NSBundle where the nib is located.\n   */\n  public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {\n    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)\n  }\n  \n  /**\n   An initializer for the NavigationDrawerController.\n   - Parameter rootViewController: The main UIViewController.\n   - Parameter leftViewController: An Optional left UIViewController.\n   - Parameter rightViewController: An Optional right UIViewController.\n   */\n  public init(rootViewController: UIViewController, leftViewController: UIViewController? = nil, rightViewController: UIViewController? = nil) {\n    super.init(rootViewController: rootViewController)\n    self.leftViewController = leftViewController\n    self.rightViewController = rightViewController\n  }\n  \n  open override func transition(to viewController: UIViewController, completion: ((Bool) -> Void)? = nil) {\n    super.transition(to: viewController) { [weak self, completion = completion] (result) in\n      guard let `self` = self else {\n        return\n      }\n      \n      self.view.sendSubviewToBack(self.contentViewController.view)\n      completion?(result)\n    }\n  }\n  \n  /// Layout subviews.\n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    toggleStatusBar()\n    \n    if let v = leftView {\n      v.frame.size.width = leftViewWidth\n      v.frame.size.height = view.bounds.height\n      leftViewThreshold = leftViewWidth / 2\n      \n      if let vc = leftViewController {\n        vc.view.frame = v.bounds\n        vc.view.frame.size.width = leftViewWidth\n      }\n    }\n    \n    if let v = rightView {\n      v.frame.size.width = rightViewWidth\n      v.frame.size.height = view.bounds.height\n      rightViewThreshold = view.bounds.width - rightViewWidth / 2\n      \n      if let vc = rightViewController {\n        vc.view.frame = v.bounds\n        vc.view.frame.size.width = rightViewWidth\n      }\n    }\n    \n    rootViewController.view.frame = container.bounds\n  }\n  \n  open override func viewWillAppear(_ animated: Bool) {\n    super.viewWillAppear(animated)\n    leftViewController?.beginAppearanceTransition(true, animated: animated)\n    rightViewController?.beginAppearanceTransition(true, animated: animated)\n  }\n  \n  open override func viewDidAppear(_ animated: Bool) {\n    super.viewDidAppear(animated)\n    leftViewController?.endAppearanceTransition()\n    rightViewController?.endAppearanceTransition()\n  }\n  \n  open override func viewWillDisappear(_ animated: Bool) {\n    super.viewWillDisappear(animated)\n    leftViewController?.beginAppearanceTransition(false, animated: animated)\n    rightViewController?.beginAppearanceTransition(false, animated: animated)\n  }\n  \n  open override func viewDidDisappear(_ animated: Bool) {\n    super.viewDidDisappear(animated)\n    leftViewController?.endAppearanceTransition()\n    rightViewController?.endAppearanceTransition()\n  }\n  \n  open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {\n    super.viewWillTransition(to: size, with: coordinator)\n    // Ensures the view is isHidden.\n    guard let v = rightView else {\n      return\n    }\n    \n    v.layer.position.x = size.width + (isRightViewOpened ? -v.bounds.width : v.bounds.width) / 2\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    prepareContentViewController()\n    prepareLeftView()\n    prepareRightView()\n  }\n  \n  /**\n   A method that is used to set the width of the leftView when\n   opened. This is the recommended method of setting the leftView\n   width.\n   - Parameter width: A CGFloat value to set as the new width.\n   - Parameter isHidden: A Boolean value of whether the leftView\n   should be isHidden after the width has been updated or not.\n   - Parameter animated: A Boolean value that indicates to animate\n   the leftView width change.\n   */\n  open func setLeftViewWidth(width: CGFloat, isHidden: Bool, animated: Bool, duration: TimeInterval = 0.5) {\n    guard let v = leftView else {\n      return\n    }\n    \n    leftViewWidth = width\n    \n    var hide = isHidden\n    \n    if isRightViewOpened {\n      hide = true\n    }\n    \n    if animated {\n      v.isShadowPathAutoSizing = false\n      \n      if hide {\n        UIView.animate(withDuration: duration,\n                       animations: { [weak self, v = v] in\n                        guard let `self` = self else {\n                          return\n                        }\n                        \n                        v.bounds.size.width = width\n                        v.layer.position.x = -width / 2\n                        self.rootViewController.view.alpha = 1\n                        \n        }) { [weak self, v = v] _ in\n          guard let `self` = self else {\n            return\n          }\n          \n          v.isShadowPathAutoSizing = true\n          self.layoutSubviews()\n          self.hideView(container: v)\n        }\n        \n      } else {\n        UIView.animate(withDuration: duration,\n                       animations: { [weak self, v = v] in\n                        guard let `self` = self else {\n                          return\n                        }\n                        \n                        v.bounds.size.width = width\n                        v.layer.position.x = width / 2\n                        self.rootViewController.view.alpha = 0.5\n                        \n        }) { [weak self, v = v] _ in\n          guard let `self` = self else {\n            return\n          }\n          \n          v.isShadowPathAutoSizing = true\n          self.layoutSubviews()\n          self.showView(container: v)\n        }\n      }\n    } else {\n      v.bounds.size.width = width\n      \n      if hide {\n        hideView(container: v)\n        v.layer.position.x = -v.bounds.width / 2\n        rootViewController.view.alpha = 1\n        \n      } else {\n        showView(container: v)\n        v.layer.position.x = width / 2\n        rootViewController.view.alpha = 0.5\n      }\n      \n      layoutSubviews()\n    }\n  }\n  \n  /**\n   A method that is used to set the width of the rightView when\n   opened. This is the recommended method of setting the rightView\n   width.\n   - Parameter width: A CGFloat value to set as the new width.\n   - Parameter isHidden: A Boolean value of whether the rightView\n   should be isHidden after the width has been updated or not.\n   - Parameter animated: A Boolean value that indicates to animate\n   the rightView width change.\n   */\n  open func setRightViewWidth(width: CGFloat, isHidden: Bool, animated: Bool, duration: TimeInterval = 0.5) {\n    guard let v = rightView else {\n      return\n    }\n    \n    rightViewWidth = width\n    \n    var hide = isHidden\n    \n    if isLeftViewOpened {\n      hide = true\n    }\n    \n    if animated {\n      v.isShadowPathAutoSizing = false\n      \n      if hide {\n        UIView.animate(withDuration: duration,\n                       animations: { [weak self, v = v] in\n                        guard let `self` = self else {\n                          return\n                        }\n                        \n                        v.bounds.size.width = width\n                        v.layer.position.x = self.view.bounds.width + width / 2\n                        self.rootViewController.view.alpha = 1\n                        \n        }) { [weak self, v = v] _ in\n          guard let `self` = self else {\n            return\n          }\n          \n          v.isShadowPathAutoSizing = true\n          self.layoutSubviews()\n          self.hideView(container: v)\n        }\n        \n      } else {\n        UIView.animate(withDuration: duration,\n                       animations: { [weak self, v = v] in\n                        guard let `self` = self else {\n                          return\n                        }\n                        \n                        v.bounds.size.width = width\n                        v.layer.position.x = self.view.bounds.width - width / 2\n                        self.rootViewController.view.alpha = 0.5\n                        \n        }) { [weak self, v = v] _ in\n          guard let `self` = self else {\n            return\n          }\n          \n          v.isShadowPathAutoSizing = true\n          self.layoutSubviews()\n          self.showView(container: v)\n        }\n      }\n    } else {\n      v.bounds.size.width = width\n      \n      if hide {\n        hideView(container: v)\n        v.layer.position.x = view.bounds.width + v.bounds.width / 2\n        rootViewController.view.alpha = 1\n        \n      } else {\n        showView(container: v)\n        v.layer.position.x = view.bounds.width - width / 2\n        rootViewController.view.alpha = 0.5\n      }\n      \n      layoutSubviews()\n    }\n  }\n  \n  /**\n   A method that toggles the leftView opened if previously closed,\n   or closed if previously opened.\n   - Parameter velocity: A CGFloat value that sets the\n   velocity of the user interaction when animating the\n   leftView. Defaults to 0.\n   */\n  open func toggleLeftView(velocity: CGFloat = 0) {\n    isLeftViewOpened ? closeLeftView(velocity: velocity) : openLeftView(velocity: velocity)\n  }\n  \n  /**\n   A method that toggles the rightView opened if previously closed,\n   or closed if previously opened.\n   - Parameter velocity: A CGFloat value that sets the\n   velocity of the user interaction when animating the\n   leftView. Defaults to 0.\n   */\n  open func toggleRightView(velocity: CGFloat = 0) {\n    isRightViewOpened ? closeRightView(velocity: velocity) : openRightView(velocity: velocity)\n  }\n  \n  /**\n   A method that opens the leftView.\n   - Parameter velocity: A CGFloat value that sets the\n   velocity of the user interaction when animating the\n   leftView. Defaults to 0.\n   */\n  open func openLeftView(velocity: CGFloat = 0) {\n    guard !isAnimating else {\n      return\n    }\n    \n    guard isLeftViewEnabled else {\n      return\n    }\n    \n    guard let v = leftView else {\n      return\n    }\n    \n    isAnimating = true\n    \n    hideStatusBar()\n    showView(container: v)\n    \n    isUserInteractionEnabled = false\n    \n    delegate?.navigationDrawerController?(navigationDrawerController: self, willOpen: .left)\n    \n    UIView.animate(withDuration: TimeInterval(0 == velocity ? animationDuration : fmax(0.1, fmin(1, Double(v.frame.origin.x / velocity)))),\n                   animations: { [weak self, v = v] in\n                    guard let `self` = self else {\n                      return\n                    }\n                    \n                    v.layer.position.x = v.bounds.width / 2\n                    self.rootViewController.view.alpha = 0.5\n                    \n    }) { [weak self] _ in\n      guard let `self` = self else {\n        return\n      }\n      \n      self.isAnimating = false\n      self.delegate?.navigationDrawerController?(navigationDrawerController: self, didOpen: .left)\n    }\n  }\n  \n  /**\n   A method that opens the rightView.\n   - Parameter velocity: A CGFloat value that sets the\n   velocity of the user interaction when animating the\n   leftView. Defaults to 0.\n   */\n  open func openRightView(velocity: CGFloat = 0) {\n    guard !isAnimating else {\n      return\n    }\n    \n    guard isRightViewEnabled else {\n      return\n    }\n    \n    guard let v = rightView else {\n      return\n    }\n    \n    isAnimating = true\n    \n    hideStatusBar()\n    showView(container: v)\n    \n    isUserInteractionEnabled = false\n    \n    delegate?.navigationDrawerController?(navigationDrawerController: self, willOpen: .right)\n    \n    UIView.animate(withDuration: TimeInterval(0 == velocity ? animationDuration : fmax(0.1, fmin(1, Double(v.frame.origin.x / velocity)))),\n                   animations: { [weak self, v = v] in\n                    guard let `self` = self else {\n                      return\n                    }\n                    \n                    v.layer.position.x = self.view.bounds.width - v.bounds.width / 2\n                    self.rootViewController.view.alpha = 0.5\n                    \n    }) { [weak self] _ in\n      guard let `self` = self else {\n        return\n      }\n      \n      self.isAnimating = false\n      \n      self.delegate?.navigationDrawerController?(navigationDrawerController: self, didOpen: .right)\n    }\n  }\n  \n  /**\n   A method that closes the leftView.\n   - Parameter velocity: A CGFloat value that sets the\n   velocity of the user interaction when animating the\n   leftView. Defaults to 0.\n   */\n  open func closeLeftView(velocity: CGFloat = 0) {\n    guard !isAnimating else {\n      return\n    }\n    \n    guard isLeftViewEnabled else {\n      return\n    }\n    \n    guard let v = leftView else {\n      return\n    }\n    \n    isAnimating = true\n    \n    delegate?.navigationDrawerController?(navigationDrawerController: self, willClose: .left)\n    \n    UIView.animate(withDuration: TimeInterval(0 == velocity ? animationDuration : fmax(0.1, fmin(1, Double(v.frame.origin.x / velocity)))),\n                   animations: { [weak self, v = v] in\n                    guard let `self` = self else {\n                      return\n                    }\n                    \n                    v.layer.position.x = -v.bounds.width / 2\n                    self.rootViewController.view.alpha = 1\n                    \n    }) { [weak self, v = v] _ in\n      guard let `self` = self else {\n        return\n      }\n      \n      self.hideView(container: v)\n      self.toggleStatusBar()\n      \n      self.isAnimating = false\n      self.isUserInteractionEnabled = true\n      \n      self.delegate?.navigationDrawerController?(navigationDrawerController: self, didClose: .left)\n    }\n  }\n  \n  /**\n   A method that closes the rightView.\n   - Parameter velocity: A CGFloat value that sets the\n   velocity of the user interaction when animating the\n   leftView. Defaults to 0.\n   */\n  open func closeRightView(velocity: CGFloat = 0) {\n    guard !isAnimating else {\n      return\n    }\n    \n    guard isRightViewEnabled else {\n      return\n    }\n    \n    guard let v = rightView else {\n      return\n    }\n    \n    isAnimating = true\n    \n    delegate?.navigationDrawerController?(navigationDrawerController: self, willClose: .right)\n    \n    UIView.animate(withDuration: TimeInterval(0 == velocity ? animationDuration : fmax(0.1, fmin(1, Double(v.frame.origin.x / velocity)))),\n                   animations: { [weak self, v = v] in\n                    guard let `self` = self else {\n                      return\n                    }\n                    \n                    v.layer.position.x = self.view.bounds.width + v.bounds.width / 2\n                    self.rootViewController.view.alpha = 1\n                    \n    }) { [weak self, v = v] _ in\n      guard let `self` = self else {\n        return\n      }\n      \n      self.hideView(container: v)\n      self.toggleStatusBar()\n      \n      self.isAnimating = false\n      self.isUserInteractionEnabled = true\n      \n      self.delegate?.navigationDrawerController?(navigationDrawerController: self, didClose: .right)\n    }\n  }\n  \n  /// A method that removes the passed in pan and leftView tap gesture recognizers.\n  fileprivate func removeLeftViewGestures() {\n    removeLeftPanGesture()\n    removeLeftTapGesture()\n  }\n  \n  /// Removes the left pan gesture.\n  fileprivate func removeLeftPanGesture() {\n    guard let v = leftPanGesture else {\n      return\n    }\n    \n    view.removeGestureRecognizer(v)\n    leftPanGesture = nil\n  }\n  \n  /// Removes the left tap gesture.\n  fileprivate func removeLeftTapGesture() {\n    guard let v = leftTapGesture else {\n      return\n    }\n    \n    view.removeGestureRecognizer(v)\n    leftTapGesture = nil\n  }\n  \n  /// A method that removes the passed in pan and rightView tap gesture recognizers.\n  fileprivate func removeRightViewGestures() {\n    removeRightPanGesture()\n    removeRightTapGesture()\n    \n  }\n  \n  /// Removes the right pan gesture.\n  fileprivate func removeRightPanGesture() {\n    guard let v = rightPanGesture else {\n      return\n    }\n    \n    view.removeGestureRecognizer(v)\n    rightPanGesture = nil\n  }\n  \n  /// Removes the right tap gesture.\n  fileprivate func removeRightTapGesture() {\n    guard let v = rightTapGesture else {\n      return\n    }\n    \n    view.removeGestureRecognizer(v)\n    rightTapGesture = nil\n  }\n  \n  /// Shows the statusBar.\n  fileprivate func showStatusBar() {\n    Motion.async { [weak self] in\n      guard let v = Application.keyWindow else {\n        return\n      }\n      \n      v.windowLevel = UIWindow.Level.normal\n      \n      guard let `self` = self else {\n        return\n      }\n      \n      self.delegate?.navigationDrawerController?(navigationDrawerController: self, statusBar: false)\n    }\n  }\n  \n  /// Hides the statusBar.\n  fileprivate func hideStatusBar() {\n    guard isHiddenStatusBarEnabled else {\n      return\n    }\n    \n    Motion.async { [weak self] in\n      guard let v = Application.keyWindow else {\n        return\n      }\n      \n      v.windowLevel = UIWindow.Level.statusBar + 1\n      \n      guard let `self` = self else {\n        return\n      }\n      \n      self.delegate?.navigationDrawerController?(navigationDrawerController: self, statusBar: true)\n    }\n  }\n  \n  /// Toggles the statusBar\n  fileprivate func toggleStatusBar() {\n    if isOpened {\n      hideStatusBar()\n    } else {\n      showStatusBar()\n    }\n  }\n  \n  /**\n   A method that determines whether the passed point is\n   contained within the bounds of the leftViewThreshold\n   and height of the NavigationDrawerController view frame\n   property.\n   - Parameter point: A CGPoint to test against.\n   - Returns: A Boolean of the result, true if yes, false\n   otherwise.\n   */\n  fileprivate func isPointContainedWithinLeftThreshold(point: CGPoint) -> Bool {\n    return point.x <= leftThreshold\n  }\n  \n  /**\n   A method that determines whether the passed point is\n   contained within the bounds of the rightViewThreshold\n   and height of the NavigationDrawerController view frame\n   property.\n   - Parameter point: A CGPoint to test against.\n   - Returns: A Boolean of the result, true if yes, false\n   otherwise.\n   */\n  fileprivate func isPointContainedWithinRighThreshold(point: CGPoint) -> Bool {\n    return point.x >= view.bounds.width - rightThreshold\n  }\n  \n  /**\n   A method that determines whether the passed in point is\n   contained within the bounds of the passed in container view.\n   - Parameter container: A UIView that sets the bounds to test\n   against.\n   - Parameter point: A CGPoint to test whether or not it is\n   within the bounds of the container parameter.\n   - Returns: A Boolean of the result, true if yes, false\n   otherwise.\n   */\n  fileprivate func isPointContainedWithinView(container: UIView, point: CGPoint) -> Bool {\n    return container.bounds.contains(point)\n  }\n  \n  /**\n   A method that shows a view.\n   - Parameter container: A container view.\n   */\n  fileprivate func showView(container: UIView) {\n    container.depthPreset = depthPreset\n    container.isHidden = false\n  }\n  \n  /**\n   A method that hides a view.\n   - Parameter container: A container view.\n   */\n  fileprivate func hideView(container: UIView) {\n    container.depthPreset = .none\n    container.isHidden = true\n  }\n}\n\nextension NavigationDrawerController {\n  /// Prepares the contentViewController.\n  fileprivate func prepareContentViewController() {\n    contentViewController.view.backgroundColor = .black\n    prepare(viewController: contentViewController, in: view)\n    view.sendSubviewToBack(contentViewController.view)\n  }\n  \n  /// A method that prepares the leftView.\n  fileprivate func prepareLeftView() {\n    guard let v = leftViewController else {\n      return\n    }\n    \n    isLeftViewEnabled = true\n    \n    leftViewWidth = .phone == Device.userInterfaceIdiom ? 280 : 320\n    leftView = UIView()\n    leftView!.frame = CGRect(x: 0, y: 0, width: leftViewWidth, height: view.bounds.height)\n    leftView!.backgroundColor = .white\n    view.addSubview(leftView!)\n    \n    leftView!.isHidden = true\n    leftView!.layer.position.x = -leftViewWidth / 2\n    leftView!.layer.zPosition = 2000\n    \n    prepare(viewController: v, in: leftView!)\n  }\n  \n  /// A method that prepares the leftView.\n  fileprivate func prepareRightView() {\n    guard let v = rightViewController else {\n      return\n    }\n    \n    isRightViewEnabled = true\n    \n    rightViewWidth = .phone == Device.userInterfaceIdiom ? 280 : 320\n    rightView = UIView()\n    rightView!.frame = CGRect(x: view.bounds.width, y: 0, width: rightViewWidth, height: view.bounds.height)\n    rightView!.backgroundColor = .white\n    view.addSubview(rightView!)\n    \n    rightView!.isHidden = true\n    rightView!.layer.position.x = view.bounds.width + rightViewWidth / 2\n    rightView!.layer.zPosition = 2000\n    \n    prepare(viewController: v, in: rightView!)\n  }\n  \n  /// Prepare the left pan gesture.\n  fileprivate func prepareLeftPanGesture() {\n    guard nil == leftPanGesture else {\n      return\n    }\n    \n    leftPanGesture = UIPanGestureRecognizer(target: self, action: #selector(handleLeftViewPanGesture(recognizer:)))\n    leftPanGesture!.delegate = self\n    leftPanGesture!.cancelsTouchesInView = false\n    view.addGestureRecognizer(leftPanGesture!)\n  }\n  \n  /// Prepare the left tap gesture.\n  fileprivate func prepareLeftTapGesture() {\n    guard nil == leftTapGesture else {\n      return\n    }\n    \n    leftTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleLeftViewTapGesture(recognizer:)))\n    leftTapGesture!.delegate = self\n    leftTapGesture!.cancelsTouchesInView = false\n    view.addGestureRecognizer(leftTapGesture!)\n  }\n  \n  /// Prepares the right pan gesture.\n  fileprivate func prepareRightPanGesture() {\n    guard nil == rightPanGesture else {\n      return\n    }\n    \n    rightPanGesture = UIPanGestureRecognizer(target: self, action: #selector(handleRightViewPanGesture(recognizer:)))\n    rightPanGesture!.delegate = self\n    rightPanGesture!.cancelsTouchesInView = false\n    view.addGestureRecognizer(rightPanGesture!)\n  }\n  \n  /// Prepares the right tap gesture.\n  fileprivate func prepareRightTapGesture() {\n    guard nil == rightTapGesture else {\n      return\n    }\n    \n    rightTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleRightViewTapGesture(recognizer:)))\n    rightTapGesture!.delegate = self\n    rightTapGesture!.cancelsTouchesInView = false\n    view.addGestureRecognizer(rightTapGesture!)\n  }\n}\n\nextension NavigationDrawerController: UIGestureRecognizerDelegate {\n  /**\n   Detects the gesture recognizer being used.\n   - Parameter gestureRecognizer: A UIGestureRecognizer to detect.\n   - Parameter touch: The UITouch event.\n   - Returns: A Boolean of whether to continue the gesture or not.\n   */\n  @objc\n  open func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {\n    if !isRightViewOpened && gestureRecognizer == leftPanGesture && (isLeftViewOpened || isPointContainedWithinLeftThreshold(point: touch.location(in: view))) {\n      return true\n    }\n    \n    if !isLeftViewOpened && gestureRecognizer == rightPanGesture && (isRightViewOpened || isPointContainedWithinRighThreshold(point: touch.location(in: view))) {\n      return true\n    }\n    \n    if isLeftViewOpened && gestureRecognizer == leftTapGesture {\n      return true\n    }\n    \n    if isRightViewOpened && gestureRecognizer == rightTapGesture {\n      return true\n    }\n    \n    return false\n  }\n  \n  /**\n   A method that is fired when the pan gesture is recognized\n   for the leftView.\n   - Parameter recognizer: A UIPanGestureRecognizer that is\n   passed to the handler when recognized.\n   */\n  @objc\n  fileprivate func handleLeftViewPanGesture(recognizer: UIPanGestureRecognizer) {\n    guard isLeftViewEnabled && (isLeftViewOpened || !isRightViewOpened && isPointContainedWithinLeftThreshold(point: recognizer.location(in: view))) else {\n      return\n    }\n    \n    guard let v = leftView else {\n      return\n    }\n    \n    let point = recognizer.location(in: view)\n    \n    // Animate the panel.\n    switch recognizer.state {\n    case .began:\n      originalX = v.layer.position.x\n      showView(container: v)\n      \n      delegate?.navigationDrawerController?(navigationDrawerController: self, didBeginPanAt: point, position: .left)\n      \n    case .changed:\n      let w = v.bounds.width\n      let translationX = recognizer.translation(in: v).x\n      \n      v.layer.position.x = originalX + translationX > (w / 2) ? (w / 2) : originalX + translationX\n      \n      let a = 1 - v.layer.position.x / v.bounds.width\n      rootViewController.view.alpha = 0.5 < a && v.layer.position.x <= v.bounds.width / 2 ? a : 0.5\n      \n      if translationX >= leftThreshold {\n        hideStatusBar()\n      }\n      \n      delegate?.navigationDrawerController?(navigationDrawerController: self, didChangePanAt: point, position: .left)\n      \n    case .ended, .cancelled, .failed:\n      let p = recognizer.velocity(in: recognizer.view)\n      let x = p.x >= 1000 || p.x <= -1000 ? p.x : 0\n      \n      delegate?.navigationDrawerController?(navigationDrawerController: self, didEndPanAt: point, position: .left)\n      \n      if v.frame.origin.x <= -leftViewWidth + leftViewThreshold || x < -1000 {\n        closeLeftView(velocity: x)\n      } else {\n        openLeftView(velocity: x)\n      }\n      \n    case .possible:break\n    default:break\n    }\n  }\n  \n  /**\n   A method that is fired when the pan gesture is recognized\n   for the rightView.\n   - Parameter recognizer: A UIPanGestureRecognizer that is\n   passed to the handler when recognized.\n   */\n  @objc\n  fileprivate func handleRightViewPanGesture(recognizer: UIPanGestureRecognizer) {\n    guard isRightViewEnabled && (isRightViewOpened || !isLeftViewOpened && isPointContainedWithinRighThreshold(point: recognizer.location(in: view))) else {\n      return\n    }\n    \n    guard let v = rightView else {\n      return\n    }\n    \n    let point = recognizer.location(in: view)\n    \n    // Animate the panel.\n    switch recognizer.state {\n    case .began:\n      originalX = v.layer.position.x\n      showView(container: v)\n      \n      delegate?.navigationDrawerController?(navigationDrawerController: self, didBeginPanAt: point, position: .right)\n      \n    case .changed:\n      let w = v.bounds.width\n      let translationX = recognizer.translation(in: v).x\n      \n      v.layer.position.x = originalX + translationX < view.bounds.width - (w / 2) ? view.bounds.width - (w / 2) : originalX + translationX\n      \n      let a = 1 - (view.bounds.width - v.layer.position.x) / v.bounds.width\n      rootViewController.view.alpha = 0.5 < a && v.layer.position.x >= v.bounds.width / 2 ? a : 0.5\n      \n      if translationX <= -rightThreshold {\n        hideStatusBar()\n      }\n      \n      delegate?.navigationDrawerController?(navigationDrawerController: self, didChangePanAt: point, position: .right)\n      \n    case .ended, .cancelled, .failed:\n      let p = recognizer.velocity(in: recognizer.view)\n      let x = p.x >= 1000 || p.x <= -1000 ? p.x : 0\n      \n      delegate?.navigationDrawerController?(navigationDrawerController: self, didEndPanAt: point, position: .right)\n      \n      if v.frame.origin.x >= rightViewThreshold || x > 1000 {\n        closeRightView(velocity: x)\n      } else {\n        openRightView(velocity: x)\n      }\n      \n    case .possible:break\n    default:break\n    }\n  }\n  \n  /**\n   A method that is fired when the tap gesture is recognized\n   for the leftView.\n   - Parameter recognizer: A UITapGestureRecognizer that is\n   passed to the handler when recognized.\n   */\n  @objc\n  fileprivate func handleLeftViewTapGesture(recognizer: UITapGestureRecognizer) {\n    guard isLeftViewOpened else {\n      return\n    }\n    \n    guard let v = leftView else {\n      return\n    }\n    \n    delegate?.navigationDrawerController?(navigationDrawerController: self, didTapAt: recognizer.location(in: view), position: .left)\n    \n    guard isLeftViewEnabled && isLeftViewOpened && !isPointContainedWithinView(container: v, point: recognizer.location(in: v)) else {\n      return\n    }\n    \n    closeLeftView()\n  }\n  \n  /**\n   A method that is fired when the tap gesture is recognized\n   for the rightView.\n   - Parameter recognizer: A UITapGestureRecognizer that is\n   passed to the handler when recognized.\n   */\n  @objc\n  fileprivate func handleRightViewTapGesture(recognizer: UITapGestureRecognizer) {\n    guard isRightViewOpened else {\n      return\n    }\n    \n    guard let v = rightView else {\n      return\n    }\n    \n    delegate?.navigationDrawerController?(navigationDrawerController: self, didTapAt: recognizer.location(in: view), position: .right)\n    \n    guard isRightViewEnabled && isRightViewOpened && !isPointContainedWithinView(container: v, point: recognizer.location(in: v)) else {\n      return\n    }\n    \n    closeRightView()\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Screen/Screen.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\npublic struct Screen {\n  /// Retrieves the device bounds.\n  public static var bounds: CGRect {\n    return UIScreen.main.bounds\n  }\n  \n  /// Retrieves the device width.\n  public static var width: CGFloat {\n    return bounds.width\n  }\n  \n  /// Retrieves the device height.\n  public static var height: CGFloat {\n    return bounds.height\n  }\n  \n  /// Retrieves the device scale.\n  public static var scale: CGFloat {\n    return UIScreen.main.scale\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/SearchBar/SearchBar.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(SearchBarDelegate)\npublic protocol SearchBarDelegate {\n  /**\n   A delegation method that is executed when the textField changed.\n   - Parameter searchBar: A SearchBar.\n   - Parameter didChange textField: A UITextField.\n   - Parameter with text: An optional String.\n   */\n  @objc\n  optional func searchBar(searchBar: SearchBar, didChange textField: UITextField, with text: String?)\n  \n  /**\n   A delegation method that is executed when the textField will clear.\n   - Parameter searchBar: A SearchBar.\n   - Parameter willClear textField: A UITextField.\n   - Parameter with text: An optional String.\n   */\n  @objc\n  optional func searchBar(searchBar: SearchBar, willClear textField: UITextField, with text: String?)\n  \n  /**\n   A delegation method that is executed when the textField is cleared.\n   - Parameter searchBar: A SearchBar.\n   - Parameter didClear textField: A UITextField.\n   - Parameter with text: An optional String.\n   */\n  @objc\n  optional func searchBar(searchBar: SearchBar, didClear textField: UITextField, with text: String?)\n}\n\nopen class SearchBar: Bar {\n  /// The UITextField for the searchBar.\n  @IBInspectable\n  public let textField = UITextField()\n  \n  /// Reference to the clearButton.\n  open fileprivate(set) var clearButton: IconButton!\n  \n  /// A reference to the delegate.\n  open weak var delegate: SearchBarDelegate?\n  \n  /// Handle the clearButton manually.\n  @IBInspectable\n  open var isClearButtonAutoHandleEnabled = true {\n    didSet {\n      clearButton.removeTarget(self, action: #selector(handleClearButton), for: .touchUpInside)\n      if isClearButtonAutoHandleEnabled {\n        clearButton.addTarget(self, action: #selector(handleClearButton), for: .touchUpInside)\n      }\n    }\n  }\n  \n  /// TintColor for searchBar.\n  @IBInspectable\n  open override var tintColor: UIColor? {\n    get {\n      return textField.tintColor\n    }\n    set(value) {\n      textField.tintColor = value\n    }\n  }\n  \n  /// TextColor for searchBar.\n  @IBInspectable\n  open var textColor: UIColor? {\n    get {\n      return textField.textColor\n    }\n    set(value) {\n      textField.textColor = value\n    }\n  }\n  \n  /// Sets the textField placeholder value.\n  @IBInspectable\n  open var placeholder: String? {\n    didSet {\n      if let v = placeholder {\n        textField.attributedPlaceholder = NSAttributedString(string: v, attributes: [.foregroundColor: placeholderColor])\n      }\n    }\n  }\n  \n  /// Placeholder text\n  @IBInspectable\n  open var placeholderColor = Color.darkText.others {\n    didSet {\n      if let v = placeholder {\n        textField.attributedPlaceholder = NSAttributedString(string: v, attributes: [.foregroundColor: placeholderColor])\n      }\n    }\n  }\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n  }\n  \n  /**\n   An initializer that initializes the object with a CGRect object.\n   If AutoLayout is used, it is better to initilize the instance\n   using the init() initializer.\n   - Parameter frame: A CGRect instance.\n   */\n  public override init(frame: CGRect) {\n    super.init(frame: frame)\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    guard willLayout else {\n      return\n    }\n    \n    layoutTextField()\n    layoutLeftView()\n    layoutClearButton()\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    prepareTextField()\n    prepareClearButton()\n  }\n}\n\nextension SearchBar {\n  /// Layout the textField.\n  open func layoutTextField() {\n    textField.frame = contentView.bounds\n  }\n  \n  /// Layout the leftView.\n  open func layoutLeftView() {\n    guard let v = textField.leftView else {\n      return\n    }\n    \n    let h = textField.frame.height\n    v.frame = CGRect(x: 4, y: 4, width: h, height: h - 8)\n    \n    (v as? UIImageView)?.contentMode = .scaleAspectFit\n  }\n  \n  /// Layout the clearButton.\n  open func layoutClearButton() {\n    let h = textField.frame.height\n    clearButton.frame = CGRect(x: textField.frame.width - h - 4, y: 4, width: h, height: h - 8)\n  }\n}\n\nfileprivate extension SearchBar {\n  /// Clears the textField text.\n  @objc\n  func handleClearButton() {\n    guard nil == textField.delegate?.textFieldShouldClear || true == textField.delegate?.textFieldShouldClear?(textField) else {\n      return\n    }\n    \n    let t = textField.text\n    \n    delegate?.searchBar?(searchBar: self, willClear: textField, with: t)\n    \n    textField.text = nil\n    \n    delegate?.searchBar?(searchBar: self, didClear: textField, with: t)\n  }\n  \n  // Live updates the search results.\n  @objc\n  func handleEditingChanged(textField: UITextField) {\n    delegate?.searchBar?(searchBar: self, didChange: textField, with: textField.text)\n  }\n}\n\nfileprivate extension SearchBar {\n  /// Prepares the textField.\n  func prepareTextField() {\n    textField.contentScaleFactor = Screen.scale\n    textField.font = Theme.font.regular(with: 17)\n    textField.backgroundColor = Color.clear\n    textField.clearButtonMode = .whileEditing\n    textField.addTarget(self, action: #selector(handleEditingChanged(textField:)), for: .editingChanged)\n    tintColor = placeholderColor\n    textColor = Color.darkText.primary\n    placeholder = \"Search\"\n    contentView.addSubview(textField)\n  }\n  \n  /// Prepares the clearButton.\n  func prepareClearButton() {\n    clearButton = IconButton(image: Icon.cm.close, tintColor: placeholderColor)\n    clearButton.contentEdgeInsets = .zero\n    isClearButtonAutoHandleEnabled = true\n    textField.clearButtonMode = .never\n    textField.rightViewMode = .whileEditing\n    textField.rightView = clearButton\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/SearchBar/SearchBarController.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(SearchBarAlignment)\npublic enum SearchBarAlignment: Int {\n  case top\n  case bottom\n}\n\nextension UIViewController {\n  /**\n   A convenience property that provides access to the SearchBarController.\n   This is the recommended method of accessing the SearchBarController\n   through child UIViewControllers.\n   */\n  public var searchBarController: SearchBarController? {\n    return traverseViewControllerHierarchyForClassType()\n  }\n}\n\nopen class SearchBarController: StatusBarController {\n  /// Reference to the SearchBar.\n  @IBInspectable\n  public let searchBar = SearchBar()\n  \n  /// The searchBar alignment.\n  open var searchBarAlignment = SearchBarAlignment.top {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    layoutSearchBar()\n    layoutContainer()\n    layoutRootViewController()\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    displayStyle = .partial\n    \n    prepareSearchBar()\n  }\n}\n\nfileprivate extension SearchBarController {\n  /// Prepares the searchBar.\n  func prepareSearchBar() {\n    searchBar.layer.zPosition = 1000\n    searchBar.depthPreset = .depth1\n    view.addSubview(searchBar)\n  }\n}\n\nfileprivate extension SearchBarController {\n  /// Layout the container.\n  func layoutContainer() {\n    switch displayStyle {\n    case .partial:\n      let p = searchBar.bounds.height\n      let q = statusBarOffsetAdjustment\n      let h = view.bounds.height - p - q\n      \n      switch searchBarAlignment {\n      case .top:\n        container.frame.origin.y = q + p\n        container.frame.size.height = h\n        \n      case .bottom:\n        container.frame.origin.y = q\n        container.frame.size.height = h\n      }\n      \n      container.frame.size.width = view.bounds.width\n      \n    case .full:\n      container.frame = view.bounds\n    }\n  }\n  \n  /// Layout the searchBar.\n  func layoutSearchBar() {\n    searchBar.frame.origin.x = 0\n    searchBar.frame.origin.y = .top == searchBarAlignment ? statusBarOffsetAdjustment : view.bounds.height - searchBar.bounds.height\n    searchBar.frame.size.width = view.bounds.width\n  }\n  \n  /// Layout the rootViewController.\n  func layoutRootViewController() {\n    rootViewController.view.frame = container.bounds\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Snackbar/Snackbar.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(SnackbarStatus)\npublic enum SnackbarStatus: Int {\n  case visible\n  case hidden\n}\n\nopen class Snackbar: Bar {\n  /// A convenience property to set the titleLabel text.\n  open var text: String? {\n    get {\n      return textLabel.text\n    }\n    set(value) {\n      textLabel.text = value\n      layoutSubviews()\n    }\n  }\n  \n  /// A convenience property to set the titleLabel attributedText.\n  open var attributedText: NSAttributedString? {\n    get {\n      return textLabel.attributedText\n    }\n    set(value) {\n      textLabel.attributedText = value\n      layoutSubviews()\n    }\n  }\n  \n  /// Text label.\n  @IBInspectable\n  public let textLabel = UILabel()\n  \n  open override var intrinsicContentSize: CGSize {\n    return CGSize(width: bounds.width, height: 49)\n  }\n  \n  /// The status of the snackbar.\n  open internal(set) var status = SnackbarStatus.hidden\n  \n  open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {\n    for v in subviews {\n      let p = v.convert(point, from: self)\n      if v.bounds.contains(p) {\n        return v.hitTest(p, with: event)\n      }\n    }\n    \n    return super.hitTest(point, with: event)\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    guard willLayout else {\n      return\n    }\n    \n    centerViews = [textLabel]\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    depthPreset = .none\n    interimSpacePreset = .interimSpace8\n    contentEdgeInsets.left = interimSpace\n    contentEdgeInsets.right = interimSpace\n    backgroundColor = Color.grey.darken3\n    clipsToBounds = false\n    prepareTextLabel()\n  }\n  \n  /// Prepares the textLabel.\n  private func prepareTextLabel() {\n    textLabel.contentScaleFactor = Screen.scale\n    textLabel.font = Theme.font.medium(with: 14)\n    textLabel.textAlignment = .left\n    textLabel.textColor = .white\n    textLabel.numberOfLines = 0\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Snackbar/SnackbarController.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\n@objc(SnackbarControllerDelegate)\npublic protocol SnackbarControllerDelegate {\n  /**\n   A delegation method that is executed when a Snackbar will show.\n   - Parameter snackbarController: A SnackbarController.\n   - Parameter snackbar: A Snackbar.\n   */\n  @objc\n  optional func snackbarController(snackbarController: SnackbarController, willShow snackbar: Snackbar)\n  \n  /**\n   A delegation method that is executed when a Snackbar did show.\n   - Parameter snackbarController: A SnackbarController.\n   - Parameter snackbar: A Snackbar.\n   */\n  @objc\n  optional func snackbarController(snackbarController: SnackbarController, didShow snackbar: Snackbar)\n  \n  /**\n   A delegation method that is executed when a Snackbar will hide.\n   - Parameter snackbarController: A SnackbarController.\n   - Parameter snackbar: A Snackbar.\n   */\n  @objc\n  optional func snackbarController(snackbarController: SnackbarController, willHide snackbar: Snackbar)\n  \n  /**\n   A delegation method that is executed when a Snackbar did hide.\n   - Parameter snackbarController: A SnackbarController.\n   - Parameter snackbar: A Snackbar.\n   */\n  @objc\n  optional func snackbarController(snackbarController: SnackbarController, didHide snackbar: Snackbar)\n}\n\n@objc(SnackbarAlignment)\npublic enum SnackbarAlignment: Int {\n  case top\n  case bottom\n}\n\nextension UIViewController {\n  /**\n   A convenience property that provides access to the SnackbarController.\n   This is the recommended method of accessing the SnackbarController\n   through child UIViewControllers.\n   */\n  public var snackbarController: SnackbarController? {\n    return traverseViewControllerHierarchyForClassType()\n  }\n}\n\nopen class SnackbarController: TransitionController {\n  /// Reference to the Snackbar.\n  public let snackbar = Snackbar()\n  \n  /// A boolean indicating if the Snacbar is animating.\n  open internal(set) var isAnimating = false\n  \n  /// Delegation handler.\n  open weak var delegate: SnackbarControllerDelegate?\n  \n  /// Snackbar alignment setting.\n  open var snackbarAlignment = SnackbarAlignment.bottom\n  \n  /// A preset wrapper around snackbarEdgeInsets.\n  open var snackbarEdgeInsetsPreset = EdgeInsetsPreset.none {\n    didSet {\n      snackbarEdgeInsets = EdgeInsetsPresetToValue(preset: snackbarEdgeInsetsPreset)\n    }\n  }\n  \n  /// A reference to snackbarEdgeInsets.\n  @IBInspectable\n  open var snackbarEdgeInsets = EdgeInsets.zero {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /**\n   A boolean that controls if layoutEdgeInsets of snackbar is adjusted\n   automatically.\n   */\n  @IBInspectable\n  open var automaticallyAdjustSnackbarLayoutEdgeInsets = true\n  \n  /**\n   Animates to a SnackbarStatus.\n   - Parameter status: A SnackbarStatus enum value.\n   */\n  @discardableResult\n  open func animate(snackbar status: SnackbarStatus, delay: TimeInterval = 0, animations: ((Snackbar) -> Void)? = nil, completion: ((Snackbar) -> Void)? = nil) -> MotionCancelBlock? {\n    return Motion.delay(delay) { [weak self, status = status, animations = animations, completion = completion] in\n      guard let s = self else {\n        return\n      }\n      \n      if .visible == status {\n        s.delegate?.snackbarController?(snackbarController: s, willShow: s.snackbar)\n      } else {\n        s.delegate?.snackbarController?(snackbarController: s, willHide: s.snackbar)\n      }\n      \n      s.isAnimating = true\n      s.isUserInteractionEnabled = false\n      \n      UIView.animate(withDuration: 0.25, animations: { [weak self, status = status, animations = animations] in\n        guard let s = self else {\n          return\n        }\n        \n        s.layoutSnackbar(status: status)\n        \n        animations?(s.snackbar)\n      }) { [weak self, status = status, completion = completion] _ in\n        guard let s = self else {\n          return\n        }\n        \n        s.isAnimating = false\n        s.isUserInteractionEnabled = true\n        s.snackbar.status = status\n        s.layoutSubviews()\n        \n        if .visible == status {\n          s.delegate?.snackbarController?(snackbarController: s, didShow: s.snackbar)\n        } else {\n          s.delegate?.snackbarController?(snackbarController: s, didHide: s.snackbar)\n        }\n        \n        completion?(s.snackbar)\n      }\n    }\n  }\n  \n  open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {\n    super.viewWillTransition(to: size, with: coordinator)\n    reload()\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    guard !isAnimating else {\n      return\n    }\n    \n    reload()\n  }\n  \n  /// Reloads the view.\n  open func reload() {\n    snackbar.frame.origin.x = snackbarEdgeInsets.left\n    snackbar.frame.size.width = view.bounds.width - snackbarEdgeInsets.left - snackbarEdgeInsets.right\n    snackbar.frame.size.height = snackbar.heightPreset.rawValue\n    \n    if automaticallyAdjustSnackbarLayoutEdgeInsets {\n      snackbar.layoutEdgeInsets = .zero\n      if .bottom == snackbarAlignment {\n        snackbar.frame.size.height += bottomLayoutGuide.length\n        snackbar.layoutEdgeInsets.bottom += bottomLayoutGuide.length\n      } else {\n        snackbar.frame.size.height += topLayoutGuide.length\n        snackbar.layoutEdgeInsets.top += topLayoutGuide.length\n      }\n      \n      rootViewController.view.frame = view.bounds\n      layoutSnackbar(status: snackbar.status)\n    }\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    prepareSnackbar()\n  }\n  \n  /// Prepares the snackbar.\n  private func prepareSnackbar() {\n    snackbar.layer.zPosition = 10000\n    view.addSubview(snackbar)\n  }\n  \n  /**\n   Lays out the Snackbar.\n   - Parameter status: A SnackbarStatus enum value.\n   */\n  private func layoutSnackbar(status: SnackbarStatus) {\n    if .bottom == snackbarAlignment {\n      snackbar.frame.origin.y = .visible == status ? view.bounds.height - snackbar.bounds.height - snackbarEdgeInsets.bottom : view.bounds.height\n    } else {\n      snackbar.frame.origin.y = .visible == status ? snackbarEdgeInsets.top : -snackbar.bounds.height\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/StatusBar/StatusBarController.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nextension UIViewController {\n  /**\n   A convenience property that provides access to the StatusBarController.\n   This is the recommended method of accessing the StatusBarController\n   through child UIViewControllers.\n   */\n  public var statusBarController: StatusBarController? {\n    return traverseViewControllerHierarchyForClassType()\n  }\n}\n\nopen class StatusBarController: TransitionController {\n  /**\n   A Display value to indicate whether or not to\n   display the rootViewController to the full view\n   bounds, or up to the toolbar height.\n   */\n  open var displayStyle = DisplayStyle.full {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// Device status bar style.\n  open var statusBarStyle: UIStatusBarStyle {\n    get {\n      return Application.statusBarStyle\n    }\n    set(value) {\n      Application.statusBarStyle = value\n    }\n  }\n  \n  /// Device visibility state.\n  open var isStatusBarHidden: Bool {\n    get {\n      return Application.isStatusBarHidden\n    }\n    set(value) {\n      Application.isStatusBarHidden = value\n      statusBar.isHidden = isStatusBarHidden\n    }\n  }\n  \n  /// An adjustment based on the rules for displaying the statusBar.\n  open var statusBarOffsetAdjustment: CGFloat {\n    return Application.shouldStatusBarBeHidden || statusBar.isHidden ? 0 : statusBar.bounds.height\n  }\n  \n  /// A boolean that indicates to hide the statusBar on rotation.\n  open var shouldHideStatusBarOnRotation = false\n  \n  /// A reference to the statusBar.\n  public let statusBar = UIView()\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    \n    if shouldHideStatusBarOnRotation {\n      statusBar.isHidden = Application.shouldStatusBarBeHidden\n    }\n    \n    statusBar.frame.size.width = view.bounds.width\n    \n    if #available(iOS 11, *) {\n      let v = topLayoutGuide.length\n      statusBar.frame.size.height = 0 < v ? v : 20\n    } else {\n      statusBar.frame.size.height = 20\n    }\n    \n    switch displayStyle {\n    case .partial:\n      let h = statusBar.bounds.height\n      container.frame.origin.y = h\n      container.frame.size.height = view.bounds.height - h\n      \n    case .full:\n      container.frame = view.bounds\n    }\n    \n    rootViewController.view.frame = container.bounds\n    \n    container.layer.zPosition = statusBar.layer.zPosition + (Application.shouldStatusBarBeHidden ? 1 : -1)\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    prepareStatusBar()\n  }\n  \n  open override func apply(theme: Theme) {\n    super.apply(theme: theme)\n    \n    statusBar.backgroundColor = theme.primary.darker\n  }\n}\n\nfileprivate extension StatusBarController {\n  /// Prepares the statusBar.\n  func prepareStatusBar() {\n    if nil == statusBar.backgroundColor {\n      statusBar.backgroundColor = .white\n    }\n    \n    view.addSubview(statusBar)\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Switch/Switch.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(SwitchState)\npublic enum SwitchState: Int {\n  case on\n  case off\n}\n\npublic enum SwitchSize {\n  case small\n  case medium\n  case large\n  case custom(width: CGFloat, height: CGFloat)\n}\n\n@objc(SwitchDelegate)\npublic protocol SwitchDelegate {\n  /**\n   A Switch delegate method for state changes.\n   - Parameter control: Switch control.\n   - Parameter state: SwitchState value.\n   */\n  func switchDidChangeState(control: Switch, state: SwitchState)\n}\n\nopen class Switch: UIControl, Themeable {\n  /// Will layout the view.\n  open var willLayout: Bool {\n    return 0 < bounds.width && 0 < bounds.height && nil != superview\n  }\n  \n  /// An internal reference to the switchState public property.\n  fileprivate var internalSwitchState = SwitchState.off\n  \n  /// Track thickness.\n  open var trackThickness: CGFloat = 0 {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// Button diameter.\n  open var buttonDiameter: CGFloat = 0 {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// Position when in the .on state.\n  fileprivate var onPosition: CGFloat = 0\n  \n  /// Position when in the .off state.\n  fileprivate var offPosition: CGFloat = 0\n  \n  /// The bounce offset when animating.\n  fileprivate var bounceOffset: CGFloat = 3\n  \n  /// An Optional delegation method.\n  open weak var delegate: SwitchDelegate?\n  \n  /// Indicates if the animation should bounce.\n  @IBInspectable\n  open var isBounceable = true {\n    didSet {\n      bounceOffset = isBounceable ? 3 : 0\n    }\n  }\n  \n  /// Button on color.\n  @IBInspectable\n  open var buttonOnColor = Color.clear {\n    didSet {\n      styleForState(state: switchState)\n    }\n  }\n  \n  /// Button off color.\n  @IBInspectable\n  open var buttonOffColor = Color.clear {\n    didSet {\n      styleForState(state: switchState)\n    }\n  }\n  \n  /// Button on image.\n  @IBInspectable\n  open var buttonOnImage: UIImage? {\n    didSet {\n      styleForState(state: switchState)\n    }\n  }\n  \n  /// Button off image.\n  @IBInspectable\n  open var buttonOffImage: UIImage? {\n    didSet {\n      styleForState(state: switchState)\n    }\n  }\n  \n  /// Track on color.\n  @IBInspectable\n  open var trackOnColor = Color.clear {\n    didSet {\n      styleForState(state: switchState)\n    }\n  }\n  \n  /// Track off color.\n  @IBInspectable\n  open var trackOffColor = Color.clear {\n    didSet {\n      styleForState(state: switchState)\n    }\n  }\n  \n  /// Button on disabled color.\n  @IBInspectable\n  open var buttonOnDisabledColor = Color.clear {\n    didSet {\n      styleForState(state: switchState)\n    }\n  }\n  \n  /// Track on disabled color.\n  @IBInspectable\n  open var trackOnDisabledColor = Color.clear {\n    didSet {\n      styleForState(state: switchState)\n    }\n  }\n  \n  /// Button off disabled color.\n  @IBInspectable\n  open var buttonOffDisabledColor = Color.clear {\n    didSet {\n      styleForState(state: switchState)\n    }\n  }\n  \n  /// Track off disabled color.\n  @IBInspectable\n  open var trackOffDisabledColor = Color.clear {\n    didSet {\n      styleForState(state: switchState)\n    }\n  }\n  \n  /// Button on disabled image.\n  @IBInspectable\n  open var buttonOnDisabledImage: UIImage? {\n    didSet {\n      styleForState(state: switchState)\n    }\n  }\n  \n  /// Button off disabled image.\n  @IBInspectable\n  open var buttonOffDisabledImage: UIImage? {\n    didSet {\n      styleForState(state: switchState)\n    }\n  }\n  \n  \n  /// Track view reference.\n  open fileprivate(set) var track: UIView {\n    didSet {\n      prepareTrack()\n    }\n  }\n  \n  /// Button view reference.\n  open fileprivate(set) var button: FABButton {\n    didSet {\n      prepareButton()\n    }\n  }\n  \n  @IBInspectable\n  open override var isEnabled: Bool {\n    didSet {\n      styleForState(state: internalSwitchState)\n    }\n  }\n  \n  /// A boolean indicating if the switch is on or not.\n  @IBInspectable\n  public var isOn: Bool {\n    get {\n      return .on == internalSwitchState\n    }\n    set(value) {\n      updateSwitchState(state: value ? .on : .off, animated: true, isTriggeredByUserInteraction: false)\n    }\n  }\n  \n  /// Switch state.\n  open var switchState: SwitchState {\n    get {\n      return internalSwitchState\n    }\n    set(value) {\n      updateSwitchState(state: value, animated: true, isTriggeredByUserInteraction: false)\n    }\n  }\n  \n  /// Switch size.\n  open var switchSize = SwitchSize.medium {\n    didSet {\n      switch switchSize {\n      case .small:\n        trackThickness = 16\n        buttonDiameter = 20\n      case .medium:\n        trackThickness = 20\n        buttonDiameter = 24\n      case .large:\n        trackThickness = 24\n        buttonDiameter = 28\n      case .custom:\n        break\n      }\n      \n      frame.size = intrinsicContentSize\n    }\n  }\n  \n  open override var intrinsicContentSize: CGSize {\n    switch switchSize {\n    case .small:\n      return CGSize(width: 34, height: 34)\n    case .medium:\n      return CGSize(width: 38, height: 38)\n    case .large:\n      return CGSize(width: 42, height: 42)\n    case .custom(let width, let height):\n      return CGSize(width: width, height: height)\n    }\n  }\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    track = UIView()\n    button = FABButton()\n    super.init(coder: aDecoder)\n    prepare()\n  }\n  \n  /**\n   An initializer that initializes the object with a CGRect object.\n   If AutoLayout is used, it is better to initilize the instance\n   using the init(state:style:size:) initializer, or set the CGRect\n   to CGRectNull.\n   - Parameter frame: A CGRect instance.\n   */\n  public override init(frame: CGRect) {\n    track = UIView()\n    button = FABButton()\n    super.init(frame: frame)\n    prepare()\n  }\n  \n  /**\n   An initializer that sets the state, style, and size of the Switch instance.\n   - Parameter state: A SwitchState value.\n   - Parameter style: A SwitchStyle value.\n   - Parameter size: A SwitchSize value.\n   */\n  public init(state: SwitchState = .off, size: SwitchSize = .medium) {\n    track = UIView()\n    button = FABButton()\n    super.init(frame: .zero)\n    prepare()\n    prepareSwitchState(state: state)\n    prepareSwitchSize(size: size)\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    guard willLayout else {\n      return\n    }\n    \n    reload()\n  }\n  \n  /// Reloads the view.\n  open func reload() {\n    let w: CGFloat = intrinsicContentSize.width\n    let px: CGFloat = (bounds.width - w) / 2\n    \n    track.frame = CGRect(x: px, y: (bounds.height - trackThickness) / 2, width: w, height: trackThickness)\n    track.layer.cornerRadius = min(w, trackThickness) / 2\n    \n    button.frame = CGRect(x: px, y: (bounds.height - buttonDiameter) / 2, width: buttonDiameter, height: buttonDiameter)\n    onPosition = bounds.width - px - buttonDiameter\n    offPosition = px\n    \n    if .on == internalSwitchState {\n      button.frame.origin.x = onPosition\n    }\n  }\n  \n  open override func willMove(toSuperview newSuperview: UIView?) {\n    super.willMove(toSuperview: newSuperview)\n    styleForState(state: internalSwitchState)\n  }\n  \n  /**\n   Toggle the Switch state, if On will be Off, and if Off will be On.\n   - Parameter completion: An Optional completion block.\n   */\n  open func toggle(completion: ((Switch) -> Void)? = nil) {\n    updateSwitchState(state: .on == internalSwitchState ? .off : .on, animated: true, isTriggeredByUserInteraction: false, completion: completion)\n  }\n  \n  open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {\n    guard track.frame.contains(layer.convert(touches.first!.location(in: self), from: layer)) else {\n      return\n    }\n    \n    updateSwitchState(state: .on == internalSwitchState ? .on : .off, animated: true, isTriggeredByUserInteraction: true)\n  }\n  \n  /**\n   Prepares the view instance when intialized. When subclassing,\n   it is recommended to override the prepare method\n   to initialize property values and other setup operations.\n   The super.prepare method should always be called immediately\n   when subclassing.\n   */\n  open func prepare() {\n    contentScaleFactor = Screen.scale\n    prepareTrack()\n    prepareButton()\n    prepareSwitchState()\n    prepareSwitchSize()\n    applyCurrentTheme()\n  }\n  \n  /**\n   Applies the given theme.\n   - Parameter theme: A Theme.\n   */\n  open func apply(theme: Theme) {\n    buttonOnColor = theme.secondary\n    trackOnColor = theme.secondary.withAlphaComponent(0.60)\n    buttonOffColor = theme.surface.blend(with: theme.onSurface.withAlphaComponent(0.15).blend(with: theme.secondary.withAlphaComponent(0.06)))\n    trackOffColor = theme.onSurface.withAlphaComponent(0.12)\n    \n    buttonOnDisabledColor = theme.surface.blend(with: theme.onSurface.withAlphaComponent(0.15))\n    trackOnDisabledColor = theme.onSurface.withAlphaComponent(0.15)\n    buttonOffDisabledColor = buttonOnDisabledColor\n    trackOffDisabledColor = trackOnDisabledColor\n  }\n}\n\nextension Switch {\n  /**\n   Set the switchState property with an option to animate.\n   - Parameter state: The SwitchState to set.\n   - Parameter animated: A Boolean indicating to set the animation or not.\n   - Parameter completion: An Optional completion block.\n   */\n  open func setSwitchState(state: SwitchState, animated: Bool = true, completion: ((Switch) -> Void)? = nil) {\n    updateSwitchState(state: state, animated: animated, isTriggeredByUserInteraction: false, completion: completion)\n  }\n}\n\nfileprivate extension Switch {\n  /**\n   Set the switchState property with an option to animate.\n   - Parameter state: The SwitchState to set.\n   - Parameter animated: A Boolean indicating to set the animation or not.\n   - Parameter isTriggeredByUserInteraction: A boolean indicating whether the\n   state was changed by a user interaction, true if yes, false otherwise.\n   - Parameter completion: An Optional completion block.\n   */\n  func updateSwitchState(state: SwitchState, animated: Bool, isTriggeredByUserInteraction: Bool, completion: ((Switch) -> Void)? = nil) {\n    guard isEnabled && internalSwitchState != state else {\n      return\n    }\n    \n    internalSwitchState = state\n    \n    if animated {\n      animateToState(state: state) { [weak self, isTriggeredByUserInteraction = isTriggeredByUserInteraction] _ in\n        guard let s = self else {\n          return\n        }\n        \n        guard isTriggeredByUserInteraction else {\n          completion?(s)\n          return\n        }\n        \n        s.sendActions(for: .valueChanged)\n        completion?(s)\n        s.delegate?.switchDidChangeState(control: s, state: s.internalSwitchState)\n      }\n    } else {\n      button.frame.origin.x = .on == state ? self.onPosition : self.offPosition\n      styleForState(state: state)\n      \n      guard isTriggeredByUserInteraction else {\n        completion?(self)\n        return\n      }\n      \n      sendActions(for: .valueChanged)\n      completion?(self)\n      delegate?.switchDidChangeState(control: self, state: internalSwitchState)\n    }\n  }\n  \n  /**\n   Updates the coloring for the enabled state.\n   - Parameter state: SwitchState.\n   */\n  func updateColorForState(state: SwitchState) {\n    if .on == state {\n      button.backgroundColor = buttonOnColor\n      track.backgroundColor = trackOnColor\n      button.image = buttonOnImage\n    } else {\n      button.backgroundColor = buttonOffColor\n      track.backgroundColor = trackOffColor\n      button.image = buttonOffImage\n    }\n  }\n  \n  /**\n   Updates the coloring for the disabled state.\n   - Parameter state: SwitchState.\n   */\n  func updateColorForDisabledState(state: SwitchState) {\n    if .on == state {\n      button.backgroundColor = buttonOnDisabledColor\n      track.backgroundColor = trackOnDisabledColor\n      button.image = buttonOnDisabledImage\n    } else {\n      button.backgroundColor = buttonOffDisabledColor\n      track.backgroundColor = trackOffDisabledColor\n      button.image = buttonOffDisabledImage\n    }\n  }\n  \n  /**\n   Updates the style based on the state.\n   - Parameter state: The SwitchState to set the style to.\n   */\n  func styleForState(state: SwitchState) {\n    if isEnabled {\n      updateColorForState(state: state)\n      \n    } else {\n      updateColorForDisabledState(state: state)\n    }\n  }\n}\n\nfileprivate extension Switch {\n  /**\n   Set the switchState property with an animate.\n   - Parameter state: The SwitchState to set.\n   - Parameter completion: An Optional completion block.\n   */\n  func animateToState(state: SwitchState, completion: ((Switch) -> Void)? = nil) {\n    isUserInteractionEnabled = false\n    UIView.animate(withDuration: 0.15,\n                   delay: 0.05,\n                   options: [.curveEaseIn, .curveEaseOut],\n                   animations: { [weak self] in\n                    guard let s = self else {\n                      return\n                    }\n                    \n                    s.button.frame.origin.x = .on == state ? s.onPosition + s.bounceOffset : s.offPosition - s.bounceOffset\n                    s.styleForState(state: state)\n    }) { [weak self] _ in\n      UIView.animate(withDuration: 0.15,\n                     animations: { [weak self] in\n                      guard let s = self else {\n                        return\n                      }\n                      \n                      s.button.frame.origin.x = .on == state ? s.onPosition : s.offPosition\n      }) { [weak self] _ in\n        guard let s = self else {\n          return\n        }\n        \n        s.isUserInteractionEnabled = true\n        completion?(s)\n      }\n    }\n  }\n}\n\nfileprivate extension Switch {\n  /**\n   Handle the TouchUpOutside and TouchCancel moments.\n   - Parameter sender: A UIButton.\n   - Parameter event: A UIEvent.\n   */\n  @objc\n  func handleTouchUpOutsideOrCanceled(sender: FABButton, event: UIEvent) {\n    guard let v = event.touches(for: sender)?.first else {\n      return\n    }\n    \n    let q: CGFloat = sender.frame.origin.x + v.location(in: sender).x - v.previousLocation(in: sender).x\n    updateSwitchState(state: q > (bounds.width - button.bounds.width) / 2 ? .on : .off, animated: true, isTriggeredByUserInteraction: true)\n  }\n  \n  /// Handles the TouchUpInside event.\n  @objc\n  func handleTouchUpInside() {\n    updateSwitchState(state: isOn ? .off : .on, animated: true, isTriggeredByUserInteraction: true)\n  }\n  \n  /**\n   Handle the TouchDragInside event.\n   - Parameter sender: A UIButton.\n   - Parameter event: A UIEvent.\n   */\n  @objc\n  func handleTouchDragInside(sender: FABButton, event: UIEvent) {\n    guard let v = event.touches(for: sender)?.first else {\n      return\n    }\n    \n    let q: CGFloat = max(min(sender.frame.origin.x + v.location(in: sender).x - v.previousLocation(in: sender).x, onPosition), offPosition)\n    \n    guard q != sender.frame.origin.x else {\n      return\n    }\n    \n    sender.frame.origin.x = q\n  }\n}\n\nfileprivate extension Switch {\n  /// Prepares the track.\n  func prepareTrack() {\n    addSubview(track)\n  }\n  \n  /// Prepares the button.\n  func prepareButton() {\n    button.addTarget(self, action: #selector(handleTouchUpInside), for: .touchUpInside)\n    button.addTarget(self, action: #selector(handleTouchDragInside), for: .touchDragInside)\n    button.addTarget(self, action: #selector(handleTouchUpOutsideOrCanceled), for: .touchCancel)\n    button.addTarget(self, action: #selector(handleTouchUpOutsideOrCanceled), for: .touchUpOutside)\n    addSubview(button)\n  }\n  \n  /**\n   Prepares the switchState property. This is used mainly to allow\n   init to set the state value and have an effect.\n   - Parameter state: The SwitchState to set.\n   */\n  func prepareSwitchState(state: SwitchState = .off) {\n    updateSwitchState(state: state, animated: false, isTriggeredByUserInteraction: false)\n  }\n  \n  /**\n   Prepares the switchSize property. This is used mainly to allow\n   init to set the size value and have an effect.\n   - Parameter size: The SwitchSize to set.\n   */\n  func prepareSwitchSize(size: SwitchSize = .medium) {\n    switchSize = size\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Tab/TabBar.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\nopen class TabItem: FlatButton {\n  /// A dictionary of TabItemStates to UIColors for states.\n  fileprivate var colorForState = [TabItemState: UIColor]()\n  \n  /// A dictionary of TabItemStates to UIImages for states.\n  fileprivate var imageForState = [TabItemState: UIImage]()\n  \n  /// Sets the normal and highlighted image for the button.\n  open override var image: UIImage? {\n    didSet {\n      setTabItemImage(image, for: .normal)\n      setTabItemImage(image, for: .selected)\n      setTabItemImage(image, for: .highlighted)\n      \n      super.image = image\n    }\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    pulseAnimation = .none\n    \n    prepareImages()\n    \n    prepareColors()\n    updateColors()\n  }\n}\n\nfileprivate extension TabItem {\n  /// Prepares the tabsItems images.\n  func prepareImages() {\n    imageForState[.normal] = image\n    imageForState[.selected] = image\n    imageForState[.highlighted] = image\n  }\n  \n  /// Prepares the tabsItems colors.\n  func prepareColors() {\n    colorForState[.normal] = Color.grey.base\n    colorForState[.selected] = Color.blue.base\n    colorForState[.highlighted] = Color.blue.base\n  }\n}\n\nfileprivate extension TabItem {\n  /// Updates the tabItems colors.\n  func updateColors() {\n    let normalColor = colorForState[.normal]!\n    let selectedColor = colorForState[.selected]!\n    let highlightedColor = colorForState[.highlighted]!\n    \n    setTitleColor(normalColor, for: .normal)\n    setImage(imageForState[.normal]?.tint(with: normalColor), for: .normal)\n    setTitleColor(selectedColor, for: .selected)\n    setImage(imageForState[.selected]?.tint(with: selectedColor), for: .selected)\n    setTitleColor(highlightedColor, for: .highlighted)\n    setImage(imageForState[.highlighted]?.tint(with: highlightedColor), for: .highlighted)\n  }\n}\n\nextension TabItem {\n  /**\n   Retrieves the tabItem color for a given state.\n   - Parameter for state: A TabItemState.\n   - Returns: A UIColor.\n   */\n  open func getTabItemColor(for state: TabItemState) -> UIColor {\n    return colorForState[state]!\n  }\n  \n  /**\n   Sets the color for the tabItem given a TabItemState.\n   - Parameter _ color: A UIColor.\n   - Parameter for state: A TabItemState.\n   */\n  open func setTabItemColor(_ color: UIColor, for state: TabItemState) {\n    colorForState[state] = color\n    updateColors()\n  }\n  \n  /**\n   Retrieves the tabItem image for a given state.\n   - Parameter for state: A TabItemState.\n   - Returns: An optional UIImage.\n   */\n  open func getTabItemImage(for state: TabItemState) -> UIImage? {\n    return imageForState[state]\n  }\n  \n  /**\n   Sets the image for the tabItem given a TabItemState.\n   - Parameter _ image: An optional UIImage.\n   - Parameter for state: A TabItemState.\n   */\n  open func setTabItemImage(_ image: UIImage?, for state: TabItemState) {\n    imageForState[state] = image\n    updateColors()\n  }\n}\n\n@objc(TabItemState)\npublic enum TabItemState: Int {\n  case normal\n  case highlighted\n  case selected\n}\n\n@objc(TabItemLineState)\npublic enum TabItemLineState: Int {\n  case selected\n}\n\n@objc(TabBarLineAlignment)\npublic enum TabBarLineAlignment: Int {\n  case top\n  case bottom\n}\n\n@objc(TabBarDelegate)\npublic protocol TabBarDelegate {\n  /**\n   A delegation method that is executed to determine if the TabBar should\n   transition to the next tab.\n   - Parameter tabBar: A TabBar.\n   - Parameter tabItem: A TabItem.\n   - Returns: A Boolean.\n   */\n  @objc\n  optional func tabBar(tabBar: TabBar, shouldSelect tabItem: TabItem) -> Bool\n  \n  /**\n   A delegation method that is executed when the tabItem will trigger the\n   animation to the next tab.\n   - Parameter tabBar: A TabBar.\n   - Parameter tabItem: A TabItem.\n   */\n  @objc\n  optional func tabBar(tabBar: TabBar, willSelect tabItem: TabItem)\n  \n  /**\n   A delegation method that is executed when the tabItem did complete the\n   animation to the next tab.\n   - Parameter tabBar: A TabBar.\n   - Parameter tabItem: A TabItem.\n   */\n  @objc\n  optional func tabBar(tabBar: TabBar, didSelect tabItem: TabItem)\n}\n\n@objc(_TabBarDelegate)\ninternal protocol _TabBarDelegate {\n  /**\n   A delegation method that is executed to determine if the TabBar should\n   transition to the next tab.\n   - Parameter tabBar: A TabBar.\n   - Parameter tabItem: A TabItem.\n   - Returns: A Boolean.\n   */\n  func _tabBar(tabBar: TabBar, shouldSelect tabItem: TabItem) -> Bool\n}\n\n@objc(TabBarStyle)\npublic enum TabBarStyle: Int {\n  case auto\n  case nonScrollable\n  case scrollable\n}\n\npublic enum TabBarCenteringStyle {\n  case never\n  case auto\n  case always\n}\n\npublic enum TabBarLineStyle {\n  case auto\n  case fixed(CGFloat)\n  case custom((TabItem) -> CGFloat)\n}\n\nopen class TabBar: Bar {\n  /// A dictionary of TabItemLineStates to UIColors for the line.\n  fileprivate var lineColorForState = [TabItemLineState: UIColor]()\n  \n  /// Only for inital load to get the line animation correct.\n  fileprivate var shouldNotAnimateLineView = false\n  \n  /// The total width of the tabItems.\n  fileprivate var tabItemsTotalWidth: CGFloat {\n    var w: CGFloat = 0\n    let q = 2 * tabItemsInterimSpace\n    let p = q + tabItemsInterimSpace\n    \n    for v in tabItems {\n      let x = v.sizeThatFits(CGSize(width: .greatestFiniteMagnitude, height: scrollView.bounds.height)).width\n      w += x\n      w += p\n    }\n    \n    w -= tabItemsInterimSpace\n    \n    return w\n  }\n  \n  /// An enum that determines the tab bar style.\n  open var tabBarStyle = TabBarStyle.auto {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// An enum that determines the tab bar centering style.\n  open var tabBarCenteringStyle = TabBarCenteringStyle.always {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// An enum that determines the tab bar items style.\n  open var tabBarLineStyle = TabBarLineStyle.auto {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// A reference to the scroll view when the tab bar style is scrollable.\n  public let scrollView = UIScrollView()\n  \n  /// Enables and disables bouncing when swiping.\n  open var isScrollBounceEnabled: Bool {\n    get {\n      return scrollView.bounces\n    }\n    set(value) {\n      scrollView.bounces = value\n    }\n  }\n  \n  /// A delegation reference.\n  open weak var delegate: TabBarDelegate?\n  internal weak var _delegate: _TabBarDelegate?\n  \n  /// The currently selected tabItem.\n  open internal(set) var selectedTabItem: TabItem? {\n    didSet {\n      oldValue?.isSelected = false\n      selectedTabItem?.isSelected = true\n      updateScrollView()\n    }\n  }\n  \n  /// A preset wrapper around tabItems contentEdgeInsets.\n  open var tabItemsContentEdgeInsetsPreset: EdgeInsetsPreset {\n    get {\n      return contentView.grid.contentEdgeInsetsPreset\n    }\n    set(value) {\n      contentView.grid.contentEdgeInsetsPreset = value\n    }\n  }\n  \n  /// A reference to EdgeInsets.\n  @IBInspectable\n  open var tabItemsContentEdgeInsets: EdgeInsets {\n    get {\n      return contentView.grid.contentEdgeInsets\n    }\n    set(value) {\n      contentView.grid.contentEdgeInsets = value\n    }\n  }\n  \n  /// A preset wrapper around tabItems interimSpace.\n  open var tabItemsInterimSpacePreset: InterimSpacePreset {\n    get {\n      return contentView.grid.interimSpacePreset\n    }\n    set(value) {\n      contentView.grid.interimSpacePreset = value\n    }\n  }\n  \n  /// A wrapper around tabItems interimSpace.\n  @IBInspectable\n  open var tabItemsInterimSpace: InterimSpace {\n    get {\n      return contentView.grid.interimSpace\n    }\n    set(value) {\n      contentView.grid.interimSpace = value\n    }\n  }\n  \n  /// TabItems.\n  @objc\n  open var tabItems = [TabItem]() {\n    didSet {\n      oldValue.forEach {\n        $0.removeFromSuperview()\n      }\n      \n      prepareTabItems()\n      layoutSubviews()\n    }\n  }\n  \n  /// A reference to the line UIView.\n  public let line = UIView()\n  \n  /// A value for the line alignment.\n  @objc\n  open var lineAlignment = TabBarLineAlignment.bottom {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// The line height.\n  @objc\n  open var lineHeight: CGFloat {\n    get {\n      return line.bounds.height\n    }\n    set(value) {\n      line.frame.size.height = value\n    }\n  }\n  \n  /// The line color.\n  @objc\n  open var lineColor: UIColor {\n    get {\n      return lineColorForState[.selected]!\n    }\n    set(value) {\n      setLineColor(value, for: .selected)\n    }\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    guard willLayout else {\n      return\n    }\n    \n    layoutScrollView()\n    layoutLine()\n    \n    updateScrollView()\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    contentEdgeInsetsPreset = .none\n    interimSpacePreset = .interimSpace6\n    tabItemsInterimSpacePreset = .interimSpace4\n    \n    prepareContentView()\n    prepareScrollView()\n    prepareDivider()\n    prepareLine()\n    prepareLineColor()\n    \n    updateLineColors()\n  }\n}\n\nfileprivate extension TabBar {\n  // Prepares the line.\n  func prepareLine() {\n    line.layer.zPosition = 10000\n    lineHeight = 3\n    scrollView.addSubview(line)\n  }\n  \n  /// Prepares the divider.\n  func prepareDivider() {\n    dividerColor = Color.grey.lighten2\n    dividerAlignment = .top\n  }\n  \n  /// Prepares the tabItems.\n  func prepareTabItems() {\n    shouldNotAnimateLineView = true\n    \n    for v in tabItems {\n      v.grid.columns = 0\n      v.contentEdgeInsets = .zero\n      \n      prepareTabItemHandler(tabItem: v)\n    }\n    \n    selectedTabItem = tabItems.first\n  }\n  \n  /// Prepares the line colors.\n  func prepareLineColor() {\n    lineColorForState[.selected] = Color.blue.base\n  }\n  \n  /**\n   Prepares the tabItem animation handler.\n   - Parameter tabItem: A TabItem.\n   */\n  func prepareTabItemHandler(tabItem: TabItem) {\n    removeTabItemHandler(tabItem: tabItem)\n    \n    tabItem.addTarget(self, action: #selector(handleTabItemsChange(tabItem:)), for: .touchUpInside)\n  }\n  \n  /// Prepares the contentView.\n  func prepareContentView() {\n    contentView.layer.zPosition = 6000\n  }\n  \n  /// Prepares the scroll view.\n  func prepareScrollView() {\n    scrollView.showsVerticalScrollIndicator = false\n    scrollView.showsHorizontalScrollIndicator = false\n    centerViews = [scrollView]\n  }\n}\n\nfileprivate extension TabBar {\n  /// Layout the scrollView.\n  func layoutScrollView() {\n    contentView.grid.reload()\n    \n    if .scrollable == tabBarStyle || (.auto == tabBarStyle && tabItemsTotalWidth > scrollView.bounds.width) {\n      var w: CGFloat = 0\n      let q = 2 * tabItemsInterimSpace\n      let p = q + tabItemsInterimSpace\n      \n      for v in tabItems {\n        v.sizeToFit()\n        let x = v.sizeThatFits(CGSize(width: .greatestFiniteMagnitude, height: scrollView.bounds.height)).width\n        v.frame.size.height = scrollView.bounds.height\n        v.frame.size.width = x + q\n        v.frame.origin.x = w\n        w += x\n        w += p\n        \n        if scrollView != v.superview {\n          scrollView.addSubview(v)\n        }\n      }\n      \n      w -= tabItemsInterimSpace\n      \n      scrollView.contentSize = CGSize(width: w, height: scrollView.bounds.height)\n      \n    } else {\n      scrollView.grid.begin()\n      scrollView.grid.views = tabItems\n      scrollView.grid.axis.columns = tabItems.count\n      scrollView.grid.contentEdgeInsets = tabItemsContentEdgeInsets\n      scrollView.grid.interimSpace = tabItemsInterimSpace\n      scrollView.grid.commit()\n      scrollView.contentSize = scrollView.frame.size\n    }\n  }\n  \n  /// Layout the line view.\n  func layoutLine() {\n    guard let v = selectedTabItem else {\n      return\n    }\n    \n    guard shouldNotAnimateLineView else {\n      let f = lineFrame(for: v, forMotion: true)\n      line.animate(.duration(0),\n                   .size(f.size),\n                   .position(f.origin))\n      return\n    }\n    \n    line.frame = lineFrame(for: v)\n    \n    shouldNotAnimateLineView = false\n  }\n  \n  func lineFrame(for tabItem: TabItem, forMotion: Bool = false) -> CGRect {\n    let y = .bottom == lineAlignment ? scrollView.bounds.height - (forMotion ? lineHeight / 2 : lineHeight) : (forMotion ? lineHeight / 2 : 0)\n    \n    let w: CGFloat = {\n      switch tabBarLineStyle {\n      case .auto:\n        return tabItem.bounds.width\n        \n      case .fixed(let w):\n        return w\n        \n      case .custom(let closure):\n        return closure(tabItem)\n      }\n    }()\n    \n    let x = forMotion ? tabItem.center.x : (tabItem.frame.origin.x + (tabItem.bounds.width - w) / 2)\n    \n    return CGRect(x: x, y: y, width: w, height: lineHeight)\n  }\n}\n\nextension TabBar {\n  /**\n   Retrieves the tabItem color for a given state.\n   - Parameter for state: A TabItemState.\n   - Returns: A optional UIColor.\n   */\n  open func getTabItemColor(for state: TabItemState) -> UIColor? {\n    return tabItems.first?.getTabItemColor(for: state)\n  }\n  \n  /**\n   Sets the color for the tabItem given a TabItemState.\n   - Parameter _ color: A UIColor.\n   - Parameter for state: A TabItemState.\n   */\n  open func setTabItemsColor(_ color: UIColor, for state: TabItemState) {\n    for v in tabItems {\n      v.setTabItemColor(color, for: state)\n    }\n  }\n  \n  /**\n   Retrieves the line color for a given state.\n   - Parameter for state: A TabItemLineState.\n   - Returns: A UIColor.\n   */\n  open func getLineColor(for state: TabItemLineState) -> UIColor {\n    return lineColorForState[state]!\n  }\n  \n  /**\n   Sets the color for the line given a TabItemLineState.\n   - Parameter _ color: A UIColor.\n   - Parameter for state: A TabItemLineState.\n   */\n  open func setLineColor(_ color: UIColor, for state: TabItemLineState) {\n    lineColorForState[state] = color\n    updateLineColors()\n  }\n}\n\ninternal extension TabBar {\n  /**\n   Starts line transition for the index with the given duration.\n   - Parameter for index: An Int.\n   - Parameter duration: A TimeInterval.\n   */\n  func startLineTransition(for index: Int, duration: TimeInterval = 0.35) {\n    guard let s = selectedTabItem, let currentIndex = tabItems.firstIndex(of: s) else {\n      return\n    }\n    \n    guard currentIndex != index else {\n      return\n    }\n    \n    let targetFrame = lineFrame(for: tabItems[index], forMotion: true)\n    \n    line.transition(.size(targetFrame.size),\n                    .position(targetFrame.origin),\n                    .duration(duration))\n    \n    line.motionViewTransition.start()\n  }\n  \n  /**\n   Updates line transition to the given progress value.\n   - Parameter _ progress: A CGFloat.\n   */\n  func updateLineTransition(_ progress: CGFloat) {\n    line.motionViewTransition.update(progress)\n  }\n  \n  /**\n   Finishes line transition.\n   - Parameter isAnimated: A Boolean indicating if the change should be animated.\n   */\n  func finishLineTransition(isAnimated: Bool = true) {\n    line.motionViewTransition.finish(isAnimated: isAnimated)\n    line.transition([])\n  }\n  \n  /**\n   Cancels line transition.\n   - Parameter isAnimated: A Boolean indicating if the change should be animated.\n   */\n  func cancelLineTransition(isAnimated: Bool = true) {\n    line.motionViewTransition.cancel(isAnimated: isAnimated)\n    line.transition([])\n  }\n}\n\nfileprivate extension TabBar {\n  /**\n   Removes the tabItem animation handler.\n   - Parameter tabItem: A TabItem.\n   */\n  func removeTabItemHandler(tabItem: TabItem) {\n    tabItem.removeTarget(self, action: #selector(handleTabItemsChange(tabItem:)), for: .touchUpInside)\n  }\n}\n\nfileprivate extension TabBar {\n  /// Handles the tabItem touch event.\n  @objc\n  func handleTabItemsChange(tabItem: TabItem) {\n    guard !(false == delegate?.tabBar?(tabBar: self, shouldSelect: tabItem)) else {\n      return\n    }\n    \n    guard !(false == _delegate?._tabBar(tabBar: self, shouldSelect: tabItem)) else {\n      return\n    }\n    \n    animate(to: tabItem, isTriggeredByUserInteraction: true)\n  }\n}\n\nextension TabBar {\n  /**\n   Selects a given index from the tabItems array.\n   - Parameter at index: An Int.\n   - Paramater completion: An optional completion block.\n   */\n  @objc\n  open func select(at index: Int, completion: ((TabItem) -> Void)? = nil) {\n    guard -1 < index, index < tabItems.count else {\n      return\n    }\n    \n    animate(to: tabItems[index], isTriggeredByUserInteraction: false, completion: completion)\n  }\n  \n  /**\n   Animates to a given tabItem.\n   - Parameter to tabItem: A TabItem.\n   - Parameter completion: An optional completion block.\n   */\n  open func animate(to tabItem: TabItem, completion: ((TabItem) -> Void)? = nil) {\n    animate(to: tabItem, isTriggeredByUserInteraction: false, completion: completion)\n  }\n}\n\nfileprivate extension TabBar {\n  /// Updates the line colors.\n  func updateLineColors() {\n    line.backgroundColor = lineColorForState[.selected]\n  }\n}\n\nfileprivate extension TabBar {\n  /**\n   Animates to a given tabItem.\n   - Parameter to tabItem: A TabItem.\n   - Parameter isTriggeredByUserInteraction: A boolean indicating whether the\n   state was changed by a user interaction, true if yes, false otherwise.\n   - Parameter completion: An optional completion block.\n   */\n  func animate(to tabItem: TabItem, isTriggeredByUserInteraction: Bool, completion: ((TabItem) -> Void)? = nil) {\n    if isTriggeredByUserInteraction {\n      delegate?.tabBar?(tabBar: self, willSelect: tabItem)\n    }\n    \n    selectedTabItem = tabItem\n    \n    let f = lineFrame(for: tabItem, forMotion: true)\n    \n    line.animate(.duration(0.25),\n                 .size(f.size),\n                 .position(f.origin),\n                 .completion({ [weak self, isTriggeredByUserInteraction = isTriggeredByUserInteraction, tabItem = tabItem, completion = completion] in\n                  guard let `self` = self else {\n                    return\n                  }\n                  \n                  if isTriggeredByUserInteraction {\n                    self.delegate?.tabBar?(tabBar: self, didSelect: tabItem)\n                  }\n                  \n                  completion?(tabItem)\n                 }))\n    \n    updateScrollView()\n  }\n}\n\nfileprivate extension TabBar {\n  /// Updates the scrollView.\n  func updateScrollView() {\n    guard let v = selectedTabItem else {\n      return\n    }\n    \n    let contentOffsetX: CGFloat? = {\n      let shouldScroll = !scrollView.bounds.contains(v.frame)\n      \n      switch tabBarCenteringStyle {\n      case .auto:\n        guard shouldScroll else {\n          return nil\n        }\n        \n        fallthrough\n        \n      case .always:\n        return v.center.x - bounds.width / 2\n        \n      case .never:\n        guard shouldScroll else {\n          return nil\n        }\n        \n        return v.frame.origin.x < scrollView.bounds.minX ? v.frame.origin.x : v.frame.maxX - scrollView.bounds.width\n      }\n    }()\n    \n    if let x = contentOffsetX {\n      let normalizedOffsetX = min(max(x, 0), scrollView.contentSize.width - scrollView.bounds.width)\n      scrollView.setContentOffset(CGPoint(x: normalizedOffsetX, y: 0), animated: true)\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Tab/TabsController.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\nfileprivate var TabItemKey: UInt8 = 0\n\n@objc(TabBarAlignment)\npublic enum TabBarAlignment: Int {\n  case top\n  case bottom\n}\n\npublic enum TabBarThemingStyle {\n  case auto\n  case primary\n  case secondary\n}\n\nextension UIViewController {\n  /// TabItem reference.\n  @objc\n  open private(set) var tabItem: TabItem {\n    get {\n      return AssociatedObject.get(base: self, key: &TabItemKey) {\n        return TabItem()\n      }\n    }\n    set(value) {\n      AssociatedObject.set(base: self, key: &TabItemKey, value: value)\n    }\n  }\n}\n\nextension UIViewController {\n  /**\n   A convenience property that provides access to the TabsController.\n   This is the recommended method of accessing the TabsController\n   through child UIViewControllers.\n   */\n  public var tabsController: TabsController? {\n    return traverseViewControllerHierarchyForClassType()\n  }\n}\n\n@objc(TabsControllerDelegate)\npublic protocol TabsControllerDelegate {\n  /**\n   A delegation method that is executed to determine if the TabsController should\n   transition to the next view controller.\n   - Parameter tabBar: A TabsController.\n   - Parameter tabItem: A TabItem.\n   - Returns: A Boolean.\n   */\n  @objc\n  optional func tabsController(tabsController: TabsController, shouldSelect viewController: UIViewController) -> Bool\n  \n  /**\n   A delegation method that is executed when the view controller will transitioned to.\n   - Parameter tabsController: A TabsController.\n   - Parameter viewController: A UIViewController.\n   */\n  @objc\n  optional func tabsController(tabsController: TabsController, willSelect viewController: UIViewController)\n  \n  /**\n   A delegation method that is executed when the view controller has been transitioned to.\n   - Parameter tabsController: A TabsController.\n   - Parameter viewController: A UIViewController.\n   */\n  @objc\n  optional func tabsController(tabsController: TabsController, didSelect viewController: UIViewController)\n  \n  /**\n   A delegation method that is executed when the interactive transition to view controller\n   will be cancelled.\n   - Parameter tabsController: A TabsController.\n   - Parameter viewController: A UIViewController.\n   */\n  @objc\n  optional func tabsController(tabsController: TabsController, willCancelSelecting viewController: UIViewController)\n  \n  /**\n   A delegation method that is executed when the interactive transition to view controller\n   has been cancelled.\n   - Parameter tabsController: A TabsController.\n   - Parameter viewController: A UIViewController.\n   */\n  @objc\n  optional func tabsController(tabsController: TabsController, didCancelSelecting viewController: UIViewController)\n}\n\nopen class TabsController: TransitionController {\n  /**\n   A Display value to indicate whether or not to\n   display the rootViewController to the full view\n   bounds, or up to the toolbar height.\n   */\n  open var displayStyle = DisplayStyle.partial {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// The TabBar used to switch between view controllers.\n  @IBInspectable\n  public let tabBar = TabBar()\n  \n  /// A Boolean that controls if the swipe feature is enabled.\n  open var isSwipeEnabled = true {\n    didSet {\n      guard isSwipeEnabled else {\n        removeSwipeGesture()\n        return\n      }\n      \n      prepareSwipeGesture()\n    }\n  }\n  \n  /// A delegation reference.\n  open weak var delegate: TabsControllerDelegate?\n  \n  /// An Array of UIViewControllers.\n  open var viewControllers: [UIViewController] {\n    didSet {\n      selectedIndex = 0\n      \n      prepareSelectedIndexViewController()\n      prepareTabBar()\n      layoutSubviews()\n    }\n  }\n  \n  /// A reference to the currently selected view controller index value.\n  @IBInspectable\n  open fileprivate(set) var selectedIndex = 0\n  \n  /// The tabBar alignment.\n  open var tabBarAlignment = TabBarAlignment.bottom {\n    didSet {\n      updateTabBarAlignment()\n      layoutSubviews()\n    }\n  }\n  \n  /// The tabBar theming style.\n  open var tabBarThemingStyle = TabBarThemingStyle.auto\n  \n  /**\n   A UIPanGestureRecognizer property internally used for the interactive\n   swipe.\n   */\n  public private(set) var interactiveSwipeGesture: UIPanGestureRecognizer?\n  \n  /**\n   A private integer for storing index of target view controller\n   during interactive transition.\n   */\n  private var targetIndex = -1\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    viewControllers = []\n    super.init(coder: aDecoder)\n  }\n  \n  /**\n   An initializer that accepts an Array of UIViewControllers.\n   - Parameter viewControllers: An Array of UIViewControllers.\n   */\n  public init(viewControllers: [UIViewController], selectedIndex: Int = 0) {\n    self.viewControllers = viewControllers\n    self.selectedIndex = selectedIndex\n    super.init(nibName: nil, bundle: nil)\n  }\n  \n  fileprivate override init(rootViewController: UIViewController) {\n    self.viewControllers = []\n    super.init(rootViewController: rootViewController)\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    layoutTabBar()\n    layoutContainer()\n    layoutRootViewController()\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    view.backgroundColor = .white\n    view.contentScaleFactor = Screen.scale\n    \n    isSwipeEnabled = true\n    \n    prepareTabBar()\n    prepareTabItems()\n    prepareSelectedIndexViewController()\n    applyCurrentTheme()\n  }\n  \n  open override func transition(to viewController: UIViewController, completion: ((Bool) -> Void)?) {\n    transition(to: viewController, isTriggeredByUserInteraction: false, completion: completion)\n  }\n  \n  open override func apply(theme: Theme) {\n    super.apply(theme: theme)\n    \n    switch tabBarThemingStyle {\n    case .auto where (parent is NavigationController || parent is ToolbarController) && tabBarAlignment == .top:\n      fallthrough\n      \n    case .primary:\n      applyPrimary(theme: theme)\n      \n    default:\n      applySecondary(theme: theme)\n    }\n  }\n}\n\nprivate extension TabsController {\n  /**\n   Applies theming taking primary color as base.\n   - Parameter theme: A Theme\n   */\n  func applyPrimary(theme: Theme) {\n    tabBar.lineColor = theme.onPrimary.withAlphaComponent(0.68)\n    tabBar.backgroundColor = theme.primary\n    tabBar.setTabItemsColor(theme.onPrimary, for: .normal)\n    tabBar.setTabItemsColor(theme.onPrimary, for: .selected)\n    tabBar.setTabItemsColor(theme.onPrimary, for: .highlighted)\n    tabBar.isDividerHidden = true\n  }\n  \n  /**\n   Applies theming taking secondary color as base.\n   - Parameter theme: A Theme\n   */\n  func applySecondary(theme: Theme) {\n    tabBar.lineColor = theme.secondary\n    tabBar.backgroundColor = theme.background\n    tabBar.setTabItemsColor(theme.onSurface.withAlphaComponent(0.60), for: .normal)\n    tabBar.setTabItemsColor(theme.secondary, for: .selected)\n    tabBar.setTabItemsColor(theme.secondary, for: .highlighted)\n    tabBar.dividerColor = theme.onSurface.withAlphaComponent(0.12)\n  }\n}\n\nfileprivate extension TabsController {\n  /**\n   Transitions to the given view controller.\n   - Parameter to viewController: A UIViewController.\n   - Parameter isTriggeredByUserInteraction: A Boolean.\n   - Parameter completion: An optional completion block.\n   */\n  func transition(to viewController: UIViewController, isTriggeredByUserInteraction: Bool, completion: ((Bool) -> Void)?) {\n    guard let fvcIndex = viewControllers.firstIndex(of: rootViewController) else {\n      return\n    }\n    \n    guard let tvcIndex = viewControllers.firstIndex(of: viewController) else {\n      return\n    }\n    \n    if case .auto = motionTransitionType, case .auto = viewController.motionTransitionType {\n      MotionTransition.shared.setAnimationForNextTransition(fvcIndex < tvcIndex ? .slide(direction: .left) : .slide(direction: .right))\n    }\n    \n    if isTriggeredByUserInteraction {\n      delegate?.tabsController?(tabsController: self, willSelect: viewController)\n    }\n    \n    super.transition(to: viewController) { [weak self] (isFinishing) in\n      guard let `self` = self else {\n        return\n      }\n      \n      completion?(isFinishing)\n      \n      if isTriggeredByUserInteraction && isFinishing {\n        self.delegate?.tabsController?(tabsController: self, didSelect: viewController)\n      } else {\n        self.delegate?.tabsController?(tabsController: self, didCancelSelecting: viewController)\n      }\n    }\n  }\n}\n\nfileprivate extension TabsController {\n  /// Prepares the view controller at the selectedIndex.\n  func prepareSelectedIndexViewController() {\n    rootViewController = viewControllers[selectedIndex]\n  }\n  \n  /// Prepares the TabBar.\n  func prepareTabBar() {\n    tabBar._delegate = self\n    view.addSubview(tabBar)\n    updateTabBarAlignment()\n  }\n  \n  func updateTabBarAlignment() {\n    tabBar.lineAlignment = .bottom == tabBarAlignment ? .top : .bottom\n    tabBar.dividerAlignment = .bottom == tabBarAlignment ? .top : .bottom\n  }\n  \n  /// Prepares the `tabBar.tabItems`.\n  func prepareTabItems() {\n    var tabItems = [TabItem]()\n    \n    for v in viewControllers {\n      // Expectation that viewDidLoad() triggers update of tabItem:\n      if #available(iOS 9.0, *) {\n        v.loadViewIfNeeded()\n        \n      } else {\n        _ = v.view\n      }\n      \n      tabItems.append(v.tabItem)\n    }\n    \n    tabBar.tabItems = tabItems\n    tabBar.selectedTabItem = tabItems[selectedIndex]\n  }\n}\n\nprivate extension TabsController {\n  /**\n   A target method contolling interactive swipe transition based on\n   gesture recognizer.\n   - Parameter _ gesture: A UIPanGestureRecognizer.\n   */\n  @objc\n  func handleTransitionPan(_ gesture: UIPanGestureRecognizer) {\n    let translationX = gesture.translation(in: nil).x\n    let velocityX = gesture.velocity(in: nil).x\n    \n    switch gesture.state {\n    case .began, .changed:\n      let isSlidingLeft = targetIndex == -1 ? velocityX < 0 : translationX < 0\n      let nextIndex = selectedIndex + (isSlidingLeft ? 1 : -1)\n      \n      guard nextIndex >= 0, nextIndex < viewControllers.count else {\n        return\n      }\n      \n      if targetIndex != nextIndex {\n        /// 5 point threshold\n        guard abs(translationX) > 5 else {\n          return\n        }\n        \n        if targetIndex != -1 {\n          delegate?.tabsController?(tabsController: self, willCancelSelecting: viewControllers[targetIndex])\n          tabBar.cancelLineTransition(isAnimated: false)\n          MotionTransition.shared.cancel(isAnimated: false)\n        }\n        \n        if internalSelect(at: nextIndex, isTriggeredByUserInteraction: true, selectTabItem: false)  {\n          tabBar.startLineTransition(for: nextIndex, duration: 0.35)\n          targetIndex = nextIndex\n        }\n      } else {\n        let progress = abs(translationX / view.bounds.width)\n        tabBar.updateLineTransition(progress)\n        MotionTransition.shared.update(Double(progress))\n      }\n      \n    default:\n      guard targetIndex != -1 else {\n        return\n      }\n      \n      let progress = (translationX + velocityX) / view.bounds.width\n      \n      let isUserHandDirectionLeft = progress < 0\n      let isTargetHandDirectionLeft = targetIndex > selectedIndex\n      \n      if isUserHandDirectionLeft == isTargetHandDirectionLeft && abs(progress) > 0.5 {\n        tabBar.finishLineTransition()\n        MotionTransition.shared.finish()\n      } else {\n        tabBar.cancelLineTransition()\n        MotionTransition.shared.cancel()\n        delegate?.tabsController?(tabsController: self, willCancelSelecting: viewControllers[targetIndex])\n      }\n      targetIndex = -1\n    }\n  }\n  \n  /// Prepares interactiveSwipeGesture.\n  func prepareSwipeGesture() {\n    guard nil == interactiveSwipeGesture else {\n      return\n    }\n    \n    interactiveSwipeGesture = UIPanGestureRecognizer(target: self, action: #selector(handleTransitionPan))\n    container.addGestureRecognizer(interactiveSwipeGesture!)\n  }\n  \n  /// Removes interactiveSwipeGesture.\n  func removeSwipeGesture() {\n    guard let v = interactiveSwipeGesture else {\n      return\n    }\n    \n    container.removeGestureRecognizer(v)\n    interactiveSwipeGesture = nil\n  }\n}\n\nfileprivate extension TabsController {\n  /// Layout the container.\n  func layoutContainer() {\n    switch displayStyle {\n    case .partial:\n      let p = tabBar.bounds.height\n      let y = view.bounds.height - p\n      \n      switch tabBarAlignment {\n      case .top:\n        container.frame.origin.y = p\n        container.frame.size.height = y\n        \n      case .bottom:\n        container.frame.origin.y = 0\n        container.frame.size.height = y\n      }\n      \n      container.frame.size.width = view.bounds.width\n      \n    case .full:\n      container.frame = view.bounds\n    }\n  }\n  \n  /// Layout the tabBar.\n  func layoutTabBar() {\n    if #available(iOS 11, *) {\n      if .bottom == tabBarAlignment {\n        let v = bottomLayoutGuide.length\n        \n        if 0 < v {\n          tabBar.heightPreset = { tabBar.heightPreset }()\n          tabBar.frame.size.height += v\n          tabBar.grid.layoutEdgeInsets.bottom = v\n        }\n      }\n    }\n    \n    tabBar.frame.origin.x = 0\n    tabBar.frame.origin.y = .top == tabBarAlignment ? 0 : view.bounds.height - tabBar.bounds.height\n    tabBar.frame.size.width = view.bounds.width\n  }\n  \n  /// Layout the rootViewController.\n  func layoutRootViewController() {\n    rootViewController.view.frame = container.bounds\n  }\n}\n\nextension TabsController {\n  /**\n   Transitions to the view controller that is at the given index.\n   - Parameter at index: An Int.\n   */\n  open func select(at index: Int) {\n    internalSelect(at: index, isTriggeredByUserInteraction: false, selectTabItem: true)\n  }\n  \n  /**\n   Transitions to the view controller that is at the given index.\n   - Parameter at index: An Int.\n   - Parameter isTriggeredByUserInteraction: A boolean indicating whether the\n   state was changed by a user interaction, true if yes, false otherwise.\n   - Returns: A boolean indicating whether the transition will take place.\n   */\n  @discardableResult\n  private func internalSelect(at index: Int, isTriggeredByUserInteraction: Bool, selectTabItem: Bool) -> Bool {\n    guard index != selectedIndex else {\n      return false\n    }\n    \n    if isTriggeredByUserInteraction {\n      guard !(false == delegate?.tabsController?(tabsController: self, shouldSelect: viewControllers[index])) else {\n        return false\n      }\n    }\n    \n    if selectTabItem {\n      tabBar.select(at: index)\n    }\n    \n    transition(to: viewControllers[index], isTriggeredByUserInteraction: isTriggeredByUserInteraction) { [weak self] (isFinishing) in\n      guard isFinishing else {\n        return\n      }\n      \n      self?.selectedIndex = index\n      self?.tabBar.selectedTabItem = self?.tabBar.tabItems[index]\n    }\n    \n    return true\n  }\n}\n\nextension TabsController: _TabBarDelegate {\n  @objc\n  func _tabBar(tabBar: TabBar, shouldSelect tabItem: TabItem) -> Bool {\n    guard let i = tabBar.tabItems.firstIndex(of: tabItem) else {\n      return false\n    }\n    \n    return internalSelect(at: i, isTriggeredByUserInteraction: true, selectTabItem: false)\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Table/TableView.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class TableView: UITableView {\n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n    prepare()\n  }\n  \n  public override init(frame: CGRect, style: UITableView.Style) {\n    super.init(frame: frame, style: style)\n    prepare()\n  }\n  \n  /**\n   An initializer that initializes the object.\n   - Parameter frame: A CGRect defining the view's frame.\n   */\n  public convenience init(frame: CGRect) {\n    self.init(frame: frame, style: .plain)\n  }\n  \n  /**\n   Prepares the view instance when intialized. When subclassing,\n   it is recommended to override the prepare method\n   to initialize property values and other setup operations.\n   The super.prepare method should always be called immediately\n   when subclassing.\n   */\n  open func prepare() {\n    backgroundColor = .white\n    contentScaleFactor = Screen.scale\n    separatorStyle = .none\n    register(TableViewCell.self, forCellReuseIdentifier: \"TableViewCell\")\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Table/TableViewCell.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\nopen class TableViewCell: UITableViewCell, Pulseable, PulseableLayer {\n  /**\n   A CAShapeLayer used to manage elements that would be affected by\n   the clipToBounds property of the backing layer. For example, this\n   allows the dropshadow effect on the backing layer, while clipping\n   the image to a desired shape within the visualLayer.\n   */\n  public let visualLayer = CAShapeLayer()\n  \n  /// A Pulse reference.\n  internal var pulse: Pulse!\n  \n  /// A reference to the pulse layer.\n  internal var pulseLayer: CALayer? {\n    return pulse.pulseLayer\n  }\n  \n  /// PulseAnimation value.\n  open var pulseAnimation: PulseAnimation {\n    get {\n      return pulse.animation\n    }\n    set(value) {\n      pulse.animation = value\n    }\n  }\n  \n  /// PulseAnimation color.\n  @IBInspectable\n  open var pulseColor: UIColor {\n    get {\n      return pulse.color\n    }\n    set(value) {\n      pulse.color = value\n    }\n  }\n  \n  /// Pulse opacity.\n  @IBInspectable\n  open var pulseOpacity: CGFloat {\n    get {\n      return pulse.opacity\n    }\n    set(value) {\n      pulse.opacity = value\n    }\n  }\n  \n  /// A property that accesses the backing layer's background\n  @IBInspectable\n  open override var backgroundColor: UIColor? {\n    didSet {\n      layer.backgroundColor = backgroundColor?.cgColor\n    }\n  }\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n    prepare()\n  }\n  \n  /**\n   An initializer that initializes the object.\n   - Parameter style: A UITableViewCellStyle enum.\n   - Parameter reuseIdentifier: A String identifier.\n   */\n  public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String!) {\n    super.init(style: .subtitle, reuseIdentifier: reuseIdentifier)\n    prepare()\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    layoutShape()\n    layoutVisualLayer()\n    layoutShadowPath()\n    layoutDivider()\n  }\n  \n  /**\n   Triggers the pulse animation.\n   - Parameter point: A Optional point to pulse from, otherwise pulses\n   from the center.\n   */\n  open func pulse(point: CGPoint? = nil) {\n    pulse.expand(point: point ?? center)\n    Motion.delay(0.35) { [weak self] in\n      self?.pulse.contract()\n    }\n  }\n  \n  /**\n   A delegation method that is executed when the view has began a\n   touch event.\n   - Parameter touches: A set of UITouch objects.\n   - Parameter event: A UIEvent object.\n   */\n  open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {\n    super.touchesBegan(touches, with: event)\n    pulse.expand(point: layer.convert(touches.first!.location(in: self), from: layer))\n  }\n  \n  /**\n   A delegation method that is executed when the view touch event has\n   ended.\n   - Parameter touches: A set of UITouch objects.\n   - Parameter event: A UIEvent object.\n   */\n  open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {\n    super.touchesEnded(touches, with: event)\n    pulse.contract()\n  }\n  \n  /**\n   A delegation method that is executed when the view touch event has\n   been cancelled.\n   - Parameter touches: A set of UITouch objects.\n   - Parameter event: A UIEvent object.\n   */\n  open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {\n    super.touchesCancelled(touches, with: event)\n    pulse.contract()\n  }\n  \n  /**\n   Prepares the view instance when intialized. When subclassing,\n   it is recommended to override the prepare method\n   to initialize property values and other setup operations.\n   The super.prepare method should always be called immediately\n   when subclassing.\n   */\n  open func prepare() {\n    selectionStyle = .none\n    separatorInset = .zero\n    contentScaleFactor = Screen.scale\n    imageView?.isUserInteractionEnabled = false\n    textLabel?.isUserInteractionEnabled = false\n    detailTextLabel?.isUserInteractionEnabled = false\n    prepareVisualLayer()\n    preparePulse()\n  }\n}\n\nextension TableViewCell {\n  /// Prepares the pulse motion.\n  fileprivate func preparePulse() {\n    pulse = Pulse(pulseView: self, pulseLayer: visualLayer)\n  }\n  \n  /// Prepares the visualLayer property.\n  fileprivate func prepareVisualLayer() {\n    visualLayer.zPosition = 0\n    visualLayer.masksToBounds = true\n    contentView.layer.addSublayer(visualLayer)\n  }\n}\n\nextension TableViewCell {\n  /// Manages the layout for the visualLayer property.\n  fileprivate func layoutVisualLayer() {\n    visualLayer.frame = bounds\n    visualLayer.cornerRadius = layer.cornerRadius\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Table/TableViewController.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\npublic protocol TableViewDelegate: UITableViewDelegate {}\n\npublic protocol TableViewDataSource: UITableViewDataSource {\n  /**\n   Retrieves the data source items for the tableView.\n   - Returns: An Array of DataSourceItem objects.\n   */\n  var dataSourceItems: [DataSourceItem] { get }\n}\n\nextension UIViewController {\n  /**\n   A convenience property that provides access to the TableViewController.\n   This is the recommended method of accessing the TableViewController\n   through child UIViewControllers.\n   */\n  public var tableViewController: TableViewController? {\n    return traverseViewControllerHierarchyForClassType()\n  }\n}\n\nopen class TableViewController: ViewController {\n  /// A reference to a Reminder.\n  public let tableView = TableView()\n  \n  /// An Array of DataSourceItems.\n  open var dataSourceItems = [DataSourceItem]()\n  \n  open override func prepare() {\n    super.prepare()\n    prepareTableView()\n  }\n}\n\nextension TableViewController {\n  /// Prepares the tableView.\n  fileprivate func prepareTableView() {\n    tableView.delegate = self\n    tableView.dataSource = self\n    tableView.backgroundColor = .clear\n    view.layout(tableView).edges()\n  }\n}\n\nextension TableViewController: TableViewDelegate {}\n\nextension TableViewController: TableViewDataSource {\n  @objc\n  open func numberOfSections(in tableView: UITableView) -> Int {\n    return 1\n  }\n  \n  @objc\n  open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {\n    return dataSourceItems.count\n  }\n  \n  @objc\n  open func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {\n    return UITableViewCell()\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Text/Editor.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\npublic enum EditorPlaceholderAnimation {\n  case `default`\n  case hidden\n}\n\nopen class Editor: View, Themeable {\n  /// Reference to textView.\n  public let textView = TextView()\n  \n  /// A boolean indicating whether the textView is in edit mode.\n  open var isEditing: Bool {\n    return textView.isEditing\n  }\n  \n  /// A boolean indicating whether the text is empty.\n  open var isEmpty: Bool {\n    return textView.isEmpty\n  }\n  \n  /// The placeholder UILabel.\n  @IBInspectable\n  open var placeholderLabel: UILabel {\n    return textView.placeholderLabel\n  }\n  \n  /// A Boolean that indicates if the placeholder label is animated.\n  @IBInspectable\n  open var isPlaceholderAnimated = true\n  \n  /// Set the placeholder animation value.\n  open var placeholderAnimation = EditorPlaceholderAnimation.default {\n    didSet {\n      updatePlaceholderVisibility()\n    }\n  }\n  \n  /// Placeholder normal text color.\n  @IBInspectable\n  open var placeholderNormalColor = Color.darkText.others {\n    didSet {\n      updatePlaceholderLabelColor()\n    }\n  }\n  \n  /// Placeholder active text color.\n  @IBInspectable\n  open var placeholderActiveColor = Color.blue.base {\n    didSet {\n      updatePlaceholderLabelColor()\n    }\n  }\n  \n  /// The scale of the active placeholder in relation to the inactive.\n  @IBInspectable\n  open var placeholderActiveScale: CGFloat = 0.75 {\n    didSet {\n      layoutPlaceholderLabel()\n    }\n  }\n  \n  /// This property adds a padding to placeholder y position animation\n  @IBInspectable\n  open var placeholderVerticalOffset: CGFloat = 0\n  \n  /// This property adds a padding to placeholder x position animation\n  @IBInspectable\n  open var placeholderHorizontalOffset: CGFloat = 0\n  \n  /// Divider normal height.\n  @IBInspectable\n  open var dividerNormalHeight: CGFloat = 1 {\n    didSet {\n      updateDividerHeight()\n    }\n  }\n  \n  /// Divider active height.\n  @IBInspectable\n  open var dividerActiveHeight: CGFloat = 2 {\n    didSet {\n      updateDividerHeight()\n    }\n  }\n  \n  /// Divider normal color.\n  @IBInspectable\n  open var dividerNormalColor = Color.grey.lighten2 {\n    didSet {\n      updateDividerColor()\n    }\n  }\n  \n  /// Divider active color.\n  @IBInspectable\n  open var dividerActiveColor = Color.blue.base {\n    didSet {\n      updateDividerColor()\n    }\n  }\n  \n  /// The detailLabel UILabel that is displayed.\n  @IBInspectable\n  public let detailLabel = UILabel()\n  \n  /// The detailLabel text value.\n  @IBInspectable\n  open var detail: String? {\n    get {\n      return detailLabel.text\n    }\n    set(value) {\n      detailLabel.text = value\n      layoutSubviews()\n    }\n  }\n  \n  /// The detailLabel text color.\n  @IBInspectable\n  open var detailColor = Color.darkText.others {\n    didSet {\n      updateDetailLabelColor()\n    }\n  }\n  \n  /// Vertical distance for the detailLabel from the divider.\n  @IBInspectable\n  open var detailVerticalOffset: CGFloat = 8 {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// A reference to titleLabel.textAlignment observation.\n  private var placeholderLabelTextObserver: NSKeyValueObservation!\n  \n  /**\n   A reference to textView.text observation.\n   Only observes programmatic changes.\n   */\n  private var textViewTextObserver: NSKeyValueObservation!\n  \n  deinit {\n    placeholderLabelTextObserver.invalidate()\n    placeholderLabelTextObserver = nil\n    \n    textViewTextObserver.invalidate()\n    textViewTextObserver = nil\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    backgroundColor = nil\n    prepareDivider()\n    prepareTextView()\n    preparePlaceholderLabel()\n    prepareDetailLabel()\n    prepareNotificationHandlers()\n    \n    applyCurrentTheme()\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    layoutPlaceholderLabel()\n    layoutDivider()\n    layoutBottomLabel(label: detailLabel, verticalOffset: detailVerticalOffset)\n  }\n  \n  /**\n   Applies the given theme.\n   - Parameter theme: A Theme.\n   */\n  open func apply(theme: Theme) {\n    placeholderActiveColor = theme.secondary\n    placeholderNormalColor = theme.onSurface.withAlphaComponent(0.38)\n    \n    dividerActiveColor = theme.secondary\n    dividerNormalColor = theme.onSurface.withAlphaComponent(0.12)\n    \n    detailColor = theme.onSurface.withAlphaComponent(0.38)\n    textView.tintColor = theme.secondary\n  }\n  \n  @discardableResult\n  open override func becomeFirstResponder() -> Bool {\n    return textView.becomeFirstResponder()\n  }\n  \n  @discardableResult\n  open override func resignFirstResponder() -> Bool {\n    return textView.resignFirstResponder()\n  }\n}\n\n\nprivate extension Editor {\n  /// Prepares the divider.\n  func prepareDivider() {\n    dividerColor = dividerNormalColor\n  }\n  \n  /// Prepares the textView.\n  func prepareTextView() {\n    layout(textView).edges()\n    textView.isPlaceholderLabelEnabled = false\n    \n    textViewTextObserver = textView.observe(\\.text) { [weak self] _, _ in\n      self?.updateEditorState()\n    }\n  }\n  \n  /// Prepares the placeholderLabel.\n  func preparePlaceholderLabel() {\n    addSubview(placeholderLabel)\n    placeholderLabelTextObserver = placeholderLabel.observe(\\.text) { [weak self] _, _ in\n      self?.layoutPlaceholderLabel()\n    }\n  }\n  \n  /// Prepares the detailLabel.\n  func prepareDetailLabel() {\n    detailLabel.font = Theme.font.regular(with: 12)\n    detailLabel.numberOfLines = 0\n    detailColor = Color.darkText.others\n    addSubview(detailLabel)\n  }\n  \n  /// Prepares the Notification handlers.\n  func prepareNotificationHandlers() {\n    let center = NotificationCenter.default\n    center.addObserver(self, selector: #selector(handleTextViewTextDidBegin), name: UITextView.textDidBeginEditingNotification, object: textView)\n    center.addObserver(self, selector: #selector(handleTextViewTextDidChange), name: UITextView.textDidChangeNotification, object: textView)\n    center.addObserver(self, selector: #selector(handleTextViewTextDidEnd), name: UITextView.textDidEndEditingNotification, object: textView)\n  }\n}\n\nprivate extension Editor {\n  /// Updates the placeholderLabel text color.\n  func updatePlaceholderLabelColor() {\n    tintColor = placeholderActiveColor\n    placeholderLabel.textColor = isEditing ? placeholderActiveColor : placeholderNormalColor\n  }\n  \n  /// Updates the placeholder visibility.\n  func updatePlaceholderVisibility() {\n    guard isEditing else {\n      placeholderLabel.isHidden = !isEmpty && .hidden == placeholderAnimation\n      return\n    }\n    \n    placeholderLabel.isHidden = .hidden == placeholderAnimation\n  }\n  \n  /// Updates the dividerColor.\n  func updateDividerColor() {\n    dividerColor = isEditing ? dividerActiveColor : dividerNormalColor\n  }\n  \n  /// Updates the dividerThickness.\n  func updateDividerHeight() {\n    dividerThickness = isEditing ? dividerActiveHeight : dividerNormalHeight\n  }\n  \n  /// Updates the detailLabel text color.\n  func updateDetailLabelColor() {\n    detailLabel.textColor = detailColor\n  }\n}\n\nprivate extension Editor {\n  /// Layout the placeholderLabel.\n  func layoutPlaceholderLabel() {\n    let inset = textView.textContainerInsets\n    let leftPadding = inset.left + textView.textContainer.lineFragmentPadding\n    let rightPadding = inset.right + textView.textContainer.lineFragmentPadding\n    let w = bounds.width - leftPadding - rightPadding\n    var h = placeholderLabel.sizeThatFits(CGSize(width: w, height: .greatestFiniteMagnitude)).height\n    h = max(h, textView.minimumTextHeight)\n    h = min(h, bounds.height - inset.top - inset.bottom)\n    \n    placeholderLabel.bounds.size = CGSize(width: w, height: h)\n    \n    guard isEditing || !isEmpty || !isPlaceholderAnimated else {\n      placeholderLabel.transform = CGAffineTransform.identity\n      placeholderLabel.frame.origin = CGPoint(x: leftPadding, y: inset.top)\n      return\n    }\n    \n    placeholderLabel.transform = CGAffineTransform(scaleX: placeholderActiveScale, y: placeholderActiveScale)\n    placeholderLabel.frame.origin.y = -placeholderLabel.frame.height + placeholderVerticalOffset\n    \n    switch placeholderLabel.textAlignment {\n    case .left, .natural:\n      placeholderLabel.frame.origin.x = leftPadding + placeholderHorizontalOffset\n    case .right:\n      let scaledWidth = w * placeholderActiveScale\n      placeholderLabel.frame.origin.x = bounds.width - scaledWidth - rightPadding + placeholderHorizontalOffset\n    default:break\n    }\n  }\n  \n  /// Layout given label at the bottom with the vertical offset provided.\n  func layoutBottomLabel(label: UILabel, verticalOffset: CGFloat) {\n    let c = dividerContentEdgeInsets\n    label.frame.origin.x = c.left\n    label.frame.origin.y = bounds.height + verticalOffset\n    label.frame.size.width = bounds.width - c.left - c.right\n    label.frame.size.height = label.sizeThatFits(CGSize(width: label.bounds.width, height: .greatestFiniteMagnitude)).height\n  }\n}\n\nprivate extension Editor {\n  /// Notification handler for when text editing began.\n  @objc\n  func handleTextViewTextDidBegin() {\n    updateEditorState(isAnimated: true)\n  }\n  \n  /// Notification handler for when text changed.\n  @objc\n  func handleTextViewTextDidChange() {\n    updateEditorState()\n  }\n  \n  /// Notification handler for when text editing ended.\n  @objc\n  func handleTextViewTextDidEnd() {\n    updateEditorState(isAnimated: true)\n  }\n  \n  /// Updates editor.\n  func updateEditorState(isAnimated: Bool = false) {\n    updatePlaceholderVisibility()\n    updatePlaceholderLabelColor()\n    updateDividerHeight()\n    updateDividerColor()\n    \n    guard isAnimated && isPlaceholderAnimated else {\n      layoutPlaceholderLabel()\n      return\n    }\n    \n    UIView.animate(withDuration: 0.15, animations: layoutPlaceholderLabel)\n  }\n}\n\npublic extension Editor {\n  /// A reference to the textView text.\n  var text: String! {\n    get {\n      return textView.text\n    }\n    set(value) {\n      textView.text = value\n    }\n  }\n  \n  /// A reference to the textView font.\n  var font: UIFont? {\n    get {\n      return textView.font\n    }\n    set(value) {\n      textView.font = value\n    }\n  }\n  \n  /// A reference to the textView placeholder.\n  var placeholder: String? {\n    get {\n      return textView.placeholder\n    }\n    set(value) {\n      textView.placeholder = value\n    }\n  }\n  \n  /// A reference to the textView textAlignment.\n  var textAlignment: NSTextAlignment {\n    get {\n      return textView.textAlignment\n    }\n    set(value) {\n      textView.textAlignment = value\n      detailLabel.textAlignment = value\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Text/ErrorTextField.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class ErrorTextField: TextField {\n  \n  /// The errorLabel UILabel that is displayed.\n  @IBInspectable\n  public let errorLabel = UILabel()\n  \n  /// The errorLabel text value.\n  @IBInspectable\n  open var error: String? {\n    get {\n      return errorLabel.text\n    }\n    set(value) {\n      errorLabel.text = value\n      layoutSubviews()\n    }\n  }\n  \n  /// Error text color\n  @IBInspectable\n  open var errorColor = Color.red.base {\n    didSet {\n      errorLabel.textColor = errorColor\n    }\n  }\n  \n  /// Vertical distance for the errorLabel from the divider.\n  @IBInspectable\n  open var errorVerticalOffset: CGFloat = 8 {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// Hide or show error text.\n  open var isErrorRevealed: Bool {\n    get {\n      return !errorLabel.isHidden\n    }\n    set(value) {\n      errorLabel.isHidden = !value\n      detailLabel.isHidden = value\n      layoutSubviews()\n    }\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    isErrorRevealed = false\n    prepareErrorLabel()\n  }\n  \n  /// Prepares the errorLabel.\n  func prepareErrorLabel() {\n    errorLabel.font = Theme.font.regular(with: 12)\n    errorLabel.numberOfLines = 0\n    errorColor = { errorColor }() // call didSet\n    addSubview(errorLabel)\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    layoutBottomLabel(label: errorLabel, verticalOffset: errorVerticalOffset)\n  }\n  \n  open override func apply(theme: Theme) {\n    super.apply(theme: theme)\n    \n    errorColor = theme.error\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Text/ErrorTextFieldValidator.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\n/**\n Validator plugin for ErrorTextField and subclasses.\n Can be accessed via `textField.validator`\n ### Example\n ```swift\n field.validator\n .notEmpty(message: \"Choose username\")\n .min(length: 3, message: \"Minimum 3 characters\")\n .noWhitespaces(message: \"Username cannot contain spaces\")\n .username(message: \"Unallowed characters in username\")\n }\n ```\n */\nopen class ErrorTextFieldValidator {\n  /// A typealias for validation closure.\n  public typealias ValidationClosure = (_ text: String) -> Bool\n  \n  /// Validation closures and their error messages.\n  open var closures: [(code: ValidationClosure, message: String)] = []\n  \n  /// A reference to the textField.\n  open weak var textField: ErrorTextField?\n  \n  /// Behavior for auto-validation.\n  open var autoValidationType: AutoValidationType = .default\n  \n  /**\n   A flag indicating if error message is shown at least once.\n   Used for `AutoValidationType.default`.\n   */\n  open var isErrorShownOnce = false\n  \n  /**\n   Initializes validator.\n   - Parameter textField: An ErrorTextField to validate.\n   */\n  public init(textField: ErrorTextField) {\n    self.textField = textField\n    prepare()\n  }\n  \n  /**\n   Prepares the validator instance when intialized. When subclassing,\n   it is recommended to override the prepare method\n   to initialize property values and other setup operations.\n   The super.prepare method should always be called immediately\n   when subclassing.\n   */\n  open func prepare() {\n    textField?.addTarget(self, action: #selector(autoValidate), for: .editingChanged)\n  }\n  \n  /**\n   Validates textField based on `autoValidationType`.\n   This method is called when textField.text changes.\n   */\n  @objc\n  private func autoValidate() {\n    guard let textField = textField else { return }\n    \n    switch autoValidationType {\n    case .none: break\n    case .custom(let closure):\n      closure(textField)\n    case .default:\n      guard isErrorShownOnce else { return }\n      textField.isValid()\n    case .always:\n      textField.isValid()\n    }\n  }\n  \n  /**\n   Validates textField.text against criteria defined in `closures`\n   and shows relevant error message on failure.\n   - Parameter isDeferred: Defer showing error message.\n   - Returns: Boolean indicating if validation passed.\n   */\n  @discardableResult\n  open func isValid(isDeferred: Bool) -> Bool {\n    guard let textField = textField else { return false }\n    for block in closures {\n      if !block.code(textField.text ?? \"\") {\n        if !isDeferred {\n          textField.error = block.message\n          textField.isErrorRevealed = true\n          isErrorShownOnce = true\n        }\n        return false\n      }\n    }\n    if !isDeferred { textField.isErrorRevealed = false }\n    return true\n  }\n  \n  \n  /** Adds provided closure and its error message to the validation chain.\n   - Parameter message: A message to be shown when validation fails.\n   - Parameter code: Closure to run for validation.\n   - Returns: Validator itself to allow chaining.\n   */\n  @discardableResult\n  open func validate(message: String, when code: @escaping ValidationClosure) -> Self {\n    closures.append((code, message))\n    return self\n  }\n  \n  \n  /**\n   Types for determining behaviour of auto-validation\n   which is run when textField.text changes.\n   */\n  public enum AutoValidationType {\n    /// Turn off.\n    case none\n    \n    /// Run validation only if error is shown once.\n    case `default`\n    \n    /// Always run validation.\n    case always\n    \n    /**\n     Custom auto-validation logic passed as closure\n     which accepts ErrorTextField. Closure is called\n     when `textField.text` changes.\n     */\n    case custom((ErrorTextField) -> Void)\n  }\n}\n\n/// Memory key pointer for `validator`.\nprivate var AssociatedInstanceKey: UInt8 = 0\nextension ErrorTextField {\n  /// A reference to validator.\n  open var validator: ErrorTextFieldValidator {\n    get {\n      return AssociatedObject.get(base: self, key: &AssociatedInstanceKey) {\n        return ErrorTextFieldValidator(textField: self)\n      }\n    }\n    set(value) {\n      AssociatedObject.set(base: self, key: &AssociatedInstanceKey, value: value)\n    }\n  }\n  \n  /**\n   Validates textField.text against criteria defined in `closures`\n   and shows relevant error message on failure.\n   - Parameter isDeferred: Defer showing error message. Default is false.\n   - Returns: Boolean indicating if validation passed.\n   */\n  @discardableResult\n  open func isValid(isDeferred: Bool = false) -> Bool {\n    return validator.isValid(isDeferred: isDeferred)\n  }\n}\n\npublic extension ErrorTextFieldValidator {\n  /**\n   Validate that field contains correct email address.\n   - Parameter message: A message to show for incorrect emails.\n   - Returns: Validator itself to allow chaining.\n   */\n  @discardableResult\n  func email(message: String) -> Self {\n    return regex(message: message, pattern: \"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\\\.[A-Za-z]{2,64}\")\n  }\n  \n  /**\n   Validate that field contains allowed usernames characters.\n   - Parameter message: A message to show for disallowed usernames.\n   - Returns: Validator itself to allow chaining.\n   */\n  @discardableResult\n  func username(message: String) -> Self {\n    return regex(message: message, pattern: \"^[a-zA-Z0-9]+([_\\\\s\\\\-\\\\.\\\\']?[a-zA-Z0-9])*$\")\n  }\n  \n  /**\n   Validate that field text matches provided regex pattern.\n   - Parameter message: A message to show for unmatched texts.\n   - Parameter pattern: A regex pattern to match.\n   - Returns: Validator itself to allow chaining.\n   */\n  @discardableResult\n  func regex(message: String, pattern: String) -> Self {\n    return validate(message: message) {\n      let pred = NSPredicate(format: \"SELF MATCHES %@\", pattern)\n      return pred.evaluate(with: $0)\n    }\n  }\n  \n  /**\n   Validate that field text has minimum `length`.\n   - Parameter length: Minimum allowed text length.\n   - Parameter message: A message to show when requirement is not met.\n   - Parameter trimmingSet: A trimming CharacterSet for trimming text before validation.\n   - Returns: Validator itself to allow chaining.\n   */\n  @discardableResult\n  func min(length: Int, message: String, trimmingSet: CharacterSet? = .whitespacesAndNewlines) -> Self {\n    let trimmingSet = trimmingSet ?? .init()\n    return validate(message: message) {\n      $0.trimmingCharacters(in: trimmingSet).count >= length\n    }\n  }\n  \n  /**\n   Validate that field text has maximum `length`.\n   - Parameter length: Minimum allowed text length.\n   - Parameter message: A message to show when requirement is not met.\n   - Parameter trimmingSet: A trimming CharacterSet for trimming text before validation.\n   - Returns: Validator itself to allow chaining.\n   */\n  @discardableResult\n  func max(length: Int, message: String, trimmingSet: CharacterSet? = .whitespacesAndNewlines) -> Self {\n    let trimmingSet = trimmingSet ?? .init()\n    return validate(message: message) {\n      $0.trimmingCharacters(in: trimmingSet).count <= length\n    }\n  }\n  \n  /**\n   Validate that field text is not empty.\n   - Parameter message: A message to show when requirement is not met.\n   - Parameter trimmingSet: A trimming CharacterSet for trimming text before validation.\n   - Returns: Validator itself to allow chaining.\n   */\n  @discardableResult\n  func notEmpty(message: String, trimmingSet: CharacterSet? = .whitespacesAndNewlines) -> Self {\n    let trimmingSet = trimmingSet ?? .init()\n    return validate(message: message) {\n      $0.trimmingCharacters(in: trimmingSet).isEmpty == false\n    }\n  }\n  \n  \n  /**\n   Validate that field text contains no whitespaces.\n   - Parameter message: A message to show when requirement is not met.\n   - Parameter trimmingSet: A trimming CharacterSet for trimming text before validation.\n   - Returns: Validator itself to allow chaining.\n   */\n  @discardableResult\n  func noWhitespaces(message: String) -> Self {\n    return validate(message: message) {\n      $0.rangeOfCharacter(from: .whitespaces) == nil\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Text/TextField.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(TextFieldPlaceholderAnimation)\npublic enum TextFieldPlaceholderAnimation: Int {\n  case `default`\n  case hidden\n}\n\n@objc(TextFieldDelegate)\npublic protocol TextFieldDelegate: UITextFieldDelegate {\n  /**\n   A delegation method that is executed when the textField changed.\n   - Parameter textField: A TextField.\n   - Parameter didChange text: An optional String.\n   */\n  @objc\n  optional func textField(textField: TextField, didChange text: String?)\n  \n  /**\n   A delegation method that is executed when the textField will clear.\n   - Parameter textField: A TextField.\n   - Parameter willClear text: An optional String.\n   */\n  @objc\n  optional func textField(textField: TextField, willClear text: String?)\n  \n  /**\n   A delegation method that is executed when the textField is cleared.\n   - Parameter textField: A TextField.\n   - Parameter didClear text: An optional String.\n   */\n  @objc\n  optional func textField(textField: TextField, didClear text: String?)\n}\n\nopen class TextField: UITextField, Themeable {\n  \n  /// Minimum TextField text height.\n  private let minimumTextHeight: CGFloat = 32\n  \n  /// Default size when using AutoLayout.\n  open override var intrinsicContentSize: CGSize {\n    let h = textInsets.top + textInsets.bottom + minimumTextHeight\n    return CGSize(width: bounds.width, height: max(h, super.intrinsicContentSize.height))\n  }\n  \n  /// A Boolean that indicates if the placeholder label is animated.\n  @IBInspectable\n  open var isPlaceholderAnimated = true\n  \n  /// Set the placeholder animation value.\n  open var placeholderAnimation = TextFieldPlaceholderAnimation.default {\n    didSet {\n      updatePlaceholderVisibility()\n    }\n  }\n  \n  /// A boolean indicating whether the text is empty.\n  open var isEmpty: Bool {\n    return 0 == text?.utf16.count\n  }\n  \n  open override var text: String? {\n    didSet {\n      updatePlaceholderVisibility()\n    }\n  }\n  \n  open override var leftView: UIView? {\n    didSet {\n      prepareLeftView()\n      layoutSubviews()\n    }\n  }\n  \n  /// The leftView width value.\n  open var leftViewWidth: CGFloat {\n    guard nil != leftView else {\n      return 0\n    }\n    \n    return leftViewOffset + bounds.height\n  }\n  \n  /// The leftView offset value.\n  open var leftViewOffset: CGFloat = 16\n  \n  /// Placeholder normal text\n  @IBInspectable\n  open var leftViewNormalColor = Color.darkText.others {\n    didSet {\n      updateLeftViewColor()\n    }\n  }\n  \n  /// Placeholder active text\n  @IBInspectable\n  open var leftViewActiveColor = Color.blue.base {\n    didSet {\n      updateLeftViewColor()\n    }\n  }\n  \n  /// Divider normal height.\n  @IBInspectable\n  open var dividerNormalHeight: CGFloat = 1 {\n    didSet {\n      updateDividerHeight()\n    }\n  }\n  \n  /// Divider active height.\n  @IBInspectable\n  open var dividerActiveHeight: CGFloat = 2 {\n    didSet {\n      updateDividerHeight()\n    }\n  }\n  \n  /// Divider normal color.\n  @IBInspectable\n  open var dividerNormalColor = Color.grey.lighten2 {\n    didSet {\n      updateDividerColor()\n    }\n  }\n  \n  /// Divider active color.\n  @IBInspectable\n  open var dividerActiveColor = Color.blue.base {\n    didSet {\n      updateDividerColor()\n    }\n  }\n  \n  /// The placeholderLabel font value.\n  @IBInspectable\n  open override var font: UIFont? {\n    didSet {\n      placeholderLabel.font = font\n    }\n  }\n  \n  /// The placeholderLabel text value.\n  @IBInspectable\n  open override var placeholder: String? {\n    get {\n      return placeholderLabel.text\n    }\n    set(value) {\n      if isEditing && isPlaceholderUppercasedWhenEditing {\n        placeholderLabel.text = value?.uppercased()\n      } else {\n        placeholderLabel.text = value\n      }\n      layoutSubviews()\n    }\n  }\n  \n  open override var isSecureTextEntry: Bool {\n    didSet {\n      updateVisibilityIcon()\n      fixCursorPosition()\n    }\n  }\n  \n  /// The placeholder UILabel.\n  @IBInspectable\n  public let placeholderLabel = UILabel()\n  \n  /// Placeholder normal text\n  @IBInspectable\n  open var placeholderNormalColor = Color.darkText.others {\n    didSet {\n      updatePlaceholderLabelColor()\n    }\n  }\n  \n  /// Placeholder active text\n  @IBInspectable\n  open var placeholderActiveColor = Color.blue.base {\n    didSet {\n      /// Keep tintColor update here. See #1229\n      tintColor = placeholderActiveColor\n      updatePlaceholderLabelColor()\n    }\n  }\n  \n  /// This property adds a padding to placeholder y position animation\n  @IBInspectable\n  open var placeholderVerticalOffset: CGFloat = 0\n  \n  /// This property adds a padding to placeholder y position animation\n  @IBInspectable\n  open var placeholderHorizontalOffset: CGFloat = 0\n  \n  /// The scale of the active placeholder in relation to the inactive\n  @IBInspectable\n  open var placeholderActiveScale: CGFloat = 0.75 {\n    didSet {\n      layoutPlaceholderLabel()\n    }\n  }\n  \n  /// The detailLabel UILabel that is displayed.\n  @IBInspectable\n  public let detailLabel = UILabel()\n  \n  /// The detailLabel text value.\n  @IBInspectable\n  open var detail: String? {\n    get {\n      return detailLabel.text\n    }\n    set(value) {\n      detailLabel.text = value\n      layoutSubviews()\n    }\n  }\n  \n  /// Detail text\n  @IBInspectable\n  open var detailColor = Color.darkText.others {\n    didSet {\n      updateDetailLabelColor()\n    }\n  }\n  \n  /// Vertical distance for the detailLabel from the divider.\n  @IBInspectable\n  open var detailVerticalOffset: CGFloat = 8 {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  /// Handles the textAlignment of the placeholderLabel.\n  open override var textAlignment: NSTextAlignment {\n    didSet {\n      placeholderLabel.textAlignment = textAlignment\n      detailLabel.textAlignment = textAlignment\n    }\n  }\n  \n  /// A reference to the clearIconButton.\n  open fileprivate(set) var clearIconButton: IconButton?\n  \n  /// Enables the clearIconButton.\n  @IBInspectable\n  open var isClearIconButtonEnabled: Bool {\n    get {\n      return nil != clearIconButton\n    }\n    set(value) {\n      guard value else {\n        clearIconButton?.removeTarget(self, action: #selector(handleClearIconButton), for: .touchUpInside)\n        removeFromRightView(view: clearIconButton)\n        clearIconButton = nil\n        return\n      }\n      \n      guard nil == clearIconButton else {\n        return\n      }\n      \n      clearIconButton = IconButton(image: Icon.cm.clear, tintColor: placeholderNormalColor)\n      clearIconButton!.contentEdgeInsetsPreset = .none\n      clearIconButton!.pulseAnimation = .none\n      \n      rightView?.grid.views.insert(clearIconButton!, at: 0)\n      isClearIconButtonAutoHandled = { isClearIconButtonAutoHandled }()\n      \n      layoutSubviews()\n    }\n  }\n  \n  /// Enables the automatic handling of the clearIconButton.\n  @IBInspectable\n  open var isClearIconButtonAutoHandled = true {\n    didSet {\n      clearIconButton?.removeTarget(self, action: #selector(handleClearIconButton), for: .touchUpInside)\n      \n      guard isClearIconButtonAutoHandled else {\n        return\n      }\n      \n      clearIconButton?.addTarget(self, action: #selector(handleClearIconButton), for: .touchUpInside)\n    }\n  }\n  \n  /// A reference to the visibilityIconButton.\n  open fileprivate(set) var visibilityIconButton: IconButton?\n  \n  /// Icon for visibilityIconButton when in the on state.\n  open var visibilityIconOn = Icon.visibility {\n    didSet {\n      updateVisibilityIcon()\n    }\n  }\n  \n  /// Icon for visibilityIconButton when in the off state.\n  open var visibilityIconOff = Icon.visibilityOff {\n    didSet {\n      updateVisibilityIcon()\n    }\n  }\n  \n  /// Enables the visibilityIconButton.\n  @IBInspectable\n  open var isVisibilityIconButtonEnabled: Bool {\n    get {\n      return nil != visibilityIconButton\n    }\n    set(value) {\n      guard value else {\n        visibilityIconButton?.removeTarget(self, action: #selector(handleVisibilityIconButton), for: .touchUpInside)\n        removeFromRightView(view: visibilityIconButton)\n        visibilityIconButton = nil\n        return\n      }\n      \n      guard nil == visibilityIconButton else {\n        return\n      }\n      \n      isSecureTextEntry = true\n      visibilityIconButton = IconButton(image: nil, tintColor: placeholderNormalColor.withAlphaComponent(0.54))\n      updateVisibilityIcon()\n      visibilityIconButton!.contentEdgeInsetsPreset = .none\n      visibilityIconButton!.pulseAnimation = .centerRadialBeyondBounds\n      \n      rightView?.grid.views.append(visibilityIconButton!)\n      isVisibilityIconButtonAutoHandled = { isVisibilityIconButtonAutoHandled }()\n      \n      layoutSubviews()\n    }\n  }\n  \n  /// Enables the automatic handling of the visibilityIconButton.\n  @IBInspectable\n  open var isVisibilityIconButtonAutoHandled = true {\n    didSet {\n      visibilityIconButton?.removeTarget(self, action: #selector(handleVisibilityIconButton), for: .touchUpInside)\n      guard isVisibilityIconButtonAutoHandled else {\n        return\n      }\n      \n      visibilityIconButton?.addTarget(self, action: #selector(handleVisibilityIconButton), for: .touchUpInside)\n    }\n  }\n  \n  @IBInspectable\n  open var isPlaceholderUppercasedWhenEditing = false {\n    didSet {\n      updatePlaceholderTextToActiveState()\n    }\n  }\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n    prepare()\n  }\n  \n  /**\n   An initializer that initializes the object with a CGRect object.\n   If AutoLayout is used, it is better to initilize the instance\n   using the init() initializer.\n   - Parameter frame: A CGRect instance.\n   */\n  public override init(frame: CGRect) {\n    super.init(frame: frame)\n    prepare()\n\n    /// Fire didSet here to update tintColor\n    placeholderActiveColor = { placeholderActiveColor }()\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    layoutShape()\n    layoutPlaceholderLabel()\n    layoutBottomLabel(label: detailLabel, verticalOffset: detailVerticalOffset)\n    layoutDivider()\n    layoutLeftView()\n    layoutRightView()\n  }\n  \n  open override func becomeFirstResponder() -> Bool {\n    layoutSubviews()\n    return super.becomeFirstResponder()\n  }\n  \n  /// EdgeInsets for text.\n  @objc\n  open var textInsets: EdgeInsets = .zero\n  \n  /// EdgeInsets preset property for text.\n  open var textInsetsPreset = EdgeInsetsPreset.none {\n    didSet {\n      textInsets = EdgeInsetsPresetToValue(preset: textInsetsPreset)\n    }\n  }\n  \n  open override func textRect(forBounds bounds: CGRect) -> CGRect {\n    return super.textRect(forBounds: bounds).inset(by: textInsets)\n  }\n  \n  open override func editingRect(forBounds bounds: CGRect) -> CGRect {\n    return textRect(forBounds: bounds)\n  }\n  \n  /**\n   Prepares the view instance when intialized. When subclassing,\n   it is recommended to override the prepare method\n   to initialize property values and other setup operations.\n   The super.prepare method should always be called immediately\n   when subclassing.\n   */\n  open func prepare() {\n    clipsToBounds = false\n    borderStyle = .none\n    backgroundColor = nil\n    contentScaleFactor = Screen.scale\n    font = Theme.font.regular(with: 16)\n    textColor = Color.darkText.primary\n    \n    prepareDivider()\n    preparePlaceholderLabel()\n    prepareDetailLabel()\n    prepareTargetHandlers()\n    prepareTextAlignment()\n    prepareRightView()\n    applyCurrentTheme()\n  }\n  \n  /**\n   Applies the given theme.\n   - Parameter theme: A Theme.\n   */\n  open func apply(theme: Theme) {\n    placeholderActiveColor = theme.secondary\n    placeholderNormalColor = theme.onSurface.withAlphaComponent(0.38)\n    \n    leftViewActiveColor = theme.secondary\n    leftViewNormalColor = theme.onSurface.withAlphaComponent(0.38)\n    \n    dividerActiveColor = theme.secondary\n    dividerNormalColor = theme.onSurface.withAlphaComponent(0.12)\n    \n    detailColor = theme.onSurface.withAlphaComponent(0.38)\n    textColor = theme.onSurface.withAlphaComponent(0.87)\n  }\n}\n\nfileprivate extension TextField {\n  /// Prepares the divider.\n  func prepareDivider() {\n    dividerColor = dividerNormalColor\n  }\n  \n  /// Prepares the placeholderLabel.\n  func preparePlaceholderLabel() {\n    placeholderNormalColor = Color.darkText.others\n    placeholderLabel.backgroundColor = .clear\n    addSubview(placeholderLabel)\n  }\n  \n  /// Prepares the detailLabel.\n  func prepareDetailLabel() {\n    detailLabel.font = Theme.font.regular(with: 12)\n    detailLabel.numberOfLines = 0\n    detailColor = Color.darkText.others\n    addSubview(detailLabel)\n  }\n  \n  /// Prepares the leftView.\n  func prepareLeftView() {\n    leftView?.contentMode = .left\n    leftViewMode = .always\n    updateLeftViewColor()\n  }\n  \n  /// Prepares the target handlers.\n  func prepareTargetHandlers() {\n    addTarget(self, action: #selector(handleEditingDidBegin), for: .editingDidBegin)\n    addTarget(self, action: #selector(handleEditingChanged), for: .editingChanged)\n    addTarget(self, action: #selector(handleEditingDidEnd), for: .editingDidEnd)\n  }\n  \n  /// Prepares the textAlignment.\n  func prepareTextAlignment() {\n    textAlignment = .rightToLeft == Application.userInterfaceLayoutDirection ? .right : .left\n  }\n  \n  /// Prepares the rightView.\n  func prepareRightView() {\n    rightView = UIView()\n    rightView?.grid.columns = 2\n    rightViewMode = .whileEditing\n    clearButtonMode = .never\n  }\n}\n\nfileprivate extension TextField {\n  /// Updates the leftView tint color.\n  func updateLeftViewColor() {\n    leftView?.tintColor = isEditing ? leftViewActiveColor : leftViewNormalColor\n  }\n  \n  /// Updates the placeholderLabel text color.\n  func updatePlaceholderLabelColor() {\n    placeholderLabel.textColor = isEditing ? placeholderActiveColor : placeholderNormalColor\n  }\n  \n  /// Updates the placeholder visibility.\n  func updatePlaceholderVisibility() {\n    guard isEditing else {\n      placeholderLabel.isHidden = !isEmpty && .hidden == placeholderAnimation\n      return\n    }\n    \n    placeholderLabel.isHidden = .hidden == placeholderAnimation\n  }\n  \n  /// Updates the dividerColor.\n  func updateDividerColor() {\n    dividerColor = isEditing ? dividerActiveColor : dividerNormalColor\n  }\n  \n  /// Updates the dividerThickness.\n  func updateDividerHeight() {\n    dividerThickness = isEditing ? dividerActiveHeight : dividerNormalHeight\n  }\n  \n  /// Update the placeholder text to the active state.\n  func updatePlaceholderTextToActiveState() {\n    guard isPlaceholderUppercasedWhenEditing else {\n      return\n    }\n    \n    guard isEditing || !isEmpty else {\n      return\n    }\n    \n    placeholderLabel.text = placeholderLabel.text?.uppercased()\n  }\n  \n  /// Update the placeholder text to the normal state.\n  func updatePlaceholderTextToNormalState() {\n    guard isPlaceholderUppercasedWhenEditing else {\n      return\n    }\n    \n    guard isEmpty else {\n      return\n    }\n    \n    placeholderLabel.text = placeholderLabel.text?.capitalized\n  }\n  \n  /// Updates the detailLabel text color.\n  func updateDetailLabelColor() {\n    detailLabel.textColor = detailColor\n  }\n}\n\nfileprivate extension TextField {\n  /// Layout the placeholderLabel.\n  func layoutPlaceholderLabel() {\n    let leftPadding = leftViewWidth + textInsets.left\n    let w = bounds.width - leftPadding - textInsets.right\n    var h = placeholderLabel.sizeThatFits(CGSize(width: w, height: .greatestFiniteMagnitude)).height\n    h = min(h, bounds.height - textInsets.top - textInsets.bottom)\n    h = max(h, minimumTextHeight)\n    \n    placeholderLabel.bounds.size = CGSize(width: w, height: h)\n    \n    guard isEditing || !isEmpty || !isPlaceholderAnimated else {\n      placeholderLabel.transform = CGAffineTransform.identity\n      placeholderLabel.frame.origin = CGPoint(x: leftPadding, y: textInsets.top)\n      return\n    }\n    \n    placeholderLabel.transform = CGAffineTransform(scaleX: placeholderActiveScale, y: placeholderActiveScale)\n    placeholderLabel.frame.origin.y = -placeholderLabel.frame.height + placeholderVerticalOffset\n    \n    switch placeholderLabel.textAlignment {\n    case .left, .natural:\n      placeholderLabel.frame.origin.x = leftPadding + placeholderHorizontalOffset\n    case .right:\n      let scaledWidth = w * placeholderActiveScale\n      placeholderLabel.frame.origin.x = bounds.width - scaledWidth - textInsets.right + placeholderHorizontalOffset\n    default:break\n    }\n  }\n  \n  /// Layout the leftView.\n  func layoutLeftView() {\n    guard let v = leftView else {\n      return\n    }\n    \n    let w = leftViewWidth\n    v.frame = CGRect(x: 0, y: 0, width: w, height: bounds.height)\n    dividerContentEdgeInsets.left = w\n  }\n  /// Layout the rightView.\n  func layoutRightView() {\n    guard let v = rightView else {\n      return\n    }\n    \n    let w = CGFloat(v.grid.views.count) * bounds.height\n    v.frame = CGRect(x: bounds.width - w, y: 0, width: w, height: bounds.height)\n    v.grid.reload()\n  }\n}\n\ninternal extension TextField {\n  /// Layout given label at the bottom with the vertical offset provided.\n  func layoutBottomLabel(label: UILabel, verticalOffset: CGFloat) {\n    let c = dividerContentEdgeInsets\n    label.frame.origin.x = c.left\n    label.frame.origin.y = bounds.height + verticalOffset\n    label.frame.size.width = bounds.width - c.left - c.right\n    label.frame.size.height = label.sizeThatFits(CGSize(width: label.bounds.width, height: .greatestFiniteMagnitude)).height\n  }\n}\n\nfileprivate extension TextField {\n  /// Handles the text editing did begin state.\n  @objc\n  func handleEditingDidBegin() {\n    leftViewEditingBeginAnimation()\n    placeholderEditingDidBeginAnimation()\n    dividerEditingDidBeginAnimation()\n  }\n  \n  // Live updates the textField text.\n  @objc\n  func handleEditingChanged(textField: UITextField) {\n    (delegate as? TextFieldDelegate)?.textField?(textField: self, didChange: textField.text)\n  }\n  \n  /// Handles the text editing did end state.\n  @objc\n  func handleEditingDidEnd() {\n    leftViewEditingEndAnimation()\n    placeholderEditingDidEndAnimation()\n    dividerEditingDidEndAnimation()\n  }\n  \n  /// Handles the clearIconButton TouchUpInside event.\n  @objc\n  func handleClearIconButton() {\n    guard nil == delegate?.textFieldShouldClear || true == delegate?.textFieldShouldClear?(self) else {\n      return\n    }\n    \n    let t = text\n    \n    (delegate as? TextFieldDelegate)?.textField?(textField: self, willClear: t)\n    \n    text = nil\n    \n    (delegate as? TextFieldDelegate)?.textField?(textField: self, didClear: t)\n  }\n  \n  /// Handles the visibilityIconButton TouchUpInside event.\n  @objc\n  func handleVisibilityIconButton() {\n    UIView.transition(\n      with: (visibilityIconButton?.imageView)!,\n      duration: 0.3,\n      options: .transitionCrossDissolve,\n      animations: { [weak self] in\n        guard let `self` = self else {\n          return\n        }\n        \n        self.isSecureTextEntry = !self.isSecureTextEntry\n    })\n  }\n}\n\nprivate extension TextField {\n  /// The animation for leftView when editing begins.\n  func leftViewEditingBeginAnimation() {\n    updateLeftViewColor()\n  }\n  \n  /// The animation for leftView when editing ends.\n  func leftViewEditingEndAnimation() {\n    updateLeftViewColor()\n  }\n  \n  /// The animation for the divider when editing begins.\n  func dividerEditingDidBeginAnimation() {\n    updateDividerHeight()\n    updateDividerColor()\n  }\n  \n  /// The animation for the divider when editing ends.\n  func dividerEditingDidEndAnimation() {\n    updateDividerHeight()\n    updateDividerColor()\n  }\n  \n  /// The animation for the placeholder when editing begins.\n  func placeholderEditingDidBeginAnimation() {\n    updatePlaceholderVisibility()\n    updatePlaceholderLabelColor()\n    \n    guard isPlaceholderAnimated else {\n      return\n    }\n    \n    updatePlaceholderTextToActiveState()\n    UIView.animate(withDuration: 0.15, animations: layoutPlaceholderLabel)\n  }\n  \n  /// The animation for the placeholder when editing ends.\n  func placeholderEditingDidEndAnimation() {\n    updatePlaceholderVisibility()\n    updatePlaceholderLabelColor()\n    \n    guard isPlaceholderAnimated else {\n      return\n    }\n    \n    updatePlaceholderTextToNormalState()\n    UIView.animate(withDuration: 0.15, animations: layoutPlaceholderLabel)\n  }\n}\n\nprivate extension TextField {\n  /// Updates visibilityIconButton image based on isSecureTextEntry value.\n  func updateVisibilityIcon() {\n    visibilityIconButton?.image = isSecureTextEntry ? visibilityIconOff : visibilityIconOn\n  }\n  \n  /// Remove view from rightView.\n  func removeFromRightView(view: UIView?) {\n    guard let v = view, let i = rightView?.grid.views.firstIndex(of: v) else {\n      return\n    }\n    \n    rightView?.grid.views.remove(at: i)\n  }\n  \n  /**\n   Reassign text to reset cursor position.\n   Fixes issue-1119. Previously issue-1030, and issue-1023.\n   */\n  func fixCursorPosition() {\n    let t = text\n    text = nil\n    text = t\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Text/TextStorage.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(TextStorageDelegate)\npublic protocol TextStorageDelegate: NSTextStorageDelegate {\n  /**\n   A delegation method that is executed when text will be \n   processed during editing.\n   - Parameter textStorage: A TextStorage.\n   - Parameter willProcessEditing text: A String.\n   - Parameter range: A NSRange.\n   */\n  @objc\n  optional func textStorage(textStorage: TextStorage, willProcessEditing text: String, range: NSRange)\n  \n  /**\n   A delegation method that is executed when text has been\n   processed after editing.\n   - Parameter textStorage: A TextStorage.\n   - Parameter didProcessEditing text: A String.\n   - Parameter result: An optional NSTextCheckingResult.\n   - Parameter flags: NSRegularExpression.MatchingFlags.\n   - Parameter top: An UnsafeMutablePointer<ObjCBool>.\n   */\n  @objc\n  optional func textStorage(textStorage: TextStorage, didProcessEditing text: String, result: NSTextCheckingResult?, flags: NSRegularExpression.MatchingFlags, stop: UnsafeMutablePointer<ObjCBool>)\n}\n\nopen class TextStorage: NSTextStorage {\n  /// A storage facility for attributed text.\n  public let storage = NSMutableAttributedString()\n  \n  /// The regular expression to match text fragments against.\n  open var expression: NSRegularExpression?\n  \n  /// Initializer.\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n  }\n  \n  /// Initializer.\n  public override init() {\n    super.init()\n  }\n}\n\nextension TextStorage {\n  /// A String value of the attirbutedString property.\n  open override var string: String {\n    return storage.string\n  }\n  \n  /// Processes the text when editing.\n  open override func processEditing() {\n    let range = (string as NSString).paragraphRange(for: editedRange)\n    \n    (delegate as? TextStorageDelegate)?.textStorage?(textStorage: self, willProcessEditing: string, range: range)\n    \n    expression?.enumerateMatches(in: string, options: [], range: range) { [unowned self] (result: NSTextCheckingResult?, flags: NSRegularExpression.MatchingFlags, stop: UnsafeMutablePointer<ObjCBool>) -> Void in\n      (self.delegate as? TextStorageDelegate)?.textStorage?(textStorage: self, didProcessEditing: self.string, result: result, flags: flags, stop: stop)\n    }\n    \n    storage.fixAttributes(in: range)\n    \n    super.processEditing()\n  }\n  \n  /**\n   Returns the attributes for the character at a given index.\n   - Parameter location: An Int\n   - Parameter effectiveRange range: Upon return, the range over which the\n   attributes and values are the same as those at index. This range\n   isn’t necessarily the maximum range covered, and its extent is\n   implementation-dependent. If you need the maximum range, use\n   attributesAtIndex:longestEffectiveRange:inRange:.\n   If you don't need this value, pass NULL.\n   - Returns: The attributes for the character at index.\n   */\n  open override func attributes(at location: Int, effectiveRange range: NSRangePointer?) -> [NSAttributedString.Key: Any] {\n    return storage.attributes(at: location, effectiveRange: range)\n  }\n  \n  /**\n   Replaces a range of text with a string value.\n   - Parameter range: The character range to replace.\n   - Parameter str: The string value that the characters\n   will be replaced with.\n   */\n  open override func replaceCharacters(in range: NSRange, with str: String) {\n    storage.replaceCharacters(in: range, with: str)\n    edited(.editedCharacters, range: range, changeInLength: str.utf16.count - range.length)\n  }\n  \n  /**\n   Sets the attributedString attribute values.\n   - Parameter attrs: The attributes to set.\n   - Parameter range: A range of characters that will have their\n   attributes updated.\n   */\n  open override func setAttributes(_ attrs: [NSAttributedString.Key : Any]?, range: NSRange) {\n    storage.setAttributes(attrs, range: range)\n    edited(.editedAttributes, range: range, changeInLength: 0)\n  }\n  \n  /**\n   Adds an individual attribute.\n   - Parameter _ name: Attribute name.\n   - Parameter value: An Any type.\n   - Parameter range: A range of characters that will have their\n   attributes added.\n   */\n  open override func addAttribute(_ name: NSAttributedString.Key, value: Any, range: NSRange) {\n    storage.addAttribute(name, value: value, range: range)\n    edited(.editedAttributes, range: range, changeInLength: 0)\n  }\n  \n  /**\n   Removes an individual attribute.\n   - Parameter _ name: Attribute name.\n   - Parameter range: A range of characters that will have their\n   attributes removed.\n   */\n  open override func removeAttribute(_ name: NSAttributedString.Key, range: NSRange) {\n    storage.removeAttribute(name, range: range)\n    edited(.editedAttributes, range: range, changeInLength: 0)\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Text/TextView.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(TextViewDelegate)\npublic protocol TextViewDelegate : UITextViewDelegate {\n  /**\n   A delegation method that is executed when the keyboard will open.\n   - Parameter textView: A TextView.\n   - Parameter willShowKeyboard value: A NSValue.\n   */\n  @objc\n  optional func textView(textView: TextView, willShowKeyboard value: NSValue)\n  \n  /**\n   A delegation method that is executed when the keyboard will close.\n   - Parameter textView: A TextView.\n   - Parameter willHideKeyboard value: A NSValue.\n   */\n  @objc\n  optional func textView(textView: TextView, willHideKeyboard value: NSValue)\n  \n  /**\n   A delegation method that is executed when the keyboard did open.\n   - Parameter textView: A TextView.\n   - Parameter didShowKeyboard value: A NSValue.\n   */\n  @objc\n  optional func textView(textView: TextView, didShowKeyboard value: NSValue)\n  \n  /**\n   A delegation method that is executed when the keyboard did close.\n   - Parameter textView: A TextView.\n   - Parameter didHideKeyboard value: A NSValue.\n   */\n  @objc\n  optional func textView(textView: TextView, didHideKeyboard value: NSValue)\n  \n  /**\n   A delegation method that is executed when text will be\n   processed during editing.\n   - Parameter textView: A TextView.\n   - Parameter willProcessEditing textStorage: A TextStorage.\n   - Parameter text: A String.\n   - Parameter range: A NSRange.\n   */\n  @objc\n  optional func textView(textView: TextView, willProcessEditing textStorage: TextStorage, text: String, range: NSRange)\n  \n  /**\n   A delegation method that is executed when text has been\n   processed after editing.\n   - Parameter textView: A TextView.\n   - Parameter didProcessEditing textStorage: A TextStorage.\n   - Parameter text: A String.\n   - Parameter range: A NSRange.\n   */\n  @objc\n  optional func textView(textView: TextView, didProcessEditing textStorage: TextStorage, text: String, range: NSRange)\n}\n\nopen class TextView: UITextView, Themeable {\n  /// A boolean indicating whether the text is empty.\n  open var isEmpty: Bool {\n    return 0 == text?.utf16.count\n  }\n  \n  /// A boolean indicating whether the text is in edit mode.\n  open fileprivate(set) var isEditing = false\n  \n  /// Is the keyboard hidden.\n  open fileprivate(set) var isKeyboardHidden = true\n  \n  /// A property that accesses the backing layer's background\n  @IBInspectable\n  open override var backgroundColor: UIColor? {\n    didSet {\n      layer.backgroundColor = backgroundColor?.cgColor\n    }\n  }\n  \n  /// Holds default font.\n  private var _font: UIFont?\n  \n  /// The placeholderLabel font value.\n  @IBInspectable\n  open override var font: UIFont? {\n    didSet {\n      _font = font\n      placeholderLabel.font = font\n    }\n  }\n  \n  /// The placeholderLabel text value.\n  @IBInspectable\n  open var placeholder: String? {\n    get {\n      return placeholderLabel.text\n    }\n    set(value) {\n      placeholderLabel.text = value\n    }\n  }\n  \n  /// The placeholder UILabel.\n  @IBInspectable\n  public let placeholderLabel = UILabel()\n  \n  /// A property to enable/disable operations on the placeholderLabel\n  internal var isPlaceholderLabelEnabled = true\n  \n  /// Placeholder normal text\n  @IBInspectable\n  open var placeholderColor = Color.darkText.others {\n    didSet {\n      updatePlaceholderLabelColor()\n    }\n  }\n  \n  /// NSTextContainer EdgeInsets preset property.\n  open var textContainerInsetsPreset = EdgeInsetsPreset.none {\n    didSet {\n      textContainerInsets = EdgeInsetsPresetToValue(preset: textContainerInsetsPreset)\n    }\n  }\n  \n  /// NSTextContainer EdgeInsets property.\n  open var textContainerInsets: EdgeInsets {\n    get {\n      return textContainerInset\n    }\n    set(value) {\n      textContainerInset = value\n    }\n  }\n  \n  /// Handles the textAlignment of the placeholderLabel and textView itself.\n  open override var textAlignment: NSTextAlignment {\n    didSet {\n      placeholderLabel.textAlignment = textAlignment\n    }\n  }\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n    prepare()\n  }\n  \n  /// The string pattern to match within the textStorage.\n  open var pattern = \"(^|\\\\s)#[\\\\d\\\\w_\\u{203C}\\u{2049}\\u{20E3}\\u{2122}\\u{2139}\\u{2194}-\\u{2199}\\u{21A9}-\\u{21AA}\\u{231A}-\\u{231B}\\u{23E9}-\\u{23EC}\\u{23F0}\\u{23F3}\\u{24C2}\\u{25AA}-\\u{25AB}\\u{25B6}\\u{25C0}\\u{25FB}-\\u{25FE}\\u{2600}-\\u{2601}\\u{260E}\\u{2611}\\u{2614}-\\u{2615}\\u{261D}\\u{263A}\\u{2648}-\\u{2653}\\u{2660}\\u{2663}\\u{2665}-\\u{2666}\\u{2668}\\u{267B}\\u{267F}\\u{2693}\\u{26A0}-\\u{26A1}\\u{26AA}-\\u{26AB}\\u{26BD}-\\u{26BE}\\u{26C4}-\\u{26C5}\\u{26CE}\\u{26D4}\\u{26EA}\\u{26F2}-\\u{26F3}\\u{26F5}\\u{26FA}\\u{26FD}\\u{2702}\\u{2705}\\u{2708}-\\u{270C}\\u{270F}\\u{2712}\\u{2714}\\u{2716}\\u{2728}\\u{2733}-\\u{2734}\\u{2744}\\u{2747}\\u{274C}\\u{274E}\\u{2753}-\\u{2755}\\u{2757}\\u{2764}\\u{2795}-\\u{2797}\\u{27A1}\\u{27B0}\\u{2934}-\\u{2935}\\u{2B05}-\\u{2B07}\\u{2B1B}-\\u{2B1C}\\u{2B50}\\u{2B55}\\u{3030}\\u{303D}\\u{3297}\\u{3299}\\u{1F004}\\u{1F0CF}\\u{1F170}-\\u{1F171}\\u{1F17E}-\\u{1F17F}\\u{1F18E}\\u{1F191}-\\u{1F19A}\\u{1F1E7}-\\u{1F1EC}\\u{1F1EE}-\\u{1F1F0}\\u{1F1F3}\\u{1F1F5}\\u{1F1F7}-\\u{1F1FA}\\u{1F201}-\\u{1F202}\\u{1F21A}\\u{1F22F}\\u{1F232}-\\u{1F23A}\\u{1F250}-\\u{1F251}\\u{1F300}-\\u{1F320}\\u{1F330}-\\u{1F335}\\u{1F337}-\\u{1F37C}\\u{1F380}-\\u{1F393}\\u{1F3A0}-\\u{1F3C4}\\u{1F3C6}-\\u{1F3CA}\\u{1F3E0}-\\u{1F3F0}\\u{1F400}-\\u{1F43E}\\u{1F440}\\u{1F442}-\\u{1F4F7}\\u{1F4F9}-\\u{1F4FC}\\u{1F500}-\\u{1F507}\\u{1F509}-\\u{1F53D}\\u{1F550}-\\u{1F567}\\u{1F5FB}-\\u{1F640}\\u{1F645}-\\u{1F64F}\\u{1F680}-\\u{1F68A}]+\" {\n    didSet {\n      prepareRegularExpression()\n    }\n  }\n  \n  /// A reference to the textView text.\n  open override var text: String! {\n    didSet {\n      setContentOffset(.zero, animated: true)\n      updatePlaceholderVisibility()\n    }\n  }\n  \n  /**\n   A convenience property that accesses the textStorage\n   string.\n   */\n  open var string: String {\n    return textStorage.string\n  }\n  \n  /// An Array of matches that match the pattern expression.\n  open var matches: [String] {\n    guard let v = (textStorage as? TextStorage)?.expression else {\n      return []\n    }\n    \n    return v.matches(in: string, options: [], range: NSMakeRange(0, string.utf16.count)).map { [unowned self] in\n      (self.string as NSString).substring(with: $0.range).trimmed\n    }\n  }\n  \n  /**\n   An Array of unique matches that match the pattern\n   expression.\n   */\n  open var uniqueMatches: [String] {\n    var set = Set<String>()\n    for x in matches {\n      set.insert(x)\n    }\n    return Array<String>(set)\n  }\n  \n  /**\n   An initializer that initializes the object with a CGRect object.\n   If AutoLayout is used, it is better to initilize the instance\n   using the init() initializer.\n   - Parameter frame: A CGRect instance.\n   - Parameter textContainer: A NSTextContainer instance.\n   */\n  public override init(frame: CGRect, textContainer: NSTextContainer?) {\n    super.init(frame: frame, textContainer: textContainer)\n    prepare()\n  }\n  \n  /**\n   A convenience initializer that is mostly used with AutoLayout.\n   - Parameter textContainer: A NSTextContainer instance.\n   */\n  public convenience init(textContainer: NSTextContainer?) {\n    self.init(frame: .zero, textContainer: textContainer)\n  }\n  \n  /// A convenience initializer that constructs all aspects of the textView.\n  public convenience init() {\n    let textContainer = NSTextContainer(size: .zero)\n    \n    let layoutManager = NSLayoutManager()\n    layoutManager.addTextContainer(textContainer)\n    \n    let textStorage = TextStorage()\n    textStorage.addLayoutManager(layoutManager)\n    \n    self.init(textContainer: textContainer)\n    \n    textContainer.size = bounds.size\n    textStorage.delegate = self\n  }\n  \n  /// Denitializer.\n  deinit {\n    NotificationCenter.default.removeObserver(self)\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    layoutShape()\n    layoutShadowPath()\n    layoutPlaceholderLabel()\n  }\n  \n  /**\n   Prepares the view instance when intialized. When subclassing,\n   it is recommended to override the prepare method\n   to initialize property values and other setup operations.\n   The super.prepare method should always be called immediately\n   when subclassing.\n   */\n  open func prepare() {\n    contentScaleFactor = Screen.scale\n    textContainerInset = .zero\n    backgroundColor = nil\n    font = Theme.font.regular(with: 16)\n    textColor = Color.darkText.primary\n    \n    prepareNotificationHandlers()\n    prepareRegularExpression()\n    preparePlaceholderLabel()\n    applyCurrentTheme()\n  }\n  \n  open override var contentSize: CGSize {\n    didSet {\n      guard isGrowEnabled else {\n        return\n      }\n      invalidateIntrinsicContentSize()\n      \n      guard isEditing && isHeightChangeAnimated else {\n        superview?.layoutIfNeeded()\n        return\n      }\n      \n      UIView.animate(withDuration: 0.15) {\n        let v = self.superview as? Editor ?? self\n        v.superview?.layoutIfNeeded()\n      }\n    }\n  }\n  \n  /// A Boolean that indicates if the height change during growing is animated.\n  open var isHeightChangeAnimated = true\n  \n  /// Maximum preffered layout height before scrolling.\n  open var preferredMaxLayoutHeight: CGFloat = 0 {\n    didSet {\n      invalidateIntrinsicContentSize()\n      superview?.layoutIfNeeded()\n    }\n  }\n  \n  /// A property indicating if textView allowed to grow.\n  private var isGrowEnabled: Bool {\n    return preferredMaxLayoutHeight > 0 && isScrollEnabled\n  }\n  \n  /// Minimum TextView text height.\n  internal let minimumTextHeight: CGFloat = 32\n  \n  open override var intrinsicContentSize: CGSize {\n    guard isGrowEnabled else {\n      return super.intrinsicContentSize\n    }\n    \n    let insets = textContainerInsets\n    \n    let w = bounds.width - insets.left - insets.right - 2 * textContainer.lineFragmentPadding\n    let placeholderH = placeholderLabel.sizeThatFits(CGSize(width: w, height: .greatestFiniteMagnitude)).height\n    var h = max(minimumTextHeight, placeholderH) + insets.top + insets.bottom\n    h = max(h, contentSize.height)\n    return CGSize(width: UIView.noIntrinsicMetric, height: min(h, preferredMaxLayoutHeight))\n  }\n  \n  open override func insertText(_ text: String) {\n    fixTypingFont()\n    super.insertText(text)\n    fixTypingFont()\n  }\n  \n  open override func paste(_ sender: Any?) {\n    fixTypingFont()\n    super.paste(sender)\n    fixTypingFont()\n  }\n  \n  /**\n   Applies the given theme.\n   - Parameter theme: A Theme.\n   */\n  open func apply(theme: Theme) {\n    textColor = theme.onSurface.withAlphaComponent(0.87)\n    placeholderColor = theme.onSurface.withAlphaComponent(0.38)\n  }\n}\n\nfileprivate extension TextView {\n  /// Prepares the Notification handlers.\n  func prepareNotificationHandlers() {\n    let defaultCenter = NotificationCenter.default\n    defaultCenter.addObserver(self, selector: #selector(handleKeyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)\n    defaultCenter.addObserver(self, selector: #selector(handleKeyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)\n    defaultCenter.addObserver(self, selector: #selector(handleKeyboardDidShow(notification:)), name: UIResponder.keyboardDidShowNotification, object: nil)\n    defaultCenter.addObserver(self, selector: #selector(handleKeyboardDidHide(notification:)), name: UIResponder.keyboardDidHideNotification, object: nil)\n    defaultCenter.addObserver(self, selector: #selector(handleTextViewTextDidBegin), name: UITextView.textDidBeginEditingNotification, object: self)\n    defaultCenter.addObserver(self, selector: #selector(handleTextViewTextDidChange), name: UITextView.textDidChangeNotification, object: self)\n    defaultCenter.addObserver(self, selector: #selector(handleTextViewTextDidEnd), name: UITextView.textDidEndEditingNotification, object: self)\n  }\n  \n  /// Prepares the regular expression for matching.\n  func prepareRegularExpression() {\n    (textStorage as? TextStorage)?.expression = try? NSRegularExpression(pattern: pattern, options: [])\n  }\n  \n  /// prepares the placeholderLabel property.\n  func preparePlaceholderLabel() {\n    placeholderLabel.textColor = Color.darkText.others\n    placeholderLabel.textAlignment = textAlignment\n    placeholderLabel.numberOfLines = 0\n    placeholderLabel.backgroundColor = .clear\n    addSubview(placeholderLabel)\n  }\n}\n\nfileprivate extension TextView {\n  /// Updates the placeholderLabel text color.\n  func updatePlaceholderLabelColor() {\n    guard isPlaceholderLabelEnabled else {\n      return\n    }\n    \n    tintColor = placeholderColor\n    placeholderLabel.textColor = placeholderColor\n  }\n  \n  /// Updates the placeholderLabel visibility.\n  func updatePlaceholderVisibility() {\n    guard isPlaceholderLabelEnabled else {\n      return\n    }\n    \n    placeholderLabel.isHidden = !isEmpty\n  }\n}\n\nfileprivate extension TextView {\n  /// Laysout the placeholder UILabel.\n  func layoutPlaceholderLabel() {\n    guard isPlaceholderLabelEnabled else {\n      return\n    }\n    \n    let insets = textContainerInsets\n    let leftPadding = insets.left + textContainer.lineFragmentPadding\n    let rightPadding = insets.right + textContainer.lineFragmentPadding\n    let w = bounds.width - leftPadding - rightPadding\n    var h = placeholderLabel.sizeThatFits(CGSize(width: w, height: .greatestFiniteMagnitude)).height\n    h = max(h, minimumTextHeight)\n    h = min(h, bounds.height - insets.top - insets.bottom)\n    \n    placeholderLabel.frame = CGRect(x: leftPadding, y: insets.top, width: w, height: h)\n  }\n}\n\nfileprivate extension TextView {\n  /**\n   Handler for when the keyboard will open.\n   - Parameter notification: A Notification.\n   */\n  @objc\n  func handleKeyboardWillShow(notification: Notification) {\n    guard isKeyboardHidden else {\n      return\n    }\n    \n    guard let v = notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue else {\n      return\n    }\n    \n    (delegate as? TextViewDelegate)?.textView?(textView: self, willShowKeyboard: v)\n  }\n  \n  /**\n   Handler for when the keyboard did open.\n   - Parameter notification: A Notification.\n   */\n  @objc\n  func handleKeyboardDidShow(notification: Notification) {\n    guard isKeyboardHidden else {\n      return\n    }\n    \n    isKeyboardHidden = false\n    \n    guard let v = notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue else {\n      return\n    }\n    \n    (delegate as? TextViewDelegate)?.textView?(textView: self, didShowKeyboard: v)\n  }\n  \n  /**\n   Handler for when the keyboard will close.\n   - Parameter notification: A Notification.\n   */\n  @objc\n  func handleKeyboardWillHide(notification: Notification) {\n    guard !isKeyboardHidden else {\n      return\n    }\n    \n    guard let v = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else {\n      return\n    }\n    \n    (delegate as? TextViewDelegate)?.textView?(textView: self, willHideKeyboard: v)\n  }\n  \n  /**\n   Handler for when the keyboard did close.\n   - Parameter notification: A Notification.\n   */\n  @objc\n  func handleKeyboardDidHide(notification: Notification) {\n    guard !isKeyboardHidden else {\n      return\n    }\n    \n    isKeyboardHidden = true\n    \n    guard let v = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else {\n      return\n    }\n    \n    (delegate as? TextViewDelegate)?.textView?(textView: self, didHideKeyboard: v)\n  }\n  \n  /// Notification handler for when text editing began.\n  @objc\n  func handleTextViewTextDidBegin() {\n    isEditing = true\n  }\n  \n  /// Notification handler for when text changed.\n  @objc\n  func handleTextViewTextDidChange() {\n    updatePlaceholderVisibility()\n  }\n  \n  /// Notification handler for when text editing ended.\n  @objc\n  func handleTextViewTextDidEnd() {\n    isEditing = false\n    updatePlaceholderVisibility()\n  }\n}\n\nextension TextView: TextStorageDelegate {\n  @objc\n  open func textStorage(textStorage: TextStorage, willProcessEditing text: String, range: NSRange) {\n    (delegate as? TextViewDelegate)?.textView?(textView: self, willProcessEditing: textStorage, text: string, range: range)\n  }\n  \n  @objc\n  open func textStorage(textStorage: TextStorage, didProcessEditing text: String, result: NSTextCheckingResult?, flags: NSRegularExpression.MatchingFlags, stop: UnsafeMutablePointer<ObjCBool>) {\n    guard let range = result?.range else {\n      return\n    }\n    \n    (delegate as? TextViewDelegate)?.textView?(textView: self, didProcessEditing: textStorage, text: string, range: range)\n  }\n}\n\nprivate extension TextView {\n  /// issue-838 and pr-1117\n  ///\n  /// Inserting (typing or pasting) an emoji character or placing cursor after some\n  /// emoji characters (e.g ☺️) was causing typing font to change to \"AppleColorEmoji\"\n  /// and which was eventually falling back to \"Courier New\" when a non-emoji\n  /// character is inserted. This only happens only if `NSTextStorage` subclass is\n  /// used, otherwise typing font never changed to \"AppleColorEmoji\". So, we fix it\n  /// by resetting typing font from AppleColorEmoji to the default font set by the\n  /// developer. The fix is applied before and after inserting text. The former fixes\n  /// typing font change due to cursor placed after an emoji character, and the\n  /// latter fixes the typing font change due to the insertion of an emoji character\n  /// (typing font changes somehow are reflected in `UITextView.font` parameter).\n  func fixTypingFont() {\n    let fontAttribute = NSAttributedString.Key.font\n    \n    guard (typingAttributes[fontAttribute] as? UIFont)?.fontName == \"AppleColorEmoji\" else {\n      return\n    }\n    \n    typingAttributes[fontAttribute] = _font\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Theme/Theme.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\npublic protocol Themeable: class {\n  /**\n   Applies given theme.\n   - Parameter theme: A Theme.\n   */\n  func apply(theme: Theme)\n  \n  /// A boolean indicating if theming is enabled.\n  var isThemingEnabled: Bool { get set }\n}\n\npublic struct Theme: Hashable {\n  /// The color displayed most frequently across the app.\n  public var primary = Color.blue.darken2\n  \n  /// Accent color for some components such as FABMenu.\n  public var secondary = Color.blue.base\n  \n  /// Background color for view controllers and some components.\n  public var background = Color.white\n  \n  /// Background color for components such as cards, and dialogs.\n  public var surface = Color.white\n  \n  /// Error color for components such as ErrorTextField.\n  public var error = Color.red.base\n  \n  \n  /// Text and iconography color to be used on primary color.\n  public var onPrimary = Color.white\n  \n  /// Text and iconography color to be used on secondary color.\n  public var onSecondary = Color.white\n  \n  /// Text and iconography color to be used on background color.\n  public var onBackground = Color.black\n  \n  /// Text and iconography color to be used on surface color.\n  public var onSurface = Color.black\n  \n  /// Text and iconography color to be used on error color.\n  public var onError = Color.white\n  \n  /// A boolean indicating if theming is enabled globally.\n  public static var isEnabled = false\n  \n  /// Global font for app.\n  public static var font: FontType.Type = RobotoFont.self\n  \n  /// An initializer.\n  public init() { }\n}\n\npublic extension Theme {\n  /// Current theme for Material.\n  static private(set) var current = Theme.light\n  \n  /// A light theme.\n  static var light = Theme()\n  \n  /// A dark theme.\n  static var dark: Theme = {\n    var t = Theme()\n    t.primary = UIColor(rgb: 0x202020)\n    t.secondary = Color.teal.base\n    t.background = UIColor(rgb: 0x303030)\n    t.surface = t.background\n    t.onBackground = .white\n    t.onSurface = .white\n    return t\n  }()\n}\n\npublic extension Theme {\n  /**\n   Applies theme to the entire app.\n   - Parameter theme: A Theme.\n   */\n  static func apply(theme: Theme) {\n    current = theme\n    guard let v = Application.rootViewController else {\n      return\n    }\n    \n    apply(theme: theme, to: v)\n  }\n  \n  /**\n   Applies theme to the hierarchy of given view.\n   - Parameter theme: A Theme.\n   - Parameter to view: A UIView.\n   */\n  static func apply(theme: Theme, to view: UIView) {\n    guard !((view as? Themeable)?.isThemingEnabled == false), !view.isProcessed else {\n      return\n    }\n    \n    view.subviews.forEach {\n      apply(theme: theme, to: $0)\n    }\n    \n    (view as? Themeable)?.apply(theme: theme)\n  }\n  \n  /**\n   Applies theme to the hierarchy of given view controller.\n   - Parameter theme: A Theme.\n   - Parameter to viewController: A UIViewController.\n   */\n  static func apply(theme: Theme, to viewController: UIViewController) {\n    guard !((viewController as? Themeable)?.isThemingEnabled == false) else {\n      return\n    }\n    \n    viewController.allChildren.forEach {\n      apply(theme: theme, to: $0)\n      $0.view.isProcessed = true\n    }\n    \n    apply(theme: theme, to: viewController.view)\n    \n    viewController.allChildren.forEach {\n      $0.view.isProcessed = false\n    }\n    \n    (viewController as? Themeable)?.apply(theme: theme)\n  }\n  \n  /**\n   Applies provided theme for the components created within the given block\n   without chaging app's theme.\n   - Parameter theme: A Theme.\n   - Parameter for block: A code block.\n   */\n  static func applying(theme: Theme, for execute: () -> Void) {\n    let v = current\n    current = theme\n    execute()\n    current = v\n  }\n}\n\n\n/// A memory reference to the isThemingEnabled for Themeable NSObject subclasses.\nprivate var IsThemingEnabledKey: UInt8 = 0\n\npublic extension Themeable where Self: NSObject {\n  /// A class-wide boolean indicating if theming is enabled.\n  static var isThemingEnabled: Bool {\n    get {\n      return Theme.isEnabled && AssociatedObject.get(base: self, key: &IsThemingEnabledKey) {\n        true\n      }\n    }\n    set(value) {\n      AssociatedObject.set(base: self, key: &IsThemingEnabledKey, value: value)\n    }\n  }\n  \n  /// A boolean indicating if theming is enabled.\n  var isThemingEnabled: Bool {\n    get {\n      return type(of: self).isThemingEnabled && AssociatedObject.get(base: self, key: &IsThemingEnabledKey) {\n        true\n      }\n    }\n    set(value) {\n      AssociatedObject.set(base: self, key: &IsThemingEnabledKey, value: value)\n    }\n  }\n  \n  /// Applies current theme to itself if theming is enabled.\n  internal func applyCurrentTheme() {\n    guard isThemingEnabled else {\n      return\n    }\n    \n    apply(theme: .current)\n  }\n}\n\nprivate extension UIViewController {\n  /// Returns all possible child view controllers.\n  var allChildren: [UIViewController] {\n    var all = children\n    \n    if let v = self as? TabsController {\n      all += v.viewControllers\n    }\n    \n    if let v = presentedViewController, v.presentingViewController === self {\n      all.append(v)\n    }\n    \n    return all\n  }\n}\n\n/// A memory reference to the isProcessed for UIView.\nprivate var IsProcessedKey: UInt8 = 0\n\nprivate extension UIView {\n  /// A boolean indicating if view is already themed.\n  var isProcessed: Bool {\n    get {\n      return AssociatedObject.get(base: self, key: &IsProcessedKey) {\n        false\n      }\n    }\n    set(value) {\n      AssociatedObject.set(base: self, key: &IsProcessedKey, value: value)\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Toolbar/Toolbar.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class Toolbar: Bar, Themeable {\n  /// A convenience property to set the titleLabel.text.\n  @IBInspectable\n  open var title: String? {\n    get {\n      return titleLabel.text\n    }\n    set(value) {\n      titleLabel.text = value\n      layoutSubviews()\n    }\n  }\n  \n  /// Title label.\n  @IBInspectable\n  public let titleLabel = UILabel()\n  \n  /// A convenience property to set the detailLabel.text.\n  @IBInspectable\n  open var detail: String? {\n    get {\n      return detailLabel.text\n    }\n    set(value) {\n      detailLabel.text = value\n      layoutSubviews()\n    }\n  }\n  \n  /// Detail label.\n  @IBInspectable\n  public let detailLabel = UILabel()\n  \n  open override var leftViews: [UIView] {\n    didSet {\n      prepareIconButtons(leftViews)\n    }\n  }\n  \n  open override var centerViews: [UIView] {\n    didSet {\n      prepareIconButtons(centerViews)\n    }\n  }\n  \n  open override var rightViews: [UIView] {\n    didSet {\n      prepareIconButtons(rightViews)\n    }\n  }\n  \n  deinit {\n    titleLabelTextAlignmentObserver.invalidate()\n    titleLabelTextAlignmentObserver = nil\n  }\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n  }\n  \n  /**\n   An initializer that initializes the object with a CGRect object.\n   If AutoLayout is used, it is better to initilize the instance\n   using the init() initializer.\n   - Parameter frame: A CGRect instance.\n   */\n  public override init(frame: CGRect) {\n    super.init(frame: frame)\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    guard willLayout else {\n      return\n    }\n    \n    if 0 < titleLabel.text?.utf16.count ?? 0 {\n      if nil == titleLabel.superview {\n        contentView.addSubview(titleLabel)\n      }\n      titleLabel.frame = contentView.bounds\n    } else {\n      titleLabel.removeFromSuperview()\n    }\n    \n    if 0 < detailLabel.text?.utf16.count ?? 0 {\n      if nil == detailLabel.superview {\n        contentView.addSubview(detailLabel)\n      }\n      \n      if nil == titleLabel.superview {\n        detailLabel.frame = contentView.bounds\n      } else {\n        titleLabel.sizeToFit()\n        detailLabel.sizeToFit()\n        \n        let diff: CGFloat = (contentView.bounds.height - titleLabel.bounds.height - detailLabel.bounds.height) / 2\n        \n        titleLabel.frame.size.height += diff\n        titleLabel.frame.size.width = contentView.bounds.width\n        \n        detailLabel.frame.size.height += diff\n        detailLabel.frame.size.width = contentView.bounds.width\n        detailLabel.frame.origin.y = titleLabel.bounds.height\n      }\n    } else {\n      detailLabel.removeFromSuperview()\n    }\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    contentViewAlignment = .center\n    \n    prepareTitleLabel()\n    prepareDetailLabel()\n  }\n  \n  /**\n   Applies the given theme.\n   - Parameter theme: A Theme.\n   */\n  open func apply(theme: Theme) {\n    backgroundColor = theme.primary\n    (leftViews + rightViews + centerViews).forEach {\n      guard let v = $0 as? IconButton, v.isThemingEnabled else {\n        return\n      }\n      \n      v.apply(theme: theme)\n    }\n    \n    if !((titleLabel as? Themeable)?.isThemingEnabled == false) {\n      titleLabel.textColor = theme.onPrimary\n    }\n    \n    if !((detailLabel as? Themeable)?.isThemingEnabled == false) {\n      detailLabel.textColor = theme.onPrimary\n    }\n  }\n  \n  /// A reference to titleLabel.textAlignment observation.\n  private var titleLabelTextAlignmentObserver: NSKeyValueObservation!\n}\n\nprivate extension Toolbar {\n  /// Prepares the titleLabel.\n  func prepareTitleLabel() {\n    titleLabel.textAlignment = .center\n    titleLabel.contentScaleFactor = Screen.scale\n    titleLabel.font = Theme.font.medium(with: 17)\n    titleLabel.textColor = Color.darkText.primary\n    titleLabelTextAlignmentObserver = titleLabel.observe(\\.textAlignment) { [weak self] titleLabel, _ in\n      self?.contentViewAlignment = .center == titleLabel.textAlignment ? .center : .full\n    }\n  }\n  \n  /// Prepares the detailLabel.\n  func prepareDetailLabel() {\n    detailLabel.textAlignment = .center\n    detailLabel.contentScaleFactor = Screen.scale\n    detailLabel.font = Theme.font.regular(with: 12)\n    detailLabel.textColor = Color.darkText.secondary\n  }\n  \n  func prepareIconButtons(_ views: [UIView]) {\n    views.forEach {\n      ($0 as? IconButton)?.themingStyle = .onPrimary\n    }\n    \n    applyCurrentTheme()\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Toolbar/ToolbarController.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(ToolbarAlignment)\npublic enum ToolbarAlignment: Int {\n  case top\n  case bottom\n}\n\nextension UIViewController {\n  /**\n   A convenience property that provides access to the ToolbarController.\n   This is the recommended method of accessing the ToolbarController\n   through child UIViewControllers.\n   */\n  public var toolbarController: ToolbarController? {\n    return traverseViewControllerHierarchyForClassType()\n  }\n}\n\n@objc(ToolbarController)\nopen class ToolbarController: StatusBarController {\n  /// Reference to the Toolbar.\n  @IBInspectable\n  public let toolbar = Toolbar()\n  \n  /// The toolbar alignment.\n  open var toolbarAlignment = ToolbarAlignment.top {\n    didSet {\n      layoutSubviews()\n    }\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    layoutToolbar()\n    layoutContainer()\n    layoutRootViewController()\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    displayStyle = .partial\n    \n    prepareToolbar()\n  }\n}\n\nfileprivate extension ToolbarController {\n  /// Prepares the toolbar.\n  func prepareToolbar() {\n    toolbar.layer.zPosition = 1000\n    toolbar.depthPreset = .depth1\n    view.addSubview(toolbar)\n  }\n}\n\nfileprivate extension ToolbarController {\n  /// Layout the container.\n  func layoutContainer() {\n    switch displayStyle {\n    case .partial:\n      let p = toolbar.bounds.height\n      let q = statusBarOffsetAdjustment\n      let h = view.bounds.height - p - q\n      \n      switch toolbarAlignment {\n      case .top:\n        container.frame.origin.y = q + p\n        container.frame.size.height = h\n        \n      case .bottom:\n        container.frame.origin.y = q\n        container.frame.size.height = h\n      }\n      \n      container.frame.size.width = view.bounds.width\n      \n    case .full:\n      container.frame = view.bounds\n    }\n  }\n  \n  /// Layout the toolbar.\n  func layoutToolbar() {\n    toolbar.frame.origin.x = 0\n    toolbar.frame.origin.y = .top == toolbarAlignment ? statusBarOffsetAdjustment : view.bounds.height - toolbar.bounds.height\n    toolbar.frame.size.width = view.bounds.width\n  }\n  \n  /// Layout the rootViewController.\n  func layoutRootViewController() {\n    rootViewController.view.frame = container.bounds\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Transition/DisplayStyle.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(DisplayStyle)\npublic enum DisplayStyle: Int {\n  case partial\n  case full\n}\n"
  },
  {
    "path": "Sources/iOS/Transition/TransitionController.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\nopen class TransitionController: ViewController {\n  /**\n   A Boolean property used to enable and disable interactivity\n   with the rootViewController.\n   */\n  @IBInspectable\n  open var isUserInteractionEnabled: Bool {\n    get {\n      return rootViewController.view.isUserInteractionEnabled\n    }\n    set(value) {\n      rootViewController.view.isUserInteractionEnabled = value\n    }\n  }\n  \n  /// A Boolean indicating whether the controller is in transitioning state.\n  open var isTransitioning: Bool {\n    return MotionTransition.shared.isTransitioning && MotionTransition.shared.fromViewController == rootViewController\n  }\n  \n  open override var childForStatusBarStyle: UIViewController? {\n    return isTransitioning ? MotionTransition.shared.toViewController ?? rootViewController : rootViewController\n  }\n  \n  open override var childForStatusBarHidden: UIViewController? {\n    return childForStatusBarStyle\n  }\n  \n  open override var childForHomeIndicatorAutoHidden: UIViewController? {\n    return childForStatusBarStyle\n  }\n  \n  open override var childForScreenEdgesDeferringSystemGestures: UIViewController? {\n    return childForStatusBarStyle\n  }\n  \n  /// A reference to the container view.\n  @IBInspectable\n  public let container = UIView()\n  \n  /**\n   A UIViewController property that references the active\n   main UIViewController. To swap the rootViewController, it\n   is recommended to use the transitionFromRootViewController\n   helper method.\n   */\n  open internal(set) var rootViewController: UIViewController! {\n    didSet {\n      guard oldValue != rootViewController else {\n        return\n      }\n      \n      if let v = oldValue {\n        removeViewController(viewController: v)\n      }\n      \n      prepare(viewController: rootViewController, in: container)\n    }\n  }\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n  }\n  \n  /**\n   An initializer that initializes the object with an Optional nib and bundle.\n   - Parameter nibNameOrNil: An Optional String for the nib.\n   - Parameter bundle: An Optional NSBundle where the nib is located.\n   */\n  public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {\n    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)\n  }\n  \n  /**\n   An initializer for the BarController.\n   - Parameter rootViewController: The main UIViewController.\n   */\n  public init(rootViewController: UIViewController) {\n    super.init(nibName: nil, bundle: nil)\n    self.rootViewController = rootViewController\n  }\n  \n  open override var shouldAutomaticallyForwardAppearanceMethods: Bool {\n    return false\n  }\n  \n  open override func viewWillAppear(_ animated: Bool) {\n    super.viewWillAppear(animated)\n    rootViewController.beginAppearanceTransition(true, animated: animated)\n  }\n  \n  open override func viewDidAppear(_ animated: Bool) {\n    super.viewDidAppear(animated)\n    rootViewController.endAppearanceTransition()\n  }\n  \n  open override func viewWillDisappear(_ animated: Bool) {\n    super.viewWillDisappear(animated)\n    rootViewController.beginAppearanceTransition(false, animated: animated)\n  }\n  \n  open override func viewDidDisappear(_ animated: Bool) {\n    super.viewDidDisappear(animated)\n    rootViewController.endAppearanceTransition()\n  }\n  \n  /**\n   A method to swap rootViewController objects.\n   - Parameter toViewController: The UIViewController to swap\n   with the active rootViewController.\n   - Parameter completion: A completion block that is execited after\n   the transition animation from the active rootViewController\n   to the toViewController has completed.\n   */\n  open func transition(to viewController: UIViewController, completion: ((Bool) -> Void)? = nil) {\n    prepare(viewController: viewController, in: container)\n    \n    if case .auto = viewController.motionTransitionType {\n      viewController.motionTransitionType = motionTransitionType\n    }\n    \n    view.isUserInteractionEnabled = false\n    MotionTransition.shared.transition(from: rootViewController, to: viewController, in: container) { [weak self] isFinishing in\n      guard let s = self else {\n        return\n      }\n      \n      defer {\n        s.view.isUserInteractionEnabled = true\n        completion?(isFinishing)\n      }\n      \n      guard isFinishing else {\n        s.removeViewController(viewController: viewController)\n        s.removeViewController(viewController: s.rootViewController)\n        s.prepare(viewController: s.rootViewController, in: s.container)\n        return\n      }\n      \n      s.rootViewController = viewController\n    }\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    \n    prepareContainer()\n    \n    guard let v = rootViewController else {\n      return\n    }\n    \n    prepare(viewController: v, in: container)\n  }\n}\n\ninternal extension TransitionController {\n  /// Prepares the container view.\n  func prepareContainer() {\n    container.frame = view.bounds\n    container.clipsToBounds = true\n    container.contentScaleFactor = Screen.scale\n    container.autoresizingMask = [.flexibleWidth, .flexibleHeight]\n    view.addSubview(container)\n  }\n  \n  /**\n   A method that adds the passed in controller as a child of\n   the BarController within the passed in\n   container view.\n   - Parameter viewController: A UIViewController to add as a child.\n   - Parameter in container: A UIView that is the parent of the\n   passed in controller view within the view hierarchy.\n   */\n  func prepare(viewController: UIViewController, in container: UIView) {\n    addChild(viewController)\n    container.addSubview(viewController.view)\n    viewController.didMove(toParent: self)\n    viewController.view.frame = container.bounds\n    viewController.view.clipsToBounds = true\n    viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]\n    viewController.view.contentScaleFactor = Screen.scale\n  }\n}\n\ninternal extension TransitionController {\n  /**\n   Removes a given view controller from the childViewControllers array.\n   - Parameter at index: An Int for the view controller position.\n   */\n  func removeViewController(viewController: UIViewController) {\n    viewController.willMove(toParent: nil)\n    viewController.view.removeFromSuperview()\n    viewController.removeFromParent()\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Type/Border.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(BorderWidthPreset)\npublic enum BorderWidthPreset: Int {\n  case none\n  case border1\n  case border2\n  case border3\n  case border4\n  case border5\n  case border6\n  case border7\n  case border8\n  case border9\n  \n  /// A CGFloat representation of the border width preset.\n  public var cgFloatValue: CGFloat {\n    switch self {\n    case .none:\n      return 0\n    case .border1:\n      return 0.5\n    case .border2:\n      return 1\n    case .border3:\n      return 2\n    case .border4:\n      return 3\n    case .border5:\n      return 4\n    case .border6:\n      return 5\n    case .border7:\n      return 6\n    case .border8:\n      return 7\n    case .border9:\n      return 8\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Type/CornerRadius.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(CornerRadiusPreset)\npublic enum CornerRadiusPreset: Int {\n  case none\n  case cornerRadius1\n  case cornerRadius2\n  case cornerRadius3\n  case cornerRadius4\n  case cornerRadius5\n  case cornerRadius6\n  case cornerRadius7\n  case cornerRadius8\n  case cornerRadius9\n}\n\n/// Converts the CornerRadiusPreset enum to a CGFloat value.\npublic func CornerRadiusPresetToValue(preset: CornerRadiusPreset) -> CGFloat {\n  switch preset {\n  case .none:\n    return 0\n  case .cornerRadius1:\n    return 2\n  case .cornerRadius2:\n    return 4\n  case .cornerRadius3:\n    return 8\n  case .cornerRadius4:\n    return 12\n  case .cornerRadius5:\n    return 16\n  case .cornerRadius6:\n    return 20\n  case .cornerRadius7:\n    return 24\n  case .cornerRadius8:\n    return 28\n  case .cornerRadius9:\n    return 32\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Type/Depth.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\npublic enum DepthPreset {\n  case none\n  case depth1\n  case depth2\n  case depth3\n  case depth4\n  case depth5\n  indirect case above(DepthPreset)\n  indirect case below(DepthPreset)\n  indirect case left(DepthPreset)\n  indirect case right(DepthPreset)\n  \n  /// Returns raw depth value without considering direction.\n  public var rawValue: DepthPreset {\n    switch self {\n    case .above(let v):\n      return v.rawValue\n    case .below(let v):\n      return v.rawValue\n    case .left(let v):\n      return v.rawValue\n    case .right(let v):\n      return v.rawValue\n    default:\n      return self\n    }\n  }\n}\n\npublic struct Depth {\n  /// Offset.\n  public var offset: Offset\n  \n  /// Opacity.\n  public var opacity: Float\n  \n  /// Radius.\n  public var radius: CGFloat\n  \n  /// A tuple of raw values.\n  public var rawValue: (CGSize, Float, CGFloat) {\n    return (offset.asSize, opacity, radius)\n  }\n  \n  /// Preset.\n  public var preset = DepthPreset.none {\n    didSet {\n      let depth = DepthPresetToValue(preset: preset)\n      offset = depth.offset\n      opacity = depth.opacity\n      radius = depth.radius\n    }\n  }\n  \n  /**\n   Initializer that takes in an offset, opacity, and radius.\n   - Parameter offset: A UIOffset.\n   - Parameter opacity: A Float.\n   - Parameter radius: A CGFloat.\n   */\n  public init(offset: Offset = .zero, opacity: Float = 0, radius: CGFloat = 0) {\n    self.offset = offset\n    self.opacity = opacity\n    self.radius = radius\n  }\n  \n  /**\n   Initializer that takes in a DepthPreset.\n   - Parameter preset: DepthPreset.\n   */\n  public init(preset: DepthPreset) {\n    self.init()\n    self.preset = preset\n  }\n  \n  /**\n   Static constructor for Depth with values of 0.\n   - Returns: A Depth struct with values of 0.\n   */\n  static var zero: Depth {\n    return Depth()\n  }\n}\n\n/// Converts the DepthPreset enum to a Depth value.\npublic func DepthPresetToValue(preset: DepthPreset) -> Depth {\n  switch preset {\n  case .none:\n    return .zero\n  case .depth1:\n    return Depth(offset: Offset(horizontal: 0, vertical: 0.5), opacity: 0.3, radius: 0.5)\n  case .depth2:\n    return Depth(offset: Offset(horizontal: 0, vertical: 1), opacity: 0.3, radius: 1)\n  case .depth3:\n    return Depth(offset: Offset(horizontal: 0, vertical: 2), opacity: 0.3, radius: 2)\n  case .depth4:\n    return Depth(offset: Offset(horizontal: 0, vertical: 4), opacity: 0.3, radius: 4)\n  case .depth5:\n    return Depth(offset: Offset(horizontal: 0, vertical: 8), opacity: 0.3, radius: 8)\n  case .above(let preset):\n    var v = DepthPresetToValue(preset: preset)\n    if preset.isRoot {\n      v.offset.vertical *= -1\n    } else {\n      let value = DepthPresetToValue(preset: preset.rawValue)\n      v.offset.vertical -= value.offset.vertical\n    }\n    return v\n  case .below(let preset):\n    var v = DepthPresetToValue(preset: preset)\n    if preset.isRoot {\n      return v\n    } else {\n      let value = DepthPresetToValue(preset: preset.rawValue)\n      v.offset.vertical += value.offset.vertical\n    }\n    return v\n  case .left(let preset):\n    var v = DepthPresetToValue(preset: preset)\n    if preset.isRoot {\n      v.offset.horizontal = -v.offset.vertical\n      v.offset.vertical = 0\n    } else {\n      let value = DepthPresetToValue(preset: preset.rawValue)\n      v.offset.horizontal -= value.offset.vertical\n    }\n    return v\n  case .right(let preset):\n    var v = DepthPresetToValue(preset: preset)\n    if preset.isRoot {\n      v.offset.horizontal = v.offset.vertical\n      v.offset.vertical = 0\n    } else {\n      let value = DepthPresetToValue(preset: preset.rawValue)\n      v.offset.horizontal += value.offset.vertical\n    }\n    return v\n  }\n}\n\nfileprivate extension DepthPreset {\n  /// Checks if the preset is the root value (has no direction).\n  var isRoot: Bool {\n    switch self {\n    case .above(_):\n      return false\n    case .below(_):\n      return false\n    case .left(_):\n      return false\n    case .right(_):\n      return false\n    default:\n      return true\n    }\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Type/EdgeInsets.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(EdgeInsetsPreset)\npublic enum EdgeInsetsPreset: Int {\n  case none\n  \n  // square\n  case square1\n  case square2\n  case square3\n  case square4\n  case square5\n  case square6\n  case square7\n  case square8\n  case square9\n  case square10\n  case square11\n  case square12\n  case square13\n  case square14\n  case square15\n  \n  // rectangle\n  case wideRectangle1\n  case wideRectangle2\n  case wideRectangle3\n  case wideRectangle4\n  case wideRectangle5\n  case wideRectangle6\n  case wideRectangle7\n  case wideRectangle8\n  case wideRectangle9\n  \n  // flipped rectangle\n  case tallRectangle1\n  case tallRectangle2\n  case tallRectangle3\n  case tallRectangle4\n  case tallRectangle5\n  case tallRectangle6\n  case tallRectangle7\n  case tallRectangle8\n  case tallRectangle9\n  \n  /// horizontally\n  case horizontally1\n  case horizontally2\n  case horizontally3\n  case horizontally4\n  case horizontally5\n  \n  /// vertically\n  case vertically1\n  case vertically2\n  case vertically3\n  case vertically4\n  case vertically5\n}\n\npublic typealias EdgeInsets = UIEdgeInsets\n\n/// Converts the EdgeInsetsPreset to a Inset value.\npublic func EdgeInsetsPresetToValue(preset: EdgeInsetsPreset) -> EdgeInsets {\n  switch preset {\n  case .none:\n    return .zero\n    \n  // square\n  case .square1:\n    return EdgeInsets(top: 4, left: 4, bottom: 4, right: 4)\n  case .square2:\n    return EdgeInsets(top: 8, left: 8, bottom: 8, right: 8)\n  case .square3:\n    return EdgeInsets(top: 16, left: 16, bottom: 16, right: 16)\n  case .square4:\n    return EdgeInsets(top: 20, left: 20, bottom: 20, right: 20)\n  case .square5:\n    return EdgeInsets(top: 24, left: 24, bottom: 24, right: 24)\n  case .square6:\n    return EdgeInsets(top: 28, left: 28, bottom: 28, right: 28)\n  case .square7:\n    return EdgeInsets(top: 32, left: 32, bottom: 32, right: 32)\n  case .square8:\n    return EdgeInsets(top: 36, left: 36, bottom: 36, right: 36)\n  case .square9:\n    return EdgeInsets(top: 40, left: 40, bottom: 40, right: 40)\n  case .square10:\n    return EdgeInsets(top: 44, left: 44, bottom: 44, right: 44)\n  case .square11:\n    return EdgeInsets(top: 48, left: 48, bottom: 48, right: 48)\n  case .square12:\n    return EdgeInsets(top: 52, left: 52, bottom: 52, right: 52)\n  case .square13:\n    return EdgeInsets(top: 56, left: 56, bottom: 56, right: 56)\n  case .square14:\n    return EdgeInsets(top: 60, left: 60, bottom: 60, right: 60)\n  case .square15:\n    return EdgeInsets(top: 64, left: 64, bottom: 64, right: 64)\n    \n  // rectangle\n  case .wideRectangle1:\n    return EdgeInsets(top: 2, left: 4, bottom: 2, right: 4)\n  case .wideRectangle2:\n    return EdgeInsets(top: 4, left: 8, bottom: 4, right: 8)\n  case .wideRectangle3:\n    return EdgeInsets(top: 8, left: 16, bottom: 8, right: 16)\n  case .wideRectangle4:\n    return EdgeInsets(top: 12, left: 24, bottom: 12, right: 24)\n  case .wideRectangle5:\n    return EdgeInsets(top: 16, left: 32, bottom: 16, right: 32)\n  case .wideRectangle6:\n    return EdgeInsets(top: 20, left: 40, bottom: 20, right: 40)\n  case .wideRectangle7:\n    return EdgeInsets(top: 24, left: 48, bottom: 24, right: 48)\n  case .wideRectangle8:\n    return EdgeInsets(top: 28, left: 56, bottom: 28, right: 56)\n  case .wideRectangle9:\n    return EdgeInsets(top: 32, left: 64, bottom: 32, right: 64)\n    \n  // flipped rectangle\n  case .tallRectangle1:\n    return EdgeInsets(top: 4, left: 2, bottom: 4, right: 2)\n  case .tallRectangle2:\n    return EdgeInsets(top: 8, left: 4, bottom: 8, right: 4)\n  case .tallRectangle3:\n    return EdgeInsets(top: 16, left: 8, bottom: 16, right: 8)\n  case .tallRectangle4:\n    return EdgeInsets(top: 24, left: 12, bottom: 24, right: 12)\n  case .tallRectangle5:\n    return EdgeInsets(top: 32, left: 16, bottom: 32, right: 16)\n  case .tallRectangle6:\n    return EdgeInsets(top: 40, left: 20, bottom: 40, right: 20)\n  case .tallRectangle7:\n    return EdgeInsets(top: 48, left: 24, bottom: 48, right: 24)\n  case .tallRectangle8:\n    return EdgeInsets(top: 56, left: 28, bottom: 56, right: 28)\n  case .tallRectangle9:\n    return EdgeInsets(top: 64, left: 32, bottom: 64, right: 32)\n    \n  /// horizontally\n  case .horizontally1:\n    return EdgeInsets(top: 0, left: 2, bottom: 0, right: 2)\n  case .horizontally2:\n    return EdgeInsets(top: 0, left: 4, bottom: 0, right: 4)\n  case .horizontally3:\n    return EdgeInsets(top: 0, left: 8, bottom: 0, right: 8)\n  case .horizontally4:\n    return EdgeInsets(top: 0, left: 16, bottom: 0, right: 16)\n  case .horizontally5:\n    return EdgeInsets(top: 0, left: 24, bottom: 0, right: 24)\n    \n  /// vertically\n  case .vertically1:\n    return EdgeInsets(top: 2, left: 0, bottom: 2, right: 0)\n  case .vertically2:\n    return EdgeInsets(top: 4, left: 0, bottom: 4, right: 0)\n  case .vertically3:\n    return EdgeInsets(top: 8, left: 0, bottom: 8, right: 0)\n  case .vertically4:\n    return EdgeInsets(top: 16, left: 0, bottom: 16, right: 0)\n  case .vertically5:\n    return EdgeInsets(top: 24, left: 0, bottom: 24, right: 0)\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Type/InterimSpace.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\n@objc(InterimSpacePreset)\npublic enum InterimSpacePreset: Int {\n  case none\n  case interimSpace1\n  case interimSpace2\n  case interimSpace3\n  case interimSpace4\n  case interimSpace5\n  case interimSpace6\n  case interimSpace7\n  case interimSpace8\n  case interimSpace9\n  case interimSpace10\n  case interimSpace11\n  case interimSpace12\n  case interimSpace13\n  case interimSpace14\n  case interimSpace15\n  case interimSpace16\n  case interimSpace17\n  case interimSpace18\n}\n\npublic typealias InterimSpace = CGFloat\n\n/// Converts the InterimSpacePreset enum to an InterimSpace value.\npublic func InterimSpacePresetToValue(preset: InterimSpacePreset) -> InterimSpace {\n  switch preset {\n  case .none:\n    return 0\n  case .interimSpace1:\n    return 1\n  case .interimSpace2:\n    return 2\n  case .interimSpace3:\n    return 4\n  case .interimSpace4:\n    return 8\n  case .interimSpace5:\n    return 12\n  case .interimSpace6:\n    return 16\n  case .interimSpace7:\n    return 20\n  case .interimSpace8:\n    return 24\n  case .interimSpace9:\n    return 28\n  case .interimSpace10:\n    return 32\n  case .interimSpace11:\n    return 36\n  case .interimSpace12:\n    return 40\n  case .interimSpace13:\n    return 44\n  case .interimSpace14:\n    return 48\n  case .interimSpace15:\n    return 52\n  case .interimSpace16:\n    return 56\n  case .interimSpace17:\n    return 60\n  case .interimSpace18:\n    return 64\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Type/Offset.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\npublic typealias Offset = UIOffset\n\nextension CGSize {\n  /// Returns an Offset version of the CGSize.\n  public var asOffset: Offset {\n    return Offset(size: self)\n  }\n}\n\nextension Offset {\n  /**\n   Initializer that accepts a CGSize value.\n   - Parameter size: A CGSize value.\n   */\n  public init(size: CGSize) {\n    self.init(horizontal: size.width, vertical: size.height)\n  }\n}\n\nextension Offset {\n  /// Returns a CGSize version of the Offset.\n  public var asSize: CGSize {\n    return CGSize(width: horizontal, height: vertical)\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/Type/Shape.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport Foundation\n\n@objc(ShapePreset)\npublic enum ShapePreset: Int {\n  case none\n  case square\n  case circle\n}\n"
  },
  {
    "path": "Sources/iOS/View/PulseView.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\nimport Motion\n\nopen class PulseView: View, Pulseable, PulseableLayer {\n  /// A Pulse reference.\n  internal var pulse: Pulse!\n  \n  /// A reference to the pulse layer.\n  internal var pulseLayer: CALayer? {\n    return pulse.pulseLayer\n  }\n  \n  /// PulseAnimation value.\n  open var pulseAnimation: PulseAnimation {\n    get {\n      return pulse.animation\n    }\n    set(value) {\n      pulse.animation = value\n    }\n  }\n  \n  /// PulseAnimation color.\n  @IBInspectable\n  open var pulseColor: UIColor {\n    get {\n      return pulse.color\n    }\n    set(value) {\n      pulse.color = value\n    }\n  }\n  \n  /// Pulse opacity.\n  @IBInspectable\n  open var pulseOpacity: CGFloat {\n    get {\n      return pulse.opacity\n    }\n    set(value) {\n      pulse.opacity = value\n    }\n  }\n  \n  /**\n   Triggers the pulse animation.\n   - Parameter point: A Optional point to pulse from, otherwise pulses\n   from the center.\n   */\n  open func pulse(point: CGPoint? = nil) {\n    pulse.expand(point: point ?? center)\n    Motion.delay(0.35) { [weak self] in\n      self?.pulse.contract()\n    }\n  }\n  \n  /**\n   A delegation method that is executed when the view has began a\n   touch event.\n   - Parameter touches: A set of UITouch objects.\n   - Parameter event: A UIEvent object.\n   */\n  open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {\n    super.touchesBegan(touches, with: event)\n    pulse.expand(point: layer.convert(touches.first!.location(in: self), from: layer))\n  }\n  \n  /**\n   A delegation method that is executed when the view touch event has\n   ended.\n   - Parameter touches: A set of UITouch objects.\n   - Parameter event: A UIEvent object.\n   */\n  open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {\n    super.touchesEnded(touches, with: event)\n    pulse.contract()\n  }\n  \n  /**\n   A delegation method that is executed when the view touch event has\n   been cancelled.\n   - Parameter touches: A set of UITouch objects.\n   - Parameter event: A UIEvent object.\n   */\n  open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {\n    super.touchesCancelled(touches, with: event)\n    pulse.contract()\n  }\n  \n  open override func prepare() {\n    super.prepare()\n    preparePulse()\n  }\n}\n\nextension PulseView {\n  /// Prepares the pulse motion.\n  fileprivate func preparePulse() {\n    pulse = Pulse(pulseView: self, pulseLayer: visualLayer)\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/View/View.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class View: UIView {\n  open override var intrinsicContentSize: CGSize {\n    return bounds.size\n  }\n  \n  /**\n   A CAShapeLayer used to manage elements that would be affected by\n   the clipToBounds property of the backing layer. For example, this\n   allows the dropshadow effect on the backing layer, while clipping\n   the image to a desired shape within the visualLayer.\n   */\n  public let visualLayer = CAShapeLayer()\n  \n  /**\n   A property that manages an image for the visualLayer's contents\n   property. Images should not be set to the backing layer's contents\n   property to avoid conflicts when using clipsToBounds.\n   */\n  @IBInspectable\n  open var image: UIImage? {\n    get {\n      guard let v = visualLayer.contents else {\n        return nil\n      }\n      \n      return UIImage(cgImage: v as! CGImage)\n    }\n    set(value) {\n      visualLayer.contents = value?.cgImage\n    }\n  }\n  \n  /**\n   Allows a relative subrectangle within the range of 0 to 1 to be\n   specified for the visualLayer's contents property. This allows\n   much greater flexibility than the contentsGravity property in\n   terms of how the image is cropped and stretched.\n   */\n  @IBInspectable\n  open var contentsRect: CGRect {\n    get {\n      return visualLayer.contentsRect\n    }\n    set(value) {\n      visualLayer.contentsRect = value\n    }\n  }\n  \n  /**\n   A CGRect that defines a stretchable region inside the visualLayer\n   with a fixed border around the edge.\n   */\n  @IBInspectable\n  open var contentsCenter: CGRect {\n    get {\n      return visualLayer.contentsCenter\n    }\n    set(value) {\n      visualLayer.contentsCenter = value\n    }\n  }\n  \n  /**\n   A floating point value that defines a ratio between the pixel\n   dimensions of the visualLayer's contents property and the size\n   of the view. By default, this value is set to the Screen.scale.\n   */\n  @IBInspectable\n  open var contentsScale: CGFloat {\n    get {\n      return visualLayer.contentsScale\n    }\n    set(value) {\n      visualLayer.contentsScale = value\n    }\n  }\n  \n  /// Determines how content should be aligned within the visualLayer's bounds.\n  @IBInspectable\n  open var contentsGravity: CALayerContentsGravity {\n    get {\n      return visualLayer.contentsGravity\n    }\n    set(value) {\n      visualLayer.contentsGravity = value\n    }\n  }\n  \n  /// A property that accesses the backing layer's background\n  @IBInspectable\n  open override var backgroundColor: UIColor? {\n    didSet {\n      layer.backgroundColor = backgroundColor?.cgColor\n    }\n  }\n  \n  /**\n   An initializer that initializes the object with a NSCoder object.\n   - Parameter aDecoder: A NSCoder instance.\n   */\n  public required init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n    prepare()\n  }\n  \n  /**\n   An initializer that initializes the object with a CGRect object.\n   If AutoLayout is used, it is better to initilize the instance\n   using the init() initializer.\n   - Parameter frame: A CGRect instance.\n   */\n  public override init(frame: CGRect) {\n    super.init(frame: frame)\n    prepare()\n  }\n  \n  open override func layoutSubviews() {\n    super.layoutSubviews()\n    layoutShape()\n    layoutVisualLayer()\n    layoutShadowPath()\n  }\n  \n  /**\n   Prepares the view instance when intialized. When subclassing,\n   it is recommended to override the prepare method\n   to initialize property values and other setup operations.\n   The super.prepare method should always be called immediately\n   when subclassing.\n   */\n  open func prepare() {\n    contentsGravity = .resizeAspectFill\n    contentScaleFactor = Screen.scale\n    backgroundColor = .white\n    prepareVisualLayer()\n  }\n}\n\nextension View {\n  /// Prepares the visualLayer property.\n  fileprivate func prepareVisualLayer() {\n    visualLayer.zPosition = 0\n    visualLayer.masksToBounds = true\n    layer.addSublayer(visualLayer)\n  }\n}\n\nextension View {\n  /// Manages the layout for the visualLayer property.\n  fileprivate func layoutVisualLayer() {\n    visualLayer.frame = bounds\n    visualLayer.cornerRadius = layer.cornerRadius\n  }\n}\n"
  },
  {
    "path": "Sources/iOS/View/ViewController.swift",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (C) 2019, CosmicMind, Inc. <http://cosmicmind.com>.\n * All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport UIKit\n\nopen class ViewController: UIViewController, Themeable {\n  open override func viewDidLoad() {\n    super.viewDidLoad()\n    prepare()\n  }\n  \n  /**\n   Prepares the view instance when intialized. When subclassing,\n   it is recommended to override the prepareView method\n   to initialize property values and other setup operations.\n   The super.prepareView method should always be called immediately\n   when subclassing.\n   */\n  open func prepare() {\n    view.clipsToBounds = true\n    view.backgroundColor = .white\n    view.contentScaleFactor = Screen.scale\n    applyCurrentTheme()\n  }\n  \n  open override func viewWillLayoutSubviews() {\n    super.viewWillLayoutSubviews()\n    layoutSubviews()\n  }\n  \n  /**\n   Calls the layout functions for the view heirarchy.\n   To execute in the order of the layout chain, override this\n   method. `layoutSubviews` should be called immediately, unless you\n   have a certain need.\n   */\n  open func layoutSubviews() { }\n  \n  /**\n   Applies given theme to the view controller.\n   - Parameter theme: A Theme.\n   */\n  open func apply(theme: Theme) {\n    view.backgroundColor = theme.background\n  }\n}\n"
  }
]