[
  {
    "path": ".bower.json",
    "content": "{\n  \"name\": \"uniflow-polymer\",\n  \"version\": \"0.6.0\",\n  \"authors\": [\n    \"Andrei Militeev <militeev@gmail.com>\"\n  ],\n  \"description\": \"A straightforward way to architect Polymer application using unidirectional data flow.\",\n  \"keywords\": [\n    \"web-component\",\n    \"polymer\",\n    \"uniflow\",\n    \"unidirectional\",\n    \"flow\"\n  ],\n  \"license\": \"https://raw.githubusercontent.com/google/uniflow-polymer/master/LICENSE\",\n  \"homepage\": \"https://github.com/google/uniflow-polymer/\",\n  \"ignore\": [\n    \"/.*\",\n    \"/test/\"\n  ],\n  \"dependencies\": {\n    \"polymer\": \"Polymer/polymer#^2.0.0\"\n  },\n  \"devDependencies\": {\n    \"app-route\": \"PolymerElements/app-route#^2.0.2\",\n    \"iron-component-page\": \"PolymerElements/iron-component-page#^3.0.0\",\n    \"iron-demo-helpers\": \"PolymerElements/iron-demo-helpers#^2.0.0\",\n    \"iron-icon\": \"PolymerElements/iron-icon#^2.0.0\",\n    \"iron-icons\": \"PolymerElements/iron-icons#^2.0.0\",\n    \"iron-test-helpers\": \"PolymerElements/iron-test-helpers#^2.0.0\",\n    \"paper-styles\": \"PolymerElements/paper-styles#^2.0.0\",\n    \"test-fixture\": \"PolymerElements/test-fixture#3.0.0-rc.1\",\n    \"web-component-tester\": \"^v6.0.0\",\n    \"todomvc-app-css\": \"^2.1.0\",\n    \"iron-localstorage\": \"PolymerElements/iron-localstorage#^2.0.0\"\n  }\n}\n"
  },
  {
    "path": ".gitignore",
    "content": "bower_components/\n.idea/"
  },
  {
    "path": "CONTRIBUTING",
    "content": "Want to contribute? Great! First, read this page (including the small print at the end).\n\n### Before you contribute\nBefore we can use your code, you must sign the\n[Google Individual Contributor License Agreement]\n(https://cla.developers.google.com/about/google-individual)\n(CLA), which you can do online. The CLA is necessary mainly because you own the\ncopyright to your changes, even after your contribution becomes part of our\ncodebase, so we need your permission to use and distribute your code. We also\nneed to be sure of various other things—for instance that you'll tell us if you\nknow that your code infringes on other people's patents. You don't have to sign\nthe CLA until after you've submitted your code for review and a member has\napproved it, but you must do it before we can put your code into our codebase.\nBefore you start working on a larger contribution, you should get in touch with\nus first through the issue tracker with your idea so that we can help out and\npossibly guide you. Coordinating up front makes it much easier to avoid\nfrustration later on.\n\n### Code reviews\nAll submissions, including submissions by project members, require review. We\nuse Github pull requests for this purpose.\n\n### The small print\nContributions made by corporations are covered by a different agreement than\nthe one above, the\n[Software Grant and Corporate Contributor License Agreement]\n(https://cla.developers.google.com/about/google-corporate).\n"
  },
  {
    "path": "LICENSE",
    "content": "\n\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2016 Google Inc.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\n"
  },
  {
    "path": "README.md",
    "content": "# UniFlow for Polymer 2.x\n\nSet of mixins to enable uni-directional data flow in Polymer application.\n\n**Important!**\n\n*This library was developed as part of internal project at Google and isn't directly affiliated with the Polymer project (although Polymer team has provided some good feedback on UniFlow implementation).*\n\n## History & Overview\n\nWhen you start working on a new Polymer application, it's easy to start and build the first few elements, and make them communicate via events and data binding, so everything looks nice and rosy. However, as the number and complexity of elements grows, it becomes increasingly difficult to manage relationships between them, trace where/when the data changes happened, and debug the problems. So this project started as an attempt by our team at Google to find a good way to architect large Polymer application. \n\nInspired by React's community Flux (and, later, Redux) architecture, we implemented a unidirectional data flow pattern (data down, events up) for Polymer. We found that when using UniFlow application code becomes more streamlined (e.g. it is clear what the responsibilities of each element are) and much easier to manage; the code has fewer bugs, and debugging is a lot more efficient. Adding new functionality no longer exponentially increases complexity.\n\nThis project was also inspired by Backbone Marionette. Backbone.js back in the days of its glory was a great library that provided a nice set of building blocks for building JavaScript applications. However, it left much of the application design, architecture and scalability to the developer, including memory management, view management, and more. Marionette brought an application architecture to Backbone, along with built in view management and memory management. It was designed to be a lightweight and flexible library of tools that sits on top of Backbone, providing the framework for building a scalable application. Uniflow strives to achieve similar goal for Polymer. \n\nWe feel that Polymer, and web components in general, is a great concept that takes interoperability and encapsulation in Web development to the next level. But it lacked the patterns for building large and complex applications, and this is the void we expect UniFlow to fill. It is still in beta, so breaking changes may be happening before the first release. However, we believe that abstractions implemented in the library can be useful for Polymer community, so we encourage people to try, fork, ask questions, send  comments, and submit pull requests.\n\n## Applicability\n\nThis library implements the architectural pattern called 'unidirectional data flow'. It works best if application logic involves complicated data management, when multiple elements need to have access to or modify the same data. Even though the pattern can be implemented just using built-in Polymer concepts, such as custom events and data binding, the UniFlow library provides a useful set of tools and abstractions, and helps to structure application code.\n\n## Implementation\n\nUniFlow is implemented as a set of mixins that developers apply to their elements. It is assumed that each application has a singleton application element that maintains state of entire application. Each element that needs access to the data is bound, directly or indirectly, to sub-tree of application state tree. Two way data binding is never used to send data up, from child to parent, so only parent elements send data to children using one way data binding. Child elements, in turn, send the events (emit actions) responding to user actions, indicating that the data may need to be modified. Special non-visual elements called action dispatchers mutate the data, then all elements listening to the data changes render new data. \n\n# API Documentation\n\n## Action Dispatcher\n\nUse UniFlow.ActionDispatcher for non-visual elements that process actions emitted by visual\nelements. Action dispatchers usually placed at the application level. Each action dispatcher\nelement gets a chance to process the action in the order the elements are present in the\nDOM tree. It is important that action dispatcher elements get two-way data binding to\napplication state as follows:\n\n   <action-dispatcher state=\"{{state}}\"></action-dispatcher>\n\nAction dispatcher elements can include nested action dispatchers, so you can have a\nhierarchical organization of action dispatchers.\n\n### Example:\n\n#### HTML:\n```html\n<dom-module id=\"parent-dispatcher\">\n<template>\n  <child-dispatcher-a state=\"{{state}}\"></child-dispatcher-a>\n  <child-dispatcher-b state=\"{{state}}\"></child-dispatcher-b>\n</template>\n</dom-module>\n```\n\n#### JavaScript:\n\n```javascript\nclass ParentDispatcher extends UniFlow.ActionDispatcher(Polymer.Element) {\n\n  static get is() { return 'parent-dispatcher'; }\n  \n  MY_ACTION(detail) {\n   // do MY_ACTION processing here\n   // return false if you want to prevent other action dispatchers from\n   // further processing of this action\n  };\n}\n\ncustomElements.define(ParentDispatcher.is, ParentDispatcher);\n```\n\n## Action Emitter\n\nWhenever element needs to emit an action, this mixin should be used. Action object must always include type property.\n\n## Application State\n\nAssign this mixin to your main application element. It provides global\nstate and functionality to maintain individual elements states. This mixin\nis responsible for notifying all state-aware elements about their state\nchanges (provided those elements have `statePath` property defined).\nOnly one element in the application is supposed to have this mixin.\n\n### Example:\n\n#### HTML:\n```html\n<template>\n  <!-- action dispatchers in the order of action processing -->\n  <action-dispatcher-a state=\"{{state}}\"></action-dispatcher-a>\n  <action-dispatcher-b state=\"{{state}}\"></action-dispatcher-b>\n  \n  <!-- state-aware elements -->\n  <some-element state-path=\"state.someElement\"></some-element>\n</template>\n```\n#### JavaScript:\n\n```javascript\nclass MyApp extends UniFlow.ApplicationState(Polymer.Element) {\n\n  static get is() { return 'my-app'; }\n\n  connectedCallback() {\n    super.connectedCallback();\n    this.state = {\n      someElement: {}\n    }\n  }\n}\n\ncustomElements.define(MayApp.is, MyApp);\n```\n\nIn the example above, `<some-element>` will receive notification of any changes to the state,\nas if it was declared as follows:\n\n```html\n<some-element state=\"[[state]]\"></some-element>\n```\n\nAlso, if `<some-element>` has `propertyA`, on element attach this property will be assigned\nthe value of `state.someElement.propertyA`, and receive all notification of the property change\nwhenever the corresponding data in state tree changes. This essentially translates to following\ndeclaration:\n\n```html\n<some-element state=\"[[state]]\"\n              propertyA=\"[[state.someElement.propertyA]]\">\n</some-element>\n```\n\nNote that data binding is one-way in both cases. Although state-aware elements can modify their\nown state, it is considered their private state and no other elements will be notified of those\nchanges.\n\n## List View\n\nThis mixin used by elements that need to render multiple models backed\nby 'list' array. You may want to use ModelView to render individual\nmodels in the list. The mixin supports element selection by setting predefined\n$selected property on list elements.\n\n### Example:\n\n#### HTML:\n\n```html\n<ul>\n  <template id=\"list-template\" is=\"dom-repeat\" items=\"[[list]]\">\n    <li id=\"[[item.id]]\">\n      <paper-checkbox checked=\"{{item.$selected}}\">\n      <model-view state-path=\"[[statePath]].list.#[[index]]\"></model-view>\n    </li>\n  </template>\n</ul>\nSelected: [[selectedCount]] items\n<paper-button on-tap=\"onDeleteTap\">Delete</paper-button>\n```\n\n#### JavaScript:\n\n```javascript\nclass ListElement extends Polymer.GestureEventListeners(UniFlow.ListView(UniFlow.StateAware(Polymer.Element))) {\n\n  static get is() { return \"list-element\"; }\n\n  onDeleteTap() {\n    this.deleteSelected();\n  }\n\n}\n\ncustomElements.define(ListElement.is, ListElement);\n```\n\nIn the example above list view element is also state-aware, meaning it has its own place\nin the application state tree. Assuming it has been declared as follows:\n\n```html\n<list-element state-path=\"state.listElement\"></list-element>\n```\n\nit will be rendering `state.listElement.list` and observing changes to it. Each `model-view`\nwithin dom-repeat template will have `state-path` property  set to\n`state.listElement.list.#<index>`  where `index` is the element's index in the array.\n\n## Model View\n\nElement rendering data represented by a single object (model) in the\napplication state should use ModelView mixin. Model View is a powerful\nconcept that encapsulates model data (likely the data received from the\nserver and to be persisted to the server if modified as a result of user\nactions), status (validity of the data, flag that data was modified,\nnotifications for the user, etc.). Auxiliary data supplied by action\ndispatchers and needed for display purposes or element's logic\nshould be defined as element’s properties. Same applies to data\ncreated/modified by the element but not intended to be persisted.\nIf `StateAware` mixin is used along with `ModelView`, you can take advantage\nof statePath property that indicates path to the element's state in the\napplication state tree. Whenever any data is mutated by action dispatchers\nat statePath or below, the element will receive notification of its\nproperties' change (even if there is no explicit binding for those\nproperties). See `UniFlow.StateAware` for more details and example.\nModelView mixin defines some properties that are intended to be overridden\nin the elements:\n\n+ `validation` property allows to specify validation rules\nthat will be applied when validateModel() method is called. As a result of\nthis method validation status will be updated to indicate result for each\nmodel field that has validation rule associated with it.\n+ `saveAction` property indicates which action should be emitted when\nsaveModel method is called to perform save of the model.\n+ `getMessage` should be overridden with the function returning message\nstring for given error code (to translate validation error code to message)\n\n\n### Example:\n\n#### HTML:\n\n```html\n<template>\n Model: [[model.id]]\n <paper-input value=\"{{model.name}}\"\n              label=\"Name\"\n              invalid=\"[[status.validation.name.invalid]]\"\n              error-message=\"[[status.validation.name.errorMessage]]\">\n </paper-input>\n <paper-button on-tap=\"onSaveTap\">Save</paper-button>\n</template>\n```\n\n#### JavaScript:\n\n```javascript\nclass MyModel extends Polymer.GestureEventListeners(UniFlow.ModelView(Polymer.Element)) {\n\n  static get is() { return \"my-model\"; }\n  \n  get saveAction() { return 'MY_SAVE'; }\n  \n  get validation() { \n    return {\n      name: (value) => {\n        if (!value || !value.trim()) {\n          return 'Name is not specified';\n        }\n      }\n    }\n  }\n  \n  connectedCallback() {\n   super.connectedCallback();\n   this.fetchData();\n  },\n  \n  fetchData() {\n   this.emitAction({\n     type: 'MY_FETCH',\n     path: 'model'\n   });\n  },\n  \n  onSaveTap() {\n   this.validateAndSave();\n  }\n}\n\ncustomElements.define(MyModel.is, MyModel);\n```\n\nIn the example above model view has input field for `name` property and Save button. On\nelement attach the action is emitted to fetch the model's data. Note that in `emitAction()` method\nthe path is specified as `'model'`. ActionEmitter mixin is responsible of expanding the path\nwith element's state path, ensuring that when action dispatcher gets to process the action, the\npath contains full path in the state tree. So assuming that `my-model` is declared as follows:\n\n```html\n<my-model state-path=\"state.myModel\"></my-model>\n```\n\nthe path in `MY_FETCH` action gets expanded to `state.myModel.model`.\n\n`validation` property is an object that contains methods for fields validation. The keys in\nthis object should match model field names, the values are validation methods. Method receives\ncurrent value of the field and should return non-falsy value (string or error code) if the value\nof the field didn't pass validation. `status.validation` object will be populated with the results\nof validation with the keys matching field names and values being objects containing two fields:\n- `invalid`: true when the value is not valid\n- `errorMessage`: the message to show to user\n\n\nSo in the example above if user clicks on Save button with name not entered, they will get\n'Name is not specified' error message on the input element. When the name is non-empty, validation\nwill pass and `MY_SAVE` action will be emitted with model passed as a parameter and `'model'` as\npath.\n\n## State Aware\n\n Key mixin that must be assigned to all elements that need to access\n application state and/or have access to the application element. The element is\n notified of any changes to application's state, as well as all its properties\n when they're modified by state mutator elements. `state-path` property must\n be used to identify path to element's state in application state tree. \n\n\n### Example:\n\n#### HTML:\n\n```html\n<template>\n <div>Value A: [[state.valueA]]</div>\n <div>Value B: [[valueB]]</div>\n</template>\n```\n\n#### JavaScript:\n\n```javascript\nclass MyElement extends UniFlow.StateAware(Polymer.Element) {\n\n  static get is() { return 'my-element'; }\n  \n  properties: {\n    valueB: String\n  }\n}\n\ncustomElements.define(MyElement.is, MyElement);\n```\n\nWhen above element is declared as follows:\n\n```html\n<my-element state-path=\"state.myElement\"></my-element>\n```\n\nit will be notified about changes (and render those) to `state.valueA` or\n`state.myElement.valueB` in action dispatchers or other state mutating\nelements.\n\n## State Mutator\n\nSome non-visual elements, like action dispatchers, need to modify application\nstate, in which case they should have this mixin assigned. Implements state-\naware and re-declares state property with notify attribute. State mutator elements\nare only supposed to exist at the application level.\n\n"
  },
  {
    "path": "action-dispatcher.html",
    "content": "<!--\nCopyright 2016 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n-->\n\n<link rel=\"import\" href=\"../polymer/polymer-element.html\">\n<link rel=\"import\" href=\"state-aware.html\">\n<link rel=\"import\" href=\"state-mutator.html\">\n\n\n<script type=\"text/javascript\">\n  var UniFlow = window.UniFlow || {};\n\n  /**\n   Use UniFlow.ActionDispatcher for non-visual elements that process actions emitted by visual\n   elements. Action dispatchers usually placed at the application level. Each action dispatcher\n   element gets a chance to process the action in the order the elements are present in the\n   DOM tree. It is important that action dispatcher elements get two-way data binding to\n   application state as follows:\n\n   <action-dispatcher state=\"{{state}}\"></action-dispatcher>\n\n   Action dispatcher elements can include nested action dispatchers, so you can have a\n   hierarchical organization of action dispatchers.\n\n   ### Example:\n\n   #### HTML:\n\n   <dom-module id=\"parent-dispatcher\">\n   <template>\n   <child-dispatcher-a state=\"{{state}}\"></child-dispatcher-a>\n   <child-dispatcher-b state=\"{{state}}\"></child-dispatcher-b>\n   </template>\n   </dom-module>\n\n   #### JavaScript:\n   class ParentDispatcher extends UniFlow.ActionDispatcher(Polymer.Element) {\n         static get is() { return 'parent-dispatcher'; }\n\n         MY_ACTION(detail) {\n           // do MY_ACTION processing here\n           // return false if you want to prevent other action dispatchers from\n           // further processing of this action\n         };\n       }\n\n   customElements.define(ParentDispatcher.is, ParentDispatcher);\n\n   @polymer\n   @mixinFunction\n   @appliesMixin UniFlow.StateMutator\n   */\n  UniFlow.ActionDispatcher = Polymer.dedupingMixin((base) =>\n      class extends UniFlow.StateMutator(base) {\n        static get properties() {\n          return {\n            actionDispatcher: {\n              type: Boolean,\n              value: true,\n              reflectToAttribute: true\n            }\n          }\n        }\n\n        /**\n         * Dispatches action by invoking the method with the name that matches\n         * action type (`detail.type`) passing detail object as a parameter;\n         * also selects all children action dispatchers in the element's DOM tree and\n         * invokes dispatchAction method on them. False returned by an action dispatcher method\n         * results in dispatchAction method returning false (which in turn stops further processing\n         * of the action by other action dispatchers).\n         *\n         * @param {{type: string}} detail\n         * @return {boolean}\n         */\n        dispatchAction(detail) {\n          if (this[detail.type] && typeof this[detail.type] === 'function') {\n            if (this[detail.type](detail) === false) {\n              return false;\n            }\n          }\n          //dispatch action on nested dispatchers\n          var nodes = this.root ? this.root.querySelectorAll('[action-dispatcher]') : [];\n          return Array.prototype.every.call(nodes,\n              (element) => element.dispatchAction(detail) !== false);\n        }\n\n      });\n</script>"
  },
  {
    "path": "action-emitter.html",
    "content": "<!--\nCopyright 2016 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n-->\n\n<link rel=\"import\" href=\"../polymer/polymer-element.html\">\n\n\n<script>\n  var UniFlow = window.UniFlow || {};\n\n  /**\n   Whenever element needs to emit an action, this mixin should be applied.\n   Action object must always include type property.\n\n   @polymer\n   @mixinFunction\n  */\n  UniFlow.ActionEmitter = Polymer.dedupingMixin((base) =>\n    class extends base {\n\n      /**\n       * Fired when action is emitted to be processed by action dispatcher.\n       *\n       * @event dispatch-action\n       */\n\n      /**\n       * Emits the action described by detail parameter. Detail object must always\n       * include type property. To emit the action we use custom event\n       * mechanism. Application element listens to the `dispatch-action` event and\n       * invokes `dispatchAction` methods for all action dispatchers associated with\n       * the application. Make sure your element is attached to DOM tree, otherwise\n       * event will never reach your application element. It is a good practice to\n       * ensure that `state` property is initialized (for state-aware elements) before\n       * emitting any actions (as `state` property is initialized on attach).\n       *\n       * @param {*} detail\n       */\n      emitAction(detail) {\n        if (detail.path && this.statePath) {\n          if (!detail.path.startsWith('state.')) {\n            detail.path = this.statePath + '.' + detail.path;\n          }\n        }\n        \n        this.dispatchEvent(new CustomEvent('dispatch-action', {\n          detail,\n          bubbles: true,\n          composed: true\n        }));\n      }\n\n    });\n</script>"
  },
  {
    "path": "all-imports.html",
    "content": "<link rel=\"import\" href=\"action-dispatcher.html\">\n<link rel=\"import\" href=\"action-emitter.html\">\n<link rel=\"import\" href=\"application-state.html\">\n<link rel=\"import\" href=\"list-view.html\">\n<link rel=\"import\" href=\"model-view.html\">\n<link rel=\"import\" href=\"state-aware.html\">\n<link rel=\"import\" href=\"state-mutator.html\">\n"
  },
  {
    "path": "analysis.json",
    "content": "{\n  \"schema_version\": \"1.0.0\",\n  \"mixins\": [\n    {\n      \"description\": \"   Key mixin that must be assigned to all elements that need to access\\n   application state and/or have access to the application element. The element is\\n   notified of any changes to application's state, as well as all its properties\\n   when they're modified by state mutator elements. `state-path` property must\\n   be used to identify path to element's state in application state tree. \\n\\n   ### Example:\\n\\n   #### HTML:\\n\\n      <template>\\n\\n        <div>Value A: [[state.valueA]]</div>\\n        <div>Value B: [[valueB]]</div>\\n\\n      </template>\\n\\n   #### JavaScript:\\n\\n      class MyElement extends UniFlow.StateAware(Polymer.Element) {\\n        static get is() { return 'my-element'; }\\n\\n        static get properties() {\\n          return {\\n            valueB: String\\n          }\\n        }\\n      }\\n\\n      customElement.define(MyElement.is, MyElement);\\n\\n   When above element is declared as follows:\\n\\n      <my-element state-path=\\\"state.myElement\\\"></my-element>\\n\\n   it will be notified about changes (and render those) to `state.valueA` or\\n   `state.myElement.valueB` in action dispatchers or other state mutating\\n   elements.\\n\\n   \",\n      \"summary\": \"\",\n      \"path\": \"state-aware.html\",\n      \"properties\": [\n        {\n          \"name\": \"state\",\n          \"type\": \"Object\",\n          \"description\": \"Application state, shared among application and all state-aware elements.\\nThis property is initialized when element is attached.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 74,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 76,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          }\n        },\n        {\n          \"name\": \"statePath\",\n          \"type\": \"string\",\n          \"description\": \"Path to element state in the application state tree.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 81,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 83,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          }\n        },\n        {\n          \"name\": \"stateAware\",\n          \"type\": \"boolean\",\n          \"description\": \"\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 85,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 89,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          },\n          \"defaultValue\": \"true\"\n        },\n        {\n          \"name\": \"application\",\n          \"type\": \"Object\",\n          \"description\": \"Application-level object that allows all state-aware objects access\\nto application element. This property is shared among all state-aware\\nelements and has element field initialized with reference to application\\nelement. Any state-aware element can access application element using\\n`getApplication()` method. Also, all state-aware elements\\nadd themselves to `application.stateAwareElements` array on attach (and\\nremove on detach); this list is used to send notification about\\nelement state changes.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 101,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 107,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          }\n        }\n      ],\n      \"methods\": [\n        {\n          \"name\": \"connectedCallback\",\n          \"description\": \"Adds this element to the list of state-aware elements in the application.\\nSets the value of state property to the state of the application element.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 116,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 132,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": []\n        },\n        {\n          \"name\": \"disconnectedCallback\",\n          \"description\": \"Removes this element from the list of state-aware elements in the\\napplication.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 138,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 145,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": []\n        },\n        {\n          \"name\": \"getApplication\",\n          \"description\": \"Returns application element.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 151,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 153,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [],\n          \"return\": {\n            \"type\": \"Element\"\n          }\n        }\n      ],\n      \"staticMethods\": [],\n      \"demos\": [],\n      \"metadata\": {},\n      \"sourceRange\": {\n        \"start\": {\n          \"line\": 65,\n          \"column\": 2\n        },\n        \"end\": {\n          \"line\": 155,\n          \"column\": 6\n        }\n      },\n      \"privacy\": \"public\",\n      \"name\": \"UniFlow.StateAware\",\n      \"attributes\": [\n        {\n          \"name\": \"state\",\n          \"description\": \"Application state, shared among application and all state-aware elements.\\nThis property is initialized when element is attached.\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 74,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 76,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"Object\"\n        },\n        {\n          \"name\": \"state-path\",\n          \"description\": \"Path to element state in the application state tree.\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 81,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 83,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"string\"\n        },\n        {\n          \"name\": \"state-aware\",\n          \"description\": \"\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 85,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 89,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"boolean\"\n        },\n        {\n          \"name\": \"application\",\n          \"description\": \"Application-level object that allows all state-aware objects access\\nto application element. This property is shared among all state-aware\\nelements and has element field initialized with reference to application\\nelement. Any state-aware element can access application element using\\n`getApplication()` method. Also, all state-aware elements\\nadd themselves to `application.stateAwareElements` array on attach (and\\nremove on detach); this list is used to send notification about\\nelement state changes.\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 101,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 107,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"Object\"\n        }\n      ],\n      \"events\": [],\n      \"styling\": {\n        \"cssVariables\": [],\n        \"selectors\": []\n      },\n      \"slots\": []\n    },\n    {\n      \"description\": \"   Some non-visual elements, like action dispatchers, need to modify application\\n   state, in which case they should have this mixin applied. Implements state-\\n   aware and re-declares state property with notify attribute. State mutator elements\\n   are only supposed to exist at the application level.\\n\\n   \",\n      \"summary\": \"\",\n      \"path\": \"state-mutator.html\",\n      \"properties\": [\n        {\n          \"name\": \"state\",\n          \"type\": \"Object\",\n          \"description\": \"Application state.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 41,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 44,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {\n              \"notify\": true\n            }\n          }\n        },\n        {\n          \"name\": \"statePath\",\n          \"type\": \"string\",\n          \"description\": \"Path to element state in the application state tree.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 81,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 83,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          },\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"stateAware\",\n          \"type\": \"boolean\",\n          \"description\": \"\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 85,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 89,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          },\n          \"defaultValue\": \"true\",\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"application\",\n          \"type\": \"Object\",\n          \"description\": \"Application-level object that allows all state-aware objects access\\nto application element. This property is shared among all state-aware\\nelements and has element field initialized with reference to application\\nelement. Any state-aware element can access application element using\\n`getApplication()` method. Also, all state-aware elements\\nadd themselves to `application.stateAwareElements` array on attach (and\\nremove on detach); this list is used to send notification about\\nelement state changes.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 101,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 107,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          },\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        }\n      ],\n      \"methods\": [\n        {\n          \"name\": \"connectedCallback\",\n          \"description\": \"Adds this element to the list of state-aware elements in the application.\\nSets the value of state property to the state of the application element.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 116,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 132,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [],\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"disconnectedCallback\",\n          \"description\": \"Removes this element from the list of state-aware elements in the\\napplication.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 138,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 145,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [],\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"getApplication\",\n          \"description\": \"Returns application element.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 151,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 153,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [],\n          \"return\": {\n            \"type\": \"Element\"\n          },\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        }\n      ],\n      \"staticMethods\": [],\n      \"demos\": [],\n      \"metadata\": {},\n      \"sourceRange\": {\n        \"start\": {\n          \"line\": 33,\n          \"column\": 2\n        },\n        \"end\": {\n          \"line\": 48,\n          \"column\": 6\n        }\n      },\n      \"privacy\": \"public\",\n      \"name\": \"UniFlow.StateMutator\",\n      \"attributes\": [\n        {\n          \"name\": \"state\",\n          \"description\": \"Application state.\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 41,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 44,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"Object\"\n        },\n        {\n          \"name\": \"state-path\",\n          \"description\": \"Path to element state in the application state tree.\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 81,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 83,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"string\",\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"state-aware\",\n          \"description\": \"\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 85,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 89,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"boolean\",\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"application\",\n          \"description\": \"Application-level object that allows all state-aware objects access\\nto application element. This property is shared among all state-aware\\nelements and has element field initialized with reference to application\\nelement. Any state-aware element can access application element using\\n`getApplication()` method. Also, all state-aware elements\\nadd themselves to `application.stateAwareElements` array on attach (and\\nremove on detach); this list is used to send notification about\\nelement state changes.\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 101,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 107,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"Object\",\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        }\n      ],\n      \"events\": [],\n      \"styling\": {\n        \"cssVariables\": [],\n        \"selectors\": []\n      },\n      \"slots\": [],\n      \"mixins\": [\n        \"UniFlow.StateAware\"\n      ]\n    },\n    {\n      \"description\": \"   Use UniFlow.ActionDispatcher for non-visual elements that process actions emitted by visual\\n   elements. Action dispatchers usually placed at the application level. Each action dispatcher\\n   element gets a chance to process the action in the order the elements are present in the\\n   DOM tree. It is important that action dispatcher elements get two-way data binding to\\n   application state as follows:\\n\\n   <action-dispatcher state=\\\"{{state}}\\\"></action-dispatcher>\\n\\n   Action dispatcher elements can include nested action dispatchers, so you can have a\\n   hierarchical organization of action dispatchers.\\n\\n   ### Example:\\n\\n   #### HTML:\\n\\n   <dom-module id=\\\"parent-dispatcher\\\">\\n   <template>\\n   <child-dispatcher-a state=\\\"{{state}}\\\"></child-dispatcher-a>\\n   <child-dispatcher-b state=\\\"{{state}}\\\"></child-dispatcher-b>\\n   </template>\\n   </dom-module>\\n\\n   #### JavaScript:\\n   class ParentDispatcher extends UniFlow.ActionDispatcher(Polymer.Element) {\\n         static get is() { return 'parent-dispatcher'; }\\n\\n         MY_ACTION(detail) {\\n           // do MY_ACTION processing here\\n           // return false if you want to prevent other action dispatchers from\\n           // further processing of this action\\n         };\\n       }\\n\\n   customElements.define(ParentDispatcher.is, ParentDispatcher);\\n\\n   \",\n      \"summary\": \"\",\n      \"path\": \"action-dispatcher.html\",\n      \"properties\": [\n        {\n          \"name\": \"state\",\n          \"type\": \"Object\",\n          \"description\": \"Application state.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-mutator.html\",\n            \"start\": {\n              \"line\": 41,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 44,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {\n              \"notify\": true\n            }\n          },\n          \"inheritedFrom\": \"UniFlow.StateMutator\"\n        },\n        {\n          \"name\": \"statePath\",\n          \"type\": \"string\",\n          \"description\": \"Path to element state in the application state tree.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 81,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 83,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          },\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"stateAware\",\n          \"type\": \"boolean\",\n          \"description\": \"\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 85,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 89,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          },\n          \"defaultValue\": \"true\",\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"application\",\n          \"type\": \"Object\",\n          \"description\": \"Application-level object that allows all state-aware objects access\\nto application element. This property is shared among all state-aware\\nelements and has element field initialized with reference to application\\nelement. Any state-aware element can access application element using\\n`getApplication()` method. Also, all state-aware elements\\nadd themselves to `application.stateAwareElements` array on attach (and\\nremove on detach); this list is used to send notification about\\nelement state changes.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 101,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 107,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          },\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"actionDispatcher\",\n          \"type\": \"boolean\",\n          \"description\": \"\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 68,\n              \"column\": 12\n            },\n            \"end\": {\n              \"line\": 72,\n              \"column\": 13\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          },\n          \"defaultValue\": \"true\"\n        }\n      ],\n      \"methods\": [\n        {\n          \"name\": \"connectedCallback\",\n          \"description\": \"Adds this element to the list of state-aware elements in the application.\\nSets the value of state property to the state of the application element.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 116,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 132,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [],\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"disconnectedCallback\",\n          \"description\": \"Removes this element from the list of state-aware elements in the\\napplication.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 138,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 145,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [],\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"getApplication\",\n          \"description\": \"Returns application element.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 151,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 153,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [],\n          \"return\": {\n            \"type\": \"Element\"\n          },\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"dispatchAction\",\n          \"description\": \"Dispatches action by invoking the method with the name that matches\\naction type (`detail.type`) passing detail object as a parameter;\\nalso selects all children action dispatchers in the element's DOM tree and\\ninvokes dispatchAction method on them. False returned by an action dispatcher method\\nresults in dispatchAction method returning false (which in turn stops further processing\\nof the action by other action dispatchers).\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 87,\n              \"column\": 8\n            },\n            \"end\": {\n              \"line\": 97,\n              \"column\": 9\n            }\n          },\n          \"metadata\": {},\n          \"params\": [\n            {\n              \"name\": \"detail\",\n              \"type\": \"{type: string}\"\n            }\n          ],\n          \"return\": {\n            \"type\": \"boolean\"\n          }\n        }\n      ],\n      \"staticMethods\": [],\n      \"demos\": [],\n      \"metadata\": {},\n      \"sourceRange\": {\n        \"start\": {\n          \"line\": 64,\n          \"column\": 2\n        },\n        \"end\": {\n          \"line\": 99,\n          \"column\": 8\n        }\n      },\n      \"privacy\": \"public\",\n      \"name\": \"UniFlow.ActionDispatcher\",\n      \"attributes\": [\n        {\n          \"name\": \"state\",\n          \"description\": \"Application state.\",\n          \"sourceRange\": {\n            \"file\": \"state-mutator.html\",\n            \"start\": {\n              \"line\": 41,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 44,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"Object\",\n          \"inheritedFrom\": \"UniFlow.StateMutator\"\n        },\n        {\n          \"name\": \"state-path\",\n          \"description\": \"Path to element state in the application state tree.\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 81,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 83,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"string\",\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"state-aware\",\n          \"description\": \"\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 85,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 89,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"boolean\",\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"application\",\n          \"description\": \"Application-level object that allows all state-aware objects access\\nto application element. This property is shared among all state-aware\\nelements and has element field initialized with reference to application\\nelement. Any state-aware element can access application element using\\n`getApplication()` method. Also, all state-aware elements\\nadd themselves to `application.stateAwareElements` array on attach (and\\nremove on detach); this list is used to send notification about\\nelement state changes.\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 101,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 107,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"Object\",\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"action-dispatcher\",\n          \"description\": \"\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 68,\n              \"column\": 12\n            },\n            \"end\": {\n              \"line\": 72,\n              \"column\": 13\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"boolean\"\n        }\n      ],\n      \"events\": [],\n      \"styling\": {\n        \"cssVariables\": [],\n        \"selectors\": []\n      },\n      \"slots\": [],\n      \"mixins\": [\n        \"UniFlow.StateMutator\"\n      ]\n    },\n    {\n      \"description\": \"   Whenever element needs to emit an action, this mixin should be applied.\\n   Action object must always include type property.\\n\\n   \",\n      \"summary\": \"\",\n      \"path\": \"action-emitter.html\",\n      \"properties\": [],\n      \"methods\": [\n        {\n          \"name\": \"emitAction\",\n          \"description\": \"Emits the action described by detail parameter. Detail object must always\\ninclude type property. To emit the action we use custom event\\nmechanism. Application element listens to the `dispatch-action` event and\\ninvokes `dispatchAction` methods for all action dispatchers associated with\\nthe application. Make sure your element is attached to DOM tree, otherwise\\nevent will never reach your application element. It is a good practice to\\nensure that `state` property is initialized (for state-aware elements) before\\nemitting any actions (as `state` property is initialized on attach).\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 50,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 62,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [\n            {\n              \"name\": \"detail\",\n              \"type\": \"*\"\n            }\n          ]\n        }\n      ],\n      \"staticMethods\": [],\n      \"demos\": [],\n      \"metadata\": {},\n      \"sourceRange\": {\n        \"start\": {\n          \"line\": 29,\n          \"column\": 2\n        },\n        \"end\": {\n          \"line\": 64,\n          \"column\": 6\n        }\n      },\n      \"privacy\": \"public\",\n      \"name\": \"UniFlow.ActionEmitter\",\n      \"attributes\": [],\n      \"events\": [\n        {\n          \"type\": \"CustomEvent\",\n          \"name\": \"dispatch-action\",\n          \"description\": \"dispatch-action\",\n          \"metadata\": {}\n        }\n      ],\n      \"styling\": {\n        \"cssVariables\": [],\n        \"selectors\": []\n      },\n      \"slots\": []\n    },\n    {\n      \"description\": \"   Apply this mixin to your main application element. It provides global\\n   state and functionality to maintain individual elements states. This mixin\\n   is responsible for notifying all state-aware elements about their state\\n   changes (provided those elements have `statePath` property defined).\\n   Only one element in the application is supposed to have this mixin.\\n\\n   ### Example:\\n\\n   #### HTML:\\n\\n       <template>\\n\\n         <!-- action dispatchers in the order of action processing -->\\n         <action-dispatcher-a state=\\\"{{state}}\\\"></action-dispatcher-a>\\n         <action-dispatcher-b state=\\\"{{state}}\\\"></action-dispatcher-b>\\n\\n         <!-- state-aware elements -->\\n         <some-element state-path=\\\"state.someElement\\\"></some-element>\\n\\n       </template>\\n\\n   #### JavaScript:\\n       class MyApp extends UniFlow.ApplicationState(Polymer.Element) {\\n         static get is() { return 'my-app'; }\\n\\n         connectedCallback() {\\n           super.ConnectedCallback();\\n\\n           this.state = {\\n             someElement: {}\\n           }\\n         }\\n       }\\n\\n       customElements.define(MyApp.is,MyApp);\\n\\n   In the example above, `<some-element>` will receive notification of any changes to the state,\\n   as if it was declared as follows:\\n\\n       <some-element state=\\\"[[state]]\\\"></some-element>\\n\\n   Also, if `<some-element>` has `propertyA`, on element attach this property will be assigned\\n   the value of `state.someElement.propertyA`, and receive all notification of the property change\\n   whenever the corresponding data in state tree changes. This essentially translates to following\\n   declaration:\\n\\n       <some-element state=\\\"[[state]]\\\"\\n                     propertyA=\\\"[[state.someElement.propertyA]]\\\">\\n       </some-element>\\n\\n   Note that data binding is one-way in both cases. Although state-aware elements can modify their\\n   own state, it is considered their private state and no other elements will be notified of those\\n   changes.\\n\\n   \",\n      \"summary\": \"\",\n      \"path\": \"application-state.html\",\n      \"properties\": [\n        {\n          \"name\": \"state\",\n          \"type\": \"Object\",\n          \"description\": \"Application state.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-mutator.html\",\n            \"start\": {\n              \"line\": 41,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 44,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {\n              \"notify\": true\n            }\n          },\n          \"inheritedFrom\": \"UniFlow.StateMutator\"\n        },\n        {\n          \"name\": \"statePath\",\n          \"type\": \"string\",\n          \"description\": \"Path to element state in the application state tree.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 81,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 83,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          },\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"stateAware\",\n          \"type\": \"boolean\",\n          \"description\": \"\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 85,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 89,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          },\n          \"defaultValue\": \"true\",\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"application\",\n          \"type\": \"Object\",\n          \"description\": \"Application-level object that allows all state-aware objects access\\nto application element. This property is shared among all state-aware\\nelements and has element field initialized with reference to application\\nelement. Any state-aware element can access application element using\\n`getApplication()` method. Also, all state-aware elements\\nadd themselves to `application.stateAwareElements` array on attach (and\\nremove on detach); this list is used to send notification about\\nelement state changes.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 101,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 107,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          },\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"actionDispatcher\",\n          \"type\": \"boolean\",\n          \"description\": \"\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"action-dispatcher.html\",\n            \"start\": {\n              \"line\": 68,\n              \"column\": 12\n            },\n            \"end\": {\n              \"line\": 72,\n              \"column\": 13\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          },\n          \"defaultValue\": \"true\",\n          \"inheritedFrom\": \"UniFlow.ActionDispatcher\"\n        }\n      ],\n      \"methods\": [\n        {\n          \"name\": \"connectedCallback\",\n          \"description\": \"Adds this element to the list of state-aware elements in the application.\\nSets the value of state property to the state of the application element.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 116,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 132,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [],\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"disconnectedCallback\",\n          \"description\": \"Removes this element from the list of state-aware elements in the\\napplication.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 138,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 145,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [],\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"getApplication\",\n          \"description\": \"Returns application element.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 151,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 153,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [],\n          \"return\": {\n            \"type\": \"Element\"\n          },\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"dispatchAction\",\n          \"description\": \"Dispatches action by invoking the method with the name that matches\\naction type (`detail.type`) passing detail object as a parameter;\\nalso selects all children action dispatchers in the element's DOM tree and\\ninvokes dispatchAction method on them. False returned by an action dispatcher method\\nresults in dispatchAction method returning false (which in turn stops further processing\\nof the action by other action dispatchers).\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"action-dispatcher.html\",\n            \"start\": {\n              \"line\": 87,\n              \"column\": 8\n            },\n            \"end\": {\n              \"line\": 97,\n              \"column\": 9\n            }\n          },\n          \"metadata\": {},\n          \"params\": [\n            {\n              \"name\": \"detail\",\n              \"type\": \"{type: string}\"\n            }\n          ],\n          \"return\": {\n            \"type\": \"boolean\"\n          },\n          \"inheritedFrom\": \"UniFlow.ActionDispatcher\"\n        },\n        {\n          \"name\": \"onDispatchAction_\",\n          \"description\": \"Application state listens to dispatch-action method and invokes\\ndispatchAction method on itself (which in turn invokes dispatchAction\\non all action dispatchers declared within application element).\",\n          \"privacy\": \"private\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 102,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 104,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [\n            {\n              \"name\": \"event\",\n              \"type\": \"!Event\"\n            }\n          ]\n        },\n        {\n          \"name\": \"stateChanged_\",\n          \"description\": \"Called when state.* changes. Notifies state-aware elements of their\\nstate changes, if applicable.\",\n          \"privacy\": \"private\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 113,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 115,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [\n            {\n              \"name\": \"change\",\n              \"type\": \"!Object\",\n              \"description\": \"the Polymer change event for the path\"\n            }\n          ]\n        },\n        {\n          \"name\": \"notifyStateAwareElements_\",\n          \"description\": \"Iterates through the array of state-aware elements in the application\\nand notifies them about their state change, if applicable. Note that\\nstate-aware elements must be attached to DOM tree in order to receive\\nnotifications.\",\n          \"privacy\": \"private\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 126,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 149,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [\n            {\n              \"name\": \"change\"\n            }\n          ]\n        },\n        {\n          \"name\": \"ready\",\n          \"description\": \"Sets application.element value to this element (so all state-aware elements\\nhave access to application element). Registers event listener to dispatch-action event.\",\n          \"privacy\": \"protected\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 155,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 159,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": []\n        }\n      ],\n      \"staticMethods\": [],\n      \"demos\": [],\n      \"metadata\": {},\n      \"sourceRange\": {\n        \"start\": {\n          \"line\": 85,\n          \"column\": 2\n        },\n        \"end\": {\n          \"line\": 161,\n          \"column\": 6\n        }\n      },\n      \"privacy\": \"public\",\n      \"name\": \"UniFlow.ApplicationState\",\n      \"attributes\": [\n        {\n          \"name\": \"state\",\n          \"description\": \"Application state.\",\n          \"sourceRange\": {\n            \"file\": \"state-mutator.html\",\n            \"start\": {\n              \"line\": 41,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 44,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"Object\",\n          \"inheritedFrom\": \"UniFlow.StateMutator\"\n        },\n        {\n          \"name\": \"state-path\",\n          \"description\": \"Path to element state in the application state tree.\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 81,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 83,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"string\",\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"state-aware\",\n          \"description\": \"\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 85,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 89,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"boolean\",\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"application\",\n          \"description\": \"Application-level object that allows all state-aware objects access\\nto application element. This property is shared among all state-aware\\nelements and has element field initialized with reference to application\\nelement. Any state-aware element can access application element using\\n`getApplication()` method. Also, all state-aware elements\\nadd themselves to `application.stateAwareElements` array on attach (and\\nremove on detach); this list is used to send notification about\\nelement state changes.\",\n          \"sourceRange\": {\n            \"file\": \"state-aware.html\",\n            \"start\": {\n              \"line\": 101,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 107,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"Object\",\n          \"inheritedFrom\": \"UniFlow.StateAware\"\n        },\n        {\n          \"name\": \"action-dispatcher\",\n          \"description\": \"\",\n          \"sourceRange\": {\n            \"file\": \"action-dispatcher.html\",\n            \"start\": {\n              \"line\": 68,\n              \"column\": 12\n            },\n            \"end\": {\n              \"line\": 72,\n              \"column\": 13\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"boolean\",\n          \"inheritedFrom\": \"UniFlow.ActionDispatcher\"\n        }\n      ],\n      \"events\": [],\n      \"styling\": {\n        \"cssVariables\": [],\n        \"selectors\": []\n      },\n      \"slots\": [],\n      \"mixins\": [\n        \"UniFlow.ActionDispatcher\"\n      ]\n    },\n    {\n      \"description\": \"   This mixin used by elements that need to render multiple models backed\\n   by 'list' array. You may want to use ModelView to render individual\\n   models in the list. The mixin supports element selection by setting predefined\\n   $selected property on list elements.\\n\\n   ### Example:\\n\\n   #### HTML:\\n\\n       <ul>\\n         <template id=\\\"list-template\\\" is=\\\"dom-repeat\\\" items=\\\"[[list]]\\\">\\n           <li id=\\\"[[item.id]]\\\">\\n             <paper-checkbox checked=\\\"{{item.$selected}}\\\">\\n             <model-view state-path=\\\"[[statePath]].list.#[[index]]\\\"></model-view>\\n           </li>\\n         </template>\\n       </ul>\\n       Selected: [[selectedCount]] items\\n       <paper-button on-tap=\\\"onDeleteTap\\\">Delete</paper-button>\\n\\n   #### JavaScript:\\n       class ListElement extends UniFlow.StateAware(UniFlow.ListView(Polymer.Element)) {\\n         static get is() { return \\\"list-element\\\"; }\\n\\n         onDeleteTap() {\\n           this.deleteSelected();\\n         }\\n       }\\n\\n       customElements.define(ListElement.is, ListElement);\\n\\n   In the example above list view element is also state-aware, meaning it has its own place\\n   in the application state tree. Assuming it has been declared as follows:\\n\\n       <list-element state-path=\\\"state.listElement\\\"></list-element>\\n\\n   it will be rendering `state.listElement.list` and observing changes to it. Each `model-view`\\n   within dom-repeat template will have `state-path` property  set to\\n   `state.listElement.list.#<index>`  where `index` is the element's index in the array.\\n\\n\\n   \",\n      \"summary\": \"\",\n      \"path\": \"list-view.html\",\n      \"properties\": [\n        {\n          \"name\": \"list\",\n          \"type\": \"Array\",\n          \"description\": \"Array which data is to be rendered by the element.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 78,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 81,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          },\n          \"defaultValue\": \"[]\"\n        },\n        {\n          \"name\": \"selectedCount\",\n          \"type\": \"number\",\n          \"description\": \"If element supports item selection (using meta-property $selected) then\\nselectedCount property will keep track of number of selected items.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 87,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 91,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {\n              \"notify\": true\n            }\n          },\n          \"defaultValue\": \"0\"\n        },\n        {\n          \"name\": \"deleteAction\",\n          \"type\": \"string\",\n          \"description\": \"Action name that will be emitted when deleteSelected method is called\\nwithout parameter.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 97,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 97,\n              \"column\": 30\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          }\n        }\n      ],\n      \"methods\": [\n        {\n          \"name\": \"emitAction\",\n          \"description\": \"Emits the action described by detail parameter. Detail object must always\\ninclude type property. To emit the action we use custom event\\nmechanism. Application element listens to the `dispatch-action` event and\\ninvokes `dispatchAction` methods for all action dispatchers associated with\\nthe application. Make sure your element is attached to DOM tree, otherwise\\nevent will never reach your application element. It is a good practice to\\nensure that `state` property is initialized (for state-aware elements) before\\nemitting any actions (as `state` property is initialized on attach).\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"action-emitter.html\",\n            \"start\": {\n              \"line\": 50,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 62,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [\n            {\n              \"name\": \"detail\",\n              \"type\": \"*\"\n            }\n          ],\n          \"inheritedFrom\": \"UniFlow.ActionEmitter\"\n        },\n        {\n          \"name\": \"itemChanged_\",\n          \"description\": \"Whenever list is set or mutated (elements added/removed), as well as\\nmeta-property $selected is modified, updates selectedCount.\",\n          \"privacy\": \"private\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 114,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 121,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [\n            {\n              \"name\": \"change\",\n              \"type\": \"!Object\"\n            }\n          ]\n        },\n        {\n          \"name\": \"updateSelectedCount_\",\n          \"description\": \"Updates selectedCount property of the element by iterating the list and\\ncounting each item that has meta-property $selected set.\",\n          \"privacy\": \"private\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 128,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 134,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": []\n        },\n        {\n          \"name\": \"deleteSelected\",\n          \"description\": \"Emits deleteAction for each selected element in the list (for which\\nmeta-property $selected is set).\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 143,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 157,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [\n            {\n              \"name\": \"deleteAction\",\n              \"type\": \"string=\",\n              \"description\": \"Action type for the action that  will be emitted\\n    for each selected element. If not specified, `deleteAction` property of the element\\n    will be used.\"\n            }\n          ]\n        }\n      ],\n      \"staticMethods\": [],\n      \"demos\": [],\n      \"metadata\": {},\n      \"sourceRange\": {\n        \"start\": {\n          \"line\": 70,\n          \"column\": 2\n        },\n        \"end\": {\n          \"line\": 159,\n          \"column\": 6\n        }\n      },\n      \"privacy\": \"public\",\n      \"name\": \"UniFlow.ListView\",\n      \"attributes\": [\n        {\n          \"name\": \"list\",\n          \"description\": \"Array which data is to be rendered by the element.\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 78,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 81,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"Array\"\n        },\n        {\n          \"name\": \"selected-count\",\n          \"description\": \"If element supports item selection (using meta-property $selected) then\\nselectedCount property will keep track of number of selected items.\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 87,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 91,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"number\"\n        },\n        {\n          \"name\": \"delete-action\",\n          \"description\": \"Action name that will be emitted when deleteSelected method is called\\nwithout parameter.\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 97,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 97,\n              \"column\": 30\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"string\"\n        }\n      ],\n      \"events\": [\n        {\n          \"type\": \"CustomEvent\",\n          \"name\": \"dispatch-action\",\n          \"description\": \"dispatch-action\",\n          \"metadata\": {},\n          \"inheritedFrom\": \"UniFlow.ActionEmitter\"\n        }\n      ],\n      \"styling\": {\n        \"cssVariables\": [],\n        \"selectors\": []\n      },\n      \"slots\": [],\n      \"mixins\": [\n        \"UniFlow.ActionEmitter\"\n      ]\n    },\n    {\n      \"description\": \"   Element rendering data represented by a single object (model) in the\\n   application state should use ModelView mixin. Model View is a powerful\\n   concept that encapsulates model data (likely the data received from the\\n   server and to be persisted to the server if modified as a result of user\\n   actions), status (validity of the data, flag that data was modified,\\n   notifications for the user, etc.). Auxiliary data supplied by action\\n   dispatchers and needed for display purposes or element's logic\\n   should be defined as element’s properties. Same applies to data\\n   created/modified by the element but not intended to be persisted.\\n   If `StateAware` mixin is used along with `ModelView`, you can take advantage\\n   of statePath property that indicates path to the element's state in the\\n   application state tree. Whenever any data is mutated by action dispatchers\\n   at statePath or below, the element will receive notification of its\\n   properties' change (even if there is no explicit binding for those\\n   properties). See `UniFlow.StateAware` for more details and example.\\n   ModelView mixin defines some properties that are intended to be overridden\\n   in the elements:\\n\\n   + `validation` property allows to specify validation rules\\n   that will be applied when validateModel() method is called. As a result of\\n   this method validation status will be updated to indicate result for each\\n   model field that has validation rule associated with it.\\n   + `saveAction` property indicates which action should be emitted when\\n   saveModel method is called to perform save of the model.\\n   + `getMessage` should be overridden with the function returning message\\n   string for given error code (to translate validation error code to message)\\n\\n\\n   ### Example:\\n\\n   #### HTML:\\n\\n      <template>\\n        Model: [[model.id]]\\n        <paper-input value=\\\"{{model.name}}\\\"\\n                     label=\\\"Name\\\"\\n                     invalid=\\\"[[status.validation.name.invalid]]\\\"\\n                     error-message=\\\"[[status.validation.name.errorMessage]]\\\">\\n        </paper-input>\\n        <paper-button on-tap=\\\"onSaveTap\\\">Save</paper-button>\\n      </template>\\n\\n   #### JavaScript:\\n      class MyModel extends UniFlow.ModelView(Polymer.Element) {\\n        static get is() { return \\\"my-model\\\"; }\\n        \\n        get saveAction() { return 'MY_SAVE' }\\n\\n        get validation() { return {\\n          name: (value) => {\\n            if (!value || !value.trim()) {\\n              return 'Name is not specified';\\n            }\\n          }\\n        }}\\n\\n        connectedCallback() {\\n          this.super();\\n          this.fetchData();\\n        },\\n\\n        fetchData() {\\n          this.emitAction({\\n            type: 'MY_FETCH',\\n            path: 'model'\\n          });\\n        },\\n\\n        onSaveTap() {\\n          this.validateAndSave();\\n        }\\n      }\\n\\n      customElements.define(MyModel.is, MyModel);\\n\\n   In the example above model view has input field for `name` property and Save button. On\\n   element attach the action is emitted to fetch the model's data. Note that in `emitAction()` method\\n   the path is specified as `'model'`. ActionEmitter mixin is responsible of expanding the path\\n   with element's state path, ensuring that when action dispatcher gets to process the action, the\\n   path contains full path in the state tree. So assuming that `my-model` is declared as follows:\\n\\n      <my-model state-path=\\\"state.myModel\\\"></my-model>\\n\\n   the path in `MY_FETCH` action gets expanded to `state.myModel.model`.\\n\\n   `validation` property is an object that contains methods for fields validation. The keys in\\n   this object should match model field names, the values are validation methods. Method receives\\n   current value of the field and should return non-falsy value (string or error code) if the value\\n   of the field didn't pass validation. `status.validation` object will be populated with the results\\n   of validation with the keys matching field names and values being objects containing two fields:\\n   - `invalid`: true when the value is not valid\\n   - `errorMessage`: the message to show to user\\n\\n\\n   So in the example above if user clicks on Save button with name not entered, they will get\\n   'Name is not specified' error message on the input element. When the name is non-empty, validation\\n   will pass and `MY_SAVE` action will be emitted with model passed as a parameter and `'model'` as\\n   path.\\n\\n\\n   \",\n      \"summary\": \"\",\n      \"path\": \"model-view.html\",\n      \"properties\": [\n        {\n          \"name\": \"model\",\n          \"type\": \"Object\",\n          \"description\": \"Object containing model data, usually mirroring server-side object.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 138,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 140,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          }\n        },\n        {\n          \"name\": \"status\",\n          \"type\": \"Object\",\n          \"description\": \"Object to contain model status, including validity of the data,\\nflag that data was modified, notifications for the user, etc.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 146,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 148,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {\n            \"polymer\": {}\n          }\n        }\n      ],\n      \"methods\": [\n        {\n          \"name\": \"emitAction\",\n          \"description\": \"Emits the action described by detail parameter. Detail object must always\\ninclude type property. To emit the action we use custom event\\nmechanism. Application element listens to the `dispatch-action` event and\\ninvokes `dispatchAction` methods for all action dispatchers associated with\\nthe application. Make sure your element is attached to DOM tree, otherwise\\nevent will never reach your application element. It is a good practice to\\nensure that `state` property is initialized (for state-aware elements) before\\nemitting any actions (as `state` property is initialized on attach).\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"file\": \"action-emitter.html\",\n            \"start\": {\n              \"line\": 50,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 62,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [\n            {\n              \"name\": \"detail\",\n              \"type\": \"*\"\n            }\n          ],\n          \"inheritedFrom\": \"UniFlow.ActionEmitter\"\n        },\n        {\n          \"name\": \"getMessage\",\n          \"description\": \"Function that translates error code (numeric or text) into human readable\\nerror message (used to translate validation error code into error text).\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 176,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 178,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": []\n        },\n        {\n          \"name\": \"saveModel\",\n          \"description\": \"Method emitting passed action or this.saveAction, sending model with\\nthe action options.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 191,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 207,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [\n            {\n              \"name\": \"action\",\n              \"type\": \"(Object|string)=\"\n            }\n          ]\n        },\n        {\n          \"name\": \"initValidationStatus_\",\n          \"description\": \"Method initializes status.validation object with invalid = false for all\\nkeys defined in this.validation object. This is needed for proper UI\\nbinding (if the value of invalid attribute is undefined, paper-input is\\nmisbehaving).\",\n          \"privacy\": \"private\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 216,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 226,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": []\n        },\n        {\n          \"name\": \"validateModel\",\n          \"description\": \"Performs validation of model object according to rules defined in\\nthis.validation object. Sets status.validation.<property-name> fields with\\ntwo properties: invalid and errorMessage.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 236,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 256,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [],\n          \"return\": {\n            \"type\": \"boolean\",\n            \"desc\": \"True if all fields validated successfully (or\\n    this.validation is not defined in the element).\"\n          }\n        },\n        {\n          \"name\": \"validateAndSave\",\n          \"description\": \"Validates and saves model if there were no validation errors.\",\n          \"privacy\": \"public\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 262,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 266,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [\n            {\n              \"name\": \"action\",\n              \"type\": \"string=\",\n              \"description\": \"Optional action type to emit for save action.\"\n            }\n          ]\n        },\n        {\n          \"name\": \"modelViewModelChanged_\",\n          \"description\": \"Observer of any changes to the model. Resets status object and initializes\\nvalidation status.\",\n          \"privacy\": \"private\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 274,\n              \"column\": 6\n            },\n            \"end\": {\n              \"line\": 288,\n              \"column\": 7\n            }\n          },\n          \"metadata\": {},\n          \"params\": [\n            {\n              \"name\": \"change\",\n              \"type\": \"!Object\"\n            }\n          ]\n        }\n      ],\n      \"staticMethods\": [],\n      \"demos\": [],\n      \"metadata\": {},\n      \"sourceRange\": {\n        \"start\": {\n          \"line\": 129,\n          \"column\": 2\n        },\n        \"end\": {\n          \"line\": 290,\n          \"column\": 6\n        }\n      },\n      \"privacy\": \"public\",\n      \"name\": \"UniFlow.ModelView\",\n      \"attributes\": [\n        {\n          \"name\": \"model\",\n          \"description\": \"Object containing model data, usually mirroring server-side object.\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 138,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 140,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"Object\"\n        },\n        {\n          \"name\": \"status\",\n          \"description\": \"Object to contain model status, including validity of the data,\\nflag that data was modified, notifications for the user, etc.\",\n          \"sourceRange\": {\n            \"start\": {\n              \"line\": 146,\n              \"column\": 10\n            },\n            \"end\": {\n              \"line\": 148,\n              \"column\": 11\n            }\n          },\n          \"metadata\": {},\n          \"type\": \"Object\"\n        }\n      ],\n      \"events\": [\n        {\n          \"type\": \"CustomEvent\",\n          \"name\": \"dispatch-action\",\n          \"description\": \"dispatch-action\",\n          \"metadata\": {},\n          \"inheritedFrom\": \"UniFlow.ActionEmitter\"\n        }\n      ],\n      \"styling\": {\n        \"cssVariables\": [],\n        \"selectors\": []\n      },\n      \"slots\": [],\n      \"mixins\": [\n        \"UniFlow.ActionEmitter\"\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "application-state.html",
    "content": "<!--\nCopyright 2016 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n-->\n\n<link rel=\"import\" href=\"../polymer/polymer-element.html\">\n<link rel=\"import\" href=\"action-dispatcher.html\">\n<link rel=\"import\" href=\"state-aware.html\">\n<link rel=\"import\" href=\"state-mutator.html\">\n\n\n<script type=\"text/javascript\">\n  var UniFlow = window.UniFlow || {};\n\n  /**\n\n   Apply this mixin to your main application element. It provides global\n   state and functionality to maintain individual elements states. This mixin\n   is responsible for notifying all state-aware elements about their state\n   changes (provided those elements have `statePath` property defined).\n   Only one element in the application is supposed to have this mixin.\n\n   ### Example:\n\n   #### HTML:\n\n       <template>\n\n         <!-- action dispatchers in the order of action processing -->\n         <action-dispatcher-a state=\"{{state}}\"></action-dispatcher-a>\n         <action-dispatcher-b state=\"{{state}}\"></action-dispatcher-b>\n\n         <!-- state-aware elements -->\n         <some-element state-path=\"state.someElement\"></some-element>\n\n       </template>\n\n   #### JavaScript:\n       class MyApp extends UniFlow.ApplicationState(Polymer.Element) {\n         static get is() { return 'my-app'; }\n\n         connectedCallback() {\n           super.ConnectedCallback();\n\n           this.state = {\n             someElement: {}\n           }\n         }\n       }\n\n       customElements.define(MyApp.is,MyApp);\n\n   In the example above, `<some-element>` will receive notification of any changes to the state,\n   as if it was declared as follows:\n\n       <some-element state=\"[[state]]\"></some-element>\n\n   Also, if `<some-element>` has `propertyA`, on element attach this property will be assigned\n   the value of `state.someElement.propertyA`, and receive all notification of the property change\n   whenever the corresponding data in state tree changes. This essentially translates to following\n   declaration:\n\n       <some-element state=\"[[state]]\"\n                     propertyA=\"[[state.someElement.propertyA]]\">\n       </some-element>\n\n   Note that data binding is one-way in both cases. Although state-aware elements can modify their\n   own state, it is considered their private state and no other elements will be notified of those\n   changes.\n\n   @polymer\n   @mixinFunction\n   @appliesMixin UniFlow.ActionDispatcher\n  */\n  UniFlow.ApplicationState = Polymer.dedupingMixin((base) =>\n    class extends UniFlow.ActionDispatcher(base) {\n\n      static get observers() {\n        return [\n          'stateChanged_(state.*)'\n        ]\n      }\n\n      /**\n       * Application state listens to dispatch-action method and invokes\n       * dispatchAction method on itself (which in turn invokes dispatchAction\n       * on all action dispatchers declared within application element).\n       *\n       * @param {!Event} event\n       * @private\n       */\n      onDispatchAction_(event) {\n        this.dispatchAction(event.detail);\n      }\n\n      /**\n       * Called when state.* changes. Notifies state-aware elements of their\n       * state changes, if applicable.\n       *\n       * @param {!Object} change the Polymer change event for the path\n       * @private\n       */\n      stateChanged_(change) {\n        this.notifyStateAwareElements_(change);\n      }\n\n      /**\n       * Iterates through the array of state-aware elements in the application\n       * and notifies them about their state change, if applicable. Note that\n       * state-aware elements must be attached to DOM tree in order to receive\n       * notifications.\n       *\n       * @param change\n       * @private\n       */\n      notifyStateAwareElements_(change) {\n        this.get('application.stateAwareElements').forEach(element => {\n          element.notifyPath(change.path, change.value, true);\n          if (element.statePath && change.path.startsWith(element.statePath)) {\n            let pathToNotify = change.path.slice(element.statePath.length + 1);\n            if (pathToNotify) {\n              if (element.get(pathToNotify) !== change.value &&\n                !change.path.endsWith('.splices')) {\n                element.set(pathToNotify, change.value);\n              } else {\n                element.notifyPath(pathToNotify, change.value, true);\n              }\n            } else {\n              // If pathToNotify empty, that means the whole element state need\n              // to be replaced. Iterating through the keys of new value (which\n              // has to be an object) and setting element properties with the same\n              // name.\n              Object.keys(change.value).forEach((key) => {\n                element.set(key, change.value[key]);\n              });\n            }\n          }\n        });\n      }\n\n      /**\n       * Sets application.element value to this element (so all state-aware elements\n       * have access to application element). Registers event listener to dispatch-action event.\n       */\n      ready() {\n        super.ready();\n        this.set('application.element', this);\n        this.addEventListener('dispatch-action', (event) => this.onDispatchAction_(event));\n      }\n\n    });\n</script>"
  },
  {
    "path": "bower.json",
    "content": "{\n  \"name\": \"uniflow-polymer\",\n  \"version\": \"0.6.0\",\n  \"authors\": [\n    \"Andrei Militeev <militeev@gmail.com>\"\n  ],\n  \"description\": \"A straightforward way to architect Polymer application using unidirectional data flow.\",\n  \"keywords\": [\n    \"web-component\",\n    \"polymer\",\n    \"uniflow\",\n    \"unidirectional\",\n    \"flow\"\n  ],\n  \"license\": \"https://raw.githubusercontent.com/google/uniflow-polymer/master/LICENSE\",\n  \"homepage\": \"https://github.com/google/uniflow-polymer/\",\n  \"ignore\": [\n    \"/.*\",\n    \"/test/\"\n  ],\n  \"dependencies\": {\n    \"polymer\": \"Polymer/polymer#^2.0.0\"\n  },\n  \"devDependencies\": {\n    \"app-route\": \"PolymerElements/app-route#^2.0.2\",\n    \"iron-component-page\": \"PolymerElements/iron-component-page#^3.0.0\",\n    \"iron-demo-helpers\": \"PolymerElements/iron-demo-helpers#^2.0.0\",\n    \"iron-icon\": \"PolymerElements/iron-icon#^2.0.0\",\n    \"iron-icons\": \"PolymerElements/iron-icons#^2.0.0\",\n    \"iron-test-helpers\": \"PolymerElements/iron-test-helpers#^2.0.0\",\n    \"paper-styles\": \"PolymerElements/paper-styles#^2.0.0\",\n    \"test-fixture\": \"PolymerElements/test-fixture#3.0.0-rc.1\",\n    \"web-component-tester\": \"^v6.0.0\",\n    \"todomvc-app-css\": \"^2.1.0\",\n    \"iron-localstorage\": \"PolymerElements/iron-localstorage#^2.0.0\"\n  }\n}\n"
  },
  {
    "path": "index.html",
    "content": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt\nThe complete set of authors may be found at http://polymer.github.io/AUTHORS.txt\nThe complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt\nCode distributed by Google as part of the polymer project is also\nsubject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt\n-->\n<html>\n<head>\n\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\n  <script src=\"../webcomponentsjs/webcomponents-loader.js\"></script>\n  <link rel=\"import\" href=\"../iron-component-page/iron-component-page.html\">\n\n</head>\n<body unresolved>\n  <!-- Note: if the main element for this repository doesn't\n       match the folder name, add a src=\"&lt;main-component&gt;.html\" attribute,\n       where &lt;main-component&gt;.html\" is a file that imports all of the\n       components you want documented. -->\n  <iron-component-page></iron-component-page>\n\n</body>\n</html>\n"
  },
  {
    "path": "list-view.html",
    "content": "<!--\nCopyright 2016 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n-->\n\n<link rel=\"import\" href=\"../polymer/polymer-element.html\">\n<link rel=\"import\" href=\"action-emitter.html\">\n\n\n<script type=\"text/javascript\">\n  var UniFlow = window.UniFlow || {};\n\n  /**\n\n   This mixin used by elements that need to render multiple models backed\n   by 'list' array. You may want to use ModelView to render individual\n   models in the list. The mixin supports element selection by setting predefined\n   $selected property on list elements.\n\n   ### Example:\n\n   #### HTML:\n\n       <ul>\n         <template id=\"list-template\" is=\"dom-repeat\" items=\"[[list]]\">\n           <li id=\"[[item.id]]\">\n             <paper-checkbox checked=\"{{item.$selected}}\">\n             <model-view state-path=\"[[statePath]].list.#[[index]]\"></model-view>\n           </li>\n         </template>\n       </ul>\n       Selected: [[selectedCount]] items\n       <paper-button on-tap=\"onDeleteTap\">Delete</paper-button>\n\n   #### JavaScript:\n       class ListElement extends UniFlow.StateAware(UniFlow.ListView(Polymer.Element)) {\n         static get is() { return \"list-element\"; }\n\n         onDeleteTap() {\n           this.deleteSelected();\n         }\n       }\n\n       customElements.define(ListElement.is, ListElement);\n\n   In the example above list view element is also state-aware, meaning it has its own place\n   in the application state tree. Assuming it has been declared as follows:\n\n       <list-element state-path=\"state.listElement\"></list-element>\n\n   it will be rendering `state.listElement.list` and observing changes to it. Each `model-view`\n   within dom-repeat template will have `state-path` property  set to\n   `state.listElement.list.#<index>`  where `index` is the element's index in the array.\n\n\n   @polymer\n   @mixinFunction\n   @appliesMixin UniFlow.ActionEmitter\n  */\n  UniFlow.ListView = Polymer.dedupingMixin((base) =>\n    class extends UniFlow.ActionEmitter(base) {\n      static get properties() {\n        return {\n\n          /**\n           * Array which data is to be rendered by the element.\n           */\n          list: {\n            type: Array,\n            value: () => []\n          },\n\n          /**\n           * If element supports item selection (using meta-property $selected) then\n           * selectedCount property will keep track of number of selected items.\n           */\n          selectedCount: {\n            type: Number,\n            notify: true,\n            value: 0,\n          },\n\n          /**\n           * Action name that will be emitted when deleteSelected method is called\n           * without parameter.\n           */\n          deleteAction: String\n\n        }\n      }\n\n      static get observers() {\n        return [\n          'itemChanged_(list.*)',\n        ]\n      }\n\n      /**\n       * Whenever list is set or mutated (elements added/removed), as well as\n       * meta-property $selected is modified, updates selectedCount.\n       * @param {!Object} change\n       * @private\n       */\n      itemChanged_(change) {\n        if (this.get('list') &&\n          (change.path == 'list' ||\n            change.path == 'list.splices' ||\n            change.path.endsWith('$selected'))) {\n          this.updateSelectedCount_();\n        }\n      }\n\n      /**\n       * Updates selectedCount property of the element by iterating the list and\n       * counting each item that has meta-property $selected set.\n       * @private\n       */\n      updateSelectedCount_() {\n        let selectedCount = 0;\n        this.get('list').forEach((elem) => {\n          selectedCount += elem.$selected ? 1 : 0;\n        });\n        this.selectedCount = selectedCount;\n      }\n\n      /**\n       * Emits deleteAction for each selected element in the list (for which\n       * meta-property $selected is set).\n       * @param {string=} deleteAction Action type for the action that  will be emitted\n       *     for each selected element. If not specified, `deleteAction` property of the element\n       *     will be used.\n       */\n      deleteSelected(deleteAction) {\n        deleteAction = deleteAction || this.deleteAction;\n        if (deleteAction) {\n          this.list.forEach(item => {\n            if (item.$selected) {\n              this.emitAction({\n                type: deleteAction,\n                item: item\n              });\n            }\n          });\n        } else {\n          console.warn('delete action is not defined');\n        }\n      }\n\n    });\n</script>"
  },
  {
    "path": "model-view.html",
    "content": "<!--\nCopyright 2016 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n-->\n\n<link rel=\"import\" href=\"../polymer/polymer-element.html\">\n<link rel=\"import\" href=\"action-emitter.html\">\n\n\n<script>\n  var UniFlow = window.UniFlow || {};\n\n  /**\n\n   Element rendering data represented by a single object (model) in the\n   application state should use ModelView mixin. Model View is a powerful\n   concept that encapsulates model data (likely the data received from the\n   server and to be persisted to the server if modified as a result of user\n   actions), status (validity of the data, flag that data was modified,\n   notifications for the user, etc.). Auxiliary data supplied by action\n   dispatchers and needed for display purposes or element's logic\n   should be defined as element’s properties. Same applies to data\n   created/modified by the element but not intended to be persisted.\n   If `StateAware` mixin is used along with `ModelView`, you can take advantage\n   of statePath property that indicates path to the element's state in the\n   application state tree. Whenever any data is mutated by action dispatchers\n   at statePath or below, the element will receive notification of its\n   properties' change (even if there is no explicit binding for those\n   properties). See `UniFlow.StateAware` for more details and example.\n   ModelView mixin defines some properties that are intended to be overridden\n   in the elements:\n\n   + `validation` property allows to specify validation rules\n   that will be applied when validateModel() method is called. As a result of\n   this method validation status will be updated to indicate result for each\n   model field that has validation rule associated with it.\n   + `saveAction` property indicates which action should be emitted when\n   saveModel method is called to perform save of the model.\n   + `getMessage` should be overridden with the function returning message\n   string for given error code (to translate validation error code to message)\n\n\n   ### Example:\n\n   #### HTML:\n\n      <template>\n        Model: [[model.id]]\n        <paper-input value=\"{{model.name}}\"\n                     label=\"Name\"\n                     invalid=\"[[status.validation.name.invalid]]\"\n                     error-message=\"[[status.validation.name.errorMessage]]\">\n        </paper-input>\n        <paper-button on-tap=\"onSaveTap\">Save</paper-button>\n      </template>\n\n   #### JavaScript:\n      class MyModel extends UniFlow.ModelView(Polymer.Element) {\n        static get is() { return \"my-model\"; }\n        \n        get saveAction() { return 'MY_SAVE' }\n\n        get validation() { return {\n          name: (value) => {\n            if (!value || !value.trim()) {\n              return 'Name is not specified';\n            }\n          }\n        }}\n\n        connectedCallback() {\n          this.super();\n          this.fetchData();\n        },\n\n        fetchData() {\n          this.emitAction({\n            type: 'MY_FETCH',\n            path: 'model'\n          });\n        },\n\n        onSaveTap() {\n          this.validateAndSave();\n        }\n      }\n\n      customElements.define(MyModel.is, MyModel);\n\n   In the example above model view has input field for `name` property and Save button. On\n   element attach the action is emitted to fetch the model's data. Note that in `emitAction()` method\n   the path is specified as `'model'`. ActionEmitter mixin is responsible of expanding the path\n   with element's state path, ensuring that when action dispatcher gets to process the action, the\n   path contains full path in the state tree. So assuming that `my-model` is declared as follows:\n\n      <my-model state-path=\"state.myModel\"></my-model>\n\n   the path in `MY_FETCH` action gets expanded to `state.myModel.model`.\n\n   `validation` property is an object that contains methods for fields validation. The keys in\n   this object should match model field names, the values are validation methods. Method receives\n   current value of the field and should return non-falsy value (string or error code) if the value\n   of the field didn't pass validation. `status.validation` object will be populated with the results\n   of validation with the keys matching field names and values being objects containing two fields:\n   - `invalid`: true when the value is not valid\n   - `errorMessage`: the message to show to user\n\n\n   So in the example above if user clicks on Save button with name not entered, they will get\n   'Name is not specified' error message on the input element. When the name is non-empty, validation\n   will pass and `MY_SAVE` action will be emitted with model passed as a parameter and `'model'` as\n   path.\n\n\n   @polymer\n   @mixinFunction\n   @appliesMixin UniFlow.ActionEmitter\n  */\n  UniFlow.ModelView = Polymer.dedupingMixin((base) =>\n    class extends UniFlow.ActionEmitter(base) {\n\n      static get properties() {\n        return {\n\n          /**\n           * Object containing model data, usually mirroring server-side object.\n           */\n          model: {\n            type: Object\n          },\n\n          /**\n           * Object to contain model status, including validity of the data,\n           * flag that data was modified, notifications for the user, etc.\n           */\n          status: {\n            type: Object\n          }\n\n        }\n      }\n\n      /**\n       * Validation rules for model properties (optional), should be defined in the\n       * element.\n       * @type {Object|undefined}\n       */\n      get validation() {\n        return undefined;\n      }\n\n      /**\n       * Save action that will be emitted when saveModel() method is called without\n       * parameters.\n       * @type {string|undefined}\n       */\n      get saveAction() {\n        return undefined;\n      }\n\n      /**\n       * Function that translates error code (numeric or text) into human readable\n       * error message (used to translate validation error code into error text).\n       * @type {Function|undefined}\n       */\n      getMessage() {\n        return undefined;\n      }\n\n      static get observers() {\n        return [\n          'modelViewModelChanged_(model.*)'\n        ]\n      }\n\n      /**\n       * Method emitting passed action or this.saveAction, sending model with\n       * the action options.\n       * @param {Object|string=} action\n       */\n      saveModel(action) {\n        let actionToEmit = {\n          model: this.model\n        };\n        if (typeof action === 'object') {\n          Object.assign(actionToEmit, action);\n        } else {\n          actionToEmit.type = action;\n        }\n        if (!actionToEmit.type) {\n          actionToEmit.type = this.saveAction;\n        }\n        if (!actionToEmit.path) {\n          actionToEmit.path = 'model';\n        }\n        this.emitAction(actionToEmit);\n      }\n\n      /**\n       * Method initializes status.validation object with invalid = false for all\n       * keys defined in this.validation object. This is needed for proper UI\n       * binding (if the value of invalid attribute is undefined, paper-input is\n       * misbehaving).\n       * @private\n       */\n      initValidationStatus_() {\n        let validationStatus = {};\n        if (this.validation) {\n          for (let key of Object.keys(this.validation)) {\n            validationStatus[key] = {\n              invalid: false\n            };\n          }\n        }\n        this.set('status.validation', validationStatus);\n      }\n\n      /**\n       * Performs validation of model object according to rules defined in\n       * this.validation object. Sets status.validation.<property-name> fields with\n       * two properties: invalid and errorMessage.\n       *\n       * @return {boolean} True if all fields validated successfully (or\n       *     this.validation is not defined in the element).\n       */\n      validateModel() {\n        if (!this.validation) {\n          return true;\n        }\n        let isValid = true;\n        for (let key of Object.keys(this.validation)) {\n          let result = this.validation[key].call(this,\n            this.get('model.' + key));\n          let errorMessage = !result || typeof result === 'string' ?\n            result : (this.getMessage ? this.getMessage(result) :\n              'Message Code ' + result);\n          this.set('status.validation.' + key, {\n            invalid: !!result,\n            errorMessage\n          });\n          if (result) {\n            isValid = false;\n          }\n        }\n        return isValid;\n      }\n\n      /**\n       * Validates and saves model if there were no validation errors.\n       * @param {string=} action Optional action type to emit for save action.\n       */\n      validateAndSave(action) {\n        if (this.validateModel()) {\n          this.saveModel(action);\n        }\n      }\n\n      /**\n       * Observer of any changes to the model. Resets status object and initializes\n       * validation status.\n       * @param {!Object} change\n       * @private\n       */\n      modelViewModelChanged_(change) {\n        // Resetting status when model changed\n        if (change.path === 'model' && this.get('model')) {\n          this.set('status', {\n            isModified: false\n          });\n          this.initValidationStatus_();\n        } else {\n          if (this.get('model')) {\n            this.set('status.isModified', true);\n          } else {\n            this.set('status', {});\n          }\n        }\n      }\n\n    });\n</script>"
  },
  {
    "path": "state-aware.html",
    "content": "<!--\nCopyright 2016 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n-->\n\n<link rel=\"import\" href=\"../polymer/polymer-element.html\">\n\n\n<script type=\"text/javascript\">\n  var UniFlow = window.UniFlow || {};\n\n  /**\n   Key mixin that must be assigned to all elements that need to access\n   application state and/or have access to the application element. The element is\n   notified of any changes to application's state, as well as all its properties\n   when they're modified by state mutator elements. `state-path` property must\n   be used to identify path to element's state in application state tree. \n\n   ### Example:\n\n   #### HTML:\n\n      <template>\n\n        <div>Value A: [[state.valueA]]</div>\n        <div>Value B: [[valueB]]</div>\n\n      </template>\n\n   #### JavaScript:\n\n      class MyElement extends UniFlow.StateAware(Polymer.Element) {\n        static get is() { return 'my-element'; }\n\n        static get properties() {\n          return {\n            valueB: String\n          }\n        }\n      }\n\n      customElement.define(MyElement.is, MyElement);\n\n   When above element is declared as follows:\n\n      <my-element state-path=\"state.myElement\"></my-element>\n\n   it will be notified about changes (and render those) to `state.valueA` or\n   `state.myElement.valueB` in action dispatchers or other state mutating\n   elements.\n\n   @polymer\n   @mixinFunction\n  */\n  UniFlow.StateAware = Polymer.dedupingMixin((base) =>\n    class extends base {\n      static get properties() {\n        return {\n\n          /**\n           * Application state, shared among application and all state-aware elements.\n           * This property is initialized when element is attached.\n           */\n          state: {\n            type: Object\n          },\n\n          /**\n           * Path to element state in the application state tree.\n           */\n          statePath: {\n            type: String\n          },\n\n          stateAware: {\n            type: Boolean,\n            value: true,\n            reflectToAttribute: true\n          },\n\n          /**\n           * Application-level object that allows all state-aware objects access\n           * to application element. This property is shared among all state-aware\n           * elements and has element field initialized with reference to application\n           * element. Any state-aware element can access application element using\n           * `getApplication()` method. Also, all state-aware elements\n           * add themselves to `application.stateAwareElements` array on attach (and\n           * remove on detach); this list is used to send notification about\n           * element state changes.\n           */\n          application: {\n            type: Object,\n            value: {\n              element: null,\n              stateAwareElements: []\n            }\n          }\n\n        }\n      }\n\n      /**\n       * Adds this element to the list of state-aware elements in the application.\n       * Sets the value of state property to the state of the application element.\n       */\n      connectedCallback() {\n        super.connectedCallback();\n\n        this.push('application.stateAwareElements', this);\n        // Copying application's element state to this element. ApplicationState behavior is\n        // responsible of notifying state aware elements about application's state changes.\n        if (!this.get('state') && this.get('application.element.state')) {\n          this.set('state', this.get('application.element.state'));\n        }\n        // If this element's state exists, the properties ot the element are\n        // initialized from state.\n        if (this.statePath && this.get(this.statePath)) {\n          Object.keys(this.get(this.statePath)).forEach((key) => {\n            this.set(key, this.get([this.statePath, key]));\n          });\n        }\n      }\n\n      /**\n       * Removes this element from the list of state-aware elements in the\n       * application.\n       */\n      disconnectedCallback() {\n        const index = this.application.stateAwareElements.indexOf(this);\n        if (index !== -1) {\n          this.application.stateAwareElements.splice(index, 1);\n        }\n\n        super.disconnectedCallback();\n      }\n\n      /**\n       * Returns application element.\n       * @return {Element}\n       */\n      getApplication() {\n        return this.get('application.element');\n      }\n\n    });\n</script>"
  },
  {
    "path": "state-mutator.html",
    "content": "<!--\nCopyright 2016 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n-->\n\n<link rel=\"import\" href=\"../polymer/polymer-element.html\">\n<link rel=\"import\" href=\"state-aware.html\">\n\n<script>\n  var UniFlow = window.UniFlow || {};\n\n  /**\n\n   Some non-visual elements, like action dispatchers, need to modify application\n   state, in which case they should have this mixin applied. Implements state-\n   aware and re-declares state property with notify attribute. State mutator elements\n   are only supposed to exist at the application level.\n\n   @polymer\n   @mixinFunction\n   @appliesMixin UniFlow.StateAware\n  */\n  UniFlow.StateMutator = Polymer.dedupingMixin((base) =>\n    class extends UniFlow.StateAware(base) {\n\n      static get properties() {\n        return {\n          /**\n           * Application state.\n           */\n          state: {\n            type: Object,\n            notify: true\n          }\n        }\n\n      };\n    });\n</script>"
  },
  {
    "path": "test/action-dispatcher_test.html",
    "content": "<!doctype html>\n<!--\nCopyright 2017 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n-->\n<html>\n\n<head>\n  <meta charset=\"UTF-8\">\n  <title>UniFlow.ActionDispatcher tests</title>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0\">\n\n  <script src=\"../../webcomponentsjs/webcomponents-lite.js\"></script>\n  <script src=\"../../web-component-tester/browser.js\"></script>\n\n  <link rel=\"import\" href=\"../action-dispatcher.html\">\n\n</head>\n\n<body>\n\n  <dom-module id=\"action-dispatcher-test\">\n    <script>\n      class ActionDispatcherTest extends UniFlow.ActionDispatcher(Polymer.Element) {\n        static get is() {\n          return 'action-dispatcher-test';\n        }\n      }\n\n      customElements.define(ActionDispatcherTest.is, ActionDispatcherTest);\n    </script>\n  </dom-module>\n\n  <dom-module id=\"nested-action-dispatcher-test\">\n    <template>\n      <action-dispatcher-test id=\"inner\"></action-dispatcher-test>\n    </template>\n    <script>\n      class NestedActionDispatcherTest extends UniFlow.ActionDispatcher(Polymer.Element) {\n        static get is() {\n          return 'nested-action-dispatcher-test';\n        }\n      }\n\n      customElements.define(NestedActionDispatcherTest.is, NestedActionDispatcherTest);\n    </script>\n  </dom-module>\n\n  <test-fixture id=\"basic\">\n    <template>\n      <action-dispatcher-test></action-dispatcher-test>\n    </template>\n  </test-fixture>\n\n  <test-fixture id=\"nested\">\n    <template>\n      <nested-action-dispatcher-test></nested-action-dispatcher-test>\n    </template>\n  </test-fixture>\n\n  <script>\n    'use strict';\n\n    suite('UniFlow.ActionDispatcher', () => {\n\n      let actionDispatcher;\n\n      setup(() => {\n        actionDispatcher = fixture('basic');\n      });\n\n      test('is ok', () => {\n        expect(actionDispatcher).to.be.ok;\n      });\n\n      test('dispatchAction calls method with name that matches action ' +\n        'type', () => {\n          actionDispatcher.MY_ACTION = sinon.spy();\n          const detail = {\n            type: 'MY_ACTION',\n            foo: 'bar'\n          };\n          actionDispatcher.dispatchAction(detail);\n          expect(actionDispatcher.MY_ACTION).to.be.calledWith(detail);\n        });\n\n      test('dispatchAction returns false when action processor method' +\n        ' returns false', () => {\n          actionDispatcher.MY_ACTION = () => false;\n          const detail = {\n            type: 'MY_ACTION'\n          };\n          expect(actionDispatcher.dispatchAction(detail)).to.be.false;\n        });\n\n      test('nested action dispatcher\\'s method is invoked', () => {\n        actionDispatcher = fixture('nested');\n        expect(actionDispatcher).to.be.ok;\n        expect(actionDispatcher.$.inner).to.be.ok;\n        actionDispatcher.$.inner.MY_ACTION = sinon.spy();\n        const detail = {\n          type: 'MY_ACTION',\n          foo: 'bar'\n        };\n        actionDispatcher.dispatchAction(detail);\n        expect(actionDispatcher.$.inner.MY_ACTION).to.be.calledWith(detail);\n      });\n\n    });\n  </script>\n\n</body>\n\n</html>"
  },
  {
    "path": "test/action-emitter_test.html",
    "content": "<!doctype html>\n<!--\nCopyright 2017 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n-->\n<html>\n\n<head>\n  <meta charset=\"UTF-8\">\n  <title>UniFlow.ActionEmitter tests</title>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0\">\n\n  <script src=\"../../webcomponentsjs/webcomponents-lite.js\"></script>\n  <script src=\"../../web-component-tester/browser.js\"></script>\n\n  <link rel=\"import\" href=\"../action-emitter.html\">\n\n</head>\n\n<body>\n\n  <dom-module id=\"action-emitter-test\">\n    <script>\n      class ActionEmitterTest extends UniFlow.ActionEmitter(Polymer.Element) {\n        static get is() {\n          return 'action-emitter-test';\n        }\n      }\n\n      customElements.define(ActionEmitterTest.is, ActionEmitterTest);\n    </script>\n  </dom-module>\n\n  <test-fixture id=\"basic\">\n    <template>\n      <action-emitter-test></action-emitter-test>\n    </template>\n  </test-fixture>\n\n  <script>\n    'use strict';\n\n    suite('UniFlow.ActionEmitter', () => {\n\n      let actionEmitter;\n\n      setup(() => {\n        actionEmitter = fixture('basic');\n      });\n\n      test('is ok', () => {\n        expect(actionEmitter).to.be.ok;\n      });\n\n      test('fires a dispatch-action event on action emit', () => {\n        sinon.spy(actionEmitter, 'dispatchEvent');\n        let action = 'detail';\n        actionEmitter.emitAction(action);\n        expect(actionEmitter.dispatchEvent).to.be.calledWithMatch({\n          type: 'dispatch-action',\n          detail: action\n        });\n      });\n\n      test('prepends statePath to detail.path', () => {\n        sinon.spy(actionEmitter, 'dispatchEvent');\n        let action = {\n          path: 'my.path'\n        };\n        actionEmitter.statePath = 'state';\n        actionEmitter.emitAction(action);\n        expect(actionEmitter.dispatchEvent).to.be.calledWithMatch({\n          type: 'dispatch-action',\n          detail: {\n            path: 'state.my.path'\n          }\n        });\n      });\n\n      test('does not change detail.path if it starts with \"state.\"', () => {\n        sinon.spy(actionEmitter, 'dispatchEvent');\n        let action = {\n          path: 'state.my.path'\n        };\n        actionEmitter.statePath = 'some.state.path';\n        actionEmitter.emitAction(action);\n        expect(actionEmitter.dispatchEvent).to.be.calledWithMatch({\n          type: 'dispatch-action',\n          detail: {\n            path: 'state.my.path'\n          }\n        });\n      });\n\n    });\n  </script>\n\n</body>\n\n</html>"
  },
  {
    "path": "test/application-state_test.html",
    "content": "<!doctype html>\n<!--\nCopyright 2017 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n-->\n<html>\n\n<head>\n  <meta charset=\"UTF-8\">\n  <title>UniFlow.ApplicationState tests</title>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0\">\n\n  <script src=\"../../webcomponentsjs/webcomponents-lite.js\"></script>\n  <script src=\"../../web-component-tester/browser.js\"></script>\n\n  <link rel=\"import\" href=\"../application-state.html\">\n  <link rel=\"import\" href=\"../state-aware.html\">\n\n</head>\n\n<body>\n\n  <dom-module id=\"application-state-test\">\n    <script>\n      class ApplicationStateTest extends UniFlow.ApplicationState(Polymer.Element) {\n        static get is() {\n          return 'application-state-test';\n        }\n\n        connectedCallback() {\n          super.connectedCallback();\n\n          this.state = {\n            a: {\n              innerValue: 'aaa'\n            },\n            b: {}\n          };\n        }\n      }\n\n      customElements.define(ApplicationStateTest.is, ApplicationStateTest);\n    </script>\n  </dom-module>\n\n  <dom-module id=\"state-aware-a\">\n    <template>\n      <div id=\"inner\">[[innerValue]]</div>\n    </template>\n    <script>\n      class StateAwareA extends UniFlow.StateAware(Polymer.Element) {\n        static get is() {\n          return 'state-aware-a';\n        }\n      }\n\n      customElements.define(StateAwareA.is, StateAwareA);\n    </script>\n  </dom-module>\n\n  <dom-module id=\"state-aware-b\">\n    <template>\n      <div id=\"inner-state\">[[state.value]]</div>\n      <div id=\"inner\">[[innerValue]]</div>\n      <state-aware-a id=\"a\" state-path=\"state.a\"></state-aware-a>\n    </template>\n    <script>\n      class StateAwareB extends UniFlow.StateAware(Polymer.Element) {\n        static get is() {\n          return 'state-aware-b';\n        }\n      }\n\n      customElements.define(StateAwareB.is, StateAwareB);\n    </script>\n  </dom-module>\n\n  <test-fixture id=\"basic\">\n    <template>\n      <application-state-test>\n        <state-aware-b id=\"b\" state-path=\"state.b\">\n        </state-aware-b>\n      </application-state-test>\n    </template>\n  </test-fixture>\n\n  <script>\n    'use strict';\n\n    suite('UniFlow.ApplicationState', () => {\n\n      let applicationState;\n\n      setup(() => {\n        applicationState = fixture('basic');\n      });\n\n      test('is ok', () => {\n        expect(applicationState).to.be.ok;\n        expect(applicationState.querySelector('#b')).to.be.ok;\n        expect(applicationState.querySelector('#b').root.querySelector('#a')).to.be.ok;\n      });\n\n      test('dispatchAction is called on dispatch-action event', () => {\n        sinon.spy(applicationState, 'dispatchAction');\n        applicationState.dispatchEvent(new CustomEvent('dispatch-action', {\n          detail: 'detail',\n          bubbles: true,\n          composed: true\n        }));\n        expect(applicationState.dispatchAction)\n          .to.have.been.calledWith('detail');\n      });\n\n      test('application.element is set to element itself', () => {\n        expect(applicationState.get('application.element'))\n          .to.equal(applicationState);\n      });\n\n      test('state aware elements receive initial element state', () => {\n        expect(applicationState.querySelector('#b').root.querySelector('#a').root.querySelector('#inner').innerText)\n          .to.equal('aaa');\n      });\n\n      test('state aware elements listen to application state', () => {\n        applicationState.set('state.value', 'something');\n        expect(applicationState.querySelector('#b').root.querySelector('#inner-state').innerText)\n          .to.equal('something');\n      });\n\n      test('state aware elements listen to element state changes', () => {\n        applicationState.set('state.a.innerValue', 'aaa.modified');\n        expect(applicationState.querySelector('#b').root.querySelector('#a').root.querySelector('#inner').innerText)\n          .to.equal('aaa.modified');\n        applicationState.set('state.b.innerValue', 'bbb');\n        expect(applicationState.querySelector('#b').root.querySelector('#inner').innerText)\n          .to.equal('bbb');\n      });\n\n      test('state aware elements handle entire element state replacement', () => {\n        applicationState.set('state.a', {\n          innerValue: 'aaa.new'\n        });\n        expect(applicationState.querySelector('#b').root.querySelector('#a').root.querySelector('#inner').innerText)\n          .to.equal('aaa.new');\n      });\n\n      //      test('fires a dispatch-action event on action emit', () => {\n      //        sinon.spy(applicationState, 'fire');\n      //        let action = 'detail';\n      //        applicationState.emitAction(action);\n      //        expect(applicationState.fire).to.be.calledWith('dispatch-action', action);\n      //      });\n\n    });\n  </script>\n\n</body>\n\n</html>"
  },
  {
    "path": "test/list-view_test.html",
    "content": "<!doctype html>\n<!--\nCopyright 2017 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n-->\n<html>\n\n<head>\n  <meta charset=\"UTF-8\">\n  <title>UniFlow.ListView tests</title>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0\">\n\n  <script src=\"../../webcomponentsjs/webcomponents-lite.js\"></script>\n  <script src=\"../../web-component-tester/browser.js\"></script>\n\n  <link rel=\"import\" href=\"../list-view.html\">\n\n</head>\n\n<body>\n\n  <dom-module id=\"list-view-test\">\n    <script>\n      class ListViewTest extends UniFlow.ListView(Polymer.Element) {\n        static get is() {\n          return 'list-view-test';\n        }\n      }\n\n      customElements.define(ListViewTest.is, ListViewTest);\n    </script>\n  </dom-module>\n\n  <test-fixture id=\"basic\">\n    <template>\n      <list-view-test list=\"[[list]]\">\n      </list-view-test>\n    </template>\n  </test-fixture>\n\n  <script>\n    'use strict';\n\n    suite('UniFlow.ListView', () => {\n\n      let listView;\n\n      setup(() => {\n        listView = fixture('basic');\n        listView.set('list', []);\n      });\n\n      test('is ok', () => {\n        expect(listView).to.be.ok;\n      });\n\n      test('updates selected count on new list', () => {\n        sinon.spy(listView, 'updateSelectedCount_');\n        listView.set('list', [{\n          foo: 'bar'\n        }]);\n        expect(listView.updateSelectedCount_).to.be.called;\n      });\n\n      test('updates selected count on element added/removed', () => {\n        sinon.spy(listView, 'updateSelectedCount_');\n        listView.push('list', {\n          foo: 'bar'\n        });\n        listView.splice('list', 0, 1);\n        expect(listView.updateSelectedCount_).to.be.calledTwice;\n      });\n\n      test('updates selected count on $selected changed', () => {\n        listView.set('list', [{\n          foo: 'bar'\n        }]);\n        sinon.spy(listView, 'updateSelectedCount_');\n        listView.set(['list', 0, '$selected'], true);\n        listView.set(['list', 0, '$selected'], false);\n        expect(listView.updateSelectedCount_).to.be.calledTwice;\n      });\n\n      test('calculates selectedCount', () => {\n        listView.set('list', [{\n            foo: 'bar',\n            $selected: true\n          },\n          {\n            foo: 'baz',\n            $selected: false\n          },\n          {},\n        ]);\n        expect(listView.selectedCount).to.equal(1);\n      });\n\n      test('emits delete action for selected', () => {\n        sinon.spy(listView, 'emitAction');\n        listView.set('list', [{\n            foo: 'bar',\n            $selected: true\n          },\n          {\n            foo: 'baz',\n            $selected: false\n          },\n          {},\n        ]);\n        listView.deleteSelected('DELETE');\n        expect(listView.emitAction).to.be.calledOnce;\n        expect(listView.emitAction).to.be.calledWith({\n          type: 'DELETE',\n          item: {\n            foo: 'bar',\n            $selected: true\n          }\n        });\n      });\n\n    });\n  </script>\n\n</body>\n\n</html>"
  },
  {
    "path": "test/model-view_test.html",
    "content": "<!doctype html>\n<!--\nCopyright 2017 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n-->\n<html>\n\n<head>\n  <meta charset=\"UTF-8\">\n  <title>UniFlow.ModelView tests</title>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0\">\n\n  <script src=\"../../webcomponentsjs/webcomponents-lite.js\"></script>\n  <script src=\"../../web-component-tester/browser.js\"></script>\n\n  <link rel=\"import\" href=\"../model-view.html\">\n\n</head>\n\n<body>\n\n  <dom-module id=\"model-view-test\">\n    <script>\n      class ModelViewTest extends UniFlow.ModelView(Polymer.Element) {\n        static get is() {\n          return 'model-view-test';\n        }\n\n        constructor() {\n          super();\n          this._validation = {\n            'foo': (value) => !value ? 'bad foo' : '',\n            'xxx': (value) => value == 'yyy' ? 123 : ''\n          }\n        }\n\n        get validation() {\n          return this._validation;\n        }\n        \n        get saveAction() {\n          return 'SAVE';\n        }\n\n        getMessage(code) {\n          return code === 123 ? 'error 123' : '';\n        }\n      }\n\n      customElements.define(ModelViewTest.is, ModelViewTest);\n    </script>\n  </dom-module>\n\n  <test-fixture id=\"basic\">\n    <template is=\"dom-template\">\n      <model-view-test>\n      </model-view-test>\n    </template>\n  </test-fixture>\n\n  <script>\n    'use strict';\n\n    suite('UniFlow.ModelView', () => {\n\n      let modelView, model, status;\n\n      setup(() => {\n        model = {foo: 'bar'};\n        status = {};\n        modelView = fixture('basic');\n        modelView.set('model', model);\n      });\n\n      test('is ok', () => {\n        expect(modelView).to.be.ok;\n      });\n\n      test('saves model', () => {\n        sinon.spy(modelView, 'emitAction');\n        modelView.saveModel();\n        expect(modelView.emitAction).to.be.calledWith({\n          model,\n          path: 'model',\n          type: 'SAVE'\n        });\n      });\n\n      test('saves model with custom action type', () => {\n        sinon.spy(modelView, 'emitAction');\n        modelView.saveModel('CUSTOM-SAVE');\n        expect(modelView.emitAction).to.be.calledWith({\n          model,\n          path: 'model',\n          type: 'CUSTOM-SAVE'\n        });\n      });\n\n      test('saves model with custom action', () => {\n        sinon.spy(modelView, 'emitAction');\n        modelView.saveModel({\n          type: 'XXX',\n          path: 'my.model'\n        });\n        expect(modelView.emitAction).to.be.calledWith({\n          model,\n          path: 'my.model',\n          type: 'XXX'\n        });\n      });\n\n      test('initializes validation status', () => {\n        modelView.initValidationStatus_();\n        expect(modelView.get('status.validation')).to.deep.equal({\n          foo: {\n            invalid: false\n          },\n          xxx: {\n            invalid: false\n          }\n        });\n      });\n\n      test('validates model when validation not specified', () => {\n        modelView._validation = undefined;\n        expect(modelView.validateModel()).to.be.true;\n      });\n\n      test('validates model to true', () => {\n        expect(modelView.validateModel()).to.be.true;\n        expect(modelView.get('status.validation')).to.deep.equal({\n          foo: {\n            invalid: false,\n            errorMessage: ''\n          },\n          xxx: {\n            invalid: false,\n            errorMessage: ''\n          }\n        });\n      });\n\n      test('validates model to false with error text', () => {\n        modelView.set('model.foo', '');\n        expect(modelView.validateModel()).to.be.false;\n        expect(modelView.get('status.validation.foo')).to.deep.equal({\n          invalid: true,\n          errorMessage: 'bad foo'\n        });\n      });\n\n      test('validates model to false with error code', () => {\n        modelView.set('model.xxx', 'yyy');\n        expect(modelView.validateModel()).to.be.false;\n        expect(modelView.get('status.validation.xxx')).to.deep.equal({\n          invalid: true,\n          errorMessage: 'error 123'\n        });\n      });\n\n      test('validates to true and saves', () => {\n        sinon.spy(modelView, 'saveModel');\n        modelView.validateAndSave('action');\n        expect(modelView.saveModel).to.be.calledWith('action');\n      });\n\n      test('validates to false and does not save', () => {\n        sinon.spy(modelView, 'saveModel');\n        modelView.set('model.foo', '');\n        modelView.validateAndSave('action');\n        expect(modelView.saveModel).to.have.not.been.called;\n      });\n\n      test('handles model change', () => {\n        sinon.spy(modelView, 'initValidationStatus_');\n        modelView.set('model', {\n          foo: 'bar'\n        });\n        expect(modelView.initValidationStatus_).to.have.been.called;\n        expect(modelView.get('status')).to.deep.equal({\n          isModified: false,\n          validation: {\n            foo: {\n              invalid: false\n            },\n            xxx: {\n              invalid: false\n            }\n          }\n        });\n      });\n\n      test('handles model change to null', () => {\n        sinon.spy(modelView, 'initValidationStatus_');\n        modelView.set('model', null);\n        expect(modelView.initValidationStatus_).to.have.not.been.called;\n        expect(modelView.get('status')).to.deep.equal({});\n      });\n\n      test('handles model field change', () => {\n        sinon.spy(modelView, 'initValidationStatus_');\n        modelView.set('model.foo', 'baz');\n        expect(modelView.initValidationStatus_).to.have.not.been.called;\n        expect(modelView.get('status.isModified')).to.equal(true);\n      });\n\n    });\n  </script>\n\n</body>\n\n</html>"
  },
  {
    "path": "test/state-aware_test.html",
    "content": "<!doctype html>\n<!--\nCopyright 2017 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n-->\n<html>\n\n<head>\n  <meta charset=\"UTF-8\">\n  <title>UniFlow.StateAware tests</title>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0\">\n\n  <script src=\"../../webcomponentsjs/webcomponents-lite.js\"></script>\n  <script src=\"../../web-component-tester/browser.js\"></script>\n\n  <link rel=\"import\" href=\"../state-aware.html\">\n\n</head>\n\n<body>\n\n<dom-module id=\"state-aware-test\">\n  <script>\n    class StateAwareTest extends UniFlow.StateAware(Polymer.Element) {\n      static get is() {\n        return 'state-aware-test';\n      }\n    }\n\n    customElements.define(StateAwareTest.is, StateAwareTest);\n  </script>\n</dom-module>\n\n<test-fixture id=\"basic\">\n  <template is=\"dom-template\">\n    <state-aware-test>\n    </state-aware-test>\n  </template>\n</test-fixture>\n\n<script>\n  'use strict';\n\n  suite('UniFlow.StateAware', () => {\n\n    let stateAware;\n\n    setup(() => {\n      stateAware = fixture('basic');\n    });\n\n    test('is ok', () => {\n      expect(stateAware).to.be.ok;\n    });\n\n    test('added to application.stateAwareElements', () => {\n      expect(stateAware.get('application.stateAwareElements')).to.deep.equal(\n          [stateAware]);\n    });\n\n    test('removed from application.stateAwareElements', () => {\n      stateAware.parentNode.removeChild(stateAware);\n      expect(stateAware.get('application.stateAwareElements'))\n          .to.deep.equal([]);\n    });\n\n    test('added to application.stateAwareElements', () => {\n      sinon.stub(stateAware, 'get').withArgs('application.element')\n          .returns('my-app');\n      expect(stateAware.getApplication()).to.equal('my-app');\n    });\n\n  });\n</script>\n\n</body>\n\n</html>"
  },
  {
    "path": "todomvc/README.md",
    "content": "# \\<todo\\>\n\nToDo MVC application implemented with UniFlow for Polymer 2.x\n\n## Install Bower Dependencies\n\nRun `bower install`\n\n## Install the Polymer-CLI\n\nMake sure you have the [Polymer CLI](https://www.npmjs.com/package/polymer-cli) installed.\n\n## Run the Application\n\nRun `polymer serve` to serve your application locally.\n\nOpen the by adding todomvc to the url, for example:\n\nhttp://127.0.0.1:8081/components/uniflow-polymer/todomvc"
  },
  {
    "path": "todomvc/elements/todo-action-dispatcher.html",
    "content": "<link rel=\"import\" href=\"../../../polymer/polymer-element.html\">\n<link rel=\"import\" href=\"../../action-dispatcher.html\">\n<link rel=\"import\" href=\"../../action-emitter.html\">\n\n<dom-module id=\"todo-action-dispatcher\">\n  <script>\n    class TodoActionDispatcher extends UniFlow.ActionEmitter(UniFlow.ActionDispatcher(Polymer.Element)) {\n      static get is() {\n        return 'todo-action-dispatcher';\n      }\n\n      _updateAllCompleted() {\n        if (this.get('state.todoList') && this.get('state.todoList').length) {\n          this.set('state.allCompleted',\n              this.get('state.todoList').every((item) => item.completed));\n        } else {\n          this.set('state.allCompleted', false);\n        }\n      }\n\n      _updateActiveCount() {\n        this.set('state.activeCount', this.get('state.todoList').reduce((count, todoItem) => count + (\n            todoItem.completed ? 0 : 1), 0));\n      }\n\n      [todo.actions.INIT_APPLICATION](details) {\n        this._updateAllCompleted();\n        this._updateActiveCount();\n      }\n\n      [todo.actions.ADD_TODO](details) {\n        this.push('state.todoList', {\n          text: details.text,\n          completed: false\n        });\n        this._updateAllCompleted();\n        this._updateActiveCount();\n      }\n\n      [todo.actions.UPDATE_TODO](details) {\n        let index = this.get('state.todoList').indexOf(details.model);\n        this.set(['state.todoList', index, 'text'], details.text);\n      }\n\n      [todo.actions.REMOVE_TODO](details) {\n        let index = this.state.todoList.indexOf(details.model);\n        this.splice('state.todoList', index, 1);\n        this._updateAllCompleted();\n        this._updateActiveCount();\n      }\n\n      [todo.actions.SELECTION_CHANGED](details) {\n        if (details.applyToAll) {\n          this.set('state.allCompleted', details.value);\n          this.get('state.todoList').forEach((item, index) => {\n            this.set(['state.todoList', index, 'completed'],\n                details.value);\n          });\n        } else {\n          if (details.model) {\n            let index = this.get('state.todoList').indexOf(details.model);\n            this.set(['state.todoList', index, 'completed'], details.completed);\n          }\n          this._updateAllCompleted();\n        }\n        this._updateActiveCount();\n      }\n\n      [todo.actions.CLEAR_COMPLETED](details) {\n        let completed = this.get('state.todoList').filter(\n            elem => elem.completed);\n        completed.forEach(elem => {\n          let index = this.state.todoList.indexOf(elem);\n          this.splice('state.todoList', index, 1);\n        });\n        this._updateAllCompleted();\n      }\n    }\n\n    customElements.define(TodoActionDispatcher.is, TodoActionDispatcher);\n  </script>\n</dom-module>"
  },
  {
    "path": "todomvc/elements/todo-app.html",
    "content": "<link rel=\"import\" href=\"../../../polymer/polymer-element.html\">\n<link rel=\"import\" href=\"../../action-emitter.html\">\n<link rel=\"import\" href=\"../../application-state.html\">\n<link rel=\"import\" href=\"../../../app-route/app-route.html\">\n<link rel=\"import\" href=\"../../../app-route/app-location.html\">\n<link rel=\"import\" href=\"../../../iron-localstorage/iron-localstorage.html\">\n\n<link rel=\"import\" href=\"todo-header.html\">\n<link rel=\"import\" href=\"todo-items.html\">\n<link rel=\"import\" href=\"todo-footer.html\">\n<link rel=\"import\" href=\"todo-action-dispatcher.html\">\n\n<link rel=\"import\" href=\"todo-styles.html\">\n\n<dom-module id=\"todo-app\">\n  <template>\n    <style include=\"todo-styles\">\n\n    </style>\n\n    <todo-action-dispatcher state=\"{{state}}\"></todo-action-dispatcher>\n    <section class=\"todoapp\">\n      <app-location route=\"{{route}}\" use-hash-as-path></app-location>\n      <app-route route=\"{{route}}\" pattern=\"/:filterBy\" data=\"{{routeData}}\"></app-route>\n      <iron-localstorage name=\"todo-list\" value=\"{{state.todoList}}\" on-iron-localstorage-load-empty=\"onStorageLoadEmpty\" on-iron-localstorage-load=\"onStorageLoad\">\n      </iron-localstorage>\n      <todo-header></todo-header>\n      <template is=\"dom-if\" if=\"[[state.todoList.length]]\">\n        <!-- This section should be hidden by default and shown when there are todos -->\n        <section class=\"main\">\n          <input class=\"toggle-all\" type=\"checkbox\" checked=\"[[state.allCompleted]]\" on-change=\"onAllCompletedChange\">\n          <label for=\"toggle-all\">Mark all as complete</label>\n          <todo-items id=\"list\" list=\"[[state.todoList]]\" filter-by=\"[[routeData.filterBy]]\">\n          </todo-items>\n        </section>\n        <!-- This footer should hidden by default and shown when there are todos -->\n        <todo-footer filter-by=\"[[routeData.filterBy]]\">\n        </todo-footer>\n      </template>\n    </section>\n\n  </template>\n  <script>\n    class TodoApp extends UniFlow.ActionEmitter(UniFlow.ApplicationState(Polymer.Element)) {\n      static get is() {\n        return 'todo-app';\n      }\n\n      static get properties() {\n        return {\n          route: Object,\n          routeData: Object\n        }\n      }\n\n      ready() {\n        super.ready();\n        this.set('state', {\n          allCompleted: false,\n          activeCount: 0\n        });\n      }\n\n      onStorageLoadEmpty() {\n        this.set('state.todoList', []);\n      }\n\n      onStorageLoad() {\n        this.emitAction({\n          type: todo.actions.INIT_APPLICATION\n        });\n      }\n    }\n\n    customElements.define(TodoApp.is, TodoApp);\n  </script>\n</dom-module>"
  },
  {
    "path": "todomvc/elements/todo-footer.html",
    "content": "<link rel=\"import\" href=\"../../../polymer/polymer-element.html\">\n<link rel=\"import\" href=\"../../../polymer/lib/mixins/gesture-event-listeners.html\">\n<link rel=\"import\" href=\"../../action-emitter.html\">\n<link rel=\"import\" href=\"../../state-aware.html\">\n\n<link rel=\"import\" href=\"todo-styles.html\">\n\n<dom-module id=\"todo-footer\">\n  <template>\n    <style include=\"todo-styles\">\n      .filters li a[selected] {\n        border-color: rgba(175, 47, 47, 0.2);\n      }\n    </style>\n\n    <footer class=\"footer\">\n      <span class=\"todo-count\">\n        <strong>[[state.activeCount]]</strong>\n        item<span hidden$=\"[[isEqual(state.activeCount, 1)]]\">s</span> left\n      </span>\n      <ul class=\"filters\">\n        <li>\n          <a selected$=\"[[!filterBy]]\" href=\"#/\">All</a>\n        </li>\n        <li>\n          <a selected$=\"[[isEqual(filterBy, 'active')]]\" href=\"#/active\">Active</a>\n        </li>\n        <li>\n          <a selected$=\"[[isEqual(filterBy, 'completed')]]\" href=\"#/completed\">Completed</a>\n        </li>\n      </ul>\n      <!-- Hidden if no completed items are left -->\n      <template is=\"dom-if\" if=\"[[completedCount]]\">\n        <button class=\"clear-completed\" on-tap=\"onClearCompletedButtonTap\">Clear completed</button>\n      </template>\n    </footer>\n\n  </template>\n  <script>\n    class TodoFooter extends Polymer.GestureEventListeners(UniFlow.ActionEmitter(UniFlow.StateAware(Polymer.Element))) {\n\n      static get is() {\n        return 'todo-footer';\n      }\n\n      static get properties() {\n        return {\n          filterBy: String,\n          completedCount: {\n            type: Number,\n            computed: 'getCompletedCount(state.todoList.length, state.activeCount)'\n          }\n        }\n      }\n\n      isEqual(val1, val2) {\n        return val1 == val2;\n      }\n\n      getCompletedCount(totalCount, activeCount) {\n        return totalCount - activeCount;\n      }\n\n      onClearCompletedButtonTap() {\n        this.emitAction({\n          type: todo.actions.CLEAR_COMPLETED\n        })\n      }\n    }\n\n    customElements.define(TodoFooter.is, TodoFooter);\n  </script>\n</dom-module>"
  },
  {
    "path": "todomvc/elements/todo-header.html",
    "content": "<link rel=\"import\" href=\"../../../polymer/polymer-element.html\">\n<link rel=\"import\" href=\"../../action-emitter.html\">\n<link rel=\"import\" href=\"../../state-aware.html\">\n\n<link rel=\"import\" href=\"todo-styles.html\">\n\n<dom-module id=\"todo-header\">\n  <template>\n    <style include=\"todo-styles\">\n\n    </style>\n\n    <header class=\"header\">\n      <h1>todos</h1>\n      <input class=\"new-todo\" placeholder=\"What needs to be done?\" value=\"{{todoText::input}}\" on-keydown=\"onInputKeyDown\" autofocus>\n    </header>\n\n  </template>\n  <script>\n    class TodoHeader extends UniFlow.ActionEmitter(Polymer.Element) {\n      static get is() {\n        return 'todo-header';\n      }\n\n      static properties() {\n        return {\n          todoText: String\n        }\n      }\n\n      onInputKeyDown(e) {\n        if (e.keyCode == 13 && this.todoText.trim().length) {\n          this.emitAction({\n            type: todo.actions.ADD_TODO,\n            text: this.todoText\n          });\n          this.todoText = '';\n        }\n      }\n    }\n\n    customElements.define(TodoHeader.is, TodoHeader);\n  </script>\n</dom-module>"
  },
  {
    "path": "todomvc/elements/todo-item.html",
    "content": "<link rel=\"import\" href=\"../../../polymer/polymer-element.html\">\n<link rel=\"import\" href=\"../../../polymer/lib/mixins/gesture-event-listeners.html\">\n<link rel=\"import\" href=\"../../model-view.html\">\n\n<link rel=\"import\" href=\"todo-styles.html\">\n\n<dom-module id=\"todo-item\">\n  <template>\n    <style include=\"todo-styles\">\n       :host {\n        display: block;\n      }\n\n      li {\n        position: relative;\n        font-size: 24px;\n      }\n\n      li[editing] {\n        border-bottom: none;\n        padding: 0;\n      }\n\n      li[editing] .edit {\n        display: block;\n        width: 506px;\n        padding: 12px 16px;\n        margin: 0 0 0 43px;\n      }\n\n      li[editing] .view {\n        display: none;\n      }\n\n      li .toggle {\n        text-align: center;\n        width: 40px;\n        /* auto, since non-WebKit browsers doesn't support input styling */\n        height: auto;\n        position: absolute;\n        top: 9px;\n        margin: auto 0;\n        border: none;\n        /* Mobile Safari */\n        -webkit-appearance: none;\n        appearance: none;\n      }\n\n      li .toggle:after {\n        content: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"40\" height=\"40\" viewBox=\"-10 -18 100 135\"><circle cx=\"50\" cy=\"50\" r=\"50\" fill=\"none\" stroke=\"#ededed\" stroke-width=\"3\"/></svg>');\n      }\n\n      li .toggle:checked:after {\n        content: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"40\" height=\"40\" viewBox=\"-10 -18 100 135\"><circle cx=\"50\" cy=\"50\" r=\"50\" fill=\"none\" stroke=\"#bddad5\" stroke-width=\"3\"/><path fill=\"#5dc2af\" d=\"M72 25L42 71 27 56l-4 4 20 20 34-52z\"/></svg>');\n      }\n\n      li label {\n        word-break: break-all;\n        padding: 15px 60px 15px 15px;\n        margin-left: 45px;\n        display: block;\n        line-height: 1.2;\n        transition: color 0.4s;\n      }\n\n      li[completed] label {\n        color: #d9d9d9;\n        text-decoration: line-through;\n      }\n\n      li .destroy {\n        display: none;\n        position: absolute;\n        top: 0;\n        right: 10px;\n        bottom: 0;\n        width: 40px;\n        height: 40px;\n        margin: auto 0;\n        font-size: 30px;\n        color: #cc9a9a;\n        margin-bottom: 11px;\n        transition: color 0.2s ease-out;\n      }\n\n      li .destroy:hover {\n        color: #af5b5e;\n      }\n\n      li .destroy:after {\n        content: '×';\n      }\n\n      li:hover .destroy {\n        display: block;\n      }\n\n      li[editing]:last-child {\n        margin-bottom: -1px;\n      }\n\n      li .toggle:after {\n        content: url('../resources/unchecked.svg');\n      }\n\n      li .toggle:checked:after {\n        content: url('../resources/checked.svg');\n      }\n    </style>\n\n    <li completed$=\"[[model.completed]]\" editing$=\"[[isEditing]]\">\n      <div class=\"view\">\n        <input class=\"toggle\" type=\"checkbox\" checked=\"[[model.completed]]\" on-change=\"onCompletedChange\">\n        <label on-dblclick=\"onViewDblClick\">[[model.text]]</label>\n        <button class=\"destroy\" on-tap=\"onDestroyTap\"></button>\n      </div>\n      <input id=\"text-input\" class=\"edit\" hidden=\"[[!isEditing]]\" on-blur=\"onInputBlur\" on-keydown=\"onInputKeyDown\">\n    </li>\n  </template>\n  <script>\n    class TodoItem extends UniFlow.ModelView(Polymer.GestureEventListeners(Polymer.Element)) {\n\n      static get is() {\n        return 'todo-item';\n      }\n\n\n      static get properties() {\n        return {\n          filterBy: String,\n          isEditing: {\n            type: Boolean,\n            value: false\n          }\n        }\n      }\n\n      onCompletedChange(e) {\n        this.emitAction({\n          type: todo.actions.SELECTION_CHANGED,\n          model: this.model,\n          completed: e.target.checked\n        });\n      }\n\n      _removeTodo() {\n        this.emitAction({\n          type: todo.actions.REMOVE_TODO,\n          model: this.model\n        });\n      }\n\n      onDestroyTap(e) {\n        this._removeTodo();\n      }\n\n      onViewDblClick(e) {\n        this.$['text-input'].value = this.model.text;\n        this.isEditing = true;\n        this.$['text-input'].focus();\n      }\n\n      onInputBlur(e) {\n        if (this.isEditing) {\n          this._confirmEdit();\n        }\n      }\n\n      _confirmEdit() {\n        this.emitAction({\n          type: todo.actions.UPDATE_TODO,\n          model: this.model,\n          text: this.$['text-input'].value\n        });\n        this.isEditing = false;\n        if (!this.model.text.trim()) {\n          this._removeTodo();\n        }\n      }\n\n      onInputKeyDown(e) {\n        if (e.keyCode == 13) {\n          this.$['text-input'].blur();\n        } else if (e.keyCode == 27) {\n          this.isEditing = false;\n        }\n      }\n    }\n\n    customElements.define(TodoItem.is, TodoItem);\n  </script>\n</dom-module>"
  },
  {
    "path": "todomvc/elements/todo-items.html",
    "content": "<link rel=\"import\" href=\"../../../polymer/polymer-element.html\">\n<link rel=\"import\" href=\"../../list-view.html\">\n\n<link rel=\"import\" href=\"todo-item.html\">\n\n<link rel=\"import\" href=\"todo-styles.html\">\n\n<dom-module id=\"todo-items\">\n  <template>\n    <style include=\"todo-styles\">\n      :host {\n        display: block;\n      }\n\n      todo-item {\n        border-top: 1px solid #ededed;\n      }\n\n      todo-item:first-child {\n        border-top: none;\n      }\n    </style>\n\n    <section class=\"main\">\n      <input id=\"ta\" class=\"toggle-all\" type=\"checkbox\" checked=\"[[state.allCompleted]]\" on-change=\"onAllCompletedChange\">\n      <label for=\"ta\">Mark all as complete</label>\n      <ul class=\"todo-list\">\n        <template is=\"dom-repeat\" id=\"list-template\" items=\"[[list]]\" as=\"todoItem\" filter=\"[[filterList(filterBy)]]\" observe=\"completed\">\n          <todo-item model=\"[[todoItem]]\"></todo-item>\n        </template>\n      </ul>\n    </section>\n  </template>\n  <script>\n    class TodoItems extends UniFlow.ListView(UniFlow.StateAware(Polymer.Element)) {\n      static get is() {\n        return 'todo-items';\n      }\n\n      filterList(filterBy) {\n        return function (item) {\n          switch (filterBy) {\n            case 'active':\n              return !item.completed;\n            case 'completed':\n              return item.completed;\n            default:\n              return true;\n          }\n        };\n      }\n\n      onAllCompletedChange(event) {\n        this.emitAction({\n          type: todo.actions.SELECTION_CHANGED,\n          applyToAll: true,\n          value: event.target.checked\n        })\n      }\n    }\n\n    customElements.define(TodoItems.is, TodoItems);\n  </script>\n</dom-module>"
  },
  {
    "path": "todomvc/elements/todo-styles.html",
    "content": "<dom-module id=\"todo-styles\">\n  <template>\n    <style>\n      button {\n        margin: 0;\n        padding: 0;\n        border: 0;\n        background: none;\n        font-size: 100%;\n        vertical-align: baseline;\n        font-family: inherit;\n        font-weight: inherit;\n        color: inherit;\n        -webkit-appearance: none;\n        appearance: none;\n        -webkit-font-smoothing: antialiased;\n        -moz-osx-font-smoothing: grayscale;\n      }\n\n      :focus {\n        outline: 0;\n      }\n\n      .hidden {\n        display: none;\n      }\n\n      .todoapp {\n        background: #fff;\n        margin: 130px 0 40px 0;\n        position: relative;\n        box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),\n        0 25px 50px 0 rgba(0, 0, 0, 0.1);\n      }\n\n      input::-webkit-input-placeholder {\n        font-style: italic;\n        font-weight: 300;\n        color: #e6e6e6;\n      }\n\n      input::-moz-placeholder {\n        font-style: italic;\n        font-weight: 300;\n        color: #e6e6e6;\n      }\n\n      input::input-placeholder {\n        font-style: italic;\n        font-weight: 300;\n        color: #e6e6e6;\n      }\n\n      h1 {\n        position: absolute;\n        top: -155px;\n        width: 100%;\n        font-size: 100px;\n        font-weight: 100;\n        text-align: center;\n        color: rgba(175, 47, 47, 0.15);\n        -webkit-text-rendering: optimizeLegibility;\n        -moz-text-rendering: optimizeLegibility;\n        text-rendering: optimizeLegibility;\n      }\n\n      .new-todo,\n      .edit {\n        position: relative;\n        margin: 0;\n        width: 100%;\n        font-size: 24px;\n        font-family: inherit;\n        font-weight: inherit;\n        line-height: 1.4em;\n        border: 0;\n        color: inherit;\n        padding: 6px;\n        border: 1px solid #999;\n        box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);\n        box-sizing: border-box;\n        -webkit-font-smoothing: antialiased;\n        -moz-osx-font-smoothing: grayscale;\n      }\n\n      .new-todo {\n        padding: 16px 16px 16px 60px;\n        border: none;\n        background: rgba(0, 0, 0, 0.003);\n        box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03);\n      }\n\n      .main {\n        position: relative;\n        z-index: 2;\n        border-top: 1px solid #e6e6e6;\n      }\n\n      .toggle-all {\n        text-align: center;\n        border: none;\n        /* Mobile Safari */\n        opacity: 0;\n        position: absolute;\n      }\n\n      .toggle-all+label {\n        width: 60px;\n        height: 34px;\n        font-size: 0;\n        position: absolute;\n        top: -52px;\n        left: -13px;\n        -webkit-transform: rotate(90deg);\n        transform: rotate(90deg);\n      }\n\n      .toggle-all+label:before {\n        content: '❯';\n        font-size: 22px;\n        color: #e6e6e6;\n        padding: 10px 27px 10px 27px;\n      }\n\n      .toggle-all:checked+label:before {\n        color: #737373;\n      }\n\n      .todo-list {\n        margin: 0;\n        padding: 0;\n        list-style: none;\n      }\n\n      .todo-list li {\n        position: relative;\n        font-size: 24px;\n        border-bottom: 1px solid #ededed;\n      }\n\n      .todo-list li:last-child {\n        border-bottom: none;\n      }\n\n      .todo-list li.editing {\n        border-bottom: none;\n        padding: 0;\n      }\n\n      .todo-list li.editing .edit {\n        display: block;\n        width: 506px;\n        padding: 12px 16px;\n        margin: 0 0 0 43px;\n      }\n\n      .todo-list li.editing .view {\n        display: none;\n      }\n\n      .todo-list li .toggle {\n        text-align: center;\n        width: 40px;\n        /* auto, since non-WebKit browsers doesn't support input styling */\n        height: auto;\n        position: absolute;\n        top: 0;\n        bottom: 0;\n        margin: auto 0;\n        border: none;\n        /* Mobile Safari */\n        -webkit-appearance: none;\n        appearance: none;\n      }\n\n      .todo-list li .toggle {\n        opacity: 0;\n      }\n\n      .todo-list li .toggle+label {\n        /*\n\t\tFirefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433\n\t\tIE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/\n\t*/\n        background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');\n        background-repeat: no-repeat;\n        background-position: center left;\n      }\n\n      .todo-list li .toggle:checked+label {\n        background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');\n      }\n\n      .todo-list li label {\n        word-break: break-all;\n        padding: 15px 15px 15px 60px;\n        display: block;\n        line-height: 1.2;\n        transition: color 0.4s;\n      }\n\n      .todo-list li.completed label {\n        color: #d9d9d9;\n        text-decoration: line-through;\n      }\n\n      .todo-list li .destroy {\n        display: none;\n        position: absolute;\n        top: 0;\n        right: 10px;\n        bottom: 0;\n        width: 40px;\n        height: 40px;\n        margin: auto 0;\n        font-size: 30px;\n        color: #cc9a9a;\n        margin-bottom: 11px;\n        transition: color 0.2s ease-out;\n      }\n\n      .todo-list li .destroy:hover {\n        color: #af5b5e;\n      }\n\n      .todo-list li .destroy:after {\n        content: '×';\n      }\n\n      .todo-list li:hover .destroy {\n        display: block;\n      }\n\n      .todo-list li .edit {\n        display: none;\n      }\n\n      .todo-list li.editing:last-child {\n        margin-bottom: -1px;\n      }\n\n      .footer {\n        color: #777;\n        padding: 10px 15px;\n        height: 20px;\n        text-align: center;\n        border-top: 1px solid #e6e6e6;\n      }\n\n      .footer:before {\n        content: '';\n        position: absolute;\n        right: 0;\n        bottom: 0;\n        left: 0;\n        height: 50px;\n        overflow: hidden;\n        box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),\n        0 8px 0 -3px #f6f6f6,\n        0 9px 1px -3px rgba(0, 0, 0, 0.2),\n        0 16px 0 -6px #f6f6f6,\n        0 17px 2px -6px rgba(0, 0, 0, 0.2);\n      }\n\n      .todo-count {\n        float: left;\n        text-align: left;\n      }\n\n      .todo-count strong {\n        font-weight: 300;\n      }\n\n      .filters {\n        margin: 0;\n        padding: 0;\n        list-style: none;\n        position: absolute;\n        right: 0;\n        left: 0;\n      }\n\n      .filters li {\n        display: inline;\n      }\n\n      .filters li a {\n        color: inherit;\n        margin: 3px;\n        padding: 3px 7px;\n        text-decoration: none;\n        border: 1px solid transparent;\n        border-radius: 3px;\n      }\n\n      .filters li a:hover {\n        border-color: rgba(175, 47, 47, 0.1);\n      }\n\n      .filters li a.selected {\n        border-color: rgba(175, 47, 47, 0.2);\n      }\n\n      .clear-completed,\n      html .clear-completed:active {\n        float: right;\n        position: relative;\n        line-height: 20px;\n        text-decoration: none;\n        cursor: pointer;\n      }\n\n      .clear-completed:hover {\n        text-decoration: underline;\n      }\n\n      .info {\n        margin: 65px auto 0;\n        color: #bfbfbf;\n        font-size: 10px;\n        text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n        text-align: center;\n      }\n\n      .info p {\n        line-height: 1;\n      }\n\n      .info a {\n        color: inherit;\n        text-decoration: none;\n        font-weight: 400;\n      }\n\n      .info a:hover {\n        text-decoration: underline;\n      }\n      /*\n\tHack to remove background from Mobile Safari.\n\tCan't use it globally since it destroys checkboxes in Firefox\n*/\n\n      @media screen and (-webkit-min-device-pixel-ratio:0) {\n        .toggle-all,\n        .todo-list li .toggle {\n          background: none;\n        }\n\n        .todo-list li .toggle {\n          height: 40px;\n        }\n      }\n\n      @media (max-width: 430px) {\n        .footer {\n          height: 50px;\n        }\n\n        .filters {\n          bottom: 10px;\n        }\n      }\n    </style>\n  </template>\n</dom-module>"
  },
  {
    "path": "todomvc/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <title>TodoMVC with UniFlow</title>\n    <link rel=\"stylesheet\" href=\"../../todomvc-app-css/index.css\">\n\n    <!-- See https://goo.gl/OOhYW5 -->\n    <link rel=\"manifest\" href=\"/manifest.json\">\n\n    <script src=\"scripts/actions.js\"></script>\n\n    <script src=\"../../webcomponentsjs/webcomponents-loader.js\"></script>\n    <link rel=\"import\" href=\"elements/todo-app.html\">\n\n  </head>\n  <body>\n    <todo-app></todo-app>\n\n    <footer class=\"info\">\n      <p>Double-click to edit a todo</p>\n      <!-- Remove the below line -->\n      <p>Template by <a href=\"http://sindresorhus.com\">Sindre Sorhus</a></p>\n      <!-- Change this out with your name and url -->\n      <p>Created by <a href=\"mailto:militeev@google.com\">Andrei Militeev</a></p>\n      <p>Part of <a href=\"http://todomvc.com\">TodoMVC</a></p>\n    </footer>\n  </body>\n</html>\n"
  },
  {
    "path": "todomvc/manifest.json",
    "content": "{\n  \"name\": \"todo\",\n  \"short_name\": \"todo\",\n  \"description\": \"ToDo MVC application implemented with UniFlow for Polymer\",\n  \"start_url\": \"/\",\n  \"display\": \"standalone\"\n}\n"
  },
  {
    "path": "todomvc/scripts/actions.js",
    "content": "window.todo = window.todo || {};\n\ntodo.actions = {\n\n  INIT_APPLICATION: \"INIT_APPLICATION\",\n  ADD_TODO: \"ADD_TODO\",\n  REMOVE_TODO: \"REMOVE_TODO\",\n  UPDATE_TODO: \"UPDATE_TODO\",\n  SELECTION_CHANGED: \"SELECTION_CHANGED\",\n  CLEAR_COMPLETED: \"CLEAR_COMPLETED\"\n\n}\n"
  }
]