Full Code of PolymerLabs/app-layout for AI

master 5882cd26f0e6 cached
148 files
1.4 MB
384.5k tokens
24 symbols
1 requests
Download .txt
Showing preview only (1,513K chars total). Download the full file or copy to clipboard to get everything.
Repository: PolymerLabs/app-layout
Branch: master
Commit: 5882cd26f0e6
Files: 148
Total size: 1.4 MB

Directory structure:
gitextract_x_yw3dwn/

├── .github/
│   ├── CODEOWNERS
│   └── ISSUE_TEMPLATE.md
├── .gitignore
├── .npmignore
├── .travis.yml
├── CONTRIBUTING.md
├── README.md
├── app-box/
│   ├── README.md
│   ├── app-box.js
│   └── demo/
│       ├── document-scroll.html
│       ├── index.html
│       └── scrolling-region.html
├── app-drawer/
│   ├── README.md
│   ├── app-drawer.js
│   ├── demo/
│   │   ├── index.html
│   │   ├── left-drawer.html
│   │   └── right-drawer.html
│   └── test/
│       ├── app-drawer.html
│       └── index.html
├── app-drawer-layout/
│   ├── README.md
│   ├── app-drawer-layout.js
│   ├── demo/
│   │   └── index.html
│   └── test/
│       ├── app-drawer-layout.html
│       └── index.html
├── app-grid/
│   ├── README.md
│   ├── app-grid-style.js
│   ├── demo/
│   │   ├── aspect-ratio.html
│   │   ├── flickr-grid-layout.html
│   │   ├── index.html
│   │   ├── md-grid-layout.html
│   │   └── simple-responsive-grid.html
│   └── test/
│       ├── app-grid-1.html
│       ├── app-grid-2.html
│       ├── app-grid-3.html
│       └── index.html
├── app-header/
│   ├── README.md
│   ├── app-header.js
│   ├── demo/
│   │   ├── blend-background-1.html
│   │   ├── blend-background-2.html
│   │   ├── blend-background-3.html
│   │   ├── contacts.html
│   │   ├── custom-sticky-element-1.html
│   │   ├── custom-sticky-element-2.html
│   │   ├── give.html
│   │   ├── index.html
│   │   ├── music.html
│   │   ├── no-effects.html
│   │   └── notes.html
│   └── test/
│       ├── app-header.html
│       └── index.html
├── app-header-layout/
│   ├── README.md
│   ├── app-header-layout.js
│   ├── demo/
│   │   ├── footer.html
│   │   ├── index.html
│   │   ├── music.html
│   │   ├── scrolling-region.html
│   │   └── simple.html
│   └── test/
│       ├── app-header-layout.html
│       └── index.html
├── app-layout-behavior/
│   └── app-layout-behavior.js
├── app-layout.js
├── app-scroll-effects/
│   ├── README.md
│   ├── app-scroll-effects-behavior.js
│   ├── app-scroll-effects.js
│   ├── effects/
│   │   ├── blend-background.js
│   │   ├── fade-background.js
│   │   ├── material.js
│   │   ├── parallax-background.js
│   │   ├── resize-snapped-title.js
│   │   ├── resize-title.js
│   │   └── waterfall.js
│   └── test/
│       ├── app-scroll-effects-behavior.html
│       ├── blend-background.html
│       ├── fade-background.html
│       ├── index.html
│       ├── parallax-background.html
│       ├── resize-snapped-title.html
│       ├── resize-title.html
│       ├── utils.js
│       ├── waterfall.html
│       └── x-container.js
├── app-toolbar/
│   ├── README.md
│   ├── app-toolbar.js
│   ├── demo/
│   │   └── index.html
│   └── test/
│       ├── app-toolbar.html
│       └── index.html
├── bower.json
├── demo/
│   ├── contacts.json
│   ├── demo1.html
│   ├── demo2.html
│   ├── demo3.html
│   ├── demo4.html
│   ├── demo5.html
│   ├── demo6.html
│   ├── demo7.html
│   ├── index.html
│   └── sample-content.js
├── formatconfig.json
├── gen-tsd.json
├── helpers/
│   ├── helpers.js
│   └── test/
│       ├── index.html
│       ├── register-effect.html
│       └── scroll.html
├── manifest.json
├── package.json
├── patterns/
│   ├── expand-card/
│   │   └── index.html
│   ├── md-responsive-toolbar/
│   │   └── index.html
│   └── transform-navigation/
│       ├── index.html
│       └── x-app.js
├── templates/
│   ├── getting-started/
│   │   ├── index.html
│   │   ├── package.json
│   │   └── x-app.js
│   ├── landing-page/
│   │   ├── index.html
│   │   ├── package.json
│   │   └── x-app.js
│   ├── pesto/
│   │   ├── data/
│   │   │   └── recipes.json
│   │   ├── index.html
│   │   ├── manifest.json
│   │   ├── package.json
│   │   └── src/
│   │       ├── app-icons.js
│   │       ├── recipe-app.js
│   │       ├── recipe-detail.js
│   │       └── recipe-list.js
│   ├── publishing/
│   │   ├── data/
│   │   │   └── articles.json
│   │   ├── index.html
│   │   ├── manifest.json
│   │   ├── package.json
│   │   └── src/
│   │       ├── app-icons.js
│   │       ├── article-detail.js
│   │       ├── article-headline.js
│   │       ├── blog-app.js
│   │       └── two-columns-grid.js
│   ├── shrine/
│   │   ├── data/
│   │   │   ├── featured.json
│   │   │   └── items.json
│   │   ├── index.html
│   │   ├── manifest.json
│   │   ├── package.json
│   │   └── src/
│   │       ├── shrine-app.js
│   │       ├── shrine-detail.js
│   │       ├── shrine-featured-item.js
│   │       ├── shrine-item.js
│   │       ├── shrine-list.js
│   │       └── shrine-simple-item.js
│   └── test-drive/
│       ├── index.html
│       ├── package.json
│       └── test-app.js
├── test/
│   └── index.html
└── wct.conf.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/CODEOWNERS
================================================
* @keanulee @frankiefu
/.travis.yml @azakus


================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
<!-- Instructions: https://github.com/PolymerElements/app-layout/CONTRIBUTING.md#filing-issues -->
### Description
<!-- Example: The `paper-foo` element causes the page to turn pink when clicked. -->

### Expected outcome

<!-- Example: The page stays the same color. -->

### Actual outcome

<!-- Example: The page turns pink. -->

### Live Demo
<!-- Example: https://jsbin.com/cagaye/edit?html,output -->

### Steps to reproduce

<!-- Example
1. Put a `paper-foo` element in the page.
* Open the page in a web browser.
* Click the `paper-foo` element.
-->

### Browsers Affected
<!-- Check all that apply -->
- [ ] Chrome
- [ ] Firefox
- [ ] Safari 9
- [ ] Safari 8
- [ ] Safari 7
- [ ] Edge
- [ ] IE 11
- [ ] IE 10


================================================
FILE: .gitignore
================================================
bower_components*
bower-*.json
node_modules
*.d.ts
*.tgz


================================================
FILE: .npmignore
================================================
*.tgz
.github
.travis.yml
formatconfig.json
gen-tsd.json
test/
wct.conf.json


================================================
FILE: .travis.yml
================================================
language: node_js
sudo: 'false'
dist: trusty
node_js: node
addons:
  firefox: latest
  chrome: stable
before_script:
  - npm install -g polymer-cli
  - git checkout package-lock.json
  - >-
    npm run format && git diff --exit-code || (echo -e '\n\033[31mERROR:\033[0m
    Project is not formatted. Please run "npm run format".' && false)
script:
  - xvfb-run polymer test --module-resolution=node --npm
  - >-
    if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then polymer test
    --module-resolution=node --npm -s 'default'; fi
env:
  global:
    - secure: >-
        UFbrYeLJe/Z54rZ+WFw9R6BnkkSYwBM6RMUEcVRJmZpEErkXxna9mbIStFJgqPTBcRbEkU5CINj0NbHgQ/OOJZY8Dx1jozNPG6tHOxH9XGQKE6S78hOh4r6WlHiq4yUye0XJgYeZwfOaQDsPTbnL2IsNzTM5wuJr8OPHAylxkHbTzemyiXnrd9co6EGhe+ucwZ6eR+q84agdFxF2T+FbcA5V5a04KKbwrfVdTnUa1nb3wkfjMYNQMigp378HXUtMjaJkq4q16OGzORkmwheWGlPV1Paw/lh7ED6HtfkriTWOONKcrGSeW4XH4u3onyL8gKDjk1cAjcHsz3YD+b2+3Yh2r6tsSoHQk/Tk0z20qUpJ02VOB8PHYRXpHKBUVQjsvamPNx//UFoA95HOy3jix2GBfaf+cC9gElFd6IzBRZd80+WDQ2pdwYv+BJYG1Peyn+5UdqBkK7UzStWHVrqdLGMEC//c9aBLnvvguG7PGiu7ecQRrNgUib1zOgCE5IBHtqOIaxCIB9po29NYZmydpfPcuNsZyvBH+kjJQwJ0sp37mJ20B/nBwQ1m9I2b64BatkeHpnlhuAGtvGxTW1yg62OUAy5kYamWZo+rLEkcHBR98Jg6lh1kMRJWgd5pBxRs05JL28NXN+ITr0njCFxOhaJbcmhpcd/WQcS1Sar+lK4=
    - secure: >-
        g6vl6SKb0pwi5z5YUtwg5oI5Yg2oT7PQAfkS7Sl83oiL6uXWQGzpxIrzp92BLeZJbBJ/niwh1bPPZUe8ct08VD6o+6grESvxfia3wf11UQ21xGVt0y6koQPa9aZLgsfURpVUZCLDhf8zWyFAs4jN6nBdkv8VFxaIW7eRnouuQOQyiDRQYlnZv3nP6nK+D0ItOzNCIXoI27LuEGW5TgeJNm7rfE9GuGNS5ZwLgq/BeVxq17fo/3g43TwRwFXdGah1uDnhy4b7WaCzZcXyiNdN3A0TmWnWROI9s+BhAkG5fQsT0JuKpCgZwPdPn+MK3JCykcGxSot3TdnxwelvVAwxMy18BFkA+CdG7H6X0Qd8d/VeighU8AXq1qLLi5rwB+AWylQ6nWFIsAvuroZOHPeKCpq9l3MDwa4D+t5aXVrkfpi5ZtaooZF4mPKB/U4BKU2+pprCun/9qP//cwiMnJrJkP+ObgxTzl9Z6OfzbjLAE01kHzi4B8Ju/jcLkxk08Q/AyOQANpC4H1hCl+P77RJjkNN9+F4qjiz0kJftpj6hlbwmsRqTHXVBkrItTuIQ6aBLHgw415WCYrpRWVfCOL3fhe/doZnIr1KLcGm3Ht8TwOVUXxFCFapaax80rlzSrmV3eKw8ybIkOuLHjDn3vg6xc+O6O4unWmDhs0admkoRjIM=
cache:
  directories:
    - node_modules


================================================
FILE: CONTRIBUTING.md
================================================
<!--
This file is autogenerated based on
https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md

If you edit that file, it will get updated everywhere else.
If you edit this file, your changes will get overridden :)

You can however override the jsbin link with one that's customized to this
specific element:

jsbin=https://jsbin.com/cagaye/edit?html,output
-->

# Polymer Elements
## Guide for Contributors

Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines:

### Filing Issues

**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions:

 1. **Who will use the feature?** _“As someone filling out a form…”_
 2. **When will they use the feature?** _“When I enter an invalid value…”_
 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_

**If you are filing an issue to report a bug**, please provide:

 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug:

 ```markdown
 The `paper-foo` element causes the page to turn pink when clicked.

 ## Expected outcome

 The page stays the same color.

 ## Actual outcome

 The page turns pink.

 ## Steps to reproduce

 1. Put a `paper-foo` element in the page.
 2. Open the page in a web browser.
 3. Click the `paper-foo` element.
 ```

 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [https://jsbin.com/cagaye/edit?html,output](https://jsbin.com/cagaye/edit?html,output).

 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers.

### Submitting Pull Requests

**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request.

When submitting pull requests, please provide:

 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues in the pull request description using the following syntax:

 ```markdown
 (For a single issue)
 Fixes #20

 (For multiple issues)
 Fixes #32, fixes #40
 ```

 2. **A succinct description of the design** used to fix any related issues. For example:

 ```markdown
 This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked.
 ```

 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered.

If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!


================================================
FILE: README.md
================================================
[![Published on NPM](https://img.shields.io/npm/v/@polymer/app-layout.svg)](https://www.npmjs.com/package/@polymer/app-layout)
[![Build status](https://travis-ci.org/PolymerElements/app-layout.svg?branch=master)](https://travis-ci.org/PolymerElements/app-layout)
[![Published on webcomponents.org](https://img.shields.io/badge/webcomponents.org-published-blue.svg)](https://webcomponents.org/element/@polymer/app-layout)

## App Layout

<!---
```
<custom-element-demo height="368">
  <template>
    <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2.0.0/webcomponents-loader.js"></script>
    <script type="module">
      import '@polymer/app-layout/app-drawer/app-drawer.js';
      import '@polymer/app-layout/app-header/app-header.js';
      import '@polymer/app-layout/app-toolbar/app-toolbar.js';
      import '@polymer/app-layout/demo/sample-content.js';
      import '@polymer/iron-flex-layout/iron-flex-layout.js';
      import '@polymer/iron-icons/iron-icons.js';
      import '@polymer/paper-icon-button/paper-icon-button.js';
      import '@polymer/paper-progress/paper-progress.js';
    </script>
    <custom-style>
      <style is="custom-style">
        html, body {
          margin: 0;
          font-family: 'Roboto', 'Noto', sans-serif;
          -webkit-font-smoothing: antialiased;
          background: #f1f1f1;
          max-height: 368px;
        }
        app-toolbar {
          background-color: #4285f4;
          color: #fff;
        }

        paper-icon-button {
          --paper-icon-button-ink-color: white;
        }

        paper-icon-button + [main-title] {
          margin-left: 24px;
        }
        paper-progress {
          display: block;
          width: 100%;
          --paper-progress-active-color: rgba(255, 255, 255, 0.5);
          --paper-progress-container-color: transparent;
        }
        app-header {
          @apply --layout-fixed-top;
          color: #fff;
          --app-header-background-rear-layer: {
            background-color: #ef6c00;
          };
        }
        app-drawer {
          --app-drawer-scrim-background: rgba(0, 0, 100, 0.8);
          --app-drawer-content-container: {
            background-color: #B0BEC5;
          }
        }
        sample-content {
          padding-top: 64px;
        }
      </style>
    </custom-style>
    <next-code-block></next-code-block>
  </template>
</custom-element-demo>
```
-->

A collection of elements, along with guidelines and templates that can be used to structure your app’s layout.

## What is inside

### Elements

- [app-box](https://github.com/PolymerElements/app-layout/tree/master/app-box) - A container element that can have scroll effects - visual effects based on scroll position.

- [app-drawer](https://github.com/PolymerElements/app-layout/tree/master/app-drawer) - A navigation drawer that can slide in from the left or right.

- [app-drawer-layout](https://github.com/PolymerElements/app-layout/tree/master/app-drawer-layout) - A wrapper element that positions an app-drawer and other content.

- [app-grid](https://github.com/PolymerElements/app-layout/tree/master/app-grid) - A helper class useful for creating responsive, fluid grid layouts using custom properties.

- [app-header](https://github.com/PolymerElements/app-layout/tree/master/app-header) - A container element for app-toolbars at the top of the screen that can have scroll effects - visual effects based on scroll position.

- [app-header-layout](https://github.com/PolymerElements/app-layout/tree/master/app-header-layout) - A wrapper element that positions an app-header and other content.

- [app-toolbar](https://github.com/PolymerElements/app-layout/tree/master/app-toolbar) - A horizontal toolbar containing items that can be used for label, navigation, search and actions.

### Templates

The templates are a means to define, illustrate and share best practices in App Layout. Pick a template and customize it:

- **Getting started**
([Demo](https://polymerelements.github.io/app-layout/templates/getting-started) - [Source](/templates/getting-started))

- **Landing page**
([Demo](https://polymerelements.github.io/app-layout/templates/landing-page) - [Source](/templates/landing-page))

- **Publishing: Zuperkülblog**
([Demo](https://polymerelements.github.io/app-layout/templates/publishing) - [Source](/templates/publishing))

- **Shop: Shrine**
([Demo](https://polymerelements.github.io/app-layout/templates/shrine) - [Source](/templates/shrine))

- **Blog: Pesto**
([Demo](https://polymerelements.github.io/app-layout/templates/pesto) - [Source](/templates/pesto))

- **Scroll effects: Test drive**
([Demo](https://polymerelements.github.io/app-layout/templates/test-drive) - [Source](/templates/test-drive))

### Patterns

Sample code for various UI patterns:

- **Transform navigation:**
As more screen space is available, side navigation can transform into tabs.
([Demo](https://www.webcomponents.org/element/PolymerElements/app-layout/demo/patterns/transform-navigation/index.html) - [Source](/patterns/transform-navigation/x-app.html))

- **Expand Card:**
Content cards may expand to take up more horizontal space.
([Demo](https://www.webcomponents.org/element/PolymerElements/app-layout/demo/patterns/expand-card/index.html) - [Source](/patterns/expand-card/index.html))

- **Material Design Responsive Toolbar:**
Toolbar changes its height and padding to adapt mobile screen size.
([Demo](https://www.webcomponents.org/element/PolymerElements/app-layout/demo/patterns/md-responsive-toolbar/index.html) - [Source](/patterns/md-responsive-toolbar/index.html))

## Users

Here are some web apps built with App Layout:

- [Youtube Web](https://www.youtube.com/new)
- [Google I/O 2016](https://events.google.com/io2016/)
- [Polymer project site](https://www.polymer-project.org/summit)
- [Polymer summit](https://www.polymer-project.org/summit)
- [Shop](https://shop.polymer-project.org)
- [News](https://news.polymer-project.org)
- [webcomponents.org](https://www.webcomponents.org/)
- [Chrome Status](https://www.chromestatus.com/)
- [Project Fi](https://fi.google.com/about/)
- [NASA Open Source Software](https://code.nasa.gov/)

See: [Documentation](https://www.webcomponents.org/element/@polymer/app-layout),
  [Demo](https://www.webcomponents.org/element/@polymer/app-layout/demo/demo/index.html).

## Usage

### Installation
```
npm install --save @polymer/app-layout
```

### In an html file
```html
<html>
  <head>
    <script type="module">
      import '@polymer/app-layout/app-layout.js';
    </script>
  </head>
  <body>
    <app-header reveals>
      <app-toolbar>
        <div main-title>My app</div>
      </app-toolbar>
    </app-header>
    <app-drawer id="drawer" swipe-open></app-drawer>
  </body>
</html>
```
### In a Polymer 3 element
```js
import {PolymerElement, html} from '@polymer/polymer';
import '@polymer/app-layout/app-layout.js';

class SampleElement extends PolymerElement {
  static get template() {
    return html`
      <app-header reveals>
        <app-toolbar>
          <div main-title>My app</div>
        </app-toolbar>
      </app-header>
      <app-drawer id="drawer" swipe-open></app-drawer>
    `;
  }
}
customElements.define('sample-element', SampleElement);
```

## Contributing
If you want to send a PR to this element, here are
the instructions for running the tests and demo locally:

### Installation
```sh
git clone https://github.com/PolymerElements/app-layout
cd app-layout
npm install
npm install -g polymer-cli
```

### Running the demo locally
```sh
polymer serve --npm
open http://127.0.0.1:<port>/demo/
```

### Running the tests
```sh
polymer test --npm
```


================================================
FILE: app-box/README.md
================================================
## &lt;app-box&gt;

app-box is a container element that can have scroll effects - visual effects based on
scroll position. For example, the parallax effect can be used to move an image at a slower
rate than the foreground.

```html
<app-box style="height: 100px;" effects="parallax-background">
  <img slot="background" src="picture.png" style="width: 100%; height: 600px;">
</app-box>
```

Notice the `background` attribute in the `img` element; this attribute specifies that that
image is used as the background. By adding the background to the light dom, you can compose
backgrounds that can change dynamically. Alternatively, the mixin `--app-box-background-front-layer`
 allows to style the background. For example:

```css
  .parallaxAppBox {
    --app-box-background-front-layer: {
      background-image: url(picture.png);
    };
  }
```

Finally, app-box can have content inside. For example:

```html
<app-box effects="parallax-background">
  <h2>Sub title</h2>
</app-box>
```

#### Importing the effects

To use the scroll effects, you must explicitly import them in addition to `app-box`:

```js
import '@polymer/app-layout/app-scroll-effects/app-scroll-effects.js';
```

#### List of effects

* **parallax-background**
A simple parallax effect that vertically translates the backgrounds based on a fraction
of the scroll position. For example:

```css
app-header {
  --app-header-background-front-layer: {
    background-image: url(...);
  };
}
```
```html
<app-header style="height: 300px;" effects="parallax-background">
  <app-toolbar>App name</app-toolbar>
</app-header>
```

The fraction determines how far the background moves relative to the scroll position.
This value can be assigned via the `scalar` config value and it is typically a value
between 0 and 1 inclusive. If `scalar=0`, the background doesn't move away from the header.

## Styling

Mixin | Description | Default
----------------|-------------|----------
`--app-box-background-front-layer` | Applies to the front layer of the background | {}


================================================
FILE: app-box/app-box.js
================================================
/**
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at
http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
part of the polymer project is also subject to an additional IP rights grant
found at http://polymer.github.io/PATENTS.txt
*/
import '@polymer/polymer/polymer-legacy.js';
import '@polymer/iron-flex-layout/iron-flex-layout.js';

import {IronResizableBehavior} from '@polymer/iron-resizable-behavior/iron-resizable-behavior.js';
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
import {html} from '@polymer/polymer/lib/utils/html-tag.js';

import {AppScrollEffectsBehavior} from '../app-scroll-effects/app-scroll-effects-behavior.js';

/**
app-box is a container element that can have scroll effects - visual effects
based on scroll position. For example, the parallax effect can be used to move
an image at a slower rate than the foreground.

```html
<app-box style="height: 100px;" effects="parallax-background">
  <img slot="background" src="picture.png" style="width: 100%; height: 600px;">
</app-box>
```

Notice the `background` attribute in the `img` element; this attribute specifies
that that image is used as the background. By adding the background to the light
dom, you can compose backgrounds that can change dynamically. Alternatively, the
mixin `--app-box-background-front-layer` allows to style the background. For
example:

```css
  .parallaxAppBox {
    --app-box-background-front-layer: {
      background-image: url(picture.png);
    };
  }
```

Finally, app-box can have content inside. For example:

```html
<app-box effects="parallax-background">
  <h2>Sub title</h2>
</app-box>
```

#### Importing the effects

To use the scroll effects, you must explicitly import them in addition to
`app-box`:

```js
import '@polymer/app-layout/app-scroll-effects/app-scroll-effects.js';
```

#### List of effects

* **parallax-background**
A simple parallax effect that vertically translates the backgrounds based on a
fraction of the scroll position. For example:

```css
app-header {
  --app-header-background-front-layer: {
    background-image: url(...);
  };
}
```
```html
<app-header style="height: 300px;" effects="parallax-background">
  <app-toolbar>App name</app-toolbar>
</app-header>
```

The fraction determines how far the background moves relative to the scroll
position. This value can be assigned via the `scalar` config value and it is
typically a value between 0 and 1 inclusive. If `scalar=0`, the background
doesn't move away from the header.

## Styling

Mixin | Description | Default
----------------|-------------|----------
`--app-box-background-front-layer` | Applies to the front layer of the background | {}

@element app-box
@demo app-box/demo/document-scroll.html Document Scroll
@demo app-box/demo/scrolling-region.html Scrolling Region
*/
Polymer({
  /** @override */
  _template: html`
    <style>
      :host {
        position: relative;
        display: block;
      }

      #background {
        @apply --layout-fit;
        overflow: hidden;
        height: 100%;
      }

      #backgroundFrontLayer {
        min-height: 100%;
        pointer-events: none;
        background-size: cover;
        @apply --app-box-background-front-layer;
      }

      #contentContainer {
        position: relative;
        width: 100%;
        height: 100%;
      }

      :host([disabled]),
      :host([disabled]) #backgroundFrontLayer {
        transition: none !important;
      }
    </style>

    <div id="background">
      <div id="backgroundFrontLayer">
        <slot name="background"></slot>
      </div>
    </div>
    <div id="contentContainer">
      <slot></slot>
    </div>
`,

  is: 'app-box',
  behaviors: [AppScrollEffectsBehavior, IronResizableBehavior],
  listeners: {'iron-resize': '_resizeHandler'},

  /**
   * The current scroll progress.
   *
   * @type {number}
   */
  _progress: 0,

  /** @override */
  attached: function() {
    this.resetLayout();
  },

  _debounceRaf: function(fn) {
    var self = this;
    if (this._raf) {
      window.cancelAnimationFrame(this._raf);
    }
    this._raf = window.requestAnimationFrame(function() {
      self._raf = null;
      fn.call(self);
    });
  },

  /**
   * Resets the layout. This method is automatically called when the element is
   * attached to the DOM.
   *
   * @method resetLayout
   */
  resetLayout: function() {
    this._debounceRaf(function() {
      // noop if the box isn't in the rendered tree
      if (this.offsetWidth === 0 && this.offsetHeight === 0) {
        return;
      }

      var scrollTop = this._clampedScrollTop;
      var savedDisabled = this.disabled;

      this.disabled = true;
      this._elementTop = this._getElementTop();
      this._elementHeight = this.offsetHeight;
      this._cachedScrollTargetHeight = this._scrollTargetHeight;
      this._setUpEffect();
      this._updateScrollState(scrollTop);
      this.disabled = savedDisabled;
    });
  },

  _getElementTop: function() {
    var currentNode = this;
    var top = 0;

    while (currentNode && currentNode !== this.scrollTarget) {
      top += currentNode.offsetTop;
      currentNode = currentNode.offsetParent;
    }
    return top;
  },

  _updateScrollState: function(scrollTop) {
    if (this.isOnScreen()) {
      var viewportTop = this._elementTop - scrollTop;
      this._progress = 1 -
          (viewportTop + this._elementHeight) / this._cachedScrollTargetHeight;
      this._runEffects(this._progress, scrollTop);
    }
  },

  /**
   * Returns true if this app-box is on the screen.
   * That is, visible in the current viewport.
   *
   * @method isOnScreen
   * @return {boolean}
   */
  isOnScreen: function() {
    return this._elementTop <
        this._scrollTop + this._cachedScrollTargetHeight &&
        this._elementTop + this._elementHeight > this._scrollTop;
  },

  _resizeHandler: function() {
    this.resetLayout();
  },

  _getDOMRef: function(id) {
    if (id === 'background') {
      return this.$.background;
    }
    if (id === 'backgroundFrontLayer') {
      return this.$.backgroundFrontLayer;
    }
  },

  /**
   * Returns an object containing the progress value of the scroll effects.
   *
   * @method getScrollState
   * @return {Object}
   */
  getScrollState: function() {
    return {progress: this._progress};
  }
});


================================================
FILE: app-box/demo/document-scroll.html
================================================
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <title>app-box demo using the document scroll</title>

  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2.0.0/webcomponents-loader.js"></script>

  <script type="module">
    import '../../app-toolbar/app-toolbar.js';
    import '../../demo/sample-content.js';
    // Import effects before app-box.
    import '../../app-scroll-effects/effects/parallax-background.js';
    import '../app-box.js';
  </script>

  <custom-style>
    <style is="custom-style">

      body {
        margin: 0;
        font-family: 'Roboto', 'Noto', sans-serif;
        background-color: #eee;
        scroll-behavior: smooth;
      }

      header {
        background-color: white;
        height: 128px;
      }

      app-toolbar {
        font-size: 18px;
        font-weight: 400;
        letter-spacing: 5px;
        text-align: center;
        color: #1a237e;
      }

      .nav {
        height: 64px;
        margin: 0;
        padding: 0;
        text-align: center;
        background-color: rgba(255, 255, 255, 0.8);
      }

      .nav li {
        display: inline-block;
        list-style: none;
      }

      .nav a {
        display: inline-block;
        font-weight: 12px;
        line-height: 64px;
        text-decoration: none;
        color: black;
        font-weight: 300;
        margin: 0 10px;
      }

      .nav a:hover {
        color: #444;
        border-bottom: 1px solid #999;
      }

      [threshold-triggered] {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        z-index: 1;
        -webkit-backdrop-filter: saturate(180%) blur(20px);
        backdrop-filter: saturate(180%) blur(20px);
      }

      .first, .second, .third, .fourth {
        height: 640px;
      }

      .second {
        --app-box-background-front-layer: {
          background-image: url(https://app-layout-assets.appspot.com/assets/bg2.jpg);
          background-position: bottom;
          padding-bottom: 120px;
          margin-top: -20px;
          height: 100%;
        };
      }

      .third {
        --app-box-background-front-layer: {
          background-image: url(https://app-layout-assets.appspot.com/assets/bg3.jpg);
          background-position: bottom;
          padding-bottom: 120px;
          margin-top: -20px;
          height: 100%;
        };
      }

      .fourth {
        --app-box-background-front-layer: {
          background-image: url(https://app-layout-assets.appspot.com/assets/bg4.jpg);
          background-position: bottom;
          padding-bottom: 120px;
          margin-top: -20px;
          height: 100%;
        };
      }

      section {
        padding-top: 100px;
      }

      article {
        font-weight: 100;
        max-width: 500px;
        text-align: center;
        margin: 0 auto 100px auto;
      }
      article h2 {
        font-weight: 100;
        font-size: 50px;
        margin: 5px;
      }
      article p {
        font-size: 18px;
        line-height: 30px;
      }

      article hr {
        width: 100px;
        height: 1px;
        border: none;
        margin: 20px auto;
        background-color: black;
      }

    </style>
  </custom-style>
</head>
<body class="fullbleed" unresolved>

  <header>
    <app-toolbar>
      <div main-title>POLYMER</div>
    </app-toolbar>
    <app-box threshold="64">
      <ul role="navigation" class="nav">
        <li><a href="#speed">Speed</a></li>
        <li><a href="#modern">Modern</a></li>
        <li><a href="#standard">Standard</a></li>
        <li><a href="#create">Create</a></li>
      </ul>
    </app-box>
  </header>

  <main>
    <section id="speed">
      <article>
        <hr />
        <h2>Built for Speed</h2>
        <p>Polymer 1.0 replaces the shadow DOM polyfill with a lightweight shim, uses a new, faster data-binding system, and significantly reduces code size.</p>
      </article>
      <app-box class="first" effects="parallax-background">
        <!--
          app-box allows to style the mixin `--app-box-background-front-layer` or create a custom background in the light DOM.
          In this case, we create a custom background by adding the attribute `background` to the `img` in
          the light DOM.
        -->
        <img slot="background" src="//app-layout-assets.appspot.com/assets/bg1.jpg" style="width:100%; height: 900px" />
      </app-box>
    </section>

    <section id="modern">
      <article>
        <hr />
        <h2>For Modern Browsers</h2>
        <p>Polymer is built from the ground up for modern browsers, using the latest web platform APIs. Polyfills provide support on evergreen browsers for APIs that aren't universal yet.</p>
      </article>
      <!--
        This app-box uses the class `.second` and the mixin `--app-box-background-front-layer` to assign the background image.
      -->
      <app-box class="second" effects="parallax-background"></app-box>
    </section>

    <section id="standard">
      <article>
        <hr />
        <h2>Using Web Components</h2>
        <p>Polymer leverages web components, a new set of standards designed to provide reusable components for the web.</p>
      </article>
      <app-box class="third" effects="parallax-background"></app-box>
    </section>

    <section id="create">
      <article>
        <hr />
        <h2>Create your own elements</h2>
        <p>The Polymer library makes it easy to create your own powerful elements. Give your element some markup and properties, and then use it on a site. Polymer provides useful features like templating and data binding to reduce the amount of boilerplate you need to write.</p>
      </article>
      <app-box class="fourth" effects="parallax-background"></app-box>
    </section>
  </main>

</body>
</html>


================================================
FILE: app-box/demo/index.html
================================================
<!--
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<!doctype html>
<html lang="en">
<head>
  <title>app-box demos</title>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">

  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2.0.0/webcomponents-loader.js"></script>

  <script type="module">
    import '@polymer/paper-styles/demo-pages.js';
  </script>
</head>
<style>
  a {
    display: block;
    margin-bottom: 10px;
  }
</style>
<body unresolved>
  <div class="horizontal-section-container">
    <div>
      <h4>app-box demos</h4>
      <div class="horizontal-section">
        <a href="document-scroll.html">Document Scroll</a>
        <a href="scrolling-region.html">Scrolling Region</a>
      </div>
    </div>
  </div>
</body>
</html>


================================================
FILE: app-box/demo/scrolling-region.html
================================================
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <title>app-box using a custom scrolling region</title>

  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2.0.0/webcomponents-loader.js"></script>

  <script type="module">
    import '../../app-toolbar/app-toolbar.js';
    import '../../demo/sample-content.js';
    // Import effects before app-box.
    import '../../app-scroll-effects/effects/parallax-background.js';
    import '../app-box.js';
  </script>

  <custom-style>
    <style is="custom-style">

      body {
        margin: 0;
        font-family: 'Roboto', 'Noto', sans-serif;
        background-color: #eee;
      }

      header {
        background-color: white;
        height: 128px;
      }

      #scrollingRegion {
        position: fixed;
        left: 100px;
        right: 100px;
        top: 50px;
        bottom: 50px;
        overflow-y: auto;
        background-color: #fff;
        box-shadow: 0 0 50px rgba(0, 0, 0, 0.1);
        scroll-behavior: smooth;
      }

      app-toolbar {
        font-size: 18px;
        font-weight: 400;
        letter-spacing: 5px;
        text-align: center;
        color: #1a237e;
      }

      .nav {
        height: 64px;
        margin: 0;
        padding: 0;
        text-align: center;
        background-color: rgba(255, 255, 255, 0.9);
      }

      .nav li {
        display: inline-block;
        list-style: none;
      }

      .nav a {
        display: inline-block;
        font-weight: 12px;
        line-height: 64px;
        text-decoration: none;
        color: black;
        font-weight: 300;
        margin: 0 10px;
      }

      .nav a:hover {
        color: #444;
        border-bottom: 1px solid #999;
      }

      [threshold-triggered] {
        position: fixed;
        top: 50px;
        left: 100px;
        right: 100px;
        z-index: 1;
      }

      .first, .second, .third, .fourth {
        height: 640px;
      }

      .second {
        --app-box-background-front-layer: {
          background-image: url(https://app-layout-assets.appspot.com/assets/bg2.jpg);
          background-position: bottom;
          padding-bottom: 120px;
          margin-top: -20px;
          height: 100%;
        };
      }

      .third {
        --app-box-background-front-layer: {
          background-image: url(https://app-layout-assets.appspot.com/assets/bg3.jpg);
          background-position: bottom;
          padding-bottom: 120px;
          margin-top: -20px;
          height: 100%;
        };
      }

      .fourth {
        --app-box-background-front-layer: {
          background-image: url(https://app-layout-assets.appspot.com/assets/bg4.jpg);
          background-position: bottom;
          padding-bottom: 120px;
          margin-top: -20px;
          height: 100%;
        };
      }

      section {
        padding-top: 100px;
      }

      article {
        font-weight: 100;
        max-width: 500px;
        text-align: center;
        margin: 0 auto 100px auto;
      }

      article h2 {
        font-weight: 100;
        font-size: 50px;
        margin: 5px;
      }

      article p {
        font-size: 18px;
        line-height: 30px;
      }

      article hr {
        width: 100px;
        height: 1px;
        border: none;
        margin: 20px auto;
        background-color: black;
      }

    </style>
  </custom-style>
</head>
<body class="fullbleed" unresolved>


    <div class="overlay" id="scrollingRegion">
      <header>
        <app-toolbar>
          <div main-title>POLYMER</div>
        </app-toolbar>
        <app-box scroll-target="scrollingRegion" threshold="64">
          <ul role="navigation" class="nav">
            <li><a href="#speed">Speed</a></li>
            <li><a href="#modern">Modern</a></li>
            <li><a href="#standard">Standard</a></li>
            <li><a href="#create">Create</a></li>
          </ul>
        </app-box>
      </header>

      <section id="speed">
        <article>
          <hr />
          <h2>Built for Speed</h2>
          <p>Polymer 1.0 replaces the shadow DOM polyfill with a lightweight shim, uses a new, faster data-binding system, and significantly reduces code size.</p>
        </article>
        <!-- This app-box uses `#scrollingRegion` as the scroller element -->
        <app-box class="first" scroll-target="scrollingRegion" effects="parallax-background">
          <!--
            app-box allows to style the mixin `--app-box-background-front-layer` or create a custom background in the light DOM.
            In this case, we create a custom background by adding the attribute `background` to the `img` in
            the light DOM.
          -->
          <img slot="background" src="//app-layout-assets.appspot.com/assets/bg1.jpg" style="width:100%; height: 900px" />
        </app-box>
      </section>

      <section id="modern">
        <article>
          <hr />
          <h2>For Modern Browsers</h2>
          <p>Polymer is built from the ground up for modern browsers, using the latest web platform APIs. Polyfills provide support on evergreen browsers for APIs that aren't universal yet.</p>
        </article>
          <!--
            This app-box uses the class `.second` and the mixin `--app-box-background-front-layer` to assign the background image.
          -->
        <app-box class="second" scroll-target="scrollingRegion" effects="parallax-background"></app-box>
      </section>

      <section id="standard">
        <article>
          <hr />
          <h2>Using Web Components</h2>
          <p>Polymer leverages web components, a new set of standards designed to provide reusable components for the web.</p>
        </article>
        <app-box class="third" scroll-target="scrollingRegion" effects="parallax-background"></app-box>
      </section>

      <section id="create">
        <article>
          <hr />
          <h2>Create your own elements</h2>
          <p>The Polymer library makes it easy to create your own powerful elements. Give your element some markup and properties, and then use it on a site. Polymer provides useful features like templating and data binding to reduce the amount of boilerplate you need to write.</p>
        </article>
        <app-box class="fourth" scroll-target="scrollingRegion" effects="parallax-background"></app-box>
      </section>
    </div>


</body>
</html>


================================================
FILE: app-drawer/README.md
================================================
## &lt;app-drawer&gt;

![app-drawer](http://app-layout-assets.appspot.com/assets/docs/app-drawer/drawer.gif)

app-drawer is a navigation drawer that can slide in from the left or right.

Example:

Align the drawer at the start, which is left in LTR layouts (default):

```html
<app-drawer opened></app-drawer>
```

Align the drawer at the end:

```html
<app-drawer align="end" opened></app-drawer>
```

To make the contents of the drawer scrollable, create a wrapper for the scroll
content, and apply height and overflow styles to it.

```html
<app-drawer>
  <div style="height: 100%; overflow: auto;"></div>
</app-drawer>
```

### Styling

Custom property                  | Description                            | Default
---------------------------------|----------------------------------------|--------------------
`--app-drawer-width`             | Width of the drawer                    | 256px
`--app-drawer-content-container` | Mixin for the drawer content container | {}
`--app-drawer-content-padding`   | Padding of the drawer content container| 120px 0
`--app-drawer-scrim-background`  | Background for the scrim               | rgba(0, 0, 0, 0.5)

**NOTE:** If you use `<app-drawer>` with `<app-drawer-layout>` and specify a value for
`--app-drawer-width`, that value must be accessible by both elements. This can be done by
defining the value on the `:host` that contains `<app-drawer-layout>` (or `html` if outside
a shadow root):

```css
:host {
  --app-drawer-width: 300px;
}
```


================================================
FILE: app-drawer/app-drawer.js
================================================
/**
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at
http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
part of the polymer project is also subject to an additional IP rights grant
found at http://polymer.github.io/PATENTS.txt
*/
import '@polymer/polymer/polymer-legacy.js';
import '@polymer/iron-flex-layout/iron-flex-layout.js';

import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {html} from '@polymer/polymer/lib/utils/html-tag.js';
import {afterNextRender} from '@polymer/polymer/lib/utils/render-status.js';

/**
app-drawer is a navigation drawer that can slide in from the left or right.

Example:

Align the drawer at the start, which is left in LTR layouts (default):

```html
<app-drawer opened></app-drawer>
```

Align the drawer at the end:

```html
<app-drawer align="end" opened></app-drawer>
```

To make the contents of the drawer scrollable, create a wrapper for the scroll
content, and apply height and overflow styles to it.

```html
<app-drawer>
  <div style="height: 100%; overflow: auto;"></div>
</app-drawer>
```

### Styling

Custom property                  | Description                            | Default
---------------------------------|----------------------------------------|--------------------
`--app-drawer-width`             | Width of the drawer                    | 256px
`--app-drawer-content-container` | Mixin for the drawer content container | {}
`--app-drawer-scrim-background`  | Background for the scrim               | rgba(0, 0, 0, 0.5)

**NOTE:** If you use `<app-drawer>` with `<app-drawer-layout>` and specify a
value for
`--app-drawer-width`, that value must be accessible by both elements. This can
be done by defining the value on the `:host` that contains `<app-drawer-layout>`
(or `html` if outside a shadow root):

```css
:host {
  --app-drawer-width: 300px;
}
```

@element app-drawer
@demo app-drawer/demo/left-drawer.html Simple Left Drawer
@demo app-drawer/demo/right-drawer.html Right Drawer with Icons
*/
Polymer({
  /** @override */
  _template: html`
    <style>
      :host {
        position: fixed;
        /* Set a default z-index to handle most cases where the page content
           that comes after <app-drawer> in the dom has a stacking context with
           no z-index defined.
        */
        z-index: 1;
        top: -120px;
        right: 0;
        bottom: -120px;
        left: 0;

        visibility: hidden;

        transition-property: visibility;
      }

      :host([opened]) {
        visibility: visible;
      }

      :host([persistent]) {
        width: var(--app-drawer-width, 256px);
      }

      :host([persistent][position=left]) {
        right: auto;
      }

      :host([persistent][position=right]) {
        left: auto;
      }

      #contentContainer {
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;

        width: var(--app-drawer-width, 256px);
        padding: var(--app-drawer-content-padding, 120px 0);

        transition-property: -webkit-transform;
        transition-property: transform;
        -webkit-transform: translate3d(-100%, 0, 0);
        transform: translate3d(-100%, 0, 0);

        background-color: #FFF;

        @apply --app-drawer-content-container;
      }

      #contentContainer[persistent] {
        width: 100%;
      }

      #contentContainer[position=right] {
        right: 0;
        left: auto;

        -webkit-transform: translate3d(100%, 0, 0);
        transform: translate3d(100%, 0, 0);
      }

      #contentContainer[swipe-open]::after {
        position: fixed;
        top: 0;
        bottom: 0;
        left: 100%;

        visibility: visible;

        width: 20px;

        content: '';
      }

      #contentContainer[swipe-open][position=right]::after {
        right: 100%;
        left: auto;
      }

      #contentContainer[opened] {
        -webkit-transform: translate3d(0, 0, 0);
        transform: translate3d(0, 0, 0);
      }

      #scrim {
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;

        transition-property: opacity;
        -webkit-transform: translateZ(0);
        transform:  translateZ(0);

        opacity: 0;
        background: var(--app-drawer-scrim-background, rgba(0, 0, 0, 0.5));
      }

      #scrim.visible {
        opacity: 1;
      }

      :host([no-transition]) #contentContainer {
        transition-property: none;
      }
    </style>

    <div id="scrim" on-click="close"></div>

    <!-- HACK(keanulee): Bind attributes here (in addition to :host) for styling to workaround Safari
    bug. https://bugs.webkit.org/show_bug.cgi?id=170762 -->
    <div id="contentContainer" opened\$="[[opened]]" persistent\$="[[persistent]]" position\$="[[position]]" swipe-open\$="[[swipeOpen]]">
      <slot></slot>
    </div>
`,

  is: 'app-drawer',

  properties: {
    /**
     * The opened state of the drawer.
     */
    opened:
        {type: Boolean, value: false, notify: true, reflectToAttribute: true},

    /**
     * The drawer does not have a scrim and cannot be swiped close.
     */
    persistent: {type: Boolean, value: false, reflectToAttribute: true},

    /**
     * The transition duration of the drawer in milliseconds.
     */
    transitionDuration: {type: Number, value: 200},

    /**
     * The alignment of the drawer on the screen ('left', 'right', 'start' or
     * 'end'). 'start' computes to left and 'end' to right in LTR layout and
     * vice versa in RTL layout.
     */
    align: {type: String, value: 'left'},

    /**
     * The computed, read-only position of the drawer on the screen ('left' or
     * 'right').
     */
    position: {type: String, readOnly: true, reflectToAttribute: true},

    /**
     * Create an area at the edge of the screen to swipe open the drawer.
     */
    swipeOpen: {type: Boolean, value: false, reflectToAttribute: true},

    /**
     * Trap keyboard focus when the drawer is opened and not persistent.
     */
    noFocusTrap: {type: Boolean, value: false},

    /**
     * Disables swiping on the drawer.
     */
    disableSwipe: {type: Boolean, value: false}
  },

  observers: [
    'resetLayout(position, isAttached)',
    '_resetPosition(align, isAttached)',
    '_styleTransitionDuration(transitionDuration)',
    '_openedPersistentChanged(opened, persistent)'
  ],

  _translateOffset: 0,
  _trackDetails: null,
  _drawerState: 0,
  _boundEscKeydownHandler: null,
  _firstTabStop: null,
  _lastTabStop: null,

  /** @override */
  attached: function() {
    afterNextRender(this, function() {
      this._boundEscKeydownHandler = this._escKeydownHandler.bind(this);
      this.addEventListener('keydown', this._tabKeydownHandler.bind(this));

      // Only listen for horizontal track so you can vertically scroll
      // inside the drawer.
      this.listen(this, 'track', '_track');
      this.setScrollDirection('y');
    });

    this.fire('app-reset-layout');
  },

  /** @override */
  detached: function() {
    document.removeEventListener('keydown', this._boundEscKeydownHandler);
  },

  /**
   * Opens the drawer.
   */
  open: function() {
    this.opened = true;
  },

  /**
   * Closes the drawer.
   */
  close: function() {
    this.opened = false;
  },

  /**
   * Toggles the drawer open and close.
   */
  toggle: function() {
    this.opened = !this.opened;
  },

  /**
   * Gets the width of the drawer.
   *
   * @return {number} The width of the drawer in pixels.
   */
  getWidth: function() {
    return this._savedWidth || this.$.contentContainer.offsetWidth;
  },

  _isRTL: function() {
    return window.getComputedStyle(this).direction === 'rtl';
  },

  _resetPosition: function() {
    switch (this.align) {
      case 'start':
        this._setPosition(this._isRTL() ? 'right' : 'left');
        return;
      case 'end':
        this._setPosition(this._isRTL() ? 'left' : 'right');
        return;
    }
    this._setPosition(this.align);
  },

  _escKeydownHandler: function(event) {
    var ESC_KEYCODE = 27;
    if (event.keyCode === ESC_KEYCODE) {
      // Prevent any side effects if app-drawer closes.
      event.preventDefault();
      this.close();
    }
  },

  _track: function(event) {
    if (this.persistent || this.disableSwipe) {
      return;
    }

    // Disable user selection on desktop.
    event.preventDefault();

    switch (event.detail.state) {
      case 'start':
        this._trackStart(event);
        break;
      case 'track':
        this._trackMove(event);
        break;
      case 'end':
        this._trackEnd(event);
        break;
    }
  },

  _trackStart: function(event) {
    this._drawerState = this._DRAWER_STATE.TRACKING;

    var rect = this.$.contentContainer.getBoundingClientRect();
    this._savedWidth = rect.width;
    if (this.position === 'left') {
      this._translateOffset = rect.left;
    } else {
      this._translateOffset = rect.right - window.innerWidth;
    }

    this._trackDetails = [];

    // Disable transitions since style attributes will reflect user track
    // events.
    this._styleTransitionDuration(0);
    this.style.visibility = 'visible';
  },

  _trackMove: function(event) {
    this._translateDrawer(event.detail.dx + this._translateOffset);

    // Use Date.now() since event.timeStamp is inconsistent across browsers
    // (e.g. most browsers use milliseconds but FF 44 uses microseconds).
    this._trackDetails.push({dx: event.detail.dx, timeStamp: Date.now()});
  },

  _trackEnd: function(event) {
    var x = event.detail.dx + this._translateOffset;
    var drawerWidth = this.getWidth();
    var isPositionLeft = this.position === 'left';
    var isInEndState = isPositionLeft ? (x >= 0 || x <= -drawerWidth) :
                                        (x <= 0 || x >= drawerWidth);

    if (!isInEndState) {
      // No longer need the track events after this method returns - allow them
      // to be GC'd.
      var trackDetails = this._trackDetails;
      this._trackDetails = null;

      this._flingDrawer(event, trackDetails);
      if (this._drawerState === this._DRAWER_STATE.FLINGING) {
        return;
      }
    }

    // If the drawer is not flinging, toggle the opened state based on the
    // position of the drawer.
    var halfWidth = drawerWidth / 2;
    if (event.detail.dx < -halfWidth) {
      this.opened = this.position === 'right';
    } else if (event.detail.dx > halfWidth) {
      this.opened = this.position === 'left';
    }

    if (isInEndState) {
      this.debounce('_resetDrawerState', this._resetDrawerState);
    } else {
      this.debounce(
          '_resetDrawerState', this._resetDrawerState, this.transitionDuration);
    }

    this._styleTransitionDuration(this.transitionDuration);
    this._resetDrawerTranslate();
    this.style.visibility = '';
  },

  _calculateVelocity: function(event, trackDetails) {
    // Find the oldest track event that is within 100ms using binary search.
    var now = Date.now();
    var timeLowerBound = now - 100;
    var trackDetail;
    var min = 0;
    var max = trackDetails.length - 1;

    while (min <= max) {
      // Floor of average of min and max.
      var mid = (min + max) >> 1;
      var d = trackDetails[mid];
      if (d.timeStamp >= timeLowerBound) {
        trackDetail = d;
        max = mid - 1;
      } else {
        min = mid + 1;
      }
    }

    if (trackDetail) {
      var dx = event.detail.dx - trackDetail.dx;
      var dt = (now - trackDetail.timeStamp) || 1;
      return dx / dt;
    }
    return 0;
  },

  _flingDrawer: function(event, trackDetails) {
    var velocity = this._calculateVelocity(event, trackDetails);

    // Do not fling if velocity is not above a threshold.
    if (Math.abs(velocity) < this._MIN_FLING_THRESHOLD) {
      return;
    }

    this._drawerState = this._DRAWER_STATE.FLINGING;

    var x = event.detail.dx + this._translateOffset;
    var drawerWidth = this.getWidth();
    var isPositionLeft = this.position === 'left';
    var isVelocityPositive = velocity > 0;
    var isClosingLeft = !isVelocityPositive && isPositionLeft;
    var isClosingRight = isVelocityPositive && !isPositionLeft;
    var dx;
    if (isClosingLeft) {
      dx = -(x + drawerWidth);
    } else if (isClosingRight) {
      dx = (drawerWidth - x);
    } else {
      dx = -x;
    }

    // Enforce a minimum transition velocity to make the drawer feel snappy.
    if (isVelocityPositive) {
      velocity = Math.max(velocity, this._MIN_TRANSITION_VELOCITY);
      this.opened = this.position === 'left';
    } else {
      velocity = Math.min(velocity, -this._MIN_TRANSITION_VELOCITY);
      this.opened = this.position === 'right';
    }

    // Calculate the amount of time needed to finish the transition based on the
    // initial slope of the timing function.
    var t = this._FLING_INITIAL_SLOPE * dx / velocity;
    this._styleTransitionDuration(t);
    this._styleTransitionTimingFunction(this._FLING_TIMING_FUNCTION);

    this._resetDrawerTranslate();
    this.debounce('_resetDrawerState', this._resetDrawerState, t);
  },

  _styleTransitionDuration: function(duration) {
    this.style.transitionDuration = duration + 'ms';
    this.$.contentContainer.style.transitionDuration = duration + 'ms';
    this.$.scrim.style.transitionDuration = duration + 'ms';
  },

  _styleTransitionTimingFunction: function(timingFunction) {
    this.$.contentContainer.style.transitionTimingFunction = timingFunction;
    this.$.scrim.style.transitionTimingFunction = timingFunction;
  },

  _translateDrawer: function(x) {
    var drawerWidth = this.getWidth();

    if (this.position === 'left') {
      x = Math.max(-drawerWidth, Math.min(x, 0));
      this.$.scrim.style.opacity = 1 + x / drawerWidth;
    } else {
      x = Math.max(0, Math.min(x, drawerWidth));
      this.$.scrim.style.opacity = 1 - x / drawerWidth;
    }

    this.translate3d(x + 'px', '0', '0', this.$.contentContainer);
  },

  _resetDrawerTranslate: function() {
    this.$.scrim.style.opacity = '';
    this.transform('', this.$.contentContainer);
  },

  _resetDrawerState: function() {
    var oldState = this._drawerState;

    // If the drawer was flinging, we need to reset the style attributes.
    if (oldState === this._DRAWER_STATE.FLINGING) {
      this._styleTransitionDuration(this.transitionDuration);
      this._styleTransitionTimingFunction('');
      this.style.visibility = '';
    }

    this._savedWidth = null;

    if (this.opened) {
      this._drawerState = this.persistent ?
          this._DRAWER_STATE.OPENED_PERSISTENT :
          this._DRAWER_STATE.OPENED;
    } else {
      this._drawerState = this._DRAWER_STATE.CLOSED;
    }

    if (oldState !== this._drawerState) {
      if (this._drawerState === this._DRAWER_STATE.OPENED) {
        this._setKeyboardFocusTrap();
        document.addEventListener('keydown', this._boundEscKeydownHandler);
        document.body.style.overflow = 'hidden';
      } else {
        document.removeEventListener('keydown', this._boundEscKeydownHandler);
        document.body.style.overflow = '';
      }

      // Don't fire the event on initial load.
      if (oldState !== this._DRAWER_STATE.INIT) {
        this.fire('app-drawer-transitioned');
      }
    }
  },

  /**
   * Resets the layout.
   *
   * @method resetLayout
   */
  resetLayout: function() {
    this.fire('app-reset-layout');
  },

  _setKeyboardFocusTrap: function() {
    if (this.noFocusTrap) {
      return;
    }

    // NOTE: Unless we use /deep/ (which we shouldn't since it's deprecated),
    // this will not select focusable elements inside shadow roots.
    var focusableElementsSelector = [
      'a[href]:not([tabindex="-1"])',
      'area[href]:not([tabindex="-1"])',
      'input:not([disabled]):not([tabindex="-1"])',
      'select:not([disabled]):not([tabindex="-1"])',
      'textarea:not([disabled]):not([tabindex="-1"])',
      'button:not([disabled]):not([tabindex="-1"])',
      'iframe:not([tabindex="-1"])',
      '[tabindex]:not([tabindex="-1"])',
      '[contentEditable=true]:not([tabindex="-1"])'
    ].join(',');
    var focusableElements =
        dom(this).querySelectorAll(focusableElementsSelector);

    if (focusableElements.length > 0) {
      this._firstTabStop = focusableElements[0];
      this._lastTabStop = focusableElements[focusableElements.length - 1];
    } else {
      // Reset saved tab stops when there are no focusable elements in the
      // drawer.
      this._firstTabStop = null;
      this._lastTabStop = null;
    }

    // Focus on app-drawer if it has non-zero tabindex. Otherwise, focus the
    // first focusable element in the drawer, if it exists. Use the tabindex
    // attribute since the this.tabIndex property in IE/Edge returns 0 (instead
    // of -1) when the attribute is not set.
    var tabindex = this.getAttribute('tabindex');
    if (tabindex && parseInt(tabindex, 10) > -1) {
      this.focus();
    } else if (this._firstTabStop) {
      this._firstTabStop.focus();
    }
  },

  _tabKeydownHandler: function(event) {
    if (this.noFocusTrap) {
      return;
    }

    var TAB_KEYCODE = 9;
    if (this._drawerState === this._DRAWER_STATE.OPENED &&
        event.keyCode === TAB_KEYCODE) {
      if (event.shiftKey) {
        if (this._firstTabStop &&
            dom(event).localTarget === this._firstTabStop) {
          event.preventDefault();
          this._lastTabStop.focus();
        }
      } else {
        if (this._lastTabStop && dom(event).localTarget === this._lastTabStop) {
          event.preventDefault();
          this._firstTabStop.focus();
        }
      }
    }
  },

  _openedPersistentChanged: function(opened, persistent) {
    this.toggleClass('visible', opened && !persistent, this.$.scrim);

    // Use a debounce timer instead of transitionend since transitionend won't
    // fire when app-drawer is display: none.
    this.debounce(
        '_resetDrawerState', this._resetDrawerState, this.transitionDuration);
  },

  _MIN_FLING_THRESHOLD: 0.2,
  _MIN_TRANSITION_VELOCITY: 1.2,
  _FLING_TIMING_FUNCTION: 'cubic-bezier(0.667, 1, 0.667, 1)',
  _FLING_INITIAL_SLOPE: 1.5,

  _DRAWER_STATE: {
    INIT: 0,
    OPENED: 1,
    OPENED_PERSISTENT: 2,
    CLOSED: 3,
    TRACKING: 4,
    FLINGING: 5
  }

  /**
   * Fired when the layout of app-drawer has changed.
   *
   * @event app-reset-layout
   */

  /**
   * Fired when app-drawer has finished transitioning.
   *
   * @event app-drawer-transitioned
   */
});


================================================
FILE: app-drawer/demo/index.html
================================================
<!--
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<!doctype html>
<html lang="en">
<head>
  <title>app-drawer demos</title>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">

  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2.0.0/webcomponents-loader.js"></script>

  <script type="module">
    import '@polymer/paper-styles/demo-pages.js';
  </script>
</head>
<style>
  a {
    display: block;
    margin-bottom: 10px;
  }
</style>
<body unresolved>
  <div class="horizontal-section-container">
    <div>
      <h4>app-drawer demos</h4>
      <div class="horizontal-section">
        <a href="left-drawer.html">Simple Left Drawer</a>
        <a href="right-drawer.html">Right Drawer with Icons</a>
      </div>
    </div>
  </div>
</body>
</html>


================================================
FILE: app-drawer/demo/left-drawer.html
================================================
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">

  <title>app-drawer demo</title>

  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2.0.0/webcomponents-loader.js"></script>

  <script type="module">
    import '@polymer/font-roboto/roboto.js';
    import '@polymer/iron-icons/iron-icons.js';
    import '@polymer/paper-icon-button/paper-icon-button.js';
    import '../../app-toolbar/app-toolbar.js';
    import '../../demo/sample-content.js';
    import '../app-drawer.js';
  </script>

  <custom-style>
    <style is="custom-style">

      body {
        margin: 0;
        font-family: 'Roboto', 'Noto', sans-serif;
        background-color: #eee;
      }

      app-toolbar {
        background-color: #4285f4;
        color: #fff;
      }

      app-drawer {
        --app-drawer-scrim-background: rgba(0, 0, 100, 0.8);

        --app-drawer-content-container: {
          background-color: #B0BEC5;
        }
      }

    </style>
  </custom-style>

</head>
<body>

  <app-toolbar>
    <paper-icon-button icon="menu"></paper-icon-button>
  </app-toolbar>

  <sample-content size="100"></sample-content>

  <app-drawer swipe-open></app-drawer>

  <script type="module">
    import '@polymer/font-roboto/roboto.js';
    import '@polymer/iron-icons/iron-icons.js';
    import '@polymer/paper-icon-button/paper-icon-button.js';
    import '../../demo/sample-content.js';
    import '../../app-toolbar/app-toolbar.js';
    import '../app-drawer.js';
    var drawer = document.querySelector('app-drawer');
    document.querySelector('paper-icon-button')
        .addEventListener('click', function() {
          drawer.toggle();
        });
  </script>

</body>
</html>


================================================
FILE: app-drawer/demo/right-drawer.html
================================================
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">

  <title>app-drawer demo</title>

  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2.0.0/webcomponents-loader.js"></script>

  <script type="module">
    import '@polymer/font-roboto/roboto.js';
    import '@polymer/iron-icons/iron-icons.js';
    import '@polymer/paper-icon-button/paper-icon-button.js';
    import '@polymer/paper-item/paper-icon-item.js';
    import '../../app-toolbar/app-toolbar.js';
    import '../../demo/sample-content.js';
    import '../app-drawer.js';
  </script>

  <custom-style>
    <style is="custom-style">

      body {
        margin: 0;
        font-family: 'Roboto', 'Noto', sans-serif;
        background-color: #eee;
      }

      app-toolbar {
        background-color: #4285f4;
        color: #fff;
      }

      app-drawer {
        --app-drawer-content-container: {
          background-color: #B0BEC5;
        }
      }

      .drawer-contents {
        height: 100%;
        overflow-y: auto;
      }

    </style>
  </custom-style>

</head>
<body>

  <app-toolbar>
    <div main-title></div>
    <paper-icon-button icon="menu" onclick="drawer.toggle()"></paper-icon-button>
  </app-toolbar>

  <sample-content size="100"></sample-content>

  <app-drawer id="drawer" align="right" swipe-open>
    <div class="drawer-contents">
      <paper-icon-item>
        <iron-icon icon="inbox" item-icon slot="item-icon"></iron-icon>
        <span>inbox</span>
      </paper-icon-item>
      <paper-icon-item>
        <iron-icon icon="favorite" item-icon slot="item-icon"></iron-icon>
        <span>favorite</span>
      </paper-icon-item>
      <paper-icon-item>
        <iron-icon icon="polymer" item-icon slot="item-icon"></iron-icon>
        <span>polymer</span>
      </paper-icon-item>
      <paper-icon-item>
        <iron-icon icon="question-answer" item-icon slot="item-icon"></iron-icon>
        <span>question-answer</span>
      </paper-icon-item>
      <paper-icon-item>
        <iron-icon icon="send" item-icon slot="item-icon"></iron-icon>
        <span>send</span>
      </paper-icon-item>
      <paper-icon-item>
        <iron-icon icon="archive" item-icon slot="item-icon"></iron-icon>
        <span>archive</span>
      </paper-icon-item>
      <paper-icon-item>
        <iron-icon icon="backup" item-icon slot="item-icon"></iron-icon>
        <span>backup</span>
      </paper-icon-item>
      <paper-icon-item>
        <iron-icon icon="dashboard" item-icon slot="item-icon"></iron-icon>
        <span>dashboard</span>
      </paper-icon-item>
    </div>
  </app-drawer>

</body>
</html>


================================================
FILE: app-drawer/test/app-drawer.html
================================================
<!doctype html>
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE
The complete set of authors may be found at http://polymer.github.io/AUTHORS
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS
-->
<html>
<head>
  <meta charset="UTF-8">
  <title>test for app-drawer</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

  <script src="../../node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
  <script src="../../node_modules/wct-browser-legacy/browser.js"></script>
  <style is="custom-style">
    body {
      margin: 0;
    }
  </style>
</head>
<body>

  <test-fixture id="testDrawer">
    <template>
      <app-drawer>
        <input type="text">
        <div tabindex="0">Div</div>
        <span>Not focusable</span>
      </app-drawer>
    </template>
  </test-fixture>

  <test-fixture id="rtlDrawer">
    <template>
      <app-drawer dir="rtl"></app-drawer>
    </template>
  </test-fixture>

  <script type="module">
    import '@polymer/polymer/polymer-legacy.js';
    import '../app-drawer.js';

    import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
    import {afterNextRender} from '@polymer/polymer/lib/utils/render-status.js';

    suite('basic features', function() {
      var drawer, scrim, contentContainer, transformSpy;

      function fireKeydownEvent(target, keyCode, shiftKey) {
        var e = new CustomEvent('keydown', {bubbles: true, cancelable: true});
        e.keyCode = keyCode;
        e.shiftKey = !!shiftKey;
        target.dispatchEvent(e);
        return e;
      }

      function assertDrawerStyles(translateX, opacity, desc) {
        assert.equal(
            transformSpy.lastCall.args[0],
            'translate3d(' + translateX + 'px,0,0)',
            desc);
        assert.equal(
            parseFloat(scrim.style.opacity).toFixed(4), opacity.toFixed(4), desc);
      }

      function assertDrawerStylesReset() {
        assert.equal(scrim.style.opacity, '');
        assert.equal(transformSpy.lastCall.args[0], '');
      }

      function assertTransitionDuration(duration) {
        assert.equal(contentContainer.style.transitionDuration, duration);
        assert.equal(scrim.style.transitionDuration, duration);
      }

      function assertTransitionDurationBelow(d) {
        assert.isBelow(parseFloat(contentContainer.style.transitionDuration), d);
        assert.isBelow(parseFloat(scrim.style.transitionDuration), d);
      }

      function assertTransitionTimingFunction(timingFunction) {
        assert.equal(
            contentContainer.style.transitionTimingFunction, timingFunction);
        assert.equal(scrim.style.transitionTimingFunction, timingFunction);
      }

      setup(function() {
        drawer = fixture('testDrawer');
        scrim = drawer.$.scrim;
        contentContainer = drawer.$.contentContainer;
        transformSpy = sinon.spy(drawer, 'transform');
      });

      test('default values', function() {
        assert.isFalse(drawer.opened);
        assert.isFalse(drawer.persistent);
        assert.equal(drawer.transitionDuration, 200);
        assert.equal(drawer.align, 'left');
        assert.isFalse(drawer.swipeOpen);
        assert.isFalse(drawer.noFocusTrap);
      });

      test('set scroll direction', function(done) {
        afterNextRender(drawer, function() {
          assert.oneOf(drawer['__polymerGesturesTouchAction'], ['y', 'pan-y']);
          done();
        });
      });

      test('transitionDuration property', function(done) {
        afterNextRender(drawer, function() {
          assertTransitionDuration('200ms');

          drawer.transitionDuration = 10;

          assertTransitionDuration('10ms');
          done();
        });
      });

      test('computed position', function() {
        rtlDrawer.align = 'start';

        assert.equal(drawer.position, 'left');

        drawer.align = 'end';

        assert.equal(drawer.position, 'right');

        drawer.align = 'left';

        assert.equal(drawer.position, 'left');

        drawer.align = 'right';

        assert.equal(drawer.position, 'right');
      });

      test('computed position for RTL', function() {
        var rtlDrawer = fixture('rtlDrawer');
        rtlDrawer.align = 'start';

        assert.equal(rtlDrawer.position, 'right');

        rtlDrawer.align = 'end';

        assert.equal(rtlDrawer.position, 'left');

        rtlDrawer.align = 'right';

        assert.equal(rtlDrawer.position, 'right');

        rtlDrawer.align = 'left';

        assert.equal(rtlDrawer.position, 'left');
      });

      test('left drawer opens and closes', function() {
        drawer.align = 'left';
        drawer.transitionDuration = 0;

        var contentContainerClientRect = contentContainer.getBoundingClientRect();
        assert.isTrue(contentContainerClientRect.right <= 0);

        drawer.opened = true;

        contentContainerClientRect = contentContainer.getBoundingClientRect();
        assert.equal(contentContainerClientRect.left, 0);

        drawer.opened = false;

        contentContainerClientRect = contentContainer.getBoundingClientRect();
        assert.isTrue(contentContainerClientRect.right <= 0);
      });

      test('right drawer opens and closes', function() {
        drawer.align = 'right';
        drawer.transitionDuration = 0;

        var contentContainerClientRect = contentContainer.getBoundingClientRect();
        assert.isTrue(contentContainerClientRect.left >= window.innerWidth);

        drawer.opened = true;

        contentContainerClientRect = contentContainer.getBoundingClientRect();
        assert.equal(contentContainerClientRect.right, window.innerWidth);

        drawer.opened = false;

        contentContainerClientRect = contentContainer.getBoundingClientRect();
        assert.isTrue(contentContainerClientRect.left >= window.innerWidth);
      });

      test('open(), close(), and toggle()', function() {
        assert.isFalse(drawer.opened);

        drawer.open();

        assert.isTrue(drawer.opened);

        drawer.close();

        assert.isFalse(drawer.opened);

        drawer.toggle();

        assert.isTrue(drawer.opened);

        drawer.toggle();

        assert.isFalse(drawer.opened);
      });

      test('getWidth()', function() {
        assert.equal(drawer.getWidth(), contentContainer.offsetWidth);
      });

      test('app-reset-layout', function() {
        var listenerSpy = sinon.spy();
        drawer.addEventListener('app-reset-layout', listenerSpy);
        drawer.align = 'right';

        assert.isTrue(listenerSpy.called);
      });

      test('app-drawer-transitioned', function(done) {
        window.setTimeout(function() {
          var listenerSpy = sinon.spy();
          drawer.transitionDuration = 1;
          drawer.addEventListener('app-drawer-transitioned', listenerSpy);
          drawer.persistent = true;

          assert.isFalse(
              listenerSpy.called,
              'should not fire after toggling persistent when closed');

          drawer.opened = true;

          window.setTimeout(function() {
            assert.equal(
                listenerSpy.callCount,
                1,
                'should fire after toggling opened state');

            drawer.persistent = false;

            window.setTimeout(function() {
              assert.equal(
                  listenerSpy.callCount,
                  2,
                  'should fire after toggling persistent when opened');

              drawer.fire('track', {state: 'start'});
              drawer.fire('track', {state: 'track', dx: 0, ddx: 0});
              drawer.fire('track', {state: 'end', dx: -200, ddx: -200});

              window.setTimeout(function() {
                assert.isFalse(drawer.opened);
                assert.equal(
                    listenerSpy.callCount, 3, 'should fire after flinging');

                drawer.fire('track', {state: 'start'});
                drawer.fire('track', {state: 'track', dx: 10, ddx: 10});
                drawer.fire('track', {state: 'end', dx: 10, ddx: 0});

                window.setTimeout(function() {
                  assert.isFalse(drawer.opened);
                  assert.equal(
                      listenerSpy.callCount,
                      4,
                      'should fire after swiping even if opened state unchanged');

                  drawer.fire('track', {state: 'start'});
                  drawer.fire('track', {state: 'track', dx: 200, ddx: 200});
                  drawer.fire('track', {state: 'end', dx: 200, ddx: 0});

                  window.setTimeout(function() {
                    assert.isTrue(drawer.opened);
                    assert.equal(
                        listenerSpy.callCount, 5, 'should fire after swiping');

                    drawer.fire('track', {state: 'start'});
                    drawer.fire('track', {state: 'track', dx: -1000, ddx: -1000});
                    drawer.fire('track', {state: 'end', dx: -1000, ddx: 0});

                    window.setTimeout(function() {
                      assert.isFalse(drawer.opened);
                      assert.equal(
                          listenerSpy.callCount,
                          6,
                          'should fire after swiping beyond end state');
                      done();
                    }, 50);
                  }, 50);
                }, 50);
              }, 50);
            }, 50);
          }, 50);
        }, 300);
      });

      test('app-drawer-transitioned when transitionDuration is 0', function(done) {
        window.setTimeout(function() {
          var listenerSpy = sinon.spy();
          drawer.transitionDuration = 0;
          drawer.addEventListener('app-drawer-transitioned', listenerSpy);
          drawer.persistent = true;

          assert.isFalse(
              listenerSpy.called,
              'should not fire after toggling persistent when closed');

          drawer.opened = true;

          window.setTimeout(function() {
            assert.equal(
                listenerSpy.callCount,
                1,
                'should fire after toggling opened state');

            drawer.persistent = false;

            window.setTimeout(function() {
              assert.equal(
                  listenerSpy.callCount,
                  2,
                  'should fire after toggling persistent when opened');

              drawer.fire('track', {state: 'start'});
              drawer.fire('track', {state: 'track', dx: 0, ddx: 0});
              drawer.fire('track', {state: 'end', dx: -200, ddx: -200});

              window.setTimeout(function() {
                assert.isFalse(drawer.opened);
                assert.equal(
                    listenerSpy.callCount, 3, 'should fire after flinging');

                drawer.fire('track', {state: 'start'});
                drawer.fire('track', {state: 'track', dx: 200, ddx: 200});
                drawer.fire('track', {state: 'end', dx: 200, ddx: 0});
                window.setTimeout(function() {
                  assert.isTrue(drawer.opened);
                  assert.equal(
                      listenerSpy.callCount, 4, 'should fire after swiping');

                  drawer.fire('track', {state: 'start'});
                  drawer.fire('track', {state: 'track', dx: -1000, ddx: -1000});
                  drawer.fire('track', {state: 'end', dx: -1000, ddx: 0});

                  window.setTimeout(function() {
                    assert.isFalse(drawer.opened);
                    assert.equal(
                        listenerSpy.callCount,
                        5,
                        'should fire after swiping beyond end state');
                    done();
                  }, 50);
                }, 50);
              }, 50);
            }, 50);
          }, 50);
        }, 300);
      });

      test('disable swipe', function(done) {
        afterNextRender(drawer, function() {
          var drawerWidth = drawer.getWidth();
          var halfWidth = drawerWidth / 2;
          drawer.disableSwipe = true;
          drawer.fire('track', {state: 'start'});
          var ev = drawer.fire(
              'track',
              {state: 'track', dx: halfWidth, ddx: drawerWidth},
              {cancelable: true});

          assert.isFalse(ev.defaultPrevented);
          assert.isFalse(transformSpy.called);
          done();
        });
      });

      test('track events block user selection', function(done) {
        afterNextRender(drawer, function() {
          var ev = drawer.fire('track', null /* detail */, {cancelable: true});

          assert.isTrue(ev.defaultPrevented);
          done();
        });
      });

      test('styles reset after swiping', function(done) {
        afterNextRender(drawer, function() {
          drawer.fire('track', {state: 'start'});

          assert.equal(drawer.style.visibility, 'visible');
          assertTransitionDuration('0ms');

          drawer.fire('track', {state: 'track', dx: 200, ddx: 200});
          drawer.fire('track', {state: 'end', dx: 200, ddx: 0});

          assert.equal(drawer.style.visibility, '');
          assertTransitionDuration('200ms');
          assertDrawerStylesReset();
          done();
        });
      });

      test('styles reset after swiping beyond the end state', function(done) {
        afterNextRender(drawer, function() {
          drawer.fire('track', {state: 'start'});

          assert.equal(drawer.style.visibility, 'visible');
          assertTransitionDuration('0ms');

          drawer.fire('track', {state: 'track', dx: 1000, ddx: 1000});
          drawer.fire('track', {state: 'end', dx: 1000, ddx: 0});

          assert.equal(drawer.style.visibility, '');
          assertTransitionDuration('200ms');
          assertDrawerStylesReset();
          done();
        });
      });

      test('left drawer swiping', function(done) {
        drawer.transitionDuration = 10;
        drawer.align = 'left';
        afterNextRender(drawer, function() {
          var drawerWidth = drawer.getWidth();
          var halfWidth = drawerWidth / 2;
          drawer.fire('track', {state: 'start'});
          drawer.fire('track', {state: 'track', dx: -halfWidth, ddx: -halfWidth});

          assertDrawerStyles(-drawerWidth, 0, 'styles are lower bounded');

          drawer.fire('track', {state: 'track', dx: halfWidth, ddx: drawerWidth});

          assertDrawerStyles(-halfWidth, 0.5, 'style by track distance');

          drawer.fire(
              'track',
              {state: 'track', dx: halfWidth + drawerWidth, ddx: drawerWidth});

          assertDrawerStyles(0, 1, 'styles are upper bounded');

          // Simulate break of track events.
          drawer._trackDetails = [];
          drawer.fire('track', {state: 'end', dx: halfWidth, ddx: -drawerWidth});

          assert.isFalse(
              drawer.opened, 'drawer stays closed when track distance is small');

          drawer.fire('track', {state: 'start'});
          drawer.fire(
              'track', {state: 'track', dx: halfWidth + 1, ddx: halfWidth + 1});
          drawer.fire('track', {state: 'end', dx: halfWidth + 1, ddx: 0});

          assert.isTrue(drawer.opened, 'drawer opens when track distance is large');

          drawer.fire('track', {state: 'start'});
          drawer.fire('track', {state: 'track', dx: -halfWidth, ddx: -halfWidth});
          drawer.fire('track', {state: 'end', dx: -halfWidth, ddx: 0});

          assert.isTrue(
              drawer.opened, 'drawer stays opened when track distance is small');

          drawer.fire('track', {state: 'start'});
          drawer.fire(
              'track', {state: 'track', dx: -halfWidth - 1, ddx: -halfWidth - 1});
          drawer.fire('track', {state: 'end', dx: -halfWidth - 1, ddx: 0});

          assert.isFalse(
              drawer.opened, 'drawer closes when track distance is large');
          done();
        });
      });

      test('right drawer swiping', function(done) {
        drawer.transitionDuration = 10;
        drawer.align = 'right';
        window.setTimeout(function() {
          afterNextRender(drawer, function() {
            var drawerWidth = drawer.getWidth();
            var halfWidth = drawerWidth / 2;
            drawer.fire('track', {state: 'start'});
            drawer.fire('track', {state: 'track', dx: halfWidth, ddx: halfWidth});

            assertDrawerStyles(drawerWidth, 0, 'styles are lower bounded');

            drawer.fire(
                'track', {state: 'track', dx: -halfWidth, ddx: -drawerWidth});

            assertDrawerStyles(halfWidth, 0.5, 'style by track distance');

            drawer.fire(
                'track',
                {state: 'track', dx: -halfWidth - drawerWidth, ddx: -drawerWidth});

            assertDrawerStyles(0, 1, 'styles are upper bounded');

            // Simulate break of track events.
            drawer._trackDetails = [];
            drawer.fire('track', {state: 'end', dx: -halfWidth, ddx: drawerWidth});

            assert.isFalse(
                drawer.opened, 'drawer stays closed when track distance is small');

            drawer.fire('track', {state: 'start'});
            drawer.fire(
                'track', {state: 'track', dx: -halfWidth - 1, ddx: -halfWidth - 1});
            drawer.fire('track', {state: 'end', dx: -halfWidth - 1, ddx: 0});

            assert.isTrue(
                drawer.opened, 'drawer opens when track distance is large');

            drawer.fire('track', {state: 'start'});
            drawer.fire('track', {state: 'track', dx: halfWidth, ddx: halfWidth});
            drawer.fire('track', {state: 'end', dx: halfWidth, ddx: 0});

            assert.isTrue(
                drawer.opened, 'drawer stays opened when track distance is small');

            drawer.fire('track', {state: 'start'});
            drawer.fire(
                'track', {state: 'track', dx: halfWidth + 1, ddx: halfWidth + 1});
            drawer.fire('track', {state: 'end', dx: halfWidth + 1, ddx: 0});

            assert.isFalse(
                drawer.opened, 'drawer closes when track distance is large');
            done();
          });
        }, 100);
      });

      test('styles reset after flinging', function(done) {
        afterNextRender(drawer, function() {
          drawer.fire('track', {state: 'start'});

          assert.equal(drawer.style.visibility, 'visible');
          assertTransitionDuration('0ms');

          drawer.fire('track', {state: 'track', dx: 0, ddx: 0});
          drawer.fire('track', {state: 'end', dx: 200, ddx: 200});

          window.setTimeout(function() {
            assert.equal(drawer.style.visibility, '');
            assertTransitionDuration('200ms');
            assertTransitionTimingFunction('');
            assertDrawerStylesReset();
            done();
          }, 100);
        });
      });

      test('styles reset after flinging beyond the end state', function(done) {
        afterNextRender(drawer, function() {
          drawer.fire('track', {state: 'start'});

          assert.equal(drawer.style.visibility, 'visible');
          assertTransitionDuration('0ms');

          drawer.fire('track', {state: 'track', dx: 0, ddx: 0});
          drawer.fire('track', {state: 'end', dx: 1000, ddx: 1000});

          assert.equal(drawer.style.visibility, '');
          assertTransitionDuration('200ms');
          assertTransitionTimingFunction('');
          assertDrawerStylesReset();
          done();
        });
      });

      test('left drawer flinging open', function(done) {
        drawer.transitionDuration = 10;
        drawer.align = 'left';
        afterNextRender(drawer, function() {
          drawer.fire('track', {state: 'start'});
          drawer.fire('track', {state: 'track', dx: 0, ddx: 0});
          drawer.fire('track', {state: 'end', dx: 0.1, ddx: 0.1});

          assert.isFalse(
              drawer.opened, 'drawer stays closed when velocity is small');
          assertTransitionDuration('10ms');
          assertTransitionTimingFunction('');
          assertDrawerStylesReset();

          drawer.fire('track', {state: 'start'});
          drawer.fire('track', {state: 'track', dx: 0, ddx: 0});
          drawer.fire('track', {state: 'end', dx: 50, ddx: 50});

          assert.isTrue(drawer.opened, 'drawer opens when velocity is large');
          assertTransitionDurationBelow(150);
          assertTransitionTimingFunction(drawer._FLING_TIMING_FUNCTION);
          assertDrawerStylesReset();

          window.setTimeout(function() {
            assertTransitionDuration('10ms');
            assertTransitionTimingFunction('');
            done();
          }, 100);
        });
      });

      test('left drawer flinging close', function(done) {
        drawer.transitionDuration = 10;
        drawer.align = 'left';
        drawer.opened = true;
        afterNextRender(drawer, function() {
          drawer.fire('track', {state: 'start'});
          drawer.fire('track', {state: 'track', dx: 0, ddx: 0});
          drawer.fire('track', {state: 'end', dx: -0.1, ddx: -0.1});

          assert.isTrue(
              drawer.opened, 'drawer stays opened when velocity is small');
          assertTransitionDuration('10ms');
          assertTransitionTimingFunction('');
          assertDrawerStylesReset();

          drawer.fire('track', {state: 'start'});
          drawer.fire('track', {state: 'track', dx: 0, ddx: 0});
          drawer.fire('track', {state: 'end', dx: -50, ddx: -50});

          assert.isFalse(drawer.opened, 'drawer closes when velocity is large');
          assertTransitionDurationBelow(150);
          assertTransitionTimingFunction(drawer._FLING_TIMING_FUNCTION);
          assertDrawerStylesReset();

          window.setTimeout(function() {
            assertTransitionDuration('10ms');
            assertTransitionTimingFunction('');
            done();
          }, 100);
        });
      });

      test('right drawer flinging open', function(done) {
        drawer.transitionDuration = 10;
        drawer.align = 'right';
        window.setTimeout(function() {
          afterNextRender(drawer, function() {
            drawer.fire('track', {state: 'start'});
            drawer.fire('track', {state: 'track', dx: 0, ddx: 0});
            drawer.fire('track', {state: 'end', dx: -0.1, ddx: -0.1});

            assert.isFalse(
                drawer.opened, 'drawer stays closed when velocity is small');
            assertTransitionDuration('10ms');
            assertTransitionTimingFunction('');
            assertDrawerStylesReset();

            drawer.fire('track', {state: 'start'});
            drawer.fire('track', {state: 'track', dx: 0, ddx: 0});
            drawer.fire('track', {state: 'end', dx: -50, ddx: -50});

            assert.isTrue(drawer.opened, 'drawer opens when velocity is large');
            assertTransitionDurationBelow(150);
            assertTransitionTimingFunction(drawer._FLING_TIMING_FUNCTION);
            assertDrawerStylesReset();

            window.setTimeout(function() {
              assertTransitionDuration('10ms');
              assertTransitionTimingFunction('');
              done();
            }, 100);
          });
        }, 100);
      });

      test('right drawer flinging close', function(done) {
        drawer.transitionDuration = 10;
        drawer.align = 'right';
        drawer.opened = true;
        window.setTimeout(function() {
          afterNextRender(drawer, function() {
            drawer.fire('track', {state: 'start'});
            drawer.fire('track', {state: 'track', dx: 0, ddx: 0});
            drawer.fire('track', {state: 'end', dx: 0.1, ddx: 0.1});

            assert.isTrue(
                drawer.opened, 'drawer stays opened when velocity is small');
            assertTransitionDuration('10ms');
            assertTransitionTimingFunction('');
            assertDrawerStylesReset();

            drawer.fire('track', {state: 'start'});
            drawer.fire('track', {state: 'track', dx: 0, ddx: 0});
            drawer.fire('track', {state: 'end', dx: 50, ddx: 50});

            assert.isFalse(drawer.opened, 'drawer closes when velocity is large');
            assertTransitionDurationBelow(150);
            assertTransitionTimingFunction(drawer._FLING_TIMING_FUNCTION);
            assertDrawerStylesReset();

            window.setTimeout(function() {
              assertTransitionDuration('10ms');
              assertTransitionTimingFunction('');
              done();
            }, 100);
          });
        }, 100);
      });

      test('doc scroll', function(done) {
        drawer.transitionDuration = 0;
        drawer.opened = true;

        window.setTimeout(function() {
          assert.equal(
              document.body.style.overflow,
              'hidden',
              'should block scrolling when opened');

          drawer.persistent = true;

          window.setTimeout(function() {
            assert.equal(
                document.body.style.overflow,
                '',
                'should not block scrolling when persistent');

            drawer.persistent = false;

            window.setTimeout(function() {
              assert.equal(
                  document.body.style.overflow,
                  'hidden',
                  'should block scrolling when not persistent');

              drawer.opened = false;

              window.setTimeout(function() {
                assert.equal(
                    document.body.style.overflow,
                    '',
                    'should not block scrolling when closed');
                done();
              }, 50);
            }, 50);
          }, 50);
        }, 50);
      });

      test('focus trap', function(done) {
        var input = dom(drawer).querySelector('input');
        var div = dom(drawer).querySelector('div[tabindex]');
        var inputFocusSpy = sinon.spy(input, 'focus');
        var divFocusSpy = sinon.spy(div, 'focus');

        afterNextRender(drawer, function() {
          drawer.transitionDuration = 0;
          drawer.opened = true;

          window.setTimeout(function() {
            assert.isTrue(inputFocusSpy.called);

            var e = fireKeydownEvent(input, 9);

            assert.isFalse(e.defaultPrevented, 'should not prevent default');

            input.focus();
            inputFocusSpy.reset();
            e = fireKeydownEvent(input, 9, true /* shiftKey */);

            assert.isTrue(divFocusSpy.called);
            assert.isTrue(e.defaultPrevented, 'should prevent default');

            e = fireKeydownEvent(div, 9, true /* shiftKey */);

            assert.isFalse(e.defaultPrevented, 'should not prevent default');

            div.focus();
            e = fireKeydownEvent(div, 9);

            assert.isTrue(inputFocusSpy.called);
            assert.isTrue(e.defaultPrevented, 'should prevent default');
            done();
          }, 50);
        });
      });

      test('focus trap with app-drawer tabindex set', function(done) {
        var input = dom(drawer).querySelector('input');
        var drawerFocusSpy = sinon.spy(drawer, 'focus');
        var inputFocusSpy = sinon.spy(input, 'focus');

        afterNextRender(drawer, function() {
          drawer.transitionDuration = 0;
          drawer.tabIndex = 0;
          drawer.opened = true;

          window.setTimeout(function() {
            assert.isTrue(drawerFocusSpy.called);
            assert.isFalse(inputFocusSpy.called);
            done();
          }, 50);
        });
      });

      test('no focus trap', function(done) {
        var input = dom(drawer).querySelector('input');
        var inputFocusSpy = sinon.spy(input, 'focus');

        afterNextRender(drawer, function() {
          drawer.transitionDuration = 0;
          drawer.noFocusTrap = true;
          drawer.opened = true;

          assert.isFalse(inputFocusSpy.called);
          done();
        });
      });

      test('esc key handler', function(done) {
        afterNextRender(drawer, function() {
          drawer.transitionDuration = 0;
          drawer.opened = true;
          window.setTimeout(function() {
            var e = fireKeydownEvent(document, 27);

            assert.isFalse(drawer.opened, 'should close drawer on esc');
            assert.isTrue(e.defaultPrevented, 'should prevent default');
            done();
          }, 50);
        });
      });

      test('scrim', function() {
        drawer.transitionDuration = 0;

        assert.equal(window.getComputedStyle(scrim)['opacity'], 0);

        drawer.opened = true;

        assert.equal(window.getComputedStyle(scrim)['opacity'], 1);

        drawer.persistent = true;

        assert.equal(window.getComputedStyle(scrim)['opacity'], 0);
      });

      test('click on scrim closes drawer', function() {
        drawer.opened = true;
        drawer.fire('click', null /* detail */, {node: scrim});

        assert.isFalse(drawer.opened);
      });

      test('persistent drawer should not cover content', function() {
        drawer.opened = true;
        drawer.persistent = true;

        assert.notEqual(document.elementFromPoint(400, 10).tagName, 'APP-DRAWER');
      });

      test('right persistent drawer should be in the correct position', function() {
        drawer.align = 'right';
        drawer.opened = true;
        drawer.persistent = true;

        assert.equal(drawer.getBoundingClientRect().right, window.innerWidth);
      });
    });
  </script>

</body>
</html>


================================================
FILE: app-drawer/test/index.html
================================================
<!doctype html>
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE
The complete set of authors may be found at http://polymer.github.io/AUTHORS
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS
-->
<html>
<head>
  <meta charset="UTF-8">
  <title>app-drawer tests</title>
  <script src="../../node_modules/wct-browser-legacy/browser.js"></script>
</head>
<body>
  <script>
    WCT.loadSuites(
        ['app-drawer.html', 'app-drawer.html?wc-shadydom=true&wc-ce=true']);
  </script>
</body>
</html>


================================================
FILE: app-drawer-layout/README.md
================================================
## &lt;app-drawer-layout&gt;

app-drawer-layout is a wrapper element that positions an app-drawer and other content. When
the viewport width is smaller than `responsiveWidth`, this element changes to narrow layout.
In narrow layout, the drawer will be stacked on top of the main content. The drawer will slide
in/out to hide/reveal the main content.


By default the drawer is aligned to the start, which is left in LTR layouts:

```html
<app-drawer-layout>
  <app-drawer slot="drawer">
    drawer content
  </app-drawer>
  <div>
    main content
  </div>
</app-drawer-layout>
```

Align the drawer at the end:

```html
<app-drawer-layout>
  <app-drawer slot="drawer" align="end">
     drawer content
  </app-drawer>
  <div>
    main content
  </div>
</app-drawer-layout>
```

With an app-header-layout:

```html
<app-drawer-layout>
  <app-drawer slot="drawer">
    drawer-content
  </app-drawer>
  <app-header-layout>
    <app-header slot="header">
      <app-toolbar>
        <div main-title>App name</div>
      </app-toolbar>
    </app-header>

    main content

  </app-header-layout>
</app-drawer-layout>
```

Add the `drawer-toggle` attribute to elements inside `app-drawer-layout` that toggle the drawer on click events:

```html
<app-drawer-layout>
  <app-drawer slot="drawer">
    drawer-content
  </app-drawer>
  <app-header-layout>
    <app-header slot="header">
      <app-toolbar>
        <paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
        <div main-title>App name</div>
      </app-toolbar>
    </app-header>

    main content

  </app-header-layout>
</app-drawer-layout>
```

**NOTE:** With app-layout 2.0, the `drawer-toggle` element needs to be manually hidden
when app-drawer-layout is not in narrow layout. To add this, add the following CSS rule where
app-drawer-layout is used:

```css
app-drawer-layout:not([narrow]) [drawer-toggle] {
  display: none;
}
```

Add the `fullbleed` attribute to app-drawer-layout to make it fit the size of its container:

```html
<app-drawer-layout fullbleed>
  <app-drawer slot="drawer">
     drawer content
  </app-drawer>
  <div>
    main content
  </div>
</app-drawer-layout>
```

### Styling

Custom property                          | Description                          | Default
-----------------------------------------|--------------------------------------|---------
`--app-drawer-width`                     | Width of the drawer                  | 256px
`--app-drawer-layout-content-transition` | Transition for the content container | none

**NOTE:** If you use <app-drawer> with <app-drawer-layout> and specify a value for
`--app-drawer-width`, that value must be accessible by both elements. This can be done by
defining the value on the `:host` that contains <app-drawer-layout> (or `html` if outside
a shadow root):

```css
:host {
  --app-drawer-width: 300px;
}
```


================================================
FILE: app-drawer-layout/app-drawer-layout.js
================================================
/**
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at
http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
part of the polymer project is also subject to an additional IP rights grant
found at http://polymer.github.io/PATENTS.txt
*/
import '@polymer/polymer/polymer-legacy.js';
import '@polymer/iron-media-query/iron-media-query.js';

import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {html} from '@polymer/polymer/lib/utils/html-tag.js';
import {afterNextRender} from '@polymer/polymer/lib/utils/render-status.js';

import {AppLayoutBehavior} from '../app-layout-behavior/app-layout-behavior.js';

/**
app-drawer-layout is a wrapper element that positions an app-drawer and other
content. When the viewport width is smaller than `responsiveWidth`, this element
changes to narrow layout. In narrow layout, the drawer will be stacked on top of
the main content. The drawer will slide in/out to hide/reveal the main content.

By default the drawer is aligned to the start, which is left in LTR layouts:

```html
<app-drawer-layout>
  <app-drawer slot="drawer">
    drawer content
  </app-drawer>
  <div>
    main content
  </div>
</app-drawer-layout>
```

Align the drawer at the end:

```html
<app-drawer-layout>
  <app-drawer slot="drawer" align="end">
     drawer content
  </app-drawer>
  <div>
    main content
  </div>
</app-drawer-layout>
```

With an app-header-layout:

```html
<app-drawer-layout>
  <app-drawer slot="drawer">
    drawer-content
  </app-drawer>
  <app-header-layout>
    <app-header slot="header">
      <app-toolbar>
        <div main-title>App name</div>
      </app-toolbar>
    </app-header>

    main content

  </app-header-layout>
</app-drawer-layout>
```

Add the `drawer-toggle` attribute to elements inside `app-drawer-layout` that
toggle the drawer on click events:

```html
<app-drawer-layout>
  <app-drawer slot="drawer">
    drawer-content
  </app-drawer>
  <app-header-layout>
    <app-header slot="header">
      <app-toolbar>
        <paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
        <div main-title>App name</div>
      </app-toolbar>
    </app-header>

    main content

  </app-header-layout>
</app-drawer-layout>
```

**NOTE:** With app-layout 2.0, the `drawer-toggle` element needs to be manually
hidden when app-drawer-layout is not in narrow layout. To add this, add the
following CSS rule where app-drawer-layout is used:

```css
app-drawer-layout:not([narrow]) [drawer-toggle] {
  display: none;
}
```

Add the `fullbleed` attribute to app-drawer-layout to make it fit the size of
its container:

```html
<app-drawer-layout fullbleed>
  <app-drawer slot="drawer">
     drawer content
  </app-drawer>
  <div>
    main content
  </div>
</app-drawer-layout>
```

### Styling

Custom property                          | Description                          | Default
-----------------------------------------|--------------------------------------|---------
`--app-drawer-width`                     | Width of the drawer                  | 256px
`--app-drawer-layout-content-transition` | Transition for the content container | none

**NOTE:** If you use <app-drawer> with <app-drawer-layout> and specify a value
for
`--app-drawer-width`, that value must be accessible by both elements. This can
be done by defining the value on the `:host` that contains <app-drawer-layout>
(or `html` if outside a shadow root):

```css
:host {
  --app-drawer-width: 300px;
}
```

@element app-drawer-layout
@demo app-drawer-layout/demo/index.html
*/
Polymer({
  /** @override */
  _template: html`
    <style>
      :host {
        display: block;
        /**
         * Force app-drawer-layout to have its own stacking context so that its parent can
         * control the stacking of it relative to other elements.
         */
        position: relative;
        z-index: 0;
      }

      :host ::slotted([slot=drawer]) {
        z-index: 1;
      }

      :host([fullbleed]) {
        @apply --layout-fit;
      }

      #contentContainer {
        /* Create a stacking context here so that all children appear below the header. */
        position: relative;
        z-index: 0;
        height: 100%;
        transition: var(--app-drawer-layout-content-transition, none);
      }

      #contentContainer[drawer-position=left] {
        margin-left: var(--app-drawer-width, 256px);
      }

      #contentContainer[drawer-position=right] {
        margin-right: var(--app-drawer-width, 256px);
      }
    </style>

    <slot id="drawerSlot" name="drawer"></slot>

    <div id="contentContainer" drawer-position\$="[[_drawerPosition]]">
      <slot></slot>
    </div>

    <iron-media-query query="[[_computeMediaQuery(forceNarrow, responsiveWidth)]]" on-query-matches-changed="_onQueryMatchesChanged"></iron-media-query>
`,

  is: 'app-drawer-layout',
  behaviors: [AppLayoutBehavior],

  properties: {
    /**
     * If true, ignore `responsiveWidth` setting and force the narrow layout.
     */
    forceNarrow: {type: Boolean, value: false},

    /**
     * If the viewport's width is smaller than this value, the panel will change
     * to narrow layout. In the mode the drawer will be closed.
     */
    responsiveWidth: {type: String, value: '640px'},

    /**
     * Returns true if it is in narrow layout. This is useful if you need to
     * show/hide elements based on the layout.
     */
    narrow:
        {type: Boolean, reflectToAttribute: true, readOnly: true, notify: true},

    /**
     * If true, the drawer will initially be opened when in narrow layout mode.
     */
    openedWhenNarrow: {type: Boolean, value: false},

    _drawerPosition: {type: String}
  },

  listeners: {'click': '_clickHandler'},
  observers: ['_narrowChanged(narrow)'],

  /**
   * A reference to the app-drawer element.
   *
   * @property drawer
   */
  get drawer() {
    return dom(this.$.drawerSlot).getDistributedNodes()[0];
  },

  /** @override */
  attached: function() {
    // Disable drawer transitions until after app-drawer-layout sets the initial
    // opened state.
    var drawer = this.drawer;
    if (drawer) {
      drawer.setAttribute('no-transition', '');
    }
  },

  _clickHandler: function(e) {
    var target = dom(e).localTarget;
    if (target && target.hasAttribute('drawer-toggle')) {
      var drawer = this.drawer;
      if (drawer && !drawer.persistent) {
        drawer.toggle();
      }
    }
  },

  _updateLayoutStates: function() {
    var drawer = this.drawer;
    if (!this.isAttached || !drawer) {
      return;
    }

    this._drawerPosition = this.narrow ? null : drawer.position;
    if (this._drawerNeedsReset) {
      if (this.narrow) {
        drawer.opened = this.openedWhenNarrow;
        drawer.persistent = false;
      } else {
        drawer.opened = drawer.persistent = true;
      }
      if (drawer.hasAttribute('no-transition')) {
        // Enable drawer transitions after app-drawer-layout sets the initial
        // opened state.
        afterNextRender(this, function() {
          drawer.removeAttribute('no-transition');
        });
      }
      this._drawerNeedsReset = false;
    }
  },

  _narrowChanged: function() {
    this._drawerNeedsReset = true;
    this.resetLayout();
  },

  _onQueryMatchesChanged: function(event) {
    this._setNarrow(event.detail.value);
  },

  _computeMediaQuery: function(forceNarrow, responsiveWidth) {
    return forceNarrow ? '(min-width: 0px)' :
                         '(max-width: ' + responsiveWidth + ')';
  }
});


================================================
FILE: app-drawer-layout/demo/index.html
================================================
<!--
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">

  <title>app-drawer-layout demo</title>

  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2.0.0/webcomponents-loader.js"></script>

  <script type="module">
    import '@polymer/font-roboto/roboto.js';
    import '@polymer/iron-icons/iron-icons.js';
    import '@polymer/paper-icon-button/paper-icon-button.js';
    import '../../app-drawer/app-drawer.js';
    import '../../app-toolbar/app-toolbar.js';
    import '../../demo/sample-content.js';
    import '../app-drawer-layout.js';
  </script>

  <custom-style>
    <style is="custom-style">

      html {
        --app-drawer-width: 350px;
      }

      body {
        margin: 0;
        font-family: 'Roboto', 'Noto', sans-serif;
        background-color: #eee;
      }

      app-toolbar {
        background-color: #4285f4;
        color: #fff;
      }

      app-drawer-layout:not([narrow]) [drawer-toggle] {
        display: none;
      }

      app-drawer {
        --app-drawer-content-container: {
          background-color: #B0BEC5;
        }
      }

    </style>
  </custom-style>

</head>
<body>

  <app-drawer-layout>

    <app-drawer slot="drawer"></app-drawer>

    <app-toolbar>
      <paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
    </app-toolbar>

    <sample-content size="100"></sample-content>

  </app-drawer-layout>

</body>
</html>


================================================
FILE: app-drawer-layout/test/app-drawer-layout.html
================================================
<!doctype html>
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE
The complete set of authors may be found at http://polymer.github.io/AUTHORS
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS
-->
<html>
<head>
  <meta charset="UTF-8">
  <title>test for app-drawer-layout</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

  <script src="../../node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
  <script src="../../node_modules/wct-browser-legacy/browser.js"></script>

  <custom-style>
    <style is="custom-style">
      body {
        margin: 0;
        padding: 0;
      }

      app-drawer-layout {
        width: 1000px;
        --app-drawer-content-container: {
          background-color: cyan;
        };
      }
    </style>
  </custom-style>

</head>
<body>

  <test-fixture id="testDrawerLayout">
    <template>
      <app-drawer-layout>
        <app-drawer slot="drawer">Drawer</app-drawer>
        <div drawer-toggle>Toggle</div>
        <p>Content</p>
        <x-resizeable></x-resizeable>
      </app-drawer-layout>
    </template>
  </test-fixture>

  <script type="module">
    import '../../app-drawer/app-drawer.js';
    import '../app-drawer-layout.js';

    import {IronResizableBehavior} from '@polymer/iron-resizable-behavior/iron-resizable-behavior.js';
    import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
    import {dom, flush} from '@polymer/polymer/lib/legacy/polymer.dom.js';
    import {Base} from '@polymer/polymer/polymer-legacy.js';

    Polymer({is: 'x-resizeable', behaviors: [IronResizableBehavior]});

    suite('basic features', function() {
      var drawerLayout, drawer;

      setup(function() {
        drawerLayout = fixture('testDrawerLayout');
        drawer = drawerLayout.querySelector('app-drawer');
        flush();
      });

      test('default values', function() {
        assert.isFalse(drawerLayout.forceNarrow);
        assert.equal(drawerLayout.responsiveWidth, '640px');
        assert.isFalse(drawerLayout.openedWhenNarrow);
      });

      test('get drawer', function() {
        assert.equal(drawerLayout.drawer, drawer);
      });

      test('forceNarrow', function() {
        drawerLayout.responsiveWidth = '0px';
        drawerLayout.forceNarrow = true;

        assert.isTrue(drawerLayout.narrow);
      });

      test('responsiveWidth', function(done) {
        var xResizeable = drawerLayout.querySelector('x-resizeable');
        var notifyResizeSpy = sinon.spy(xResizeable, 'notifyResize');
        drawerLayout.responsiveWidth = '0px';

        window.setTimeout(function() {
          assert.isFalse(drawerLayout.narrow);
          assert.isTrue(drawer.opened);
          assert.isTrue(notifyResizeSpy.called);

          notifyResizeSpy.reset();
          drawerLayout.responsiveWidth = '10000px';

          window.setTimeout(function() {
            assert.isTrue(drawerLayout.narrow);
            assert.isFalse(drawer.opened);
            assert.isTrue(notifyResizeSpy.called);

            done();
          }, 150);
        }, 150);
      });

      test('drawer-toggle', function(done) {
        drawerLayout.responsiveWidth = '10000px';

        assert.isFalse(drawer.opened);

        Base.fire(
            'click', null /* detail */, {node: drawerLayout.querySelector('p')});

        assert.isFalse(drawer.opened);

        Base.fire('click', null /* detail */, {
          node: drawerLayout.querySelector('[drawer-toggle]')
        });

        assert.isTrue(drawer.opened);

        drawerLayout.responsiveWidth = '0px';

        window.setTimeout(function() {
          Base.fire('click', null /* detail */, {
            node: drawerLayout.querySelector('[drawer-toggle]')
          });
          assert.isTrue(drawer.opened);
          done();
        }, 150);
      });

      test('disable initial drawer transition', function(done) {
        assert.isTrue(drawer.hasAttribute('no-transition'));
        flush();

        window.setTimeout(function() {
          assert.isFalse(drawer.hasAttribute('no-transition'));
          done();
        }, 150);
      });

      test('content layout', function(done) {
        drawerLayout.responsiveWidth = '10000px';

        window.setTimeout(function() {
          var contentContainer = drawerLayout.$.contentContainer;
          var computedStyle = window.getComputedStyle(contentContainer);
          assert.equal(computedStyle.marginLeft, '0px');
          assert.equal(computedStyle.marginRight, '0px');

          drawerLayout.responsiveWidth = '0px';

          window.setTimeout(function() {
            computedStyle = window.getComputedStyle(contentContainer);
            assert.equal(computedStyle.marginLeft, '256px');
            assert.equal(computedStyle.marginRight, '0px');

            drawer.align = 'right';

            window.setTimeout(function() {
              computedStyle = window.getComputedStyle(contentContainer);
              assert.equal(computedStyle.marginLeft, '0px');
              assert.equal(computedStyle.marginRight, '256px');

              done();
            }, 100);
          }, 100);
        }, 100);
      });

      test('iron-resize triggers content layout', function() {
        var resetLayoutSpy = sinon.spy(drawerLayout, 'resetLayout');

        assert.isFalse(resetLayoutSpy.called);

        drawerLayout.notifyResize();

        assert.isTrue(resetLayoutSpy.called);

        resetLayoutSpy.restore();
      });

      test('openedWhenNarrow', function(done) {
        drawerLayout.openedWhenNarrow = true;
        drawerLayout.responsiveWidth = '0px';

        window.setTimeout(function() {
          assert.isFalse(drawerLayout.narrow);
          assert.isTrue(drawer.opened);

          drawerLayout.responsiveWidth = '10000px';

          window.setTimeout(function() {
            assert.isTrue(drawerLayout.narrow);
            assert.isTrue(drawer.opened);

            done();
          }, 100);
        }, 100);
      });

      test('app-drawer appended later', function(done) {
        assert.doesNotThrow(function() {
          drawerLayout = document.body.appendChild(
              document.createElement('app-drawer-layout'));
        });
        flush();

        var contentContainer = drawerLayout.$.contentContainer;
        var computedStyle = window.getComputedStyle(contentContainer);
        assert.isUndefined(drawerLayout.drawer);
        assert.equal(computedStyle.marginLeft, '0px');
        assert.equal(computedStyle.marginRight, '0px');

        drawerLayout.responsiveWidth = '0px';
        drawer = document.createElement('app-drawer');
        drawer.setAttribute('slot', 'drawer');
        dom(drawerLayout).appendChild(drawer);
        flush();

        window.setTimeout(function() {
          computedStyle = window.getComputedStyle(contentContainer);
          assert.isTrue(drawerLayout.drawer.opened);
          assert.equal(computedStyle.marginLeft, '256px');
          assert.equal(computedStyle.marginRight, '0px');

          done();
        }, 100);
      });
    });
  </script>

</body>
</html>


================================================
FILE: app-drawer-layout/test/index.html
================================================
<!doctype html>
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE
The complete set of authors may be found at http://polymer.github.io/AUTHORS
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS
-->
<html>
<head>
  <meta charset="UTF-8">
  <title>app-drawer-layout tests</title>
  <script src="../../node_modules/wct-browser-legacy/browser.js"></script>
</head>
<body>
  <script>
    WCT.loadSuites([
      'app-drawer-layout.html',
      'app-drawer-layout.html?wc-shadydom=true&wc-ce=true'
    ]);
  </script>
</body>
</html>


================================================
FILE: app-grid/README.md
================================================
## &lt;app-grid&gt;

app-grid is a helper class useful for creating responsive, fluid grid layouts using custom properties.
Because custom properties can be defined inside a `@media` rule, you can customize the grid layout
for different responsive breakpoints.

Example:

Import `app-grid-style.html` and include `app-grid-style` in the style of an element's definition.
Then, add the class `app-grid` to a container such as `ul` or `div`:

```html
<template>
  <style include="app-grid-style">

    :host {
      --app-grid-columns: 3;
      --app-grid-item-height: 100px;
    }

    ul {
      padding: 0;
      list-style: none;
    }

    .item {
      background-color: white;
    }

    @media (max-width: 640px) {
      :host {
        --app-grid-columns: 1;
      }
    }

  </style>
  <ul class="app-grid">
    <li class="item">1</li>
    <li class="item">2</li>
    <li class="item">3</li>
  </ul>
</template>
```

In this example, the grid  will take 3 columns per row and only 1 column if the viewport width is
smaller than 640px.

### Expandible items

In many cases, it's useful to expand an item more than 1 column. To achieve this type of layout,
you can specify the number of columns the item should expand to by setting the custom property
`--app-grid-expandible-item-columns`. To indicate which item should expand, apply the mixin
`--app-grid-expandible-item` to a rule with a selector to the item. For example:

```html
<template>
  <style include="app-grid-style">
    :host {
      --app-grid-columns: 3;
      --app-grid-item-height: 100px;
      --app-grid-expandible-item-columns: 3;
    }

    ul {
      padding: 0;
      list-style: none;
    }

    /* Only the first item should expand */
    .item:first-child {
      @apply --app-grid-expandible-item;
    }
  </style>
</template>
```

### Preserving the aspect ratio

When the size of a grid item should preserve the aspect ratio, you can add the `has-aspect-ratio`
attribute to the element with the class `app-grid`. Now, every item element becomes a wrapper around
the item content. For example:

```html
<template>
  <style include="app-grid-style">

    :host {
      --app-grid-columns: 3;
      /* 50% the width of the item is equivalent to 2:1 aspect ratio*/
      --app-grid-item-height: 50%;
    }

    ul {
      padding: 0;
      list-style: none;
    }

    .item {
      background-color: white;
    }

  </style>
  <ul class="app-grid" has-aspect-ratio>
    <li class="item">
      <div>item 1</div>
    </li>
    <li class="item">
      <div>item 2</div>
    </li>
    <li class="item">
      <div>item 3</div>
    </li>
  </ul>
</template>
```

### Styling

Custom property                               | Description                                                | Default
----------------------------------------------|------------------------------------------------------------|------------------
`--app-grid-columns`                          | The number of columns per row.                             | 1
`--app-grid-gutter`                           | The space between two items.                               | 0px
`--app-grid-item-height`                      | The height of the items.                                   | auto
`--app-grid-expandible-item-columns`          | The number of columns an expandible item should expand to. | 1

### CSS grid layout

[CSS grid layout](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout) is a new layout system for CSS that lets you create complex grids. It's richer than app-grid in many cases, but it's only supported in a [few browsers](http://caniuse.com/#search=css%20grid%20layout).


================================================
FILE: app-grid/app-grid-style.js
================================================
/**
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at
http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
part of the polymer project is also subject to an additional IP rights grant
found at http://polymer.github.io/PATENTS.txt
*/
/**
app-grid is a helper class useful for creating responsive, fluid grid layouts
using custom properties. Because custom properties can be defined inside a
`@media` rule, you can customize the grid layout for different responsive
breakpoints.

Example:

Import `app-grid-style.html` and include `app-grid-style` in the style of an
element's definition. Then, add the class `app-grid` to a container such as `ul`
or `div`:

```html
<template>
  <style include="app-grid-style">
    :host {
      --app-grid-columns: 3;
      --app-grid-item-height: 100px;
    }

    ul {
      padding: 0;
      list-style: none;
    }

    .item {
      background-color: white;
    }
  </style>
  <ul class="app-grid">
    <li class="item">1</li>
    <li class="item">2</li>
    <li class="item">3</li>
  </ul>
</template>
```
In the example above, the grid  will take 3 columns per row.

### Expandible items

In many cases, it's useful to expand an item more than 1 column. To achieve this
type of layout, you can specify the number of columns the item should expand to
by setting the custom property
`--app-grid-expandible-item-columns`. To indicate which item should expand,
apply the mixin
`--app-grid-expandible-item` to a rule with a selector to the item. For example:

<pre><code>
&lt;template>
  &lt;style include="app-grid-style">
    :host {
      --app-grid-columns: 3;
      --app-grid-item-height: 100px;
      --app-grid-expandible-item-columns: 3;
    }

    /* Only the first item should expand *\/
    .item:first-child {
      &#64;apply --app-grid-expandible-item;
    }
  &lt;/style>
&lt;/template>
</code></pre>

### Preserving the aspect ratio

When the size of a grid item should preserve the aspect ratio, you can add the
`has-aspect-ratio` attribute to the element with the class `.app-grid`. Now,
every item element becomes a wrapper around the item content. For example:

```html
<template>
  <style include="app-grid-style">
    :host {
      --app-grid-columns: 3;
      /* 50% the width of the item is equivalent to 2:1 aspect ratio*\/
      --app-grid-item-height: 50%;
    }

    .item {
      background-color: white;
    }
  </style>
  <ul class="app-grid" has-aspect-ratio>
    <li class="item">
      <div>item 1</div>
    </li>
    <li class="item">
      <div>item 2</div>
    </li>
    <li class="item">
      <div>item 3</div>
    </li>
  </ul>
</template>
```

### Styling

Custom property                               | Description                                                | Default
----------------------------------------------|------------------------------------------------------------|------------------
`--app-grid-columns`                          | The number of columns per row.                             | 1
`--app-grid-gutter`                           | The space between two items.                               | 0px
`--app-grid-item-height`                      | The height of the items.                                   | auto
`--app-grid-expandible-item-columns`          | The number of columns an expandible item should expand to. | 1

@pseudoElement app-grid
@demo app-grid/demo/index.html
*/
import '@polymer/polymer/polymer-legacy.js';
const $_documentContainer = document.createElement('template');
$_documentContainer.setAttribute('style', 'display: none;');

$_documentContainer.innerHTML = `<dom-module id="app-grid-style">
  <template>
    <style>
      :host {
        /**
         * The width for the expandible item is:
         * ((100% - subPixelAdjustment) / columns * itemColumns - gutter
         *
         * - subPixelAdjustment: 0.1px (Required for IE 11)
         * - gutter: var(--app-grid-gutter)
         * - columns: var(--app-grid-columns)
         * - itemColumn: var(--app-grid-expandible-item-columns)
         */
        --app-grid-expandible-item: {
          -webkit-flex-basis: calc((100% - 0.1px) / var(--app-grid-columns, 1) * var(--app-grid-expandible-item-columns, 1) - var(--app-grid-gutter, 0px)) !important;
          flex-basis: calc((100% - 0.1px) / var(--app-grid-columns, 1) * var(--app-grid-expandible-item-columns, 1) - var(--app-grid-gutter, 0px)) !important;
          max-width: calc((100% - 0.1px) / var(--app-grid-columns, 1) * var(--app-grid-expandible-item-columns, 1) - var(--app-grid-gutter, 0px)) !important;
        };
      }

      .app-grid {
        display: -ms-flexbox;
        display: -webkit-flex;
        display: flex;

        -ms-flex-direction: row;
        -webkit-flex-direction: row;
        flex-direction: row;

        -ms-flex-wrap: wrap;
        -webkit-flex-wrap: wrap;
        flex-wrap: wrap;

        padding-top: var(--app-grid-gutter, 0px);
        padding-left: var(--app-grid-gutter, 0px);
        box-sizing: border-box;
      }

      .app-grid > * {
        /* Required for IE 10 */
        -ms-flex: 1 1 100%;
        -webkit-flex: 1;
        flex: 1;

        /* The width for an item is: (100% - subPixelAdjustment - gutter * columns) / columns */
        -webkit-flex-basis: calc((100% - 0.1px - (var(--app-grid-gutter, 0px) * var(--app-grid-columns, 1))) / var(--app-grid-columns, 1));
        flex-basis: calc((100% - 0.1px - (var(--app-grid-gutter, 0px) * var(--app-grid-columns, 1))) / var(--app-grid-columns, 1));

        max-width: calc((100% - 0.1px - (var(--app-grid-gutter, 0px) * var(--app-grid-columns, 1))) / var(--app-grid-columns, 1));
        margin-bottom: var(--app-grid-gutter, 0px);
        margin-right: var(--app-grid-gutter, 0px);
        height: var(--app-grid-item-height);
        box-sizing: border-box;
      }

      .app-grid[has-aspect-ratio] > * {
        position: relative;
      }

      .app-grid[has-aspect-ratio] > *::before {
        display: block;
        content: "";
        padding-top: var(--app-grid-item-height, 100%);
      }

      .app-grid[has-aspect-ratio] > * > * {
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
      }
    </style>
  </template>
</dom-module>`;

document.head.appendChild($_documentContainer.content);


================================================
FILE: app-grid/demo/aspect-ratio.html
================================================
<!--
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">

  <title>Preserving aspect ratio using app-grid-style</title>

  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2.0.0/webcomponents-loader.js"></script>

  <style>
    body {
      margin: 0;
      background-color: #ddd;
    }
  </style>
</head>
<body>
  <dom-module id="x-app">
    <template>
      <style include="app-grid-style">

        :host {
          display: block;
          --app-grid-columns: 3;
          --app-grid-gutter: 10px;
          /* Height is 100% the width of the item. This is equivalent to 1:1 aspect ratio */
          --app-grid-item-height: 100%;
        }

        h1 {
          font-family: 'Roboto', 'Noto', sans-serif;
          text-align: center;
          font-size: 18px;
          line-height: 30px;
          font-weight: 400;
          margin: 10px 20px;
        }

        ul {
          margin: 0;
          padding: 0;
          list-style: none;
        }

        .item {
          background-color: white;
        }

        @media(max-width: 799px) {
          :host {
            /* Height is 50% the width of the item. This is equivalent to 2:1 aspect ratio */
            --app-grid-item-height: 50%;
          }
        }

      </style>

      <h1>Aspect ratio: items have an aspect ratio of 1:1 on large screens and 2:1 on small ones.</h1>

      <ul class="app-grid" has-aspect-ratio>
        <template is="dom-repeat" items="[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]">
          <li>
            <div class="item"></div>
          </li>
        </template>
      </ul>

    </template>

    <script type="module">
      import '@polymer/polymer/polymer-legacy.js';
      import '../app-grid-style.js';
      import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
      Polymer({

        is: 'x-app',

        attached: function() {
          this._updateGridStyles = this._updateGridStyles || function() {
            this.updateStyles();
          }.bind(this);
          window.addEventListener('resize', this._updateGridStyles);
        },

        detached: function() {
          window.removeEventListener('resize', this._updateGridStyles);
        }

      });
    </script>
  </dom-module>

  <x-app></x-app>

</body>
</html>


================================================
FILE: app-grid/demo/flickr-grid-layout.html
================================================
<!--
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">

  <title>Flickr grid layout</title>

  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2.0.0/webcomponents-loader.js"></script>

  <style>

    body {
      font-family: 'Roboto', 'Noto', sans-serif;
      background-color: #f0f0f0;
      margin: 0;
    }

  </style>

</head>
<body>

  <dom-module id="x-grid">
    <template>
      <style include="app-grid-style">

        :host {
          display: block;
          --app-grid-columns: 4;
          --app-grid-gutter: 5px;
          --app-grid-item-height: 250px;
          --app-grid-expandible-item-columns: 4;
        }

        app-header {
          background-color: rgba(255, 255, 255, 0.8);
          color: black;
          -webkit-backdrop-filter: saturate(180%) blur(20px);
          backdrop-filter: saturate(180%) blur(20px);
        }

        ul {
          padding: 0;
          list-style: none;
        }

        [main-title] {
          font-weight: bold;
        }

        .centered-container {
          margin-top: 40px;
          max-width: 1000px;
          margin: 40px auto;
        }

        .loadingIndicator {
          font-size: 16px;
          text-align: center;
          height: 60px;
        }

        .loadingIndicator paper-spinner {
          margin-right: 20px;
          vertical-align: middle;
        }

        .item {
          background-color: white;
          background-size: cover;
          background-position: center center;
        }

        .item:nth-child(5n + 1) {
          @apply --app-grid-expandible-item;
          height: 400px;
        }

        @media(max-width: 799px) {

          :host {
            --app-grid-columns: 2;
            --app-grid-gutter: 5px;
            --app-grid-item-height: 200px;
          }

          .centered-container {
            margin: 10px 5px;
          }

          .item:nth-child(5n + 1) {
            height: 250px;
          }

          [spacer] {
            margin-left: 0;
          }

        }

      </style>

      <app-header-layout>
        <app-header slot="header" reveals effects="waterfall">
          <app-toolbar>
            <div spacer main-title>Flickr grid layout</div>
          </app-toolbar>
        </app-header>
        <div class="centered-container">
          <ul class="app-grid">
            <template is="dom-repeat" items="[[photos]]" as="photo">
              <li class="item" style$="[[_getItemStyle(photo)]]"></li>
            </template>
          </ul>
        </div>
      </app-header-layout>

      <div class="loadingIndicator" hidden$="[[!loadingPhotos]]">
        <paper-spinner active$="[[loadingPhotos]]"></paper-spinner> Fetching photos
      </div>

      <iron-ajax id="ajax" loading="{{loadingPhotos}}" handle-as="text" on-response="_didReceiveResponse"></iron-ajax>

      <!-- this element loads more photos when the user scrolls down and reached the lower threshold -->
      <iron-scroll-threshold id="scrollTheshold"
        lower-threshold="500"
        on-lower-threshold="_loadMorePhotos"
        scroll-target="document">
      </iron-scroll-threshold>

    </template>

    <script type="module">
      import '@polymer/polymer/polymer-legacy.js';
      import '@polymer/iron-scroll-threshold/iron-scroll-threshold.js';
      import '@polymer/iron-ajax/iron-ajax.js';
      import '@polymer/paper-styles/shadow.js';
      import '@polymer/paper-spinner/paper-spinner.js';
      import '../../app-header-layout/app-header-layout.js';
      import '../../app-scroll-effects/effects/waterfall.js';
      import '../../app-header/app-header.js';
      import '../../app-toolbar/app-toolbar.js';
      import '../app-grid-style.js';
      import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
      Polymer({
        is: 'x-grid',

        properties: {

          apiKey: {type: String, value: 'c304f1096a06486d3c1e7ab271bf7f3f'},

          photos: {
            type: Array,
            value: function() {
              return [];
            }
          },

          perPage: {type: Number, value: 36},

          page: {type: Number, value: 0},

          userId: {type: String, value: '142203852@N04'},

          totalPages: {type: Number, value: 1},

          loadingPhotos: Boolean
        },

        attached: function() {
          this._updateGridStyles = this._updateGridStyles || function() {
            this.updateStyles();
          }.bind(this);
          window.addEventListener('resize', this._updateGridStyles);
        },

        detached: function() {
          window.removeEventListener('resize', this._updateGridStyles);
        },

        _getAPIEndpoint: function(apiKey, userId, page) {
          return 'https://api.flickr.com/services/rest/?method=flickr.photos.search' +
              '&api_key=' + apiKey + '&safe_search=1&sort=interestingness-desc' +
              '&user_id=' + userId + '&page=' + page + '&format=json' +
              '&per_page=' + this.perPage;
        },

        _didReceiveResponse: function(e) {
          var payload =
              JSON.parse(e.detail.response.match('jsonFlickrApi\\((.*)\\)')[1]);

          if (!payload || !payload.photos || !payload.photos.photo) {
            return;
          }

          this.totalPages = payload.photos.pages;

          payload.photos.photo.forEach(function(photo) {
            this.push('photos', photo);
          }, this);

          this.$.scrollTheshold.clearTriggers();
        },

        _loadMorePhotos: function() {
          if (this.loadingPhotos) {
            return;
          }
          if (this.page < this.totalPages) {
            this.page++;
            this.$.ajax.url =
                this._getAPIEndpoint(this.apiKey, this.userId, this.page);
            this.$.ajax.generateRequest();
          } else {
            this.$.scrollTheshold.clearTriggers();
          }
        },

        _getItemStyle: function(photo) {
          return 'background-image: url(//farm' + photo.farm + '.staticflickr.com/' +
              photo.server + '/' + photo.id + '_' + photo.secret + '_b.jpg);';
        },

      });
    </script>
  </dom-module>

  <x-grid></x-grid>

</body>
</html>


================================================
FILE: app-grid/demo/index.html
================================================
<!--
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<!doctype html>
<html lang="en">
<head>
  <title>app-grid demos</title>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">
  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2.0.0/webcomponents-loader.js"></script>
  <script type="module">
    import '@polymer/paper-styles/demo-pages.js';
  </script>
  <style>
    a {
      display: block;
      margin-bottom: 10px;
    }
  </style>
</head>

<body unresolved>
  <div class="horizontal-section-container">
    <div>
      <h4>app-grid demos</h4>
      <div class="horizontal-section">
        <a href="flickr-grid-layout.html">Flickr grid layout</a>
        <a href="md-grid-layout.html">Material design grid layout</a>
        <a href="simple-responsive-grid.html">Simple responsive grid layout</a>
        <a href="aspect-ratio.html">Aspect ratios</a>
      </div>
    </div>
  </div>
</body>
</html>


================================================
FILE: app-grid/demo/md-grid-layout.html
================================================
<!--
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">

  <title>Material design grid layout using app-grid</title>

  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2.0.0/webcomponents-loader.js"></script>

  <style>

    body {
      font-family: 'Roboto', 'Noto', sans-serif;
      background-color: #ddd;
      margin: 0;
    }

  </style>

</head>
<body>
  <dom-module id="x-grid">
    <template>
      <style include="app-grid-style">

        :host {
          display: block;
          --app-grid-columns: 4;
          --app-grid-gutter: 10px;
          --app-grid-expandible-item-columns: 4;
          --paper-icon-button-ink-color: white;
        }

        app-header {
          background-color: #0b8043;
          color: white;
        }

        ul {
          padding: 0;
          list-style: none;
        }

        .centered-container {
          margin-top: 40px;
          max-width: 1000px;
          margin: 40px auto;
        }

        .item {
          height: 250px;
          position: relative;
          background-color: white;
          background-size: cover;
          background-position: center center;
        }

        .item:nth-child(5n + 1) {
          height: 30vmax;
          @apply --app-grid-expandible-item;
        }

        .item-title {
          position: absolute;
          bottom: 0;
          left: 0;
          right: 0;
          background-color: rgba(0, 0, 0, 0.2);
          color: white;
          font-weight: 400;
          padding: 16px;
        }

        @media(max-width: 799px) {

          .centered-container {
            margin: 10px 5px;
          }

          :host {
            --app-grid-columns: 2;
            --app-grid-gutter: 5px;
            --app-grid-item-height: 200px;
          }

        }

      </style>

      <app-header-layout>
        <app-header slot="header" reveals effects="waterfall">
          <app-toolbar>
            <div spacer main-title>Material responsive grid</div>
          </app-toolbar>
        </app-header>
        <div class="centered-container">
          <ul class="app-grid">
            <template is="dom-repeat" items="[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]">
              <li class="item" style$="background-image: url(//lorempixel.com/800/800/nature/?i=[[item]]);">
                <div class="item-title">Nature [[item]]</div>
              </li>
            </template>
          </ul>
        </div>
      </app-header-layout>

    </template>

    <script type="module">
      import '@polymer/polymer/polymer-legacy.js';
      import '@polymer/iron-icons/iron-icons.js';
      import '@polymer/paper-styles/shadow.js';
      import '@polymer/paper-icon-button/paper-icon-button.js';
      import '../../app-header-layout/app-header-layout.js';
      import '../../app-scroll-effects/effects/waterfall.js';
      import '../../app-header/app-header.js';
      import '../../app-toolbar/app-toolbar.js';
      import '../app-grid-style.js';
      import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
      Polymer({
        is: 'x-grid',

        attached: function() {
          this._updateGridStyles = this._updateGridStyles || function() {
            this.updateStyles();
          }.bind(this);
          window.addEventListener('resize', this._updateGridStyles);
        },

        detached: function() {
          window.removeEventListener('resize', this._updateGridStyles);
        },
      });
    </script>
  </dom-module>

  <x-grid></x-grid>

</body>
</html>


================================================
FILE: app-grid/demo/simple-responsive-grid.html
================================================
<!--
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">

  <title>Responsive grid layout using app-grid-style</title>

  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2.0.0/webcomponents-loader.js"></script>

  <style>

    body {
      margin: 0;
      background-color: #ddd;
    }

  </style>
</head>
<body>
  <dom-module id="x-app">
    <template>
      <style include="app-grid-style">

        :host {
          display: block;
          --app-grid-columns: 3;
          --app-grid-gutter: 10px;
          --app-grid-expandible-item-columns: 2;
          --app-grid-item-height: 20vw;
        }

        ul {
          padding: 0;
          list-style: none;
        }

        h1 {
          font-family: 'Roboto', 'Noto', sans-serif;
          text-align: center;
          font-size: 18px;
          line-height: 30px;
          font-weight: 400;
          margin: 10px 20px;
        }

        .item {
          list-style: none;
          background-color: white;
        }

        @media (min-width: 800px) {
          .item:nth-child(5n+1) {
            @apply --app-grid-expandible-item;
          }
        }

        @media (max-width: 799px) {
          :host {
            --app-grid-columns: 2;
            --app-grid-gutter: 5px;
            --app-grid-expandible-item-columns: 2;
          }

          .item:nth-child(3n+1) {
            @apply --app-grid-expandible-item;
          }
        }

      </style>

      <h1>3 columns on large screens and 2 columns on small ones.</h1>

      <ul class="app-grid">
        <template is="dom-repeat" items="[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]">
          <li class="item"></li>
        </template>
      </ul>

    </template>

    <script type="module">
      import '@polymer/polymer/polymer-legacy.js';
      import '../app-grid-style.js';
      import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
      Polymer({

        is: 'x-app',

        attached: function() {
          this._updateGridStyles = this._updateGridStyles || function() {
            this.updateStyles();
          }.bind(this);
          window.addEventListener('resize', this._updateGridStyles);
        },

        detached: function() {
          window.removeEventListener('resize', this._updateGridStyles);
        }

      });
    </script>
  </dom-module>

  <x-app></x-app>

</body>
</html>


================================================
FILE: app-grid/test/app-grid-1.html
================================================
<!doctype html>
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE
The complete set of authors may be found at http://polymer.github.io/AUTHORS
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS
-->
<html>
<head>
  <meta charset="UTF-8">
  <title>test for app-grid</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

  <script src="../../node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
  <script src="../../node_modules/wct-browser-legacy/browser.js"></script>

  <style>
    body {
      margin: 0;
      padding: 0;
    }
  </style>
</head>
<body>

 <dom-module id="x-grid">
    <template>
      <style include="app-grid-style">

        :host {
          display: block;
          --app-grid-columns: 3;
          --app-grid-gutter: 10px;
          --app-grid-expandible-item-columns: 3;
          --app-grid-item-height: 20vw;
          width: 200px;
          background-color: red;

        }

        ul {
          margin: 0;
          padding: 0;
          list-style: none;
        }

        .item {
          list-style: none;
          background-color: green;
        }

        .item:nth-child(4n + 1) {
            @apply --app-grid-expandible-item;
        }

      </style>

      <ul class="app-grid">
        <template is="dom-repeat" items="[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]">
          <li class="item">[[item]]</li>
        </template>
      </ul>

    </template>

    <script type="module">
      import '../app-grid-style.js';
      import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
      Polymer({is: 'x-grid'});
    </script>
  </dom-module>


  <test-fixture id="trivialGrid">
    <template>
      <x-grid></x-grid>
    </template>
  </test-fixture>

  <script type="module">
    import '../app-grid-style.js';
    import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
    function valueAsInt(obj) {
      var rtn = {top: 0, right: 0, bottom: 0, left: 0, width: 0};
      for (var k in obj) {
        if (rtn.hasOwnProperty(k)) {
          rtn[k] = Math.round(obj[k]);
        }
      }
      return rtn;
    }

    suite('basic features', function() {
      var grid;

      setup(function() {
        grid = fixture('trivialGrid');
      });

      test('bounding rectangle for each item', function(done) {
        flush(function() {
          var i, k, currentRect;
          var gridItems = dom(grid.root).querySelectorAll('li');
          var expectedBoundingRect = [
            {top: 10, right: 190, bottom: 110, left: 10, width: 180},
            {top: 120, right: 63, bottom: 220, left: 10, width: 53},
            {top: 120, right: 126, bottom: 220, left: 73, width: 53},
            {top: 120, right: 189, bottom: 220, left: 136, width: 53},
            {top: 230, right: 190, bottom: 330, left: 10, width: 180},
            {top: 340, right: 63, bottom: 440, left: 10, width: 53},
            {top: 340, right: 126, bottom: 440, left: 73, width: 53},
            {top: 340, right: 189, bottom: 440, left: 136, width: 53},
            {top: 450, right: 190, bottom: 550, left: 10, width: 180},
            {top: 560, right: 63, bottom: 660, left: 10, width: 53},
            {top: 560, right: 126, bottom: 660, left: 73, width: 53},
            {top: 560, right: 189, bottom: 660, left: 136, width: 53}
          ];

          for (i = 0; i < gridItems.length; i++) {
            currentRect = valueAsInt(gridItems[i].getBoundingClientRect());

            for (k in expectedBoundingRect[i]) {
              if (expectedBoundingRect[i].hasOwnProperty(k)) {
                assert.approximately(
                    expectedBoundingRect[i][k],
                    currentRect[k],
                    4,
                    ' ItemRect[' + i + '].' + k);
              }
            }
          }

          done();
        });
      });
    });
  </script>

</body>
</html>


================================================
FILE: app-grid/test/app-grid-2.html
================================================
<!doctype html>
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE
The complete set of authors may be found at http://polymer.github.io/AUTHORS
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS
-->
<html>
<head>
  <meta charset="UTF-8">
  <title>test for app-grid</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

  <script src="../../node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
  <script src="../../node_modules/wct-browser-legacy/browser.js"></script>

  <style>
    body {
      margin: 0;
      padding: 0;
    }
  </style>
</head>
<body>

 <dom-module id="x-grid">
    <template>
      <style include="app-grid-style">

        :host {
          display: block;
          --app-grid-columns: 4;
          --app-grid-gutter: 16px;
          --app-grid-expandible-item-columns: 2;
          --app-grid-item-height: 100px;
          width: 480px;
          background-color: red;

        }

        ul {
          margin: 0;
          padding: 0;
          list-style: none;
        }

        .item {
          list-style: none;
          background-color: green;
        }

        .item:nth-child(2),
        .item:nth-child(5),
        .item:nth-child(8),
        .item:nth-child(11) {
            @apply --app-grid-expandible-item;
        }

      </style>

      <ul class="app-grid">
        <template items="[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]" is="dom-repeat">
          <li class="item">[[item]]</li>
        </template>
      </ul>

    </template>

    <script type="module">
      import '../app-grid-style.js';
      import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
      Polymer({is: 'x-grid'});
    </script>
  </dom-module>


  <test-fixture id="trivialGrid">
    <template>
      <x-grid></x-grid>
    </template>
  </test-fixture>

  <script type="module">
    import '../app-grid-style.js';
    import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
    function valueAsInt(obj) {
      var rtn = {top: 0, right: 0, bottom: 0, left: 0, width: 0};
      for (var k in obj) {
        if (rtn.hasOwnProperty(k)) {
          rtn[k] = Math.round(obj[k]);
        }
      }
      return rtn;
    }

    suite('basic features', function() {
      var grid;

      setup(function() {
        grid = fixture('trivialGrid');
      });

      test('bounding rectangle for each item', function(done) {
        flush(function() {
          var i, k, currentRect;
          var gridItems = dom(grid.root).querySelectorAll('li');
          var expectedBoundingRect = [
            {top: 16, right: 116, bottom: 116, left: 16, width: 100},
            {top: 16, right: 348, bottom: 116, left: 132, width: 216},
            {top: 16, right: 464, bottom: 116, left: 364, width: 100},
            {top: 132, right: 116, bottom: 232, left: 16, width: 100},
            {top: 132, right: 348, bottom: 232, left: 132, width: 216},
            {top: 132, right: 464, bottom: 232, left: 364, width: 100},
            {top: 248, right: 116, bottom: 348, left: 16, width: 100},
            {top: 248, right: 348, bottom: 348, left: 132, width: 216},
            {top: 248, right: 464, bottom: 348, left: 364, width: 100},
            {top: 364, right: 116, bottom: 464, left: 16, width: 100},
            {top: 364, right: 348, bottom: 464, left: 132, width: 216},
            {top: 364, right: 464, bottom: 464, left: 364, width: 100}
          ];

          for (i = 0; i < gridItems.length; i++) {
            currentRect = valueAsInt(gridItems[i].getBoundingClientRect());

            for (k in expectedBoundingRect[i]) {
              if (expectedBoundingRect[i].hasOwnProperty(k)) {
                assert.approximately(
                    expectedBoundingRect[i][k],
                    currentRect[k],
                    4,
                    ' ItemRect[' + i + '].' + k);
              }
            }
          }

          done();
        });
      });
    });
  </script>

</body>
</html>


================================================
FILE: app-grid/test/app-grid-3.html
================================================
<!doctype html>
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE
The complete set of authors may be found at http://polymer.github.io/AUTHORS
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS
-->
<html>
<head>
  <meta charset="UTF-8">
  <title>test for app-grid</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

  <script src="../../node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
  <script src="../../node_modules/wct-browser-legacy/browser.js"></script>

  <style>
    body {
      margin: 0;
      padding: 0;
    }
  </style>
</head>
<body>

 <dom-module id="x-grid">
    <template>
      <style include="app-grid-style">

        :host {
          display: block;
          --app-grid-columns: 4;
          --app-grid-gutter: 16px;
          --app-grid-expandible-item-columns: 3;
          --app-grid-item-height: 100px;
          width: 480px;
          background-color: red;

        }

        ul {
          margin: 0;
          padding: 0;
          list-style: none;
        }

        .item {
          list-style: none;
          background-color: green;
        }

        .item:nth-child(2),
        .item:nth-child(3),
        .item:nth-child(6),
        .item:nth-child(7),
        .item:nth-child(10) {
            @apply --app-grid-expandible-item;
        }

      </style>

      <ul class="app-grid">
        <template items="[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]" is="dom-repeat">
          <li class="item">[[item]]</li>
        </template>
      </ul>

    </template>

    <script type="module">
      import '../app-grid-style.js';
      import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
      Polymer({is: 'x-grid'});
    </script>
  </dom-module>


  <test-fixture id="trivialGrid">
    <template>
      <x-grid></x-grid>
    </template>
  </test-fixture>

  <script type="module">
    import '../app-grid-style.js';
    import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
    function valueAsInt(obj) {
      var rtn = {top: 0, right: 0, bottom: 0, left: 0, width: 0};
      for (var k in obj) {
        if (rtn.hasOwnProperty(k)) {
          rtn[k] = Math.round(obj[k]);
        }
      }
      return rtn;
    }

    suite('basic features', function() {
      var grid;

      setup(function() {
        grid = fixture('trivialGrid');
      });

      test('bounding rectangle for each item', function(done) {
        flush(function() {
          var i, k, currentRect;
          var gridItems = dom(grid.root).querySelectorAll('li');
          var expectedBoundingRect = [
            {top: 16, right: 116, bottom: 116, left: 16, width: 100},
            {top: 16, right: 464, bottom: 116, left: 132, width: 332},
            {top: 132, right: 348, bottom: 232, left: 16, width: 332},
            {top: 132, right: 464, bottom: 232, left: 364, width: 100},
            {top: 248, right: 116, bottom: 348, left: 16, width: 100},
            {top: 248, right: 464, bottom: 348, left: 132, width: 332},
            {top: 364, right: 348, bottom: 464, left: 16, width: 332},
            {top: 364, right: 464, bottom: 464, left: 364, width: 100},
            {top: 480, right: 116, bottom: 580, left: 16, width: 100},
            {top: 480, right: 464, bottom: 580, left: 132, width: 332},
            {top: 596, right: 116, bottom: 696, left: 16, width: 100},
            {top: 596, right: 232, bottom: 696, left: 132, width: 100},
            {top: 596, right: 348, bottom: 696, left: 248, width: 100},
            {top: 596, right: 464, bottom: 696, left: 364, width: 100}
          ];

          for (i = 0; i < gridItems.length; i++) {
            currentRect = valueAsInt(gridItems[i].getBoundingClientRect());
            for (k in expectedBoundingRect[i]) {
              if (expectedBoundingRect[i].hasOwnProperty(k)) {
                assert.approximately(
                    expectedBoundingRect[i][k],
                    currentRect[k],
                    4,
                    ' ItemRect[' + i + '].' + k);
              }
            }
          }

          done();
        });
      });
    });
  </script>

</body>
</html>


================================================
FILE: app-grid/test/index.html
================================================
<!doctype html>
<!--
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE
The complete set of authors may be found at http://polymer.github.io/AUTHORS
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS
-->
<html>
<head>
  <meta charset="UTF-8">
  <title>app-grid tests</title>
  <script src="../../node_modules/wct-browser-legacy/browser.js"></script>
</head>
<body>
  <script>
    WCT.loadSuites([
      'app-grid-1.html',
      'app-grid-2.html',
      'app-grid-3.html',
      'app-grid-1.html?wc-shadydom=true&wc-ce=true',
      'app-grid-2.html?wc-shadydom=true&wc-ce=true',
      'app-grid-3.html?wc-shadydom=true&wc-ce=true'
    ]);
  </script>
</body>
</html>


================================================
FILE: app-header/README.md
================================================
## &lt;app-header&gt;

![app-header](http://app-layout-assets.appspot.com/assets/docs/app-header/header.gif)

app-header is container element for app-toolbars at the top of the screen that can have scroll
effects. By default, an app-header moves away from the viewport when scrolling down and
if using `reveals`, the header slides back when scrolling back up. For example:

```html
<app-header reveals>
  <app-toolbar>
    <div main-title>App name</div>
  </app-toolbar>
</app-header>
```

app-header can also condense when scrolling down. To achieve this behavior, the header
must have a larger height than the `sticky` element in the light DOM. For example:

```html
<app-header style="height: 96px;" condenses fixed>
  <app-toolbar style="height: 64px;">
    <div main-title>App name</div>
  </app-toolbar>
</app-header>
```

In this case the header is initially `96px` tall, and it shrinks to `64px` when scrolling down.
That is what is meant by "condensing".

### Sticky element

The element that is positioned fixed to top of the header's `scrollTarget` when a threshold
is reached, similar to `position: sticky` in CSS. This element **must** be an immediate
child of app-header. By default, the `sticky` element is the first `app-toolbar that
is an immediate child of app-header.

```html
<app-header condenses>
  <app-toolbar> Sticky element </app-toolbar>
  <app-toolbar></app-toolbar>
</app-header>
```

#### Customizing the sticky element

```html
<app-header condenses>
  <app-toolbar></app-toolbar>
  <app-toolbar sticky> Sticky element </app-toolbar>
</app-header>
```

### Scroll target

The app-header's `scrollTarget` property allows to customize the scrollable element to which
the header responds when the user scrolls. By default, app-header uses the document as
the scroll target, but you can customize this property by setting the id of the element, e.g.

```html
<div id="scrollingRegion" style="overflow-y: auto;">
  <app-header scroll-target="scrollingRegion">
  </app-header>
</div>
```

In this case, the `scrollTarget` property points to the outer div element. Alternatively,
you can set this property programmatically:

```js
appHeader.scrollTarget = document.querySelector("#scrollingRegion");
```

## Backgrounds
app-header has two background layers that can be used for styling when the header is condensed
or when the scrollable element is scrolled to the top.

## Scroll effects

Scroll effects are _optional_ visual effects applied in app-header based on scroll position. For example,
The [Material Design scrolling techniques](https://www.google.com/design/spec/patterns/scrolling-techniques.html)
recommends effects that can be installed via the `effects` property. e.g.

```html
<app-header effects="waterfall">
  <app-toolbar>App name</app-toolbar>
</app-header>
```

#### Importing the effects

To use the scroll effects, you must explicitly import them in addition to `app-header`:

```js
import '@polymer/app-layout/app-scroll-effects/app-scroll-effects.js';
```

#### List of effects

* **blend-background**
Fades in/out two background elements by applying CSS opacity based on scroll position.
You can use this effect to smoothly change the background color or image of the header.
For example, using the mixin `--app-header-background-rear-layer` lets you assign a different
background when the header is condensed:

```css
app-header {
  background-color: red;
  --app-header-background-rear-layer: {
    /* The header is blue when condensed */
    background-color: blue;
  };
}
```

* **fade-background**
Upon scrolling past a threshold, this effect will trigger an opacity transition to
fade in/out the backgrounds. Compared to the `blend-background` effect,
this effect doesn't interpolate the opacity based on scroll position.

* **parallax-background**
A simple parallax effect that vertically translates the backgrounds based on a fraction
of the scroll position. For example:

```css
app-header {
  --app-header-background-front-layer: {
    background-image: url(...);
  };
}
```
```html
<app-header style="height: 300px;" effects="parallax-background">
  <app-toolbar>App name</app-toolbar>
</app-header>
```

The fraction determines how far the background moves relative to the scroll position.
This value can be assigned via the `scalar` config value and it is typically a value
between 0 and 1 inclusive. If `scalar=0`, the background doesn't move away from the header.

* **resize-title**
Progressively interpolates the size of the title from the element with the `main-title` attribute
to the element with the `condensed-title` attribute as the header condenses. For example:

```html
<app-header condenses reveals effects="resize-title">
  <app-toolbar>
      <h4 condensed-title>App name</h4>
  </app-toolbar>
  <app-toolbar>
      <h1 main-title>App name</h1>
  </app-toolbar>
</app-header>
```

* **resize-snapped-title**
Upon scrolling past a threshold, this effect fades in/out the titles using opacity transitions.
Similarly to `resize-title`, the `main-title` and `condensed-title` elements must be placed in the
light DOM.

* **waterfall**
Toggles the shadow property in app-header to create a sense of depth (as recommended in the
MD spec) between the header and the underneath content. You can change the shadow by
customizing the `--app-header-shadow` mixin. For example:

```css
app-header {
  --app-header-shadow: {
    box-shadow: inset 0px 5px 2px -3px rgba(0, 0, 0, 0.2);
  };
}
```

```html
<app-header condenses reveals effects="waterfall">
  <app-toolbar>
      <h1 main-title>App name</h1>
  </app-toolbar>
</app-header>
```

* **material**
Installs the waterfall, resize-title, blend-background and parallax-background effects.

### Content attributes

Attribute | Description         | Default
----------|---------------------|----------------------------------------
`sticky` | Element that remains at the top when the header condenses. | The first app-toolbar in the light DOM.


## Styling

Mixin | Description | Default
------|-------------|----------
`--app-header-background-front-layer` | Applies to the front layer of the background. | {}
`--app-header-background-rear-layer` | Applies to the rear layer of the background. | {}
`--app-header-shadow` | Applies to the shadow. | {}


================================================
FILE: app-header/app-header.js
================================================
/**
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at
http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
part of the polymer project is also subject to an additional IP rights grant
found at http://polymer.github.io/PATENTS.txt
*/
import '@polymer/polymer/polymer-legacy.js';
import '@polymer/iron-flex-layout/iron-flex-layout.js';

import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {html} from '@polymer/polymer/lib/utils/html-tag.js';

import {AppLayoutBehavior} from '../app-layout-behavior/app-layout-behavior.js';
import {AppScrollEffectsBehavior} from '../app-scroll-effects/app-scroll-effects-behavior.js';

/**
app-header is container element for app-toolbars at the top of the screen that
can have scroll effects. By default, an app-header moves away from the viewport
when scrolling down and if using `reveals`, the header slides back when
scrolling back up. For example:

```html
<app-header reveals>
  <app-toolbar>
    <div main-title>App name</div>
  </app-toolbar>
</app-header>
```

app-header can also condense when scrolling down. To achieve this behavior, the
header must have a larger height than the `sticky` element in the light DOM. For
example:

```html
<app-header style="height: 96px;" condenses fixed>
  <app-toolbar style="height: 64px;">
    <div main-title>App name</div>
  </app-toolbar>
</app-header>
```

In this case the header is initially `96px` tall, and it shrinks to `64px` when
scrolling down. That is what is meant by "condensing".

### Sticky element

The element that is positioned fixed to top of the header's `scrollTarget` when
a threshold is reached, similar to `position: sticky` in CSS. This element
**must** be an immediate child of app-header. By default, the `sticky` element
is the first `app-toolbar that is an immediate child of app-header.

```html
<app-header condenses>
  <app-toolbar> Sticky element </app-toolbar>
  <app-toolbar></app-toolbar>
</app-header>
```

#### Customizing the sticky element

```html
<app-header condenses>
  <app-toolbar></app-toolbar>
  <app-toolbar sticky> Sticky element </app-toolbar>
</app-header>
```

### Scroll target

The app-header's `scrollTarget` property allows to customize the scrollable
element to which the header responds when the user scrolls. By default,
app-header uses the document as the scroll target, but you can customize this
property by setting the id of the element, e.g.

```html
<div id="scrollingRegion" style="overflow-y: auto;">
  <app-header scroll-target="scrollingRegion">
  </app-header>
</div>
```

In this case, the `scrollTarget` property points to the outer div element.
Alternatively, you can set this property programmatically:

```js
appHeader.scrollTarget = document.querySelector("#scrollingRegion");
```

## Backgrounds
app-header has two background layers that can be used for styling when the
header is condensed or when the scrollable element is scrolled to the top.

## Scroll effects

Scroll effects are _optional_ visual effects applied in app-header based on
scroll position. For example, The [Material Design scrolling
techniques](https://www.google.com/design/spec/patterns/scrolling-techniques.html)
recommends effects that can be installed via the `effects` property. e.g.

```html
<app-header effects="waterfall">
  <app-toolbar>App name</app-toolbar>
</app-header>
```

#### Importing the effects

To use the scroll effects, you must explicitly import them in addition to
`app-header`:

```js
import '@polymer/app-layout/app-scroll-effects/app-scroll-effects.js';
```

#### List of effects

* **blend-background**
Fades in/out two background elements by applying CSS opacity based on scroll
position. You can use this effect to smoothly change the background color or
image of the header. For example, using the mixin
`--app-header-background-rear-layer` lets you assign a different background when
the header is condensed:

```css
app-header {
  background-color: red;
  --app-header-background-rear-layer: {
    /* The header is blue when condensed *\/
    background-color: blue;
  };
}
```

* **fade-background**
Upon scrolling past a threshold, this effect will trigger an opacity transition
to fade in/out the backgrounds. Compared to the `blend-background` effect, this
effect doesn't interpolate the opacity based on scroll position.


* **parallax-background**
A simple parallax effect that vertically translates the backgrounds based on a
fraction of the scroll position. For example:

```css
app-header {
  --app-header-background-front-layer: {
    background-image: url(...);
  };
}
```
```html
<app-header style="height: 300px;" effects="parallax-background">
  <app-toolbar>App name</app-toolbar>
</app-header>
```

The fraction determines how far the background moves relative to the scroll
position. This value can be assigned via the `scalar` config value and it is
typically a value between 0 and 1 inclusive. If `scalar=0`, the background
doesn't move away from the header.

* **resize-title**
Progressively interpolates the size of the title from the element with the
`main-title` attribute to the element with the `condensed-title` attribute as
the header condenses. For example:

```html
<app-header condenses reveals effects="resize-title">
  <app-toolbar>
      <h4 condensed-title>App name</h4>
  </app-toolbar>
  <app-toolbar>
      <h1 main-title>App name</h1>
  </app-toolbar>
</app-header>
```

* **resize-snapped-title**
Upon scrolling past a threshold, this effect fades in/out the titles using
opacity transitions. Similarly to `resize-title`, the `main-title` and
`condensed-title` elements must be placed in the light DOM.

* **waterfall**
Toggles the shadow property in app-header to create a sense of depth (as
recommended in the MD spec) between the header and the underneath content. You
can change the shadow by customizing the `--app-header-shadow` mixin. For
example:

```css
app-header {
  --app-header-shadow: {
    box-shadow: inset 0px 5px 2px -3px rgba(0, 0, 0, 0.2);
  };
}
```

```html
<app-header condenses reveals effects="waterfall">
  <app-toolbar>
      <h1 main-title>App name</h1>
  </app-toolbar>
</app-header>
```

* **material**
Installs the waterfall, resize-title, blend-background and parallax-background
effects.

### Content attributes

Attribute | Description         | Default
----------|---------------------|----------------------------------------
`sticky` | Element that remains at the top when the header condenses. | The first app-toolbar in the light DOM.


## Styling

Mixin | Description | Default
------|-------------|----------
`--app-header-background-front-layer` | Applies to the front layer of the background. | {}
`--app-header-background-rear-layer` | Applies to the rear layer of the background. | {}
`--app-header-shadow` | Applies to the shadow. | {}

@element app-header
@demo app-header/demo/blend-background-1.html Blend Background Image
@demo app-header/demo/blend-background-2.html Blend 2 Background Images
@demo app-header/demo/blend-background-3.html Blend Background Colors
@demo app-header/demo/contacts.html Contacts Demo
@demo app-header/demo/give.html Resize Snapped Title Demo
@demo app-header/demo/music.html Reveals Demo
@demo app-header/demo/no-effects.html Condenses and Reveals Demo
@demo app-header/demo/notes.html Fixed with Dynamic Shadow Demo
@demo app-header/demo/custom-sticky-element-1.html Custom Sticky Element Demo 1
@demo app-header/demo/custom-sticky-element-2.html Custom Sticky Element Demo 2

*/
Polymer({
  /** @override */
  _template: html`
    <style>
      :host {
        position: relative;
        display: block;
        transition-timing-function: linear;
        transition-property: -webkit-transform;
        transition-property: transform;
      }

      :host::before {
        position: absolute;
        right: 0px;
        bottom: -5px;
        left: 0px;
        width: 100%;
        height: 5px;
        content: "";
        transition: opacity 0.4s;
        pointer-events: none;
        opacity: 0;
        box-shadow: inset 0px 5px 6px -3px rgba(0, 0, 0, 0.4);
        will-change: opacity;
        @apply --app-header-shadow;
      }

      :host([shadow])::before {
        opacity: 1;
      }

      #background {
        @apply --layout-fit;
        overflow: hidden;
      }

      #backgroundFrontLayer,
      #backgroundRearLayer {
        @apply --layout-fit;
        height: 100%;
        pointer-events: none;
        background-size: cover;
      }

      #backgroundFrontLayer {
        @apply --app-header-background-front-layer;
      }

      #backgroundRearLayer {
        opacity: 0;
        @apply --app-header-background-rear-layer;
      }

      #contentContainer {
        position: relative;
        width: 100%;
        height: 100%;
      }

      :host([disabled]),
      :host([disabled])::after,
      :host([disabled]) #backgroundFrontLayer,
      :host([disabled]) #backgroundRearLayer,
      /* Silent scrolling should not run CSS transitions */
      :host([silent-scroll]),
      :host([silent-scroll])::after,
      :host([silent-scroll]) #backgroundFrontLayer,
      :host([silent-scroll]) #backgroundRearLayer {
        transition: none !important;
      }

      :host([disabled]) ::slotted(app-toolbar:first-of-type),
      :host([disabled]) ::slotted([sticky]),
      /* Silent scrolling should not run CSS transitions */
      :host([silent-scroll]) ::slotted(app-toolbar:first-of-type),
      :host([silent-scroll]) ::slotted([sticky]) {
        transition: none !important;
      }

    </style>
    <div id="contentContainer">
      <slot id="slot"></slot>
    </div>
`,

  is: 'app-header',
  behaviors: [AppScrollEffectsBehavior, AppLayoutBehavior],

  properties: {
    /**
     * If true, the header will automatically collapse when scrolling down.
     * That is, the `sticky` element remains visible when the header is fully
     *condensed whereas the rest of the elements will collapse below `sticky`
     *element.
     *
     * By default, the `sticky` element is the first toolbar in the light DOM:
     *
     *```html
     * <app-header condenses>
     *   <app-toolbar>This toolbar remains on top</app-toolbar>
     *   <app-toolbar></app-toolbar>
     *   <app-toolbar></app-toolbar>
     * </app-header>
     * ```
     *
     * Additionally, you can specify which toolbar or element remains visible in
     *condensed mode by adding the `sticky` attribute to that element. For
     *example: if we want the last toolbar to remain visible, we can add the
     *`sticky` attribute to it.
     *
     *```html
     * <app-header condenses>
     *   <app-toolbar></app-toolbar>
     *   <app-toolbar></app-toolbar>
     *   <app-toolbar sticky>This toolbar remains on top</app-toolbar>
     * </app-header>
     * ```
     *
     * Note the `sticky` element must be a direct child of `app-header`.
     */
    condenses: {type: Boolean, value: false},

    /**
     * Mantains the header fixed at the top so it never moves away.
     */
    fixed: {type: Boolean, value: false},

    /**
     * Slides back the header when scrolling back up.
     */
    reveals: {type: Boolean, value: false},

    /**
     * Displays a shadow below the header.
     */
    shadow: {type: Boolean, reflectToAttribute: true, value: false}
  },

  observers: ['_configChanged(isAttached, condenses, fixed)'],

  /**
   * A cached offsetHeight of the current element.
   *
   * @type {number}
   */
  _height: 0,

  /**
   * The distance in pixels the header will be translated to when scrolling.
   *
   * @type {number}
   */
  _dHeight: 0,

  /**
   * The offsetTop of `_stickyEl`
   *
   * @type {number}
   */
  _stickyElTop: 0,

  /**
   * A reference to the element that remains visible when the header condenses.
   *
   * @type {HTMLElement}
   */
  _stickyElRef: null,

  /**
   * The header's top value used for the `transformY`
   *
   * @type {number}
   */
  _top: 0,

  /**
   * The current scroll progress.
   *
   * @type {number}
   */
  _progress: 0,

  _wasScrollingDown: false,
  _initScrollTop: 0,
  _initTimestamp: 0,
  _lastTimestamp: 0,
  _lastScrollTop: 0,

  /**
   * The distance the header is allowed to move away.
   *
   * @type {number}
   */
  get _maxHeaderTop() {
    return this.fixed ? this._dHeight : this._height + 5;
  },

  /**
   * Returns a reference to the sticky element.
   *
   * @return {HTMLElement}?
   */
  get _stickyEl() {
    if (this._stickyElRef) {
      return this._stickyElRef;
    }
    var nodes = dom(this.$.slot).getDistributedNodes();
    // Get the element with the sticky attribute on it or the first element in
    // the light DOM.
    for (var i = 0, node; node = /** @type {!HTMLElement} */ (nodes[i]); i++) {
      if (node.nodeType === Node.ELEMENT_NODE) {
        if (node.hasAttribute('sticky')) {
          this._stickyElRef = node;
          break;
        } else if (!this._stickyElRef) {
          this._stickyElRef = node;
        }
      }
    }
    return this._stickyElRef;
  },

  _configChanged: function() {
    this.resetLayout();
    this._notifyLayoutChanged();
  },

  _updateLayoutStates: function() {
    if (this.offsetWidth === 0 && this.offsetHeight === 0) {
      return;
    }
    var scrollTop = this._clampedScrollTop;
    var firstSetup = this._height === 0 || scrollTop === 0;
    var currentDisabled = this.disabled;
    this._height = this.offsetHeight;
    this._stickyElRef = null;
    this.disabled = true;
    // prepare for measurement
    if (!firstSetup) {
      this._updateScrollState(0, true);
    }
    if (this._mayMove()) {
      this._dHeight =
          this._stickyEl ? this._height - this._stickyEl.offsetHeight : 0;
    } else {
      this._dHeight = 0;
    }
    this._stickyElTop = this._stickyEl ? this._stickyEl.offsetTop : 0;
    this._setUpEffect();
    if (firstSetup) {
      this._updateScrollState(scrollTop, true);
    } else {
      this._updateScrollState(this._lastScrollTop, true);
      this._layoutIfDirty();
    }
    // restore no transition
    this.disabled = currentDisabled;
  },

  /**
   * Updates the scroll state.
   *
   * @param {number} scrollTop
   * @param {boolean=} forceUpdate (default: false)
   */
  _updateScrollState: function(scrollTop, forceUpdate) {
    if (this._height === 0) {
      return;
    }
    var progress = 0;
    var top = 0;
    var lastTop = this._top;
    var lastScrollTop = this._lastScrollTop;
    var maxHeaderTop = this._maxHeaderTop;
    var dScrollTop = scrollTop - this._lastScrollTop;
    var absDScrollTop = Math.abs(dScrollTop);
    var isScrollingDown = scrollTop > this._lastScrollTop;
    var now = performance.now();

    if (this._mayMove()) {
      top = this._clamp(
          this.reveals ? lastTop + dScrollTop : scrollTop, 0, maxHeaderTop);
    }
    if (scrollTop >= this._dHeight) {
      top = this.condenses && !this.fixed ? Math.max(this._dHeight, top) : top;
      this.style.transitionDuration = '0ms';
    }
    if (this.reveals && !this.disabled && absDScrollTop < 100) {
      // set the initial scroll position
      if (now - this._initTimestamp > 300 ||
          this._wasScrollingDown !== isScrollingDown) {
        this._initScrollTop = scrollTop;
        this._initTimestamp = now;
      }
      if (scrollTop >= maxHeaderTop) {
        // check if the header is allowed to snap
        if (Math.abs(this._initScrollTop - scrollTop) > 30 ||
            absDScrollTop > 10) {
          if (isScrollingDown && scrollTop >= maxHeaderTop) {
            top = maxHeaderTop;
          } else if (!isScrollingDown && scrollTop >= this._dHeight) {
            top = this.condenses && !this.fixed ? this._dHeight : 0;
          }
          var scrollVelocity = dScrollTop / (now - this._lastTimestamp);
          this.style.transitionDuration =
              this._clamp((top - lastTop) / scrollVelocity, 0, 300) + 'ms';
        } else {
          top = this._top;
        }
      }
    }
    if (this._dHeight === 0) {
      progress = scrollTop > 0 ? 1 : 0;
    } else {
      progress = top / this._dHeight;
    }
    if (!forceUpdate) {
      this._lastScrollTop = scrollTop;
      this._top = top;
      this._wasScrollingDown = isScrollingDown;
      this._lastTimestamp = now;
    }
    if (forceUpdate || progress !== this._progress || lastTop !== top ||
        scrollTop === 0) {
      this._progress = progress;
      this._runEffects(progress, top);
      this._transformHeader(top);
    }
  },

  /**
   * Returns true if the current header is allowed to move as the user scrolls.
   *
   * @return {boolean}
   */
  _mayMove: function() {
    return this.condenses || !this.fixed;
  },

  /**
   * Returns true if the current header will condense based on the size of the
   * header and the `consenses` property.
   *
   * @return {boolean}
   */
  willCondense: function() {
    return this._dHeight > 0 && this.condenses;
  },

  /**
   * Returns true if the current element is on the screen.
   * That is, visible in the current viewport.
   *
   * @method isOnScreen
   * @return {boolean}
   */
  isOnScreen: function() {
    return this._height !== 0 && this._top < this._height;
  },

  /**
   * Returns true if there's content below the current element.
   *
   * @method isContentBelow
   * @return {boolean}
   */
  isContentBelow: function() {
    return this._top === 0 ? this._clampedScrollTop > 0 :
                             this._clampedScrollTop - this._maxHeaderTop >= 0;
  },

  /**
   * Transforms the header.
   *
   * @param {number} y
   */
  _transformHeader: function(y) {
    this.translate3d(0, (-y) + 'px', 0);
    if (this._stickyEl) {
      this.translate3d(
          0,
          this.condenses && y >= this._stickyElTop ?
              (Math.min(y, this._dHeight) - this._stickyElTop) + 'px' :
              0,
          0,
          this._stickyEl);
    }
  },

  _clamp: function(v, min, max) {
    return Math.min(max, Math.max(min, v));
  },

  _ensureBgContainers: function() {
    if (!this._bgContainer) {
      this._bgContainer = document.createElement('div');
      this._bgContainer.id = 'background';
      this._bgRear = document.createElement('div');
      this._bgRear.id = 'backgroundRearLayer';
      this._bgContainer.appendChild(this._bgRear);
      this._bgFront = document.createElement('div');
      this._bgFront.id = 'backgroundFrontLayer';
      this._bgContainer.appendChild(this._bgFront);
      dom(this.root).insertBefore(this._bgContainer, this.$.contentContainer);
    }
  },

  _getDOMRef: function(id) {
    switch (id) {
      case 'backgroundFrontLayer':
        this._ensureBgContainers();
        return this._bgFront;
      case 'backgroundRearLayer':
        this._ensureBgContainers();
        return this._bgRear;
      case 'background':
        this._ensureBgContainers();
        return this._bgContainer;
      case 'mainTitle':
        return dom(this).querySelector('[main-title]');
      case 'condensedTitle':
        return dom(this).querySelector('[condensed-title]');
    }
    return null;
  },

  /**
   * Returns an object containing the progress value of the scroll effects
   * and the top position of the header.
   *
   * @method getScrollState
   * @return {Object}
   */
  getScrollState: function() {
    return {progress: this._progress, top: this._top};
  }
});


================================================
FILE: app-header/demo/blend-background-1.html
================================================
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <title>app-header demo</title>

  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2.0.0/webcomponents-loader.js"></script>

  <script type="module">
    import '@polymer/iron-icons/iron-icons.js';
    import '@polymer/paper-icon-button/paper-icon-button.js';
    // Import effects before app-header.
    import '../../app-scroll-effects/app-scroll-effects.js';
    import '../../app-toolbar/app-toolbar.js';
    import '../../demo/sample-content.js';
    import '../app-header.js';
  </script>

  <custom-style>
    <style is="custom-style">

      body {
        margin: 0;
        font-family: arial;
        background-color: #eee;
      }

      app-header {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 212px;
        color: #fff;
        background-color: #3f51b5;
        /* https://bugs.chromium.org/p/chromium/issues/detail?id=637072 */
        --app-header-background-front-layer: {
          background-image: url(https://app-layout-assets.appspot.com/assets/bg1.jpg);
          background-position: left center;
        };
      }

      paper-icon-button {
        --paper-icon-button-ink-color: white;
      }

      app-toolbar.tall {
        height: 148px;
      }

      sample-content {
        padding-top: 212px;
      }

      [main-title] {
        font-weight: lighter;
        margin-left: 108px;
      }

      [condensed-title] {
        font-weight: lighter;
        margin-left: 30px;
        overflow: hidden;
        text-overflow: ellipsis;
      }

      [condensed-title] i {
        font-weight: 100;
        font-style: normal;
      }

      @media (max-width: 639px) {
        [main-title] {
          margin-left: 50px;
          font-size: 30px;
        }
        [condensed-title] {
          font-size: 15px;
        }
      }

    </style>
  </custom-style>
</head>
<body class="fullbleed" unresolved>

  <app-header condenses reveals effects="waterfall resize-title blend-background parallax-background">
    <app-toolbar>
      <paper-icon-button icon="menu"></paper-icon-button>
      <h4 condensed-title>What is material? &mdash; Environment</h4>
      <paper-icon-button icon="search"></paper-icon-button>
    </app-toolbar>
    <app-toolbar class="tall">
      <h1 main-title>What is material?</h1>
    </app-toolbar>
  </app-header>

  <sample-content size="100"></sample-content>

</body>
</html>


================================================
FILE: app-header/demo/blend-background-2.html
================================================
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <title>app-header demo</title>

  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2.0.0/webcomponents-loader.js"></script>

  <script type="module">
    import '@polymer/iron-icons/iron-icons.js';
    import '@polymer/paper-icon-button/paper-icon-button.js';
    // Import effects before app-header.
    import '../../app-scroll-effects/app-scroll-effects.js';
    import '../../app-toolbar/app-toolbar.js';
    import '../../demo/sample-content.js';
    import '../app-header.js';
  </script>

  <custom-style>
    <style is="custom-style">

      body {
        margin: 0;
        font-family: arial;
        background-color: #eee;
      }

      app-header {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 212px;
        color: #fff;
        background-color: #3f51b5;
        --app-header-background-front-layer: {
          background-image: url(https://app-layout-assets.appspot.com/assets/bg1.jpg);
          background-position: left center;
        };
        --app-header-background-rear-layer: {
          background-image: url(https://app-layout-assets.appspot.com/assets/bg2.jpg);
          background-position: left center;
        };
      }

      paper-icon-button {
        --paper-icon-button-ink-color: white;
      }

      app-toolbar.tall {
        height: 148px;
      }

      sample-content {
        padding-top: 212px;
      }

      [main-title] {
        font-weight: lighter;
        margin-left: 108px;
      }

      [condensed-title] {
        font-weight: lighter;
        margin-left: 30px;
        overflow: hidden;
        text-overflow: ellipsis;
      }

      [condensed-title] i {
        font-weight: 100;
        font-style: normal;
      }

      @media (max-width: 639px) {
        [main-title] {
          margin-left: 50px;
          font-size: 30px;
        }

        [condensed-title] {
          font-size: 15px;
        }
      }

    </style>
  </custom-style>
</head>
<body class="fullbleed" unresolved>

  <app-header condenses reveals effects="waterfall resize-title blend-background parallax-background">
    <app-toolbar>
      <paper-icon-button icon="menu"></paper-icon-button>
      <h4 condensed-title>What is material? &mdash; Environment</h4>
      <paper-icon-button icon="search"></paper-icon-button>
    </app-toolbar>
    <app-toolbar class="tall">
      <h1 main-title>What is material?</h1>
    </app-toolbar>
  </app-header>

  <sample-content size="100"></sample-content>

</body>
</html>


================================================
FILE: app-header/demo/blend-background-3.html
================================================
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <title>app-header demo</title>

  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@^2.0.0/webcomponents-loader.js"></script>

  <script type="module">
    import '@polymer/iron-icons/iron-icons.js';
    import '@polymer/paper-icon-button/paper-icon-button.js';
    // Import effects before app-header.
    import '../../app-scroll-effects/app-scroll-effects.js';
    import '../../app-toolbar/app-toolbar.js';
    import '../../demo/sample-content.js';
    import '../app-header.js';
  </script>

  <custom-style>
    <style is="custom-style">

      body {
        margin: 0;
        font-family: arial;
        background-color: #eee;
      }

      app-header {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 212px;
        color: #fff;
        --app-header-background-front-layer: {
          background-color: red;
        };
        --app-header-background-rear-layer: {
          background-color: blue;
        };
      }

      paper-icon-button {
        --paper-icon-button-ink-color: white;
      }

      app-toolbar.tall {
        height: 148px;
      }

      sample-content {
        padding-top: 212px;
      }

      [main-title] {
        font-weight: lighter;
        margin-left: 108px;
      }

      [condensed-title] {
        font-weight: lighter;
        margin-left: 30px;
        overflow: hidden;
        text-overflow: ellipsis;
      }

      [condensed-title] i {
        font-weight: 100;
        font-style: normal;
      }

      @media (max-width: 639px) {
        [main-title] {
          margin-left: 50px;
          font-size: 30px;
        }
        [condensed-title] {
          font-size: 15px;
        }
      }

    </style>
  </custom-style>
</head>
<body class="fullbleed" unresolved>

  <app-header condenses reveals effects="waterfall resize-tit
Download .txt
gitextract_x_yw3dwn/

├── .github/
│   ├── CODEOWNERS
│   └── ISSUE_TEMPLATE.md
├── .gitignore
├── .npmignore
├── .travis.yml
├── CONTRIBUTING.md
├── README.md
├── app-box/
│   ├── README.md
│   ├── app-box.js
│   └── demo/
│       ├── document-scroll.html
│       ├── index.html
│       └── scrolling-region.html
├── app-drawer/
│   ├── README.md
│   ├── app-drawer.js
│   ├── demo/
│   │   ├── index.html
│   │   ├── left-drawer.html
│   │   └── right-drawer.html
│   └── test/
│       ├── app-drawer.html
│       └── index.html
├── app-drawer-layout/
│   ├── README.md
│   ├── app-drawer-layout.js
│   ├── demo/
│   │   └── index.html
│   └── test/
│       ├── app-drawer-layout.html
│       └── index.html
├── app-grid/
│   ├── README.md
│   ├── app-grid-style.js
│   ├── demo/
│   │   ├── aspect-ratio.html
│   │   ├── flickr-grid-layout.html
│   │   ├── index.html
│   │   ├── md-grid-layout.html
│   │   └── simple-responsive-grid.html
│   └── test/
│       ├── app-grid-1.html
│       ├── app-grid-2.html
│       ├── app-grid-3.html
│       └── index.html
├── app-header/
│   ├── README.md
│   ├── app-header.js
│   ├── demo/
│   │   ├── blend-background-1.html
│   │   ├── blend-background-2.html
│   │   ├── blend-background-3.html
│   │   ├── contacts.html
│   │   ├── custom-sticky-element-1.html
│   │   ├── custom-sticky-element-2.html
│   │   ├── give.html
│   │   ├── index.html
│   │   ├── music.html
│   │   ├── no-effects.html
│   │   └── notes.html
│   └── test/
│       ├── app-header.html
│       └── index.html
├── app-header-layout/
│   ├── README.md
│   ├── app-header-layout.js
│   ├── demo/
│   │   ├── footer.html
│   │   ├── index.html
│   │   ├── music.html
│   │   ├── scrolling-region.html
│   │   └── simple.html
│   └── test/
│       ├── app-header-layout.html
│       └── index.html
├── app-layout-behavior/
│   └── app-layout-behavior.js
├── app-layout.js
├── app-scroll-effects/
│   ├── README.md
│   ├── app-scroll-effects-behavior.js
│   ├── app-scroll-effects.js
│   ├── effects/
│   │   ├── blend-background.js
│   │   ├── fade-background.js
│   │   ├── material.js
│   │   ├── parallax-background.js
│   │   ├── resize-snapped-title.js
│   │   ├── resize-title.js
│   │   └── waterfall.js
│   └── test/
│       ├── app-scroll-effects-behavior.html
│       ├── blend-background.html
│       ├── fade-background.html
│       ├── index.html
│       ├── parallax-background.html
│       ├── resize-snapped-title.html
│       ├── resize-title.html
│       ├── utils.js
│       ├── waterfall.html
│       └── x-container.js
├── app-toolbar/
│   ├── README.md
│   ├── app-toolbar.js
│   ├── demo/
│   │   └── index.html
│   └── test/
│       ├── app-toolbar.html
│       └── index.html
├── bower.json
├── demo/
│   ├── contacts.json
│   ├── demo1.html
│   ├── demo2.html
│   ├── demo3.html
│   ├── demo4.html
│   ├── demo5.html
│   ├── demo6.html
│   ├── demo7.html
│   ├── index.html
│   └── sample-content.js
├── formatconfig.json
├── gen-tsd.json
├── helpers/
│   ├── helpers.js
│   └── test/
│       ├── index.html
│       ├── register-effect.html
│       └── scroll.html
├── manifest.json
├── package.json
├── patterns/
│   ├── expand-card/
│   │   └── index.html
│   ├── md-responsive-toolbar/
│   │   └── index.html
│   └── transform-navigation/
│       ├── index.html
│       └── x-app.js
├── templates/
│   ├── getting-started/
│   │   ├── index.html
│   │   ├── package.json
│   │   └── x-app.js
│   ├── landing-page/
│   │   ├── index.html
│   │   ├── package.json
│   │   └── x-app.js
│   ├── pesto/
│   │   ├── data/
│   │   │   └── recipes.json
│   │   ├── index.html
│   │   ├── manifest.json
│   │   ├── package.json
│   │   └── src/
│   │       ├── app-icons.js
│   │       ├── recipe-app.js
│   │       ├── recipe-detail.js
│   │       └── recipe-list.js
│   ├── publishing/
│   │   ├── data/
│   │   │   └── articles.json
│   │   ├── index.html
│   │   ├── manifest.json
│   │   ├── package.json
│   │   └── src/
│   │       ├── app-icons.js
│   │       ├── article-detail.js
│   │       ├── article-headline.js
│   │       ├── blog-app.js
│   │       └── two-columns-grid.js
│   ├── shrine/
│   │   ├── data/
│   │   │   ├── featured.json
│   │   │   └── items.json
│   │   ├── index.html
│   │   ├── manifest.json
│   │   ├── package.json
│   │   └── src/
│   │       ├── shrine-app.js
│   │       ├── shrine-detail.js
│   │       ├── shrine-featured-item.js
│   │       ├── shrine-item.js
│   │       ├── shrine-list.js
│   │       └── shrine-simple-item.js
│   └── test-drive/
│       ├── index.html
│       ├── package.json
│       └── test-app.js
├── test/
│   └── index.html
└── wct.conf.json
Download .txt
SYMBOL INDEX (24 symbols across 12 files)

FILE: app-drawer-layout/app-drawer-layout.js
  method drawer (line 227) | get drawer() {

FILE: app-header-layout/app-header-layout.js
  method header (line 169) | get header() {

FILE: app-header/app-header.js
  method _maxHeaderTop (line 436) | get _maxHeaderTop() {
  method _stickyEl (line 445) | get _stickyEl() {

FILE: app-scroll-effects/app-scroll-effects-behavior.js
  method _clampedScrollTop (line 226) | get _clampedScrollTop() {

FILE: app-scroll-effects/effects/blend-background.js
  class BlendBackground (line 48) | class BlendBackground {
    method constructor (line 49) | constructor() {

FILE: app-scroll-effects/effects/fade-background.js
  class FadeBackground (line 57) | class FadeBackground {
    method constructor (line 58) | constructor() {

FILE: app-scroll-effects/effects/material.js
  class Material (line 36) | class Material {
    method constructor (line 37) | constructor() {

FILE: app-scroll-effects/effects/parallax-background.js
  class ParallaxBackground (line 66) | class ParallaxBackground {
    method constructor (line 67) | constructor() {

FILE: app-scroll-effects/effects/resize-snapped-title.js
  class ResizeSnappedTitle (line 70) | class ResizeSnappedTitle {
    method constructor (line 71) | constructor() {

FILE: app-scroll-effects/effects/resize-title.js
  function interpolate (line 15) | function interpolate(progress, points, fn, ctx) {
  class ResizeTitle (line 100) | class ResizeTitle {
    method constructor (line 101) | constructor() {

FILE: app-scroll-effects/effects/waterfall.js
  class Waterfall (line 30) | class Waterfall {
    method constructor (line 31) | constructor() {

FILE: helpers/helpers.js
  class ElementWithBackground (line 163) | class ElementWithBackground {
    method isContentBelow (line 165) | isContentBelow() {
    method isOnScreen (line 170) | isOnScreen() {
    method _getDOMRef (line 177) | _getDOMRef(title) {
Condensed preview — 148 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,570K chars).
[
  {
    "path": ".github/CODEOWNERS",
    "chars": 44,
    "preview": "* @keanulee @frankiefu\n/.travis.yml @azakus\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "chars": 718,
    "preview": "<!-- Instructions: https://github.com/PolymerElements/app-layout/CONTRIBUTING.md#filing-issues -->\n### Description\n<!-- "
  },
  {
    "path": ".gitignore",
    "chars": 57,
    "preview": "bower_components*\nbower-*.json\nnode_modules\n*.d.ts\n*.tgz\n"
  },
  {
    "path": ".npmignore",
    "chars": 77,
    "preview": "*.tgz\n.github\n.travis.yml\nformatconfig.json\ngen-tsd.json\ntest/\nwct.conf.json\n"
  },
  {
    "path": ".travis.yml",
    "chars": 2005,
    "preview": "language: node_js\nsudo: 'false'\ndist: trusty\nnode_js: node\naddons:\n  firefox: latest\n  chrome: stable\nbefore_script:\n  -"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 3481,
    "preview": "<!--\nThis file is autogenerated based on\nhttps://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.m"
  },
  {
    "path": "README.md",
    "chars": 7664,
    "preview": "[![Published on NPM](https://img.shields.io/npm/v/@polymer/app-layout.svg)](https://www.npmjs.com/package/@polymer/app-l"
  },
  {
    "path": "app-box/README.md",
    "chars": 2028,
    "preview": "## &lt;app-box&gt;\n\napp-box is a container element that can have scroll effects - visual effects based on\nscroll positio"
  },
  {
    "path": "app-box/app-box.js",
    "chars": 6588,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-box/demo/document-scroll.html",
    "chars": 6552,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-box/demo/index.html",
    "chars": 1369,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-box/demo/scrolling-region.html",
    "chars": 7125,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-drawer/README.md",
    "chars": 1498,
    "preview": "## &lt;app-drawer&gt;\n\n![app-drawer](http://app-layout-assets.appspot.com/assets/docs/app-drawer/drawer.gif)\n\napp-drawer"
  },
  {
    "path": "app-drawer/app-drawer.js",
    "chars": 18828,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-drawer/demo/index.html",
    "chars": 1377,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-drawer/demo/left-drawer.html",
    "chars": 2318,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-drawer/demo/right-drawer.html",
    "chars": 3240,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-drawer/test/app-drawer.html",
    "chars": 29905,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-drawer/test/index.html",
    "chars": 812,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-drawer-layout/README.md",
    "chars": 2862,
    "preview": "## &lt;app-drawer-layout&gt;\n\napp-drawer-layout is a wrapper element that positions an app-drawer and other content. Whe"
  },
  {
    "path": "app-drawer-layout/app-drawer-layout.js",
    "chars": 7853,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-drawer-layout/demo/index.html",
    "chars": 2040,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-drawer-layout/test/app-drawer-layout.html",
    "chars": 7459,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-drawer-layout/test/index.html",
    "chars": 842,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-grid/README.md",
    "chars": 3656,
    "preview": "## &lt;app-grid&gt;\n\napp-grid is a helper class useful for creating responsive, fluid grid layouts using custom properti"
  },
  {
    "path": "app-grid/app-grid-style.js",
    "chars": 6589,
    "preview": "/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-grid/demo/aspect-ratio.html",
    "chars": 2900,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-grid/demo/flickr-grid-layout.html",
    "chars": 6842,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-grid/demo/index.html",
    "chars": 1531,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-grid/demo/md-grid-layout.html",
    "chars": 4151,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-grid/demo/simple-responsive-grid.html",
    "chars": 3002,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-grid/test/app-grid-1.html",
    "chars": 4239,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-grid/test/app-grid-2.html",
    "chars": 4335,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-grid/test/app-grid-3.html",
    "chars": 4513,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-grid/test/index.html",
    "chars": 975,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-header/README.md",
    "chars": 6272,
    "preview": "## &lt;app-header&gt;\n\n![app-header](http://app-layout-assets.appspot.com/assets/docs/app-header/header.gif)\n\napp-header"
  },
  {
    "path": "app-header/app-header.js",
    "chars": 19677,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-header/demo/blend-background-1.html",
    "chars": 3223,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-header/demo/blend-background-2.html",
    "chars": 3337,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-header/demo/blend-background-3.html",
    "chars": 3106,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-header/demo/contacts.html",
    "chars": 3451,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-header/demo/custom-sticky-element-1.html",
    "chars": 2436,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-header/demo/custom-sticky-element-2.html",
    "chars": 2614,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-header/demo/give.html",
    "chars": 3437,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-header/demo/index.html",
    "chars": 1899,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-header/demo/music.html",
    "chars": 8931,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-header/demo/no-effects.html",
    "chars": 1911,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-header/demo/notes.html",
    "chars": 4284,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-header/test/app-header.html",
    "chars": 15229,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-header/test/index.html",
    "chars": 812,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-header-layout/README.md",
    "chars": 963,
    "preview": "## &lt;app-header-layout&gt;\n\napp-header-layout is a wrapper element that positions an app-header and other content. Thi"
  },
  {
    "path": "app-header-layout/app-header-layout.js",
    "chars": 6360,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-header-layout/demo/footer.html",
    "chars": 2551,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-header-layout/demo/index.html",
    "chars": 1470,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-header-layout/demo/music.html",
    "chars": 9254,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-header-layout/demo/scrolling-region.html",
    "chars": 2608,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-header-layout/demo/simple.html",
    "chars": 2595,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-header-layout/test/app-header-layout.html",
    "chars": 5037,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-header-layout/test/index.html",
    "chars": 842,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-layout-behavior/app-layout-behavior.js",
    "chars": 2649,
    "preview": "/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-layout.js",
    "chars": 827,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-scroll-effects/README.md",
    "chars": 2400,
    "preview": "# Scroll effects\n\n`Polymer.AppScrollEffectsBehavior` provides an interface that allows an element to use scrolls effects"
  },
  {
    "path": "app-scroll-effects/app-scroll-effects-behavior.js",
    "chars": 12025,
    "preview": "/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-scroll-effects/app-scroll-effects.js",
    "chars": 778,
    "preview": "/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-scroll-effects/effects/blend-background.js",
    "chars": 1857,
    "preview": "/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-scroll-effects/effects/fade-background.js",
    "chars": 2260,
    "preview": "/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-scroll-effects/effects/material.js",
    "chars": 1208,
    "preview": "/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-scroll-effects/effects/parallax-background.js",
    "chars": 2267,
    "preview": "/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-scroll-effects/effects/resize-snapped-title.js",
    "chars": 2363,
    "preview": "/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-scroll-effects/effects/resize-title.js",
    "chars": 3442,
    "preview": "/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-scroll-effects/effects/waterfall.js",
    "chars": 1089,
    "preview": "/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-scroll-effects/test/app-scroll-effects-behavior.html",
    "chars": 8114,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-scroll-effects/test/blend-background.html",
    "chars": 2730,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-scroll-effects/test/fade-background.html",
    "chars": 3085,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-scroll-effects/test/index.html",
    "chars": 1393,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-scroll-effects/test/parallax-background.html",
    "chars": 2647,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-scroll-effects/test/resize-snapped-title.html",
    "chars": 2774,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-scroll-effects/test/resize-title.html",
    "chars": 3262,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-scroll-effects/test/utils.js",
    "chars": 1324,
    "preview": "/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-scroll-effects/test/waterfall.html",
    "chars": 2494,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-scroll-effects/test/x-container.js",
    "chars": 2134,
    "preview": "/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-toolbar/README.md",
    "chars": 1328,
    "preview": "## &lt;app-toolbar&gt;\n\napp-toolbar is a horizontal toolbar containing items that can be used for\nlabel, navigation, sea"
  },
  {
    "path": "app-toolbar/app-toolbar.js",
    "chars": 3135,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "app-toolbar/demo/index.html",
    "chars": 2731,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "app-toolbar/test/app-toolbar.html",
    "chars": 2352,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "app-toolbar/test/index.html",
    "chars": 815,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "bower.json",
    "chars": 80,
    "preview": "{\n  \"name\": \"app-layout\",\n  \"license\": \"http://polymer.github.io/LICENSE.txt\"\n}\n"
  },
  {
    "path": "demo/contacts.json",
    "chars": 942578,
    "preview": "[\n  {\n    \"index\": 0,\n    \"name\": \"Liz Grimes\",\n    \"first\": \"Isabel\",\n    \"last\": \"Conrad\",\n    \"image\": \"https://s3.am"
  },
  {
    "path": "demo/demo1.html",
    "chars": 2626,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "demo/demo2.html",
    "chars": 2343,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "demo/demo3.html",
    "chars": 2474,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "demo/demo4.html",
    "chars": 5929,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "demo/demo5.html",
    "chars": 4542,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "demo/demo6.html",
    "chars": 4524,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "demo/demo7.html",
    "chars": 2382,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "demo/index.html",
    "chars": 1817,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "demo/sample-content.js",
    "chars": 3290,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "formatconfig.json",
    "chars": 49,
    "preview": "{\n  \"style\": {\n    \"ReflowComments\": false\n  }\n}\n"
  },
  {
    "path": "gen-tsd.json",
    "chars": 328,
    "preview": "{\n  \"excludeFiles\": [\n    \"index.html\",\n    \"**/test/**\",\n    \"**/demo/**\",\n    \"templates/**\",\n    \"patterns/**\"\n  ],\n "
  },
  {
    "path": "helpers/helpers.js",
    "chars": 5713,
    "preview": "/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "helpers/test/index.html",
    "chars": 898,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "helpers/test/register-effect.html",
    "chars": 1391,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "helpers/test/scroll.html",
    "chars": 3460,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "manifest.json",
    "chars": 15327,
    "preview": "{\n  \"files\": {\n    \"app-layout.html\": {\n      \"convertedUrl\": \"app-layout.js\",\n      \"exports\": {}\n    },\n    \"helpers/h"
  },
  {
    "path": "package.json",
    "chars": 1727,
    "preview": "{\n  \"description\": \"A set of layout elements for your app\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://githu"
  },
  {
    "path": "patterns/expand-card/index.html",
    "chars": 1666,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "patterns/md-responsive-toolbar/index.html",
    "chars": 1795,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2017 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "patterns/transform-navigation/index.html",
    "chars": 1089,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "patterns/transform-navigation/x-app.js",
    "chars": 3448,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/getting-started/index.html",
    "chars": 1058,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "templates/getting-started/package.json",
    "chars": 219,
    "preview": "{\n  \"private\": true,\n  \"dependencies\": {\n    \"@polymer/app-layout\": \"^3.0.0-pre.20\",\n    \"@polymer/iron-icons\": \"^3.0.0-"
  },
  {
    "path": "templates/getting-started/x-app.js",
    "chars": 2019,
    "preview": "/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/landing-page/index.html",
    "chars": 1052,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "templates/landing-page/package.json",
    "chars": 269,
    "preview": "{\n  \"private\": true,\n  \"dependencies\": {\n    \"@polymer/app-layout\": \"^3.0.0-pre.20\",\n    \"@polymer/iron-flex-layout\": \"^"
  },
  {
    "path": "templates/landing-page/x-app.js",
    "chars": 5206,
    "preview": "/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/pesto/data/recipes.json",
    "chars": 12756,
    "preview": "[\n  {\n\n    \"id\": \"1\",\n    \"name\": \"Pesto Bruchetta\",\n    \"author\": \"Peter Carlsson\",\n    \"imageUrl\": \"https://app-layout"
  },
  {
    "path": "templates/pesto/index.html",
    "chars": 1650,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "templates/pesto/manifest.json",
    "chars": 393,
    "preview": "{\n  \"short_name\": \"Pesto\",\n  \"name\": \"Pesto by Polymer\",\n  \"display\": \"standalone\",\n  \"icons\": [{\n    \"src\": \"https://ap"
  },
  {
    "path": "templates/pesto/package.json",
    "chars": 724,
    "preview": "{\n  \"private\": true,\n  \"dependencies\": {\n    \"@polymer/app-layout\": \"^3.0.0-pre.20\",\n    \"@polymer/app-route\": \"^3.0.0-p"
  },
  {
    "path": "templates/pesto/src/app-icons.js",
    "chars": 3096,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/pesto/src/recipe-app.js",
    "chars": 6626,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/pesto/src/recipe-detail.js",
    "chars": 5530,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/pesto/src/recipe-list.js",
    "chars": 4511,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/publishing/data/articles.json",
    "chars": 10822,
    "preview": "[\n  {\n    \"name\":\"art\",\n    \"title\":\"Art\",\n    \"items\":[\n      {\n        \"id\": \"1\",\n        \"title\":\"Tooling Up\",\n      "
  },
  {
    "path": "templates/publishing/index.html",
    "chars": 1476,
    "preview": "<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "templates/publishing/manifest.json",
    "chars": 655,
    "preview": "{\n  \"name\": \"Zuperkülblog\",\n  \"short_name\": \"Zuperkülblog\",\n  \"icons\": [{\n      \"src\": \"//app-layout-assets.appspot.com/"
  },
  {
    "path": "templates/publishing/package.json",
    "chars": 679,
    "preview": "{\n  \"private\": true,\n  \"dependencies\": {\n    \"@polymer/app-layout\": \"^3.0.0-pre.20\",\n    \"@polymer/app-route\": \"^3.0.0-p"
  },
  {
    "path": "templates/publishing/src/app-icons.js",
    "chars": 1246,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/publishing/src/article-detail.js",
    "chars": 2556,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/publishing/src/article-headline.js",
    "chars": 1694,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/publishing/src/blog-app.js",
    "chars": 8737,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/publishing/src/two-columns-grid.js",
    "chars": 3684,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/shrine/data/featured.json",
    "chars": 2909,
    "preview": "[\n  {\n    \"id\": 16,\n    \"title\": \"Green comfort chair\",\n    \"quote\": \"Leave the tunnel and the rain is fallin amazing th"
  },
  {
    "path": "templates/shrine/data/items.json",
    "chars": 11515,
    "preview": "[{\n  \"id\": 0,\n  \"title\": \"Vintage Bluetooth Radio\",\n  \"description\": \"Isn’t it cool when things look old, but their not."
  },
  {
    "path": "templates/shrine/index.html",
    "chars": 1610,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "templates/shrine/manifest.json",
    "chars": 631,
    "preview": "{\n  \"name\": \"Shrine\",\n  \"short_name\": \"Shrine by Polymer\",\n  \"icons\": [{\n      \"src\": \"//app-layout-assets.appspot.com/a"
  },
  {
    "path": "templates/shrine/package.json",
    "chars": 579,
    "preview": "{\n  \"private\": true,\n  \"dependencies\": {\n    \"@polymer/app-layout\": \"^3.0.0-pre.20\",\n    \"@polymer/app-route\": \"^3.0.0-p"
  },
  {
    "path": "templates/shrine/src/shrine-app.js",
    "chars": 10022,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/shrine/src/shrine-detail.js",
    "chars": 6796,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/shrine/src/shrine-featured-item.js",
    "chars": 4145,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/shrine/src/shrine-item.js",
    "chars": 2893,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/shrine/src/shrine-list.js",
    "chars": 2814,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/shrine/src/shrine-simple-item.js",
    "chars": 1784,
    "preview": "/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "templates/test-drive/index.html",
    "chars": 1108,
    "preview": "<!--\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the "
  },
  {
    "path": "templates/test-drive/package.json",
    "chars": 273,
    "preview": "{\n  \"private\": true,\n  \"dependencies\": {\n    \"@polymer/app-layout\": \"^3.0.0-pre.20\",\n    \"@polymer/iron-iconset-svg\": \"^"
  },
  {
    "path": "templates/test-drive/test-app.js",
    "chars": 5781,
    "preview": "/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the B"
  },
  {
    "path": "test/index.html",
    "chars": 1170,
    "preview": "<!doctype html>\n<!--\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be"
  },
  {
    "path": "wct.conf.json",
    "chars": 231,
    "preview": "{\n  \"plugins\": {\n    \"local\": {\n      \"browserOptions\": {\n        \"chrome\": [\n          \"no-sandbox\",\n          \"headles"
  }
]

About this extraction

This page contains the full source code of the PolymerLabs/app-layout GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 148 files (1.4 MB), approximately 384.5k tokens, and a symbol index with 24 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!