diff --git a/.drone.sec b/.drone.sec deleted file mode 100644 index 4c90224d5..000000000 --- a/.drone.sec +++ /dev/null @@ -1 +0,0 @@ -eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.j9veXnMfiC38KqZqVlEv-j3kQ4P8M9bmPYrCb3gkGhYNxJAs43Hzj30_rFiPJvW_JFjX2yGIVqGmxImJxDq9EXU0burdWRIcdKywASKtO5UCigwaBx0q_bPcXiPYCvT21ADX9HcukA_e04XcKExPJUJTlOJhfAA747p8lqheBXQjcidZJ6nVc6xt8dLpqyhcRZIX6wbKOKX3p8K60BnlHzqZ2YnnTuqk9XblJRwKwSIuSlJWqSKhYwLpJmWf8mtB9n7_Rn2vU1W3nK4o1j_-o1R6skxraNmdw9sbk26UNBUb8UtTdwbaMt0LnE_CD1TNSHW7gy05bmKjmZxGEXMH_w.gHtDLk7eq3RvXES7.f0peFsiIVOy7XTiYxakjJzPS_3U0rMesmc3PEjXbfz_ywNiGrSpbvA7lvnIgY6VgWNZyXZUmVjj34_FuwRCi6O6dqtRyYVy2-q5cJIVFWvpOtUdlQGcOfSL-TiyJS49AsbiXk0RI6-pi2hA9sfwOX8fbZK4YC1rcvEHc5xUd5WJhn0zRjyV0SowVGktVwjKXznHyxV5FCFqBHq83R7uOQIEm-nmMdlooUqQrWc3sKpwJv7fhyHfu5N5L33SIdrPHVhnc4HfCeuSESTvxV2XwZjzFxcj9Kr4BlnZyG7Dbn8WBaYEDkJ0HTie2h4MbeOewY9_SQ4YfYVhWwFzZTDCmD-Ou09G5siDA_0SyHZpS1JZI0NkKibdIkLEHB_BdpSSyFDTOFRbjf_2beXNOtD8-DCis0ZYR5h3coz6sOZaSde2Sh3IcCOLolaQvt5pZN4JB1JJspLjv6iD5R2VYGTJy8fYfH7juZi6NVq4316eQepoFgtjsjusTkTKcczkSPYxvgnjegdmNQvqKWMgZKcgV9IWdtDZCgBr3W3_K92G0xRkyMnmHevEfC0WzSTYE5SY4spDix2WF-of1SF_jrIjC3LSQlwXCHdeF8yoouWlVDqFvVB5jLlSjJG0yWi7GYgxwnweIhmduO4ojZbHUIX3UGDMYbxZkXiEegLXMCqQtTrkvutZsZFSnmULHCS1J-JF6JVgifnPOn6TSOh7h-FG-x72AtgX6W7_gmZRl_wPFTzDFtkvgsB5g6aB8jycAQfQhFSSOtNfMl4mfwqcT2dAf_orKohwGCwMfnamLOIfzfNcRXE1xHyClHTiTiDK3Nf7MMnvcxxmGq_yVjF9mSffBJMP25hMSMlg3DYqdbT88JVHXHRgE3vrl15BocpHU3E1ZEKF4VEV4bGE2MKkOOW0dBzKqFwAbFBivoD3vZEzKXpwTwg88cLwLPLnqsWyoNRKpWNFhnu6X_BmcCXNI7JP_gQxyRTe7ZHOCOW_oL93cDgA0nGWQG05pI1H87SYhZhByiaUlAwtMbo-wE_aMzwiLYjBdJ4QiOUk4Kzf4-P5QaWBEPEAHwbfuRjtSCPd9LYJzqGdCdabsv3mtgVPNdzDOTnI7mvdD5oLd9XEHV9vNuOI-xjpF4Tz130G_6V0Cvq3-oR2hCHE8ZugX9Qja7KqIwSM6sxV4JAlGv2etfJRqV01mdD2W_CnkSfWBoz6soTHTqrg1y1380DS42WvXNFAUhNj92J6n-W0MNfXWcsaFGRBwjTExerTK3HveEt3iB-gmx3DcPhXyM1FM39DbyQiHbwFV2Aw7cuQP6uYc5qgYPVdxrfrasvwPZweubHtrttZJNbbbBY2wJTbXrUX0X08U4NpDcTf80s43XNjO_P19to-tIz8WBr2BHY_-jA-ea7zIVlZGdn624tUcubHWxUsoci0jBlPX8jWQnhx4MI5vDDVKRSOotJdD7t4BD47SNJLi2H31wGOgi8MS9JTw9g8-ZXdN-WfCN4nNi5NTMhq3FbRBXIV1BRbVhvcWrpp2g4eAsDlv7ycUjcGFfExaePB1RhiqQwj-RSmXz_GbWPwOoUw3lacjoKEcf8787l6NWh9dYRXiaSzM1rNvHg4vNb2LPTkUGsPhtxUj-xO-S4ENw2FBQnPkgN0IHRKPPcagdUEWWGMEMBLFjZrTF1ihMEFLga6MnTMOoFPR7y9NjpBIHBm324aEV0IUfi2o4ML-IitbFhWSUeeyIKqBOW3ZFZMuNOQYlt0obuZYhS77vT-VIgNdr2OiGj8FSNkN6uqi-IxvjRqKBAnQaBuRgfPtMAg2AoQ4FiiALEZIEg3V9SunpmNH8WEonz3Pka-_en9dcRXffzrlVKyUAPs45Tg5330JN6OaI6jOtTSLZN0KEY2p77sTPxuPQsG5TuIX9g6mZiRZVFlzlJsi2VfhFdmR0GtZV8cwp0Sc9PVtUHkuAfZlHGaWTBGB4P7ttJlHu9iU3pEXMWrOABgf5JWan4uBwPDw_faU7vKvZ6s6PEIG7uM13RPTAnmQKCcn5xC_8Rao_GIseAQG-BKDZAsAKnJFXuUmwrwoaMOxyF6S8pw-1IFh-vr0FMne3DIl-K9T5NEjD7nF-HAXciVi4dGd1ayTymq6adh68nkNis4-ANauctQlFzGNp0_Na-3BaiDJi_DGhjXFY-w5ckLLlTuEaYVc99y8DQcTuOjfhTKo1AKcprKBe_FNmpwxjA6Pb4PO8NLOG7jksyPueFRgjfnITeTzRXuW-L4v63jR20It9wiW4T26NsYGo0sdz7C7DW3apD6Tv2wcqdr7_rbNhzqjDKBlFG-cuGBWkTaDdb5QiMxAqpBp71xt7IE4zh9vpUEUo0jL7uliKzPKch8nttjcNbhXBVkplWRwCzOLK9Kwbb1WPgNIt5Z_-qigFeHWo6p1r9ZZnO2uIhX5fXQ7ufja3NN2D5tJ1DjnHT0J-ubJd-pq2U5tOOuDRKuDlVXxa_0vWDLGEp5pOp0BQa6vUj9f8X8g5N9iajAappzI_zLG4HzEG8P0t4xDO6pO8NWSwcHgXl5VVIsXf7dVhlquH_ewkOUVNRXBk7GrhGxYjygX_yscHo57fY4O0ePexeuXoZxQw-dob99C4ZrnQQ0RhSU0n7WpByssezhB04pYbAzx_A998b5MP2gxTe4kVARgv5AgInzwx4KlrgCLpXt7bq3ZpDvk2SHSNVbGpkNFVNj3frYfo7NVxET9EAJ7VvoVeuyb7PBL-ix4cdbHkbEjp14PvvZEzJxz6ad7RflXkrd2PMJEiJ6ay8wYPFEPjO8v31cEwp9d8TOhsDfQ0O2nTGmcK_BG9ZFjIvZpIyYlrgSdcXOncL4i7LCDOmMlJdwEvAm4HMhnuMUwdLzty_V0iXqPyJR7gSpyhEgV0e7XEieUsPTNDcZ6yw14zQW6m7rjqg8XFXPw9JCTbqUIGgDAHDrSLGaknemFzlek6nq_KrTAhxlFFyopNNHMgMkjbqgw8kyFo-YVZ5dkvwgX8ux0pxW8MgBVTI4wz3vonPX-ilBKAOdrujRd6282Nih0u9ri6UjFSqikoUN_hu_K6O7gQdATrUNKEjYJc_sMKegaOk1jraogA8_YG8t-oWu8YEjzTjkehdPkhiqrCLZUDHsq3mFu0yqT4AyRjb-4S53Zfs6DqtQv8THl-iimvCV1GFTquN0fBnQRjdJh.YLmdpxyEz-RjqU8lHkRGYg \ No newline at end of file diff --git a/.drone.yml b/.drone.yml deleted file mode 100644 index 45000d06c..000000000 --- a/.drone.yml +++ /dev/null @@ -1,50 +0,0 @@ -# Note: if you modify this file, don't forget to update -# checksum in .drone.sec with: -# drone secure --repo google/material-design-lite --checksum -clone: - depth: 1 -cache: - mount: - - node_modules -matrix: - NODE_VERSION: - - 4 - - 5 -build: - image: crhym3/ci:node$$NODE_VERSION-go15 - environment: - - CHROME=https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb - - WEBDRIVER=http://chromedriver.storage.googleapis.com/2.16/chromedriver_linux64.zip - - DISPLAY=:99 - commands: - - npm update -qq - # build and unit test - - gulp all - - gulp mocha:closure - # additional browser tests - # do this after the build and unit tests to fail fast - - Xvfb $DISPLAY & - - curl -sSLo chrome.deb $CHROME && dpkg -i chrome.deb - - curl -sSLo driver.zip $WEBDRIVER && unzip -q driver.zip -d /usr/bin - - node test/memory/test.js -publish: - # see http://addons.drone.io/google_cloud_storage/ for details - gcs: - when: - repo: google/material-design-lite - branch: master - event: push - matrix: - NODE_VERSION: 5 - auth_key: > - $$SERVICE_ACCOUNT_KEY - source: dist - target: mdl-staging - cache_control: public,max-age=0 - acl: - - allUsers:READER - gzip: - - html - - css - - js - - svg diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..cf7098890 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +**/node_modules diff --git a/.eslintrc.yaml b/.eslintrc.yaml new file mode 100644 index 000000000..a84ba764d --- /dev/null +++ b/.eslintrc.yaml @@ -0,0 +1,44 @@ +extends: google +globals: + goog: false +env: + browser: true +plugins: + - tape +rules: + max-len: [error, 120] + no-new: warn + quotes: [error, single, {"avoidEscape": true}] + no-var: error + curly: error + no-floating-decimal: error + no-unused-vars: error + # Disabling jsdoc rules for the time being, but should be discussed as to whether or not this is + # something we should add in. For closure compatibility, we can investigate using something like + # https://github.com/angular/tsickle with .dts files. + require-jsdoc: off + valid-jsdoc: off + prefer-const: error + + # tape rules + # see: https://github.com/atabel/eslint-plugin-tape/blob/master/index.js + tape/assertion-message: + - off + - always + tape/max-asserts: + - off + - 5 + tape/no-identical-title: error + tape/no-ignored-test-files: error + tape/no-only-test: error + tape/no-skip-assert: error + tape/no-skip-test: error + tape/no-statement-after-end: error + tape/no-unknown-modifiers: error + tape/test-ended: error + tape/test-title: + - error + - if-multiple + tape/use-t-well: error + tape/use-t: error + tape/use-test: error diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 176a458f9..000000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* text=auto diff --git a/.gitignore b/.gitignore index c4684424d..abd977c32 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,6 @@ node_modules -.tmp -gulp-cache .DS_Store -docs/out -.publish -/dist -.drone.sec.yml +/build +/coverage +packages/*/dist +*.log diff --git a/.jscsrc b/.jscsrc deleted file mode 100644 index ca195c19f..000000000 --- a/.jscsrc +++ /dev/null @@ -1,25 +0,0 @@ -{ - "preset": "google", - "esnext": true, - "disallowSpacesInAnonymousFunctionExpression": null, - "validateLineBreaks": "LF", - "validateIndentation": 2, - "excludeFiles": ["node_modules/**"], - "maximumLineLength": 130, - "validateQuoteMarks": "'", - "requireDotNotation": false, - "requireCamelCaseOrUpperCaseIdentifiers": null, - "additionalRules": ["./utils/jscs-rules/*.js", "../utils/jscs-rules/*.js"], - "closureCamelCase": true, - "jsDoc": { - "checkAnnotations": { - "preset": "closurecompiler", - "extra": { - "type": true, - "suppress": true - } - }, - "checkTypes": "strictNativeCase", - "enforceExistence": "exceptExports" - } -} diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 861686a06..000000000 --- a/.jshintrc +++ /dev/null @@ -1,18 +0,0 @@ -{ - "node": true, - "browser": true, - "esnext": true, - "bitwise": true, - "curly": true, - "eqeqeq": true, - "immed": true, - "newcap": true, - "noarg": true, - "undef": true, - "unused": "vars", - "strict": true, - "sub": true, - "globals": { - "componentHandler": true - } -} diff --git a/.stylelintrc.yaml b/.stylelintrc.yaml new file mode 100644 index 000000000..e80ef32cc --- /dev/null +++ b/.stylelintrc.yaml @@ -0,0 +1,268 @@ +extends: stylelint-config-standard +ignoreFiles: + - node_modules/**/* + - packages/**/node_modules/**/* + - build/**/* +plugins: + - stylelint-selector-bem-pattern + - stylelint-scss +rules: + # Follow best practices + font-family-name-quotes: always-where-recommended + # http://stackoverflow.com/questions/2168855/is-quoting-the-value-of-url-really-necessary + function-url-quotes: never + # https://www.w3.org/TR/selectors/#attribute-selectors + # http://stackoverflow.com/q/3851091 + selector-attribute-quotes: always + # Double-quotes are our convention throughout our codebase within (S)CSS. They also reflect how + # attribute strings are normally quoted within the DOM. + string-quotes: double + # https://github.com/sasstools/sass-lint/blob/develop/lib/config/property-sort-orders/smacss.yml + declaration-block-properties-order: + - display + - position + - top + - right + - bottom + - left + + - flex + - flex-basis + - flex-direction + - flex-flow + - flex-grow + - flex-shrink + - flex-wrap + - align-content + - align-items + - align-self + - justify-content + - order + + - width + - min-width + - max-width + + - height + - min-height + - max-height + + - margin + - margin-top + - margin-right + - margin-bottom + - margin-left + + - padding + - padding-top + - padding-right + - padding-bottom + - padding-left + + - float + - clear + + - columns + - column-gap + - column-fill + - column-rule + - column-span + - column-count + - column-width + + - transform + - transform-box + - transform-origin + - transform-style + + - transition + - transition-delay + - transition-duration + - transition-property + - transition-timing-function + + # Border + + - border + - border-top + - border-right + - border-bottom + - border-left + - border-width + - border-top-width + - border-right-width + - border-bottom-width + - border-left-width + + - border-style + - border-top-style + - border-right-style + - border-bottom-style + - border-left-style + + - border-radius + - border-top-left-radius + - border-top-right-radius + - border-bottom-left-radius + - border-bottom-right-radius + + - border-color + - border-top-color + - border-right-color + - border-bottom-color + - border-left-color + + - outline + - outline-color + - outline-offset + - outline-style + - outline-width + + # Background + + - background + - background-attachment + - background-clip + - background-color + - background-image + - background-repeat + - background-position + - background-size + + # Text + + - color + + - font + - font-family + - font-size + - font-smoothing + - font-style + - font-variant + - font-weight + + - letter-spacing + - line-height + - list-style + + - text-align + - text-decoration + - text-indent + - text-overflow + - text-rendering + - text-shadow + - text-transform + - text-wrap + + - white-space + - word-spacing + + # Other + + - border-collapse + - border-spacing + - box-shadow + - caption-side + - content + - cursor + - empty-cells + - opacity + - overflow + - quotes + - speak + - table-layout + - vertical-align + - visibility + - z-index + declaration-property-unit-whitelist: + font-size: + - "rem" + - "px" + # The following prefix rules are enabled since we use autoprefixer + at-rule-no-vendor-prefix: true + media-feature-name-no-vendor-prefix: true + selector-no-vendor-prefix: true + value-no-vendor-prefix: true + # Usually if you're nesting past 3 levels deep there's a problem + max-nesting-depth: 3 + # Because we adhere to BEM we can limit the amount of necessary compound selectors. Most should + # just be 1 level selector. However, modifiers can introduce an additional compound selector. + # Futhermore, generic qualifying selectors (e.g. `[dir="rtl"]`) can introduce yet another level. + selector-max-compound-selectors: 4 + # For specificity: disallow IDs (0). Allow for complex combinations of classes, pseudo-classes, + # attribute modifiers based on selector-max-compound-selectors, plus an addition for + # pseudo-classes (4). Allow for pseudo-elements (1). + selector-max-specificity: 0,4,1 + # Disallow "@extend" in scss. + # http://csswizardry.com/2016/02/mixins-better-for-performance/ + # http://vanseodesign.com/css/sass-mixin-or-extend/ + # Besides performance, @extend actually *changes* the selector precedence by creating a compound + # selector, which can lead to ambiguous results. + at-rule-blacklist: + - extend + # Extremely useful for typos, and anything emergent can be ignored by this rule + property-no-unknown: true + # There is no reason that a specific ID would be needed for UI components + selector-no-id: true + # Qualifying types are not needed when using a naming system like BEM + selector-no-qualifying-type: true + # In general, we should *never* be modifying elements within our components, since we can't + # predict the use cases in which users would add a certain type of element into a component. + # The only hard exception to this are `fieldset` elements, which can be disabled and in that case + # we want our UI components within that fieldset to be disabled as well. + # Other exceptions to this may be in packages/material-design-lite, in which case this rule could + # be disabled for that file, with an explanation. + selector-no-type: + - true + - ignoreTypes: + - fieldset + # Styles for components should never need the universal selector. + selector-no-universal: true + # Ensure any defined symbols are prefixed with "mdl-" + # TODO: Remove "md-" pattern. + custom-media-pattern: ^mdl?-.+ + custom-property-pattern: ^mdl?-.+ + selector-class-pattern: + - ^mdl?-.+ + - resolveNestedSelectors: true + selector-id-pattern: ^mdl?-.+ + # Names are more semantic than numbers + font-weight-notation: named-where-possible + # :root is an important enough selector that it always stands on it's own. Also, there is no + # reason to make root a compound selector (?) + selector-root-no-composition: true + # http://www.paulirish.com/2010/the-protocol-relative-url/ + function-url-no-scheme-relative: true + # TODO: and FIXME: warnings are super useful because they remind us that we should address these + # within our codebase + comment-word-blacklist: + - + - /^TODO:/ + - /^FIXME:/ + - severity: warning + # Part of google's style guide + number-leading-zero: never + + # We use Harry Roberts' BEM dialect as our preferred way to format classes. + # See: http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/ + # See: https://github.com/postcss/postcss-bem-linter/blob/c59db3f/lib/preset-patterns.js#L39 + plugin/selector-bem-pattern: + componentName: ^[a-z]+(?:-[a-z]+)*$ + # -__*--*[]* + componentSelectors: ^\.mdl?-{componentName}(?:__[a-z]+(?:-[a-z]+)*)*(?:--[a-z]+(?:-[a-z]+)*)*(?:\[.+\])*$ + ignoreSelectors: + - ^fieldset + - ^\[aria\-disabled=(?:.+)\] + + # SCSS naming patterns, just like our CSS conventions above. + # (note for $-vars we use a leading underscore for "private" variables) + scss/dollar-variable-pattern: ^_?mdl?-.+ + scss/at-function-pattern: ^mdl?-.+ + scss/at-mixin-pattern: ^mdl?-.+ + # Prevents unneeded nesting selectors + scss/selector-no-redundant-nesting-selector: true + # Since leading underscores are not needed, they can be omitted + scss/at-import-no-partial-leading-underscore: true + # Since mixins are explicit (`@include`) and parens are unnecessary for argumentless mixins, they + # can be omitted. + scss/at-mixin-no-argumentless-call-parentheses: true diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..dcfcc1819 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,22 @@ +# Force TravisCI to run outside of a container +sudo: required +language: node_js +node_js: + - node # stable + - '4' # LTS +branches: + only: + - master +env: + global: + - SAUCE_USERNAME=material-sauce + - SAUCE_ACCESS_KEY=5e3395b4-2026-48a4-82a0-35bc756a0d2b +addons: + sauce_connect: true +notifications: + webhooks: + urls: + - https://webhooks.gitter.im/e/8bceea29a64b5fb7f608 + on_success: change + on_failure: always + on_start: never diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1b57ef6f1..91b05a9a4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,17 +1,24 @@ - # Contributing to Material Design Lite We'd love for you to contribute to our source code and to make Material Design Lite even better than it is today! Here are the guidelines we'd like you to follow: - - [Code of Conduct](#coc) - - [Question or Problem?](#question) - - [Issues and Bugs](#issue) - - [Feature Requests](#feature) - - [Submission Guidelines](#submit) - - [Coding Rules](#rules) - - [Signing the CLA](#cla) -## Code of Conduct +- [Code of Conduct](#code-of-conduct) +- [Development Process](#development-process) + - [Setting up your development environment](#setting-up-your-development-environment) + - [Building Components](#building-components) + - [Running the development server](#running-the-development-server) + - [Building MDL](#building-mdl) + - [Linting / Testing / Coverage Enforcement](#linting--testing--coverage-enforcement) + - [Running Tests across browsers](#running-tests-across-browsers) + - [Coding Style](#coding-style) + - [Signing the CLA](#signing-the-cla) + - [Submitting Pull Requests](#submitting-pull-requests) +- [Questions / Problems](#questions--problems) +- [Issues / Bugs](#issues--bugs) +- ["What's the core team up to?"](#whats-the-core-team-up-to) + +## Code of Conduct As contributors and maintainers of the Material Design Lite project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities. @@ -21,213 +28,146 @@ We promise to extend courtesy and respect to everyone involved in this project r If any member of the community violates this code of conduct, the maintainers of the Material Design Lite project may take action, removing issues, comments, and PRs or blocking accounts as deemed appropriate. -If you are subject to or witness unacceptable behavior, or have any other concerns, please drop us a line at addyo@google.com. +If you are subject to or witness unacceptable behavior, or have any other concerns, please drop us a line at sgomes@google.com. -## Got a Question or Problem? +## Development Process -If you have questions about how to use Material Design Lite, please direct these to [StackOverflow][stackoverflow] and use the `material-design-lite` tag. We are also available on GitHub issues. +> NOTE: As we are still in **pre-alpha** for v2, this section may be incomplete, in flux, and/or lacking some info. We hope to stabilize it by the time we reach alpha. If you have additional follow-up questions about our development process or find something confusing / ambiguous, reach out to us on [gitter](https://gitter.im/google/material-design-lite) and we may be able to help. -If you feel that we're missing an important bit of documentation, feel free to -file an issue so we can help. Here's an example to get you started: +We strive to make developing Material Design Lite as frictionless as possible, both for ourselves and for our community. This section should get you up and running working on the Material Design Lite codebase. Before beginning development, you may want to read through our brief [v2 developer guide](https://github.com/google/material-design-lite/blob/master/docs/DEVELOPER.md) to get a better understanding of our overall architecture. -``` -Component (if any): +### Setting up your development environment -What are you trying to do or find out more about? - -Where have you looked? - -Where did you expect to find this information? -``` +You'll need a recent version of [nodejs](https://nodejs.org/en/) to work on MDL. We [test our builds](https://travis-ci.org/google/material-design-lite) using both the latest and LTS node versions, so use of one of those is recommended. You can use [nvm](https://github.com/creationix/nvm) to easily install and manage different versions of node on your system. -Or, if you're looking for a new design template: +Once node is installed, simply clone our repo (or your fork of it) and run `npm install` ``` -Please provide a short summary of the template you’re looking for. - -What makes this template interesting or challenging from a design perspective? - -Please provide any URLs to good examples of this type of page that you may have come across. +git clone git@github.com:google/material-design-lite.git # or a path to your fork +cd material-design-lite && npm i ``` -## Found an Issue? -If you find a bug in the source code or a mistake in the documentation, you can help us by -submitting an issue to our [GitHub Repository][github]. Even better you can submit a Pull Request -with a fix. +### Building Components -See [below](#submit) for some guidelines. +Each component requires the following items in order to be complete: -## Want a Feature? -You can request a new feature by submitting an issue to our [GitHub Repository][github]. +- A **foundation class** which is integrated into actual components +- A **component class** using vanilla JS + SCSS +- A **README.md** in its subdir which contains developer documentation on the component, including usage. +- A **set of unit tests** within `test/unit/` with adequate coverage (which we enforce automatically). +- A **demo page** within `demos/` that shows example usage of the component. -Here is a template to get you started: +### Running the development server ``` -Is this a new component, or a missing feature in an existing one? -Component name: -Material Design spec URL for the component (if any): - -What does this component or feature allow you to do which isn’t possible at the moment? - -Please provide any URLs or screenshots of good examples of usage of this component or feature that you may have come across. +npm run dev +open http://localhost:8080 ``` -If you would like to implement a new feature then consider what kind of change it is: +`npm run dev` runs a [webpack-dev-server](https://webpack.github.io/docs/webpack-dev-server.html) instance that uses `demos/` as its content base. This should aid you in initial development of a component. It's served on port 8080. -* **Major Changes** that you wish to contribute to the project should be discussed first on our -[issue tracker][https://github.com/google/material-design-lite/issues] so that we can better coordinate our efforts, prevent -duplication of work, and help you to craft the change so that it is successfully accepted into the -project. -* **Small Changes** can be crafted and submitted to the [GitHub Repository][github] as a Pull Request. +### Building MDL -## Submission Guidelines - -### Submitting an Issue -Before you submit your issue search the archive, maybe your question was already answered. +``` +npm run build # Builds an unminified version of MDL within build/ +npm run build:min # Same as above, but enables minification +npm run dist # Cleans out build/ and runs both of the above commands sequentially +``` -If your issue appears to be a bug, and hasn't been reported, open a new issue. -Help us to maximize the effort we can spend fixing issues and adding new -features, by not reporting duplicate issues. Providing the following information will increase the -chances of your issue being dealt with quickly: +### Linting / Testing / Coverage Enforcement -* **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps -* **Motivation for or Use Case** - explain why this is a bug for you -* **Material Design Lite Version(s)** - is it a regression? -* **Browsers and Operating System** - is this a problem with all browsers or only IE9? -* **Reproduce the Error** - provide a live example (using JSBin) or a unambiguous set of steps. -* **Related Issues** - has a similar issue been reported before? -* **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be - causing the problem (line of code or commit) +``` +npm run lint:js # Lints javascript using eslint +npm run lint:css # Lints (S)CSS using stylelint +npm run lint # Runs both of the above commands in parallel -**If you get help, help others. Good karma rulez!** +npm run fix:js # Runs eslint with the --fix option enabled +npm run fix:css # Runs stylefmt, which helps fix simple stylelint errors +npm run fix # Runs both of the above commands in parallel -Here's a template to get you started: +npm run test:watch # Runs karma on Chrome, re-running when source files change +npm test # Lints all files, runs karma, and then runs coverage enforcement checks. ``` -MDL version: -Browser: -Browser version: -Operating system: -Operating system version: -URL, if applicable (you can use a [codepen as a starting point][http://codepen.io/pen/def?fork=xGWgXa]): -What steps will reproduce the problem: -1. -2. -3. +#### Running Tests across browsers -What is the expected result? +If you're making big changes or developing new components, we encourage you to be a good citizen and test your changes across browsers! A super simple way to do this is to use [sauce labs](https://saucelabs.com/), which is how we tests our collaborator PRs on TravisCI: -What happens instead of that? +1. [Sign up](https://saucelabs.com/beta/signup) for a sauce labs account (choose "Open Sauce" as your selected plan; [it's free](https://saucelabs.com/opensauce/)!) +2. [Download sauce connect](https://wiki.saucelabs.com/display/DOCS/Setting+Up+Sauce+Connect) for your OS and make sure that the `bin` folder in the downloaded zip is somewhere on your `$PATH`. +3. Navigate to your dashboard, scroll down to where it says "Access Key", and click "Show" +4. Enter your password when prompted +5. Copy your access key +6. Run `SAUCE_USERNAME= SAUCE_ACCESS_KEY= npm test` -Please provide any other information below, and attach a screenshot if possible. -``` +This will have karma run our unit tests across all browsers we support, and ensure your changes will not introduce regressions. -### Submitting a Pull Request -Before you submit your pull request consider the following guidelines: +Alternatively, you can run `npm run test:watch` and manually open browsers / use VMs / use emulators to test your changes. -* Search [GitHub](https://github.com/google/material-design-lite/pulls) for an open or closed Pull Request - that relates to your submission. You don't want to duplicate effort. -* Please sign our [Contributor License Agreement (CLA)](#cla) before sending pull - requests. We cannot accept code without this. -* Make your changes in a new git branch: +### Coding Style - ```shell - git checkout -b my-fix-branch master - ``` +Our entire coding style is enforced automatically through the use of linters. Check out our [eslint config](https://github.com/google/material-design-lite/blob/master/.eslintrc.yaml) (heavily influenced by [Google's Javascript Styleguide](js-style-guide)) as well as our [stylelint config](css-style-guide) (heavily annotated, with justifications for each rule) for further details. -* Create your patch, **including appropriate test cases**. -* Follow our [Coding Rules](#rules). -* Run the full Material Design Lite test suite (`gulp test`), - and ensure that all tests pass. -* Avoid checking in files that shouldn't be tracked (e.g `node_modules`, `gulp-cache`, `.tmp`, `.idea`). We recommend using a [global .gitignore](https://help.github.com/articles/ignoring-files/#create-a-global-gitignore) for this. -* Make sure **not** to include a recompiled version of the files found in `/css` and `/js` as part of your PR. We will generate these automatically. -* Commit your changes using a descriptive commit message. +### Signing the CLA - ```shell - git commit -a - ``` - Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files. - -* Build your changes locally to ensure all the tests pass: - - ```shell - gulp - ``` +Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code +changes to be accepted, the CLA must be signed. It's a quick process, we promise! -* Push your branch to GitHub: +* For individuals we have a [simple click-through form][individual-cla]. +* For corporations we'll need you to + [print, sign and one of scan+email, fax or mail the form][corporate-cla]. - ```shell - git push origin my-fix-branch - ``` -* In GitHub, send a pull request to `material-design-lite:master`. -* If we suggest changes then: - * Make the required updates. - * Re-run the Material Design Lite test suite to ensure tests are still passing. - * Rebase your branch and force push to your GitHub repository (this will update your Pull Request): +### Submitting Pull Requests - ```shell - git rebase master -i - git push origin my-fix-branch -f - ``` +We prefer small, incremental changes over large, sweeping ones, so please try to adhere to this when submitting PRs. Also, make sure you're following our commit message conventions (which are the same as [angular's](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit)); our `commit-msg` hook should automatically enforce this. We also support [commitizen](https://www.npmjs.com/package/commitizen), which you can +use to auto-format commit messages for you. -That's it! Thank you for your contribution! +If you've done some experimental work on your branch/fork and committed these via `git commit --no-verify`, you can rebase them into one correctly-formatted commit before submitting. -#### After your pull request is merged +Finally, it helps to make sure that your branch/fork is up to date with what's currently on master. You can ensure this by running `git pull --rebase origin master` on your branch. -After your pull request is merged, you can safely delete your branch and pull the changes -from the main (upstream) repository: +> **NOTE**: Please do _not merge_ master into your branch. _Always_ `pull --rebase` instead. This ensures a linear history by always putting the work you've done after the work that's already on master, regardless of the date in which those commits were made. -* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows: +To submit code for v2, open a PR for your fork/branch against `master` (_not_ `mdl-1.x`, which is currently our default branch). - ```shell - git push origin --delete my-fix-branch - ``` +Once you've submitted a PR, it'll be assigned to a core team member for review. If all CI tests pass and you get a `LGTM` from a reviewer, your code will be merged into master. -* Check out the master branch: +## Questions / Problems - ```shell - git checkout master -f - ``` +If you have questions about how to use Material Design Lite, please direct these to [StackOverflow][stackoverflow] and use the `material-design-lite` tag. -* Delete the local branch: +If you feel that we're missing an important bit of documentation, feel free to +file an issue so we can help. Here's an example to get you started: - ```shell - git branch -D my-fix-branch - ``` +``` +Component (if any): -* Update your master with the latest upstream version: +What are you trying to do or find out more about? - ```shell - git pull --ff upstream master - ``` +Where have you looked? -## Coding Rules +Where did you expect to find this information? +``` -We generally follow the [Google JavaScript style guide][js-style-guide] with a few minor exceptions documented in our [JSCS configuration][jscs-config]. +## Issues / Bugs -[JSCS](http://jscs.info) is a tool for linting code against a style guide and has plugins available for both editors and build tools. Should -you find that you would prefer to automatically format your code to match our style guide, you can use the JSCS [autoformatting][autoformatting] -feature. +If you find a bug in the source code or a mistake in the documentation, you can help us by +submitting an issue to our [GitHub Repository][github]. Even better, you can submit a Pull Request with a fix. Before submitting issues, please ensure that you've read through our [issue template](https://github.com/google/material-design-lite/blob/mdl-1.x/.github/ISSUE_TEMPLATE.md) to ensure a fast and helpful response from the maintainers. -## Signing the CLA +## "What's the core team up to?" -Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code -changes to be accepted, the CLA must be signed. It's a quick process, we promise! +The core team maintains a [public Pivotal Tracker](https://www.pivotaltracker.com/n/projects/1664011) (**tracker** for short) which details all the items we're working on within our current two-week [iteration](https://www.agilealliance.org/glossary/iteration/). This tracker mirrors in what's in our GH issues. It is used _purely for planning and prioritization purposes, **not** for discussions or community issue filing_. That being said, it's a great place to look at the overall state of our project as well as some the big ticket issues we're working on. -* For individuals we have a [simple click-through form][individual-cla]. -* For corporations we'll need you to - [print, sign and one of scan+email, fax or mail the form][corporate-cla]. +Each tracker story contains a link to its corresponding GH issue within its description. Each GH issue present in tracker is tagged with an `in-tracker` label. This will hopefully make it easy to move between the two if so desired. -*This guide was inspired by the [AngularJS contribution guidelines](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md).* [github]: https://github.com/google/material-design-lite [individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html [corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html -[js-style-guide]: http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml +[js-style-guide]: https://github.com/google/material-design-lite/blob/master/.eslintrc.yaml +[css-style-guide]: https://github.com/google/material-design-lite/blob/master/.stylelintrc.yaml [jsbin]: http://jsbin.com/ [stackoverflow]: http://stackoverflow.com/questions/tagged/material-design-lite [global-gitignore]: https://help.github.com/articles/ignoring-files/#create-a-global-gitignore -[autoformatting]: https://medium.com/@addyosmani/auto-formatting-javascript-code-style-fe0f98a923b8 -[jscs-config]: https://github.com/google/material-design-lite/blob/master/.jscsrc diff --git a/README.md b/README.md index 7d9555006..af89f1d56 100644 --- a/README.md +++ b/README.md @@ -1,173 +1,59 @@ -# Material Design Lite +# Material Design Lite V2 -[![GitHub version](https://badge.fury.io/gh/google%2Fmaterial-design-lite.svg)](https://badge.fury.io/gh/google%2Fmaterial-design-lite) -[![npm version](https://badge.fury.io/js/material-design-lite.svg)](https://badge.fury.io/js/material-design-lite) -[![Bower version](https://badge.fury.io/bo/material-design-lite.svg)](https://badge.fury.io/bo/material-design-lite) -[![Gitter version](https://img.shields.io/gitter/room/gitterHQ/gitter.svg)](https://gitter.im/google/material-design-lite) -[![Dependency Status](https://david-dm.org/google/material-design-lite.svg)](https://david-dm.org/google/material-design-lite) +> Project status: **pre-alpha** -> An implementation of [Material Design](http://www.google.com/design/spec/material-design/introduction.html) -components in vanilla CSS, JS, and HTML +**NOTE:** This is the experimental, pre-alpha branch for the next version of Material Design Lite. If you are looking for the current stable version, please see the [MDL 1.x branch](https://github.com/google/material-design-lite/tree/mdl-1.x) or visit the [MDL website](https://getmdl.io/). -Material Design Lite (MDL) lets you add a Material Design look and feel to your -static content websites. It doesn't rely on any JavaScript frameworks or -libraries. Optimized for cross-device use, gracefully degrades in older -browsers, and offers an experience that is accessible from the get-go. +## Overview -## Use MDL on your site? +MDL V2 is the next generation of the MDL component library, incorporating the latest in material design thinking and a new, flexible component architecture under the hood. -**This document is targeted at developers that will contribute to or compile -MDL. If you are looking to use MDL on your website or web app please head to -[getmdl.io](http://getmdl.io).** +The project has 3 high-level goals: -## Browser Support - -| IE9 | IE10 | IE11 | Chrome | Opera | Firefox | Safari | Chrome (Android) | Mobile Safari | -|-----|------|------|--------|-------|---------|--------|------------------|---------------| -| B | A | A | A | A | A | A | A | A | - -A-grade browsers are fully supported. B-grade browsers will gracefully degrade -to our CSS-only experience. - -## Getting Started - -### Download / Clone - -Clone the repo using Git: - -```bash -git clone https://github.com/google/material-design-lite.git -``` - -Alternatively you can [download](https://github.com/google/material-design-lite/archive/master.zip) -this repository. - -Windows users, if you have trouble compiling due to line endings then make sure -you configure git to checkout the repository with `lf` (unix) line endings. This -can be achieved by setting `core.eol`. - -``` -git config core.eol lf -git config core.autocrlf input -git rm --cached -r . -git reset --hard -``` - -> Remember, the master branch is considered unstable. Do not use this in -production. Use a tagged state of the repository, npm, or bower for stability! +- Production-ready components consumable in an a-la-carte fashion +- Best-in-class performance and adherence to the [material design guidelines](https://material.google.com) +- Seamless integration with other JS frameworks and libraries -### What's included +In order to achieve these goals, we are planning a complete re-architecture of the original MDL component library, alongside new tooling and infrastructure. -In the repo you'll find the following directories and files. +Please see our [developer's guide](docs/DEVELOPER.md) for more in-depth information. -| File/Folder | Provides | -|-----------------|------------------------------------------------| -| CONTRIBUTING.md | MDL contribution guidelines. | -| docs | Files for the documentation site. | -| gulpfile.js | gulp configuration for MDL. | -| LICENSE | Project license information. | -| package.json | npm package information. | -| README.md | Details for quickly understanding the project. | -| src | Source code for MDL components. | -| templates | Example templates. | -| test | Project test files. | -### Build +## Getting Started -To get started modifying the components or the docs, first install the necessary -dependencies, from the root of the project: +Setup the repo: -```bash -npm install && npm install -g gulp ``` - -> MDL requires NodeJS 0.12. - -Next, run the following one-liner to compile the components and the docs and -spawn a local instance of the documentation site: - -```bash -gulp all && gulp serve +git clone https://github.com/google/material-design-lite.git && cd material-design-lite +npm i ``` -Most changes made to files inside the `src` or the `docs` directory will cause -the page to reload. This page can also be loaded up on physical devices thanks -to BrowserSync. +Run the development server (served out of `demos/`): -To build a production version of the components, run: - -```bash -gulp ``` - -This will clean the `dist` folder and rebuild the assets for serving. - -### Templates - -The `templates/` subdirectory contains a few exemplary usages of MDL. Templates -have their own, quasi-separate gulp pipeline and can be compiled with -`gulp templates`. The templates use the vanilla MDL JS and -[themed](http://www.getmdl.io/customize/index.html) CSS files. Extraneous styles -are kept in a separate CSS file. Use `gulp serve` to take a look at the -templates: - -* [Blog Template](http://www.getmdl.io/templates/blog) -* [Dashboard Template](http://www.getmdl.io/templates/dashboard) -* [Text Heavy Webpage Template](http://www.getmdl.io/templates/text-only) -* [Stand Alone Article Template](http://www.getmdl.io/templates/article) -* [Android.com MDL Skin Template](http://www.getmdl.io/templates/android-dot-com) -* [Portfolio Template](http://www.getmdl.io/templates/portfolio) - -> Templates are not officially supported in IE9 and legacy browsers that do not -pass the minimum-requirements defined in our -[cutting-the-mustard test](https://github.com/google/material-design-lite/blob/87c48c22416c3e83850f7711365b2a43ba19c5ce/src/mdlComponentHandler.js#L336-L349). - -The templates refer to CDN hosted versions of the libraries. If you'd like to -test the templates against locally built MDL libraries you need to run the -`templates:localtestingoverride` gulp task before running `gulp serve`: - -```bash -gulp all && gulp templates:localtestingoverride && gulp serve +cd /path/to/material-design-lite +npm run dev +open http://localhost:8080 ``` -> Beware as any changes to the `templates` directory will automatically revert -the templates local testing overrides. In this case make sure you run the -`templates:localtestingoverride` gulp task again or modify the `watch()` -function in the gulp file. - -## Versioning - -For transparency into our release cycle and in striving to maintain backward -compatibility, Material Design Lite is maintained under -[the Semantic Versioning guidelines](http://semver.org/). Sometimes we screw up, -but we'll adhere to those rules whenever possible. +## Browser Support -## Feature requests +- Chrome +- Safari 8+ +- Firefox +- IE 11/Edge +- Opera -If you find MDL doesn't contain a particular component you think would be -useful, please check the issue tracker in case work has already started on it. -If not, you can request a [new component](https://github.com/Google/material-design-lite/issues/new?title=[Component%20Request]%20{Component}&body=Please%20include:%0A*%20Description%0A*%20Material%20Design%20Spec%20link%0A*%20Use%20Case%28s%29). -Please keep in mind that one of the goals of MDL is to adhere to the Material -Design specs and therefore some requests might not be within the scope of this -project. -## Want to contribute? +## Contributing -If you found a bug, have any questions or want to contribute. Follow our -[guidelines](https://github.com/google/material-design-lite/blob/master/CONTRIBUTING.md), -and help improve the Material Design Lite. For more information visit our -[wiki](https://github.com/google/material-design-lite/wiki). +We welcome early feedback from the community, though we recommend waiting until an alpha release before opening any pull requests. -## Do you include any features that a framework comes with? +See also our [contributing guidelines](CONTRIBUTING.md). -Material Design Lite is focused on delivering a vanilla CSS/JS/HTML library of -components. We are not a framework. If you are building a single-page app and -require features like two-way data-binding, templating, CSS scoping and so -forth, we recommend trying out the excellent -[Polymer](http://polymer-project.org) project. ## License -© Google, 2015. Licensed under an -[Apache-2](https://github.com/google/material-design-lite/blob/master/LICENSE) +© Google, 2016. Licensed under an +[Apache-2](LICENSE) license. diff --git a/bower.json b/bower.json deleted file mode 100644 index 3f205e172..000000000 --- a/bower.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "material-design-lite", - "version": "1.1.3", - "homepage": "https://github.com/google/material-design-lite", - "authors": [ - "Material Design Lite team" - ], - "description": "Material Design Components in CSS, JS and HTML", - "main": [ - "material.min.css", - "material.min.js" - ], - "keywords": [ - "material", - "design", - "styleguide", - "style", - "guide" - ], - "license": "Apache-2", - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "./lib/.bower_components", - "test", - "tests" - ] -} diff --git a/demos/button.html b/demos/button.html new file mode 100644 index 000000000..47ca98ce6 --- /dev/null +++ b/demos/button.html @@ -0,0 +1,98 @@ + + + + + + MDL Button Demo + + + + + +
+

MDL BUTTON

+
+
+ Buttons + + + + + + + + +
+ Div +
+
+
+ Disabled Buttons + + + + + + + + +
+ Div +
+
+
+
+ + + diff --git a/demos/card.html b/demos/card.html new file mode 100644 index 000000000..10d5e8b03 --- /dev/null +++ b/demos/card.html @@ -0,0 +1,170 @@ + + + + + + MDL Card Demo + + + + + + +
+

MDL Cards

+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor. +
+
+ +
+
+
+

Title

+

Subhead

+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor. +
+
+ + +
+
+ +
+
+
+

Title

+

Subhead

+
+
+
+ + +
+
+ +
+
+
+

Title goes here

+

Subtitle here

+
+
+ + +
+
+ +
+
+

Title goes here

+

Subtitle here

+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex + ea commodo consequat. +
+
+ + +
+
+ + +
+
+

Title goes here

+

Subtitle here

+
+
+ + +
+
+ + +
+
+

Title

+
+
+ +
+
+
+
+ + diff --git a/demos/checkbox.html b/demos/checkbox.html new file mode 100644 index 000000000..30e633802 --- /dev/null +++ b/demos/checkbox.html @@ -0,0 +1,157 @@ + + + + + + MDL Checkbox Demo + + + + +
+

MDL Checkbox

+
+

Basic Example, no Javascript

+
+
+
+ +
+ + + +
+
+
+ +
+
+ + + + +
+
+

With Javascript

+
+
+
+ +
+ + + +
+
+
+ +
+
+ +
+
+

Dark Theme

+
+
+
+ +
+ + + +
+
+
+ +
+
+ +
+
+ + + + diff --git a/demos/fab.html b/demos/fab.html new file mode 100644 index 000000000..ff2c0650e --- /dev/null +++ b/demos/fab.html @@ -0,0 +1,89 @@ + + + + + + MDL FAB Demo + + + + + +
+

MDL FAB

+ + + +
+
+ Normal FABs + + + + +
+
+ Disabled FABs + + + + +
+
+
+ + + diff --git a/demos/images/1-1.jpg b/demos/images/1-1.jpg new file mode 100644 index 000000000..357a3d025 Binary files /dev/null and b/demos/images/1-1.jpg differ diff --git a/demos/images/16-9.jpg b/demos/images/16-9.jpg new file mode 100644 index 000000000..95a7a1774 Binary files /dev/null and b/demos/images/16-9.jpg differ diff --git a/demos/index.html b/demos/index.html new file mode 100644 index 000000000..7428f3f53 --- /dev/null +++ b/demos/index.html @@ -0,0 +1,40 @@ + + + + + + MDL Demos + + + +
+ +
+ + + diff --git a/demos/radio.html b/demos/radio.html new file mode 100644 index 000000000..fa4529405 --- /dev/null +++ b/demos/radio.html @@ -0,0 +1,99 @@ + + + + + + MDL Radio Demo + + + + +
+
+ + + + +
+
+ + + + diff --git a/demos/ripple.html b/demos/ripple.html new file mode 100644 index 000000000..b1e1053b0 --- /dev/null +++ b/demos/ripple.html @@ -0,0 +1,99 @@ + + + + + + MDL Ripple Demo + + + + +
+
+

Bounded

+
+ +
+
+

Unbounded

+
+ +
+
+

Pre-rendered DOM

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + diff --git a/demos/toolbar.html b/demos/toolbar.html new file mode 100644 index 000000000..7a58ec01e --- /dev/null +++ b/demos/toolbar.html @@ -0,0 +1,56 @@ + + + + + + MDL Toolbar Demo + + + + + + + +
+
+ + + Page Title + +
+ +
+
+
+ +
+

Content

+

Content

+

Content

+
+ + diff --git a/demos/typography.html b/demos/typography.html new file mode 100644 index 000000000..4453a6a79 --- /dev/null +++ b/demos/typography.html @@ -0,0 +1,107 @@ + + + + + + MDL Typography Demo + + + + + + +
+

MDL Typography

+

Styles

+
+

Display 4

+

Display 3

+

Display 2

+

Display 1

+

Headline

+

+ Title Caption. +

+

Subheading 2

+

Subheading 1

+

Body 1 paragraph. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed + do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit + in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

+ +
+ +

Styles with margin adjustments

+
+

Display 4

+

Display 3

+

Display 2

+

Display 1

+

Headline

+

+ Title Caption. +

+

Subheading 2

+

Subheading 1

+

Body 1 paragraph. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed + do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit + in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

+ +
+ +

Color Classes

+
+

+ Primary Dark + Secondary Dark + Hint Dark + Disabled Dark + + favorite (Icon Dark) + +

+

+ Primary Light + Secondary Light + Hint Light + Disabled Light + + favorite (Icon Light) + +

+
+
+ + diff --git a/docs/DEVELOPER.md b/docs/DEVELOPER.md new file mode 100644 index 000000000..80227115b --- /dev/null +++ b/docs/DEVELOPER.md @@ -0,0 +1,63 @@ +# MDL V2 Developer's Guide + + +## Overview + +Material Design Lite (MDL) was originally envisioned as UI component library with minimal dependencies, providing an easy way to add a Material Design look and feel to any website. Following the spirit of MDL V1, MDL V2 strives to seamlessly incorporate into an even wider range of usage contexts, from simple static websites to complex, Javascript-heavy applications to hybrid client/server rendering systems. In short, whether you're already heavily invested in another framework or not, it should be easy to incorporate material components into your site in a lightweight, idiomatic fashion. + +To make this possible, our new component library is internally split into two parts: + +- **MDL V2 Vanilla**: ready-to-use components (what the majority of our current users are interested in) +- **MDL V2 Foundation**: shared UI code (for lower-level usage by other frameworks or complex rendering scenarios) + +On the whole, many of these changes will be transparent to Vanilla end-users, and are primarily intended to enable MDL to work across the entire web platform. + +## Component Architecture + +There are several key design decisions that underpin MDL V2 Foundation: + +- Event handling and DOM rendering responsibilities delegated to host framework +- Heavy reliance on CSS for code simplicity, portability, and graceful degradation +- Minimal assumptions about component lifecycle + +The aim being to push forward a clear separation of concerns, with the Foundation code being entirely about UI-related matters - as opposed to data-binding, templating, key/input handling, etc. In the case of Vanilla, we take a plain JS approach towards wrapping Foundation and providing the necessary code to make things usable out-of-the-box. + +> NOTE: This next section is currently being reworked. See [#4568](https://github.com/google/material-design-lite/issues/4568) + +Foundation components are implemented as [functional mixins](http://raganwald.com/2015/06/17/functional-mixins.html) and thus must be bound to a host class in order to be used. The mixin automatically binds when called with the host prototype as the receiver. Additionally, each mixin must be passed in an `adapter` implementation at creation time which is the contract by which the component communicates with its host. + +```javascript +class MyHostComponent { + constructor() { + this.rootElement_ = document.createElement('div'); + } +} + +MDLComponentMixin.call(MyHostComponent, { + // Adapter implementation. + addClass(className) { + this.rootElement_.classList.add(className); + } + // ... +}); +``` + +## Infrastructure and Tooling + +### Build System + +[Webpack](https://webpack.github.io/) is our build system of choice, which provides: + +- Bundling of SASS/JS into umbrella or per-component distributions +- Fast, modern development environment (incremental compilation, source maps, live reloading, etc.) + +Check out our `webpack.config.js` for more details! + +### A-la-carte Components + +We use [Lerna JS](https://lernajs.io/) to allow individual components to co-exist and be built within the same repository. Builds via webpack will produce artifacts for each component, which can then be used independently or via the umbrella package (`material-design-lite`). + +When cloning the repo for the first time, you must run `lerna bootstrap` which installs all subpackage dependencies and symlinks any project cross-dependencies. + +In this manner, each MDL component is isolated and can be versioned and published independently. + diff --git a/docs/_assets/android-desktop.png b/docs/_assets/android-desktop.png deleted file mode 100644 index 72a7f12ef..000000000 Binary files a/docs/_assets/android-desktop.png and /dev/null differ diff --git a/docs/_assets/app-icon.png b/docs/_assets/app-icon.png deleted file mode 100644 index 8cf86a099..000000000 Binary files a/docs/_assets/app-icon.png and /dev/null differ diff --git a/docs/_assets/button_degradation.png b/docs/_assets/button_degradation.png deleted file mode 100644 index 47863f3d1..000000000 Binary files a/docs/_assets/button_degradation.png and /dev/null differ diff --git a/docs/_assets/codepen-logo.png b/docs/_assets/codepen-logo.png deleted file mode 100644 index b06bc1bef..000000000 Binary files a/docs/_assets/codepen-logo.png and /dev/null differ diff --git a/docs/_assets/codepen.js b/docs/_assets/codepen.js deleted file mode 100644 index d7375a019..000000000 --- a/docs/_assets/codepen.js +++ /dev/null @@ -1,141 +0,0 @@ -/** - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -function CodeBlockCodePen() { - 'use strict'; - - this.codepenButtons = document.getElementsByClassName('codepen-button'); - this.init(); -} - -// Also insert the MDL Library. -CodeBlockCodePen.prototype.MDLIBS = [ - '', - '', - '', - '', - '' -]; - -/** - * Creates CodePen buttons in all code blocks (`pre`) that are HTML. - */ -CodeBlockCodePen.prototype.init = function() { - 'use strict'; - - [].slice.call(this.codepenButtons).forEach(function(form) { - // Attach the click event to the codepen button. - form.addEventListener('click', this.clickHandler(form, form.parentNode)); - }, this); -}; - -/** - * Extracts the parts of the text that is inside occurrences of the tag and - * endTag. - * @param {String} tag The start tag which content we need to extract - * @param {String} endTag The end tag which content we need to extract - * @param {String} text The text for which we need to extract the content in - * the given tags - * @return {Object} An Object with 2 attributes: textRemainder which contains - * the text not inside any of the given tag. and tagContent - * which contains a concatenation of what was inside the tags - */ -CodeBlockCodePen.prototype.extractTagsContent = function(tag, endTag, text) { - 'use strict'; - var tagStartIndex; - var tagEndIndex; - var tagText = ''; - - while (text.indexOf(tag) !== -1) { - tagStartIndex = text.indexOf(tag); - tagEndIndex = text.indexOf(endTag); - tagText += text.substring(tagStartIndex + tag.length, tagEndIndex); - text = text.substring(0, tagStartIndex).trim() + '\n' + - text.substr(tagEndIndex + endTag.length).trim(); - } - - return {textRemainder: text, tagContent: tagText}; -}; - -/** - * Click handler for CodePen buttons. Prepares the content for CodePen and - * submits the form. - * @param {HTMLElement} form The CodePen form - * @param {HTMLElement} pre The pre containing the code to send to CodePen - * @return {function} The click handler - */ -CodeBlockCodePen.prototype.clickHandler = function(form, pre) { - 'use strict'; - - return function() { - - // Track codepen button clicks - if (typeof ga !== 'undefined') { - ga('send', { - hitType: 'event', - eventCategory: 'codepen', - eventAction: 'click', - eventLabel: window.location.pathname + - (window.location.hash ? window.location.hash : '') - }); - } - - // Modify relative URLs to make them absolute. - var code = pre.textContent.replace('../assets/demos/', - window.location.origin + '/assets/demos/'); - - // Extract ', - code); - - code = cssExtractResult.textRemainder; - var css = cssExtractResult.tagContent.trim(); - - // Extract ', - code); - - code = jsExtractResult.textRemainder.trim(); - var js = jsExtractResult.tagContent.trim(); - - // Remove children from previous clicks. - while (form.firstChild) { - form.removeChild(form.firstChild); - } - var input = document.createElement('input'); - input.setAttribute('type', 'hidden'); - input.setAttribute('name', 'data'); - input.setAttribute('value', JSON.stringify( - { - title: 'Material Design Lite components demo', - html: - '\n' + - ' \n ' + this.MDLIBS.join('\n ') + '\n \n' + - ' \n ' + code.split('\n').join('\n ') + '\n \n' + - '', - css: css, - js: js})); - form.appendChild(input); - - form.submit(); - }.bind(this); -}; - -window.addEventListener('load', function() { - 'use strict'; - - new CodeBlockCodePen(); -}); diff --git a/docs/_assets/colors.svg b/docs/_assets/colors.svg deleted file mode 100644 index c4c6bdca5..000000000 --- a/docs/_assets/colors.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - Oval 43 + Oval 43 + Oval 43 - Created with Sketch. - - - - - - - - - - - \ No newline at end of file diff --git a/docs/_assets/comp_badges.png b/docs/_assets/comp_badges.png deleted file mode 100644 index 9c9f524f0..000000000 Binary files a/docs/_assets/comp_badges.png and /dev/null differ diff --git a/docs/_assets/comp_buttons.png b/docs/_assets/comp_buttons.png deleted file mode 100644 index 0f0ec0463..000000000 Binary files a/docs/_assets/comp_buttons.png and /dev/null differ diff --git a/docs/_assets/comp_cards.png b/docs/_assets/comp_cards.png deleted file mode 100644 index 917315ade..000000000 Binary files a/docs/_assets/comp_cards.png and /dev/null differ diff --git a/docs/_assets/comp_dialog.png b/docs/_assets/comp_dialog.png deleted file mode 100644 index 6125b2265..000000000 Binary files a/docs/_assets/comp_dialog.png and /dev/null differ diff --git a/docs/_assets/comp_layout.png b/docs/_assets/comp_layout.png deleted file mode 100644 index aa4d74df1..000000000 Binary files a/docs/_assets/comp_layout.png and /dev/null differ diff --git a/docs/_assets/comp_lists.png b/docs/_assets/comp_lists.png deleted file mode 100644 index ae754ef42..000000000 Binary files a/docs/_assets/comp_lists.png and /dev/null differ diff --git a/docs/_assets/comp_loading.png b/docs/_assets/comp_loading.png deleted file mode 100644 index eb2948484..000000000 Binary files a/docs/_assets/comp_loading.png and /dev/null differ diff --git a/docs/_assets/comp_menus.png b/docs/_assets/comp_menus.png deleted file mode 100644 index bcb3fc206..000000000 Binary files a/docs/_assets/comp_menus.png and /dev/null differ diff --git a/docs/_assets/comp_sliders.png b/docs/_assets/comp_sliders.png deleted file mode 100644 index b31e17a53..000000000 Binary files a/docs/_assets/comp_sliders.png and /dev/null differ diff --git a/docs/_assets/comp_snackbar.png b/docs/_assets/comp_snackbar.png deleted file mode 100644 index 7bc5d619b..000000000 Binary files a/docs/_assets/comp_snackbar.png and /dev/null differ diff --git a/docs/_assets/comp_tables.png b/docs/_assets/comp_tables.png deleted file mode 100644 index a4ba2d147..000000000 Binary files a/docs/_assets/comp_tables.png and /dev/null differ diff --git a/docs/_assets/comp_textfields.png b/docs/_assets/comp_textfields.png deleted file mode 100644 index 5d4bd9e17..000000000 Binary files a/docs/_assets/comp_textfields.png and /dev/null differ diff --git a/docs/_assets/comp_toggles.png b/docs/_assets/comp_toggles.png deleted file mode 100644 index 071456b10..000000000 Binary files a/docs/_assets/comp_toggles.png and /dev/null differ diff --git a/docs/_assets/comp_tooltips.png b/docs/_assets/comp_tooltips.png deleted file mode 100644 index 9f3910a94..000000000 Binary files a/docs/_assets/comp_tooltips.png and /dev/null differ diff --git a/docs/_assets/compindex.png b/docs/_assets/compindex.png deleted file mode 100644 index 23ff6703f..000000000 Binary files a/docs/_assets/compindex.png and /dev/null differ diff --git a/docs/_assets/compindex_2x.png b/docs/_assets/compindex_2x.png deleted file mode 100644 index e6c251ae8..000000000 Binary files a/docs/_assets/compindex_2x.png and /dev/null differ diff --git a/docs/_assets/components.css b/docs/_assets/components.css deleted file mode 100644 index c0e495fa8..000000000 --- a/docs/_assets/components.css +++ /dev/null @@ -1,244 +0,0 @@ -/** - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -.mdl-components { - display: flex; -} - -.mdl-components-index { - box-sizing: border-box; - position: relative; - padding-top: 64px; -} - -.mdl-components-index-text { - max-width: 960px; - margin: 0; -} -.mdl-components-index-text .mdl-components-dl { - justify-content: flex-start; - margin-left: 40px; -} - -.mdl-components-img { - position: absolute; - margin-top: 24px; - left: 40px; - height: 90%; - width: 90%; - max-height: 600px; - background: url('../assets/compindex_2x.png') no-repeat top left / contain; -} - -.mdl-components-text { - margin: 0; - padding: 0; -} - -mdl-components-dl { - padding: 0.5em; - width: 80%; -} - -mdl-components-dt { - float: left; - clear: left; - width: 150px; - font-weight: bold; -} - -mdl-components-dd { - margin: 0 0 0 150px; - padding: 0 0 0.5em 0; -} - -.mdl-components .mdl-components__nav { - display: inline-block; - background: #fff; - width: 200px; - box-sizing: border-box; - padding: 24px 0; - flex-shrink: 0; - z-index: 1; -} - -.mdl-components .mdl-components__pages { - display: inline-block; - flex-grow: 1; -} -.mdl-components .mdl-components__pages { - padding-bottom: 120px; -} -.mdl-components .mdl-components__link { - margin: 16px; - font-weight: normal; - color: rgba(0, 0, 0, 0.66); - position: relative; - padding-left: 72px; - min-height: 48px; - display: table; - line-height: 48px; -} - -.mdl-components .mdl-components__link.is-active { - font-weight: bold; - color: #c2185b; -} - -.content { - background: #fafafa; -} - -.mdl-components .mdl-components__page { - display: none; - min-height: 1000px; -} - -.mdl-components .docs-toc { - margin-bottom: 60px; - margin-left: 32px; -} - -.mdl-components .component-title { - margin-bottom: 60px; - margin-top: 30px; - margin-left: 32px; -} - -.mdl-components .component-title h3 { - font-size: 16px; - font-weight: 500; - margin-top: 80px; - text-transform: uppercase; -} - -.mdl-components .snippet-code pre.language-markup code { - padding-left: 40px; -} - -.mdl-components .mdl-components__page.is-active { - display: block; -} - -.mdl-components__link-image { - display: inline-block; - margin: 0 10px; - position: absolute; - left: 0; - top: 0; - background-color: #ddd; - background-position: center; - background-repeat: no-repeat; - background-size: auto 48px; - - border-radius: 50%; - height: 46px; - width: 46px; -} - -.mdl-components__warning { - width: 100%; - max-width: 640px; - margin: 0 auto; - background-color: #FFF9C4; - padding: 16px; - border-radius: 2px; - color: #212121; -} - -.mdl-components__link.is-active .mdl-components__link-image { - box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.14), - 0 3px 3px -2px rgba(0, 0, 0, 0.2), - 0 1px 8px 0 rgba(0, 0, 0, 0.12); -} -.docs-readme { - width: 100%; - max-width: 640px; - margin: 0 auto; -} - -.docs-readme .language-markup { - width: 100%; -} -@media (max-width: 850px) { - .mdl-components .component-title, - .mdl-components .docs-toc { - margin-left: 0; - } - .mdl-components .snippet-code pre.language-markup code { - padding-left: 8px; - } - .docs-layout-content { - position: relative; - height: 100%; - overflow: hidden !important; - } - - .mdl-components .mdl-components__nav { - position: fixed; - top: 64px; - left: 0; - display: block; - flex-wrap: nowrap; - width: 100%; - height: 120px; - overflow-x: auto; - overflow-y: hidden; - padding: 8px; - z-index: 100; - white-space: nowrap; - } - - .mdl-components-index-text .mdl-components-dl { - margin: 0px; - } - .mdl-components-img { - left: 8px; - } - .components .content .about-panel { - padding: 8px; - } - - .mdl-components__nav .mdl-components__link { - display: inline-block; - vertical-align: top; - height: 100%; - margin: 0; - width: auto; - min-width: 48px; - margin-right: 8px; - padding-left: 0px; - padding-top: 10px; - } - - .mdl-components__nav .mdl-components__link > *{ - display: block; - width: auto; - margin: 0 auto; - text-align: center; - } - .mdl-components__nav .mdl-components__link > .mdl-components__link-image { - position: static; - width: 48px; - } - - .content { - padding-top: 64px !important; - padding-left: 0 !important; - overflow-y: auto; - height: 100%; - } -} diff --git a/docs/_assets/components.js b/docs/_assets/components.js deleted file mode 100644 index d7581ad5c..000000000 --- a/docs/_assets/components.js +++ /dev/null @@ -1,163 +0,0 @@ -/** - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -function MaterialComponentsNav() { - 'use strict'; - - this.element_ = document.querySelector('.mdl-js-components'); - if (this.element_) { - this.componentLinks = this.element_.querySelectorAll('.mdl-components__link'); - this.activeLink = null; - this.activePage = null; - - this.init(); - } -} - -/** - * Stores a Map of the components links using their corresponding hashFragment - * as key. - * @type {Object.} - * @private - */ -MaterialComponentsNav.prototype.linksMap_ = {}; - -/** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * @enum {string} - * @private - */ -MaterialComponentsNav.prototype.CssClasses_ = { - ACTIVE: 'is-active' -}; - -/** - * Initializes the MaterialComponentsNav component. - */ -MaterialComponentsNav.prototype.init = function() { - 'use strict'; - - for (var i = 0; i < this.componentLinks.length; i++) { - this.componentLinks[i].addEventListener('click', - this.clickHandler(this.componentLinks[i])); - // Mapping the list of links using their hash fragment. - this.linksMap_['#' + this.componentLinks[i].href.split('#')[1]] = - this.componentLinks[i]; - } - - // If a Hash fragment is available on the page then display the section. - this.displaySectionForFragment(window.location.hash.split('/')[0]); - - // If the hash fragment changes we display the corresponding section. - // We won't support older browser as it's not efficient. - if ('onhashchange' in window) { - var this_ = this; - window.onhashchange = function () { - this_.displaySectionForFragment(window.location.hash.split('/')[0]); - }; - } -}; - -/** - * Displays the section for the given hash fragment. - * @param {String} fragment The hash fragment used in the link to the section - */ -MaterialComponentsNav.prototype.displaySectionForFragment = function(fragment) { - 'use strict'; - - if (fragment && this.linksMap_[fragment] && this.linksMap_[fragment].click) { - this.linksMap_[fragment].click(); - } else if (!fragment || fragment === '' || fragment === '#') { - this.displayIndexPage(); - } -}; - -/** - * Displays the index page for the components. - */ -MaterialComponentsNav.prototype.displayIndexPage = function() { - 'use strict'; - - if (this.activeLink) { - this.activeLink.classList.remove(this.CssClasses_.ACTIVE); - } - this.activeLink = null; - if (this.activePage) { - this.activePage.classList.remove(this.CssClasses_.ACTIVE); - } - this.activePage = this.element_.querySelector('#index-section'); - this.activePage.classList.add(this.CssClasses_.ACTIVE); -} - -/** - * Returns a clickHandler for a navigation link. - * @param {HTMLElement} link the navigation link - * @return {function} the click handler - */ -MaterialComponentsNav.prototype.clickHandler = function(link) { - 'use strict'; - - return function(e) { - e.preventDefault(); - var page = this.findPage(link); - if (this.activePage) { - this.activePage.classList.remove(this.CssClasses_.ACTIVE); - } - if (this.activeLink) { - this.activeLink.classList.remove(this.CssClasses_.ACTIVE); - } - - this.activePage = page; - this.activeLink = link; - - link.classList.add(this.CssClasses_.ACTIVE); - page.classList.add(this.CssClasses_.ACTIVE); - - // Add an history entry and display the hash fragment in the URL. - var section = window.location.hash.split('/')[0]; - var linkWithoutHash = link.href.split('#')[1]; - if (section !== '#' + linkWithoutHash) { - history.pushState(null, 'Material Design Lite', link); - // Scroll to top of page - document.getElementById('content').scrollTop = 0; - // Track the specific component page view in Google analytics - if (ga) { - ga('send', 'pageview', '/components/' + linkWithoutHash); - } - } - return true; - }.bind(this); -}; - -/** - * Finds the corresponding page for a navigation link. - * @param {HTMLElement} link the navigation link - * @return {HTMLElement} the corresponding page - */ -MaterialComponentsNav.prototype.findPage = function(link) { - 'use strict'; - - var href = link.href.split('#')[1]; - return this.element_.querySelector('#' + href); -}; - -window.addEventListener('load', function() { - 'use strict'; - - new MaterialComponentsNav(); -}); diff --git a/docs/_assets/components.png b/docs/_assets/components.png deleted file mode 100755 index 3197a2e3f..000000000 Binary files a/docs/_assets/components.png and /dev/null differ diff --git a/docs/_assets/components.svg b/docs/_assets/components.svg deleted file mode 100644 index 067f6b2b7..000000000 --- a/docs/_assets/components.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - components - Created with Sketch. - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/_assets/components_2x.png b/docs/_assets/components_2x.png deleted file mode 100755 index e955ea5fb..000000000 Binary files a/docs/_assets/components_2x.png and /dev/null differ diff --git a/docs/_assets/components_mo.svg b/docs/_assets/components_mo.svg deleted file mode 100644 index b906f1093..000000000 --- a/docs/_assets/components_mo.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - components_mo - Created with Sketch. - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/_assets/customize.png b/docs/_assets/customize.png deleted file mode 100755 index 1963cec9e..000000000 Binary files a/docs/_assets/customize.png and /dev/null differ diff --git a/docs/_assets/customize.svg b/docs/_assets/customize.svg deleted file mode 100644 index 5739ab359..000000000 --- a/docs/_assets/customize.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - customize - Created with Sketch. - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/_assets/customize_2x.png b/docs/_assets/customize_2x.png deleted file mode 100755 index d5975022a..000000000 Binary files a/docs/_assets/customize_2x.png and /dev/null differ diff --git a/docs/_assets/customize_mo.svg b/docs/_assets/customize_mo.svg deleted file mode 100644 index 380464b01..000000000 --- a/docs/_assets/customize_mo.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - customize copy - Created with Sketch. - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/_assets/customizer.css b/docs/_assets/customizer.css deleted file mode 100644 index ed0178879..000000000 --- a/docs/_assets/customizer.css +++ /dev/null @@ -1,127 +0,0 @@ -/** - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#wheel { - position: relative; - height: 100%; - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; -} -.is-small-screen .mdl-gen #wheel { - min-height: 100vw; -} -#wheel svg { - width: 100%; - height: 100%; -} - -@media (min-width: 840px) { - #wheel svg { - max-width: 100%; - width: 100%; - } -} -#wheel .mdl-gen-download { - position: absolute; - left: 50%; - top: 50%; -} -#wheel .mdl-gen-download .mdl-button { - transform: translate(-50%, -50%); -} -#wheel g[data-color] { - opacity: 1; - transition: opacity 0.2s cubic-bezier(0.4, 0.0, 1, 1); -} -#wheel .selector { - opacity: 0; - transition: opacity 0.4s cubic-bezier(0.4, 0.0, 1, 1); - fill: #BDBDBD; -} -#wheel .selected .selector { - opacity: 1; -} -#wheel .label { - text-anchor: middle; - opacity: 0; - transition: opacity 0.4s cubic-bezier(0.4, 0.0, 1, 1); - fill: white; - font-size: 24px; -} -#wheel .selected--1 .label--1, -#wheel .selected--2 .label--2 { - opacity: 1; -} -#wheel svg.hide-nonaccents g[data-color="Blue Grey"]:not(.selected), -#wheel svg.hide-nonaccents g[data-color="Brown"]:not(.selected), -#wheel svg.hide-nonaccents g[data-color="Grey"]:not(.selected) { - opacity: 0.12; -} -#wheel .selected { - opacity: 1 !important; -} -.mdl-gen > .mdl-grid { - max-width: 1280px; - padding: 0; -} -.mdl-gen__preview { - position: relative; - height: 350px; -} -.mdl-gen__preview .mdl-layout__container { - height: auto; -} -.mdl-gen__preview .mdl-layout__content { - padding: 32px; - background-color: #EFEFEF; - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: flex-start; -} -.mdl-gen__preview .mdl-layout__content .mdl-button { - margin: 0; -} -.mdl-gen__preview .mdl-layout__content .mdl-button--fab { - align-self: flex-end; -} -.mdl-gen__preview .mdl-layout__content h3 { - margin-top: 0; -} -.mdl-gen__panel--right { - display: flex; - flex-direction: column; - align-items: stretch; - justify-content: center; - padding-bottom: 0; -} -.mdl-gen__desc strong, -.mdl-gen__desc p { - display: block; - margin-bottom: 32px; - color: rgba(0, 0, 0, 0.54); -} -.mdl-gen__cdn .demo-code { - box-sizing: border-box; -} -.content { - margin-left: auto; - margin-right: auto; - max-width: 1280px; - margin-bottom: 80px; -} diff --git a/docs/_assets/customizer.js b/docs/_assets/customizer.js deleted file mode 100644 index 33a69d26d..000000000 --- a/docs/_assets/customizer.js +++ /dev/null @@ -1,545 +0,0 @@ -/** - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/*global MaterialCustomizer:true,Prism:true,ga:true*/ - -/* exported init */ -function init() { - 'use strict'; - - var wheel = document.querySelector('#wheel > svg'); - var cdn = document.querySelector('.mdl-gen__cdn .mdl-gen__cdn-link'); - var mc = new MaterialCustomizer(wheel, cdn); - - // Workaround for IE. - var dl = document.querySelector('#download'); - dl.addEventListener('click', function() { - if (window.navigator.msSaveBlob) { - window.navigator.msSaveBlob(this.blob, 'material.min.css'); - } - }.bind(mc)); - - // Hook up GA event - dl.addEventListener('click', function() { - ga('send', { - hitType: 'event', - eventCategory: 'customizer', - eventAction: 'download', - eventLabel: mc.getSelectedPrimary() + '-' + mc.getSelectedSecondary() - }); - }); - - var clickCtr = 0; - cdn.addEventListener('click', function() { - var selection = window.getSelection(); - selection.removeAllRanges(); - - var range = document.createRange(); - if (clickCtr === 0) { - var link = cdn.querySelectorAll('.token.attr-value')[1]; - range.setStart(link, 2); - range.setEnd(link, 3); - } else { - range.setStart(cdn, 1); - range.setEnd(cdn, 2); - } - - selection.addRange(range); - clickCtr = (clickCtr + 1) % 2; - }); - - // Prevent browser's selection handling - cdn.addEventListener('mouseup', function(ev) { - ev.preventDefault(); - }); - cdn.addEventListener('mousedown', function(ev) { - ev.preventDefault(); - }); - - document.addEventListener('mouseup', function() { - if (window.getSelection().toString().indexOf('.min.css') !== -1) { - ga('send', { - hitType: 'event', - eventCategory: 'customizer', - eventAction: 'copy', - eventLabel: mc.getSelectedPrimary() + '-' + mc.getSelectedSecondary() - }); - } - }); - - // Download template - var req = new XMLHttpRequest(); - req.onload = function() { - mc.template = this.responseText; - mc.highlightField('Indigo'); - mc.highlightField('Pink'); - window.requestAnimationFrame(function() { - mc.updateCDN(); - mc.updateStylesheet(); - }); - }; - req.open('get', '../material.min.css.template', true); - req.send(); -} - -MaterialCustomizer = (function() { - 'use strict'; - - var COLORS = ['Cyan', 'Teal', 'Green', 'Light Green', 'Lime', - 'Yellow', 'Amber', 'Orange', 'Brown', 'Blue Grey', - 'Grey', 'Deep Orange', 'Red', 'Pink', 'Purple', - 'Deep Purple', 'Indigo', 'Blue', 'Light Blue']; - var FORBIDDEN_ACCENTS = ['Blue Grey', 'Brown', 'Grey']; - var MD_COLORS = ['Red', 'Pink', 'Purple', 'Deep Purple', 'Indigo', - 'Blue', 'Light Blue', 'Cyan', 'Teal', 'Green', - 'Light Green', 'Lime', 'Yellow', 'Amber', 'Orange', - 'Deep Orange', 'Brown', 'Grey', 'Blue Grey']; - var MD_SHADES = ['50', '100', '200', '300', '400', - '500', '600', '700', '800', '900', - 'A100', 'A200', 'A400', 'A700']; - var MD_PALETTE = [ - ['255,235,238', '255,205,210', '239,154,154', '229,115,115', '239,83,80', - '244,67,54', '229,57,53', '211,47,47', '198,40,40', '183,28,28', - '255,138,128', '255,82,82', '255,23,68', '213,0,0'], - ['252,228,236', '248,187,208', '244,143,177', '240,98,146', '236,64,122', - '233,30,99', '216,27,96', '194,24,91', '173,20,87', '136,14,79', - '255,128,171', '255,64,129', '245,0,87', '197,17,98'], - ['243,229,245', '225,190,231', '206,147,216', '186,104,200', '171,71,188', - '156,39,176', '142,36,170', '123,31,162', '106,27,154', '74,20,140', - '234,128,252', '224,64,251', '213,0,249', '170,0,255'], - ['237,231,246', '209,196,233', '179,157,219', '149,117,205', '126,87,194', - '103,58,183', '94,53,177', '81,45,168', '69,39,160', '49,27,146', - '179,136,255', '124,77,255', '101,31,255', '98,0,234'], - ['232,234,246', '197,202,233', '159,168,218', '121,134,203', '92,107,192', - '63,81,181', '57,73,171', '48,63,159', '40,53,147', '26,35,126', - '140,158,255', '83,109,254', '61,90,254', '48,79,254'], - ['227,242,253', '187,222,251', '144,202,249', '100,181,246', '66,165,245', - '33,150,243', '30,136,229', '25,118,210', '21,101,192', '13,71,161', - '130,177,255', '68,138,255', '41,121,255', '41,98,255'], - ['225,245,254', '179,229,252', '129,212,250', '79,195,247', '41,182,246', - '3,169,244', '3,155,229', '2,136,209', '2,119,189', '1,87,155', - '128,216,255', '64,196,255', '0,176,255', '0,145,234'], - ['224,247,250', '178,235,242', '128,222,234', '77,208,225', '38,198,218', - '0,188,212', '0,172,193', '0,151,167', '0,131,143', '0,96,100', - '132,255,255', '24,255,255', '0,229,255', '0,184,212'], - ['224,242,241', '178,223,219', '128,203,196', '77,182,172', '38,166,154', - '0,150,136', '0,137,123', '0,121,107', '0,105,92', '0,77,64', - '167,255,235', '100,255,218', '29,233,182', '0,191,165'], - ['232,245,233', '200,230,201', '165,214,167', '129,199,132', '102,187,106', - '76,175,80', '67,160,71', '56,142,60', '46,125,50', '27,94,32', - '185,246,202', '105,240,174', '0,230,118', '0,200,83'], - ['241,248,233', '220,237,200', '197,225,165', '174,213,129', '156,204,101', - '139,195,74', '124,179,66', '104,159,56', '85,139,47', '51,105,30', - '204,255,144', '178,255,89', '118,255,3', '100,221,23'], - ['249,251,231', '240,244,195', '230,238,156', '220,231,117', '212,225,87', - '205,220,57', '192,202,51', '175,180,43', '158,157,36', '130,119,23', - '244,255,129', '238,255,65', '198,255,0', '174,234,0'], - ['255,253,231', '255,249,196', '255,245,157', '255,241,118', '255,238,88', - '255,235,59', '253,216,53', '251,192,45', '249,168,37', '245,127,23', - '255,255,141', '255,255,0', '255,234,0', '255,214,0'], - ['255,248,225', '255,236,179', '255,224,130', '255,213,79', '255,202,40', - '255,193,7', '255,179,0', '255,160,0', '255,143,0', '255,111,0', - '255,229,127', '255,215,64', '255,196,0', '255,171,0'], - ['255,243,224', '255,224,178', '255,204,128', '255,183,77', '255,167,38', - '255,152,0', '251,140,0', '245,124,0', '239,108,0', '230,81,0', - '255,209,128', '255,171,64', '255,145,0', '255,109,0'], - ['251,233,231', '255,204,188', '255,171,145', '255,138,101', '255,112,67', - '255,87,34', '244,81,30', '230,74,25', '216,67,21', '191,54,12', - '255,158,128', '255,110,64', '255,61,0', '221,44,0'], - ['239,235,233', '215,204,200', '188,170,164', '161,136,127', '141,110,99', - '121,85,72', '109,76,65', '93,64,55', '78,52,46', '62,39,35'], - ['250,250,250', '245,245,245', '238,238,238', '224,224,224', '189,189,189', - '158,158,158', '117,117,117', '97,97,97', '66,66,66', '33,33,33'], - ['236,239,241', '207,216,220', '176,190,197', '144,164,174', '120,144,156', - '96,125,139', '84,110,122', '69,90,100', '55,71,79', '38,50,56'] - ]; - - function parentWrapper(p) { - return p.parentElement || p.parentNode; - } - - var MaterialCustomizer = function(wheel, cdn) { - this.wheel = wheel; - this.cdn = cdn; - if (this.cdn) { - this.cdnTpl = cdn.textContent; - } - this.paletteIndices = MD_COLORS; - this.lightnessIndices = MD_SHADES; - this.palettes = MD_PALETTE; - - this.init_(); - }; - - MaterialCustomizer.prototype.init_ = function() { - this.config = { - width: 650, // width of the SVG panel - height: 650, // height of the SVG panel - r: 250, // radius of the wheel - ri: 100, // radius of the inner hole - hd: 40, // height of the dark section - c: 40, // Distance(center of selector circle, border of wheel) - mrs: 0.5, // Percent of available width to use as radius for selector circle - alphaIncr: 0.005, // Value to add to alpha to make tiles overlap slightly - colors: COLORS - }; - this.forbiddenAccents = FORBIDDEN_ACCENTS; - this.calculateValues_(); - - if (this.wheel) { - this.buildWheel_(); - } - - return; - }; - - MaterialCustomizer.prototype.calculateValues_ = function() { - var config = this.config; - // Calculated values - // Angle of each piece of the wheel - config.alphaDeg = 360.0 / config.colors.length; - config.alphaRad = config.alphaDeg * Math.PI / 180; - // Radius of selector circle - config.rs = (config.c + config.r) * Math.sin(config.alphaRad / 2); - config.rs *= config.mrs; - // Angle of selector cone - config.selectorAlphaRad = Math.atan(config.rs / config.c) * 2; - // Angles of cone tangetial point - config.gamma1 = config.alphaRad / 2 - config.selectorAlphaRad / 2; - config.gamma2 = config.alphaRad / 2 + config.selectorAlphaRad / 2; - // Center of selector circle - config.cx = (config.c + config.r) * Math.sin(config.alphaRad) / 2; - config.cy = -(config.c + config.r) * (1 + Math.cos(config.alphaRad)) / 2; - - this.config = config; - }; - - MaterialCustomizer.prototype.buildWheel_ = function() { - var config = this.config; - var mainG = this.wheel.querySelector('g.wheel--maing'); - var wheelContainer = this.wheel.parentNode; - - this.wheel.setAttribute('viewBox', '0 0 ' + - this.config.width + ' ' + this.config.height); - this.wheel.setAttribute('preserveAspectRatio', 'xMidYMid meet'); - this.wheel.setAttribute('width', this.config.width); - this.wheel.setAttribute('height', this.config.height); - - var fieldTpl = this.generateFieldTemplate_(); - - var svgNS = 'http://www.w3.org/2000/svg'; - config.colors.forEach(function(color, idx) { - var field = fieldTpl.cloneNode(true); - var tooltip = document.createElement('div'); - - for (var i = 1; i <= 2; i++) { - var g = document.createElementNS(svgNS, 'g'); - var label = document.createElementNS(svgNS, 'text'); - label.setAttribute('class', 'label label--' + i); - label.setAttribute('transform', - 'rotate(' + (-config.alphaDeg * idx) + ')'); - label.setAttribute('dy', '0.5ex'); - label.textContent = '' + i; - g.appendChild(label); - g.setAttribute('transform', - 'translate(' + config.cx + ',' + config.cy + ')'); - field.appendChild(g); - } - field.setAttribute('data-color', color); - field.id = color; - field.querySelector('.polygons > *:nth-child(1)').style.fill = - 'rgb(' + this.getColor(color, '500') + ')'; - field.querySelector('.polygons > *:nth-child(2)').style.fill = - 'rgb(' + this.getColor(color, '700') + ')'; - field.querySelector('.polygons'). - addEventListener('click', this.fieldClicked_.bind(this)); - field.setAttribute('transform', 'rotate(' + config.alphaDeg * idx + ')'); - mainG.appendChild(field); - - tooltip.setAttribute('for', color); - tooltip.className = 'mdl-tooltip mdl-tooltip--large'; - tooltip.innerHTML = color; - wheelContainer.appendChild(tooltip); - }.bind(this)); - - mainG.setAttribute('transform', - 'translate(' + config.width / 2 + ',' + config.height / 2 + ')'); - - }; - - MaterialCustomizer.prototype.generateFieldTemplate_ = function() { - var svgNS = 'http://www.w3.org/2000/svg'; - var config = this.config; - var fieldTpl = document.createElementNS(svgNS, 'g'); - var polygons = document.createElementNS(svgNS, 'g'); - var lightField = document.createElementNS(svgNS, 'polygon'); - lightField.setAttribute('points', [ - [ - config.ri * Math.sin(config.alphaRad + config.alphaIncr), - -config.ri * Math.cos(config.alphaRad + config.alphaIncr) - ].join(','), - [ - config.r * Math.sin(config.alphaRad + config.alphaIncr), - -config.r * Math.cos(config.alphaRad + config.alphaIncr) - ].join(','), - [0, -config.r].join(','), - [0, -(config.ri + config.hd)].join(','), - ].join(' ')); - var darkField = document.createElementNS(svgNS, 'polygon'); - darkField.setAttribute('points', [ - [ - config.ri * Math.sin(config.alphaRad + config.alphaIncr), - -config.ri * Math.cos(config.alphaRad + config.alphaIncr) - ].join(','), - [ - (config.ri + config.hd) * Math.sin(config.alphaRad + config.alphaIncr), - -(config.ri + config.hd) * Math.cos(config.alphaRad + config.alphaIncr) - ].join(','), - [0, -(config.ri + config.hd)].join(','), - [0, -config.ri].join(','), - ].join(' ')); - polygons.appendChild(lightField); - polygons.appendChild(darkField); - polygons.setAttribute('class', 'polygons'); - fieldTpl.appendChild(polygons); - - var selector = document.createElementNS(svgNS, 'path'); - selector.setAttribute('class', 'selector'); - selector.setAttribute('d', - ' M ' + - (config.r * Math.sin(config.alphaRad) / 2) + - ' ' + - -(config.r * (1 + Math.cos(config.alphaRad)) / 2) + - ' L ' + - (config.cx - config.rs * Math.cos(config.gamma1)) + - ' ' + - (config.cy - config.rs * Math.sin(config.gamma1)) + - ' A ' + - config.rs + - ' ' + - config.rs + - ' ' + - config.alphaDeg + - ' 1 1 ' + - (config.cx + config.rs * Math.cos(config.gamma2)) + - ' ' + - (config.cy + config.rs * Math.sin(config.gamma2)) + - ' z ' - ); - fieldTpl.appendChild(selector); - - return fieldTpl; - }; - - MaterialCustomizer.prototype.getNumSelected = function() { - if (this.wheel.querySelector('.selected--2')) { - return 2; - } else if (this.wheel.querySelector('.selected--1')) { - return 1; - } - return 0; - }; - - MaterialCustomizer.prototype.fieldClicked_ = function (ev) { - var g = parentWrapper(parentWrapper(ev.target)); - var selectedColor = g.getAttribute('data-color'); - var numSelected = this.getNumSelected(); - // Ignore clicks on already selected fields - if ((g.getAttribute('class') || '').indexOf('selected--1') !== -1 && numSelected === 1) { - return; - } - - switch (numSelected) { - case 1: - if (this.forbiddenAccents.indexOf(selectedColor) !== -1) { - return; - } - this.highlightField(g.getAttribute('data-color')); - this.wheel.setAttribute('class', ''); - window.requestAnimationFrame(function() { - this.updateCDN(); - this.updateStylesheet(); - }.bind(this)); - break; - case 2: - Array.prototype.forEach.call( - this.wheel.querySelector('g.wheel--maing').childNodes, - function(f) { - f.setAttribute('class', ''); - f.querySelector('.polygons').setAttribute('filter', ''); - } - ); - /* falls through */ - case 0: - this.highlightField(g.getAttribute('data-color')); - window.requestAnimationFrame(function() { - this.wheel.setAttribute('class', 'hide-nonaccents'); - }.bind(this)); - break; - } - }; - - MaterialCustomizer.prototype.replaceDict = function(s, dict) { - for (var key in dict) { - s = s.replace(new RegExp(key, 'g'), dict[key]); - } - return s; - }; - - MaterialCustomizer.prototype.urlsafeName = function(s) { - return s.toLowerCase().replace(' ', '_'); - }; - - MaterialCustomizer.prototype.getSelectedPrimary = function() { - return this.wheel.querySelector('.selected--1') - .getAttribute('data-color'); - }; - - MaterialCustomizer.prototype.getSelectedSecondary = function() { - return this.wheel.querySelector('.selected--2') - .getAttribute('data-color'); - }; - - MaterialCustomizer.prototype.updateCDN = function() { - var primaryColor = this.getSelectedPrimary(); - var secondaryColor = this.getSelectedSecondary(); - - this.cdn.textContent = this.replaceDict(this.cdnTpl, { - '\\$primary': this.urlsafeName(primaryColor), - '\\$accent': this.urlsafeName(secondaryColor) - }); - Prism.highlightElement(this.cdn); - }; - - MaterialCustomizer.prototype.highlightField = function(color) { - var g = this.wheel.querySelector('[data-color="' + color + '"]'); - var parent = parentWrapper(g); - - // Make the current polygon the last child of its parent - // so shadows are visible. - parent.removeChild(g); - parent.appendChild(g); - - // We changed the DOM hierarchy, CSS animations might not show until - // DOM has updated internally. - g.setAttribute('class', 'selected selected--' + (this.getNumSelected() + 1)); - - var isIE = window.navigator.msPointerEnabled; - // FIXME: Shadows in IE10 don't disappear, for now they are disabled - if (!isIE) { - g.querySelector('.polygons') - .setAttribute('filter', 'url(#drop-shadow)'); - } - }; - - MaterialCustomizer.prototype.getColor = function(name, lightness) { - var r = this.palettes[this.paletteIndices.indexOf(name)]; - if (!r) { - return null; - } - return r[this.lightnessIndices.indexOf(lightness)]; - }; - - MaterialCustomizer.prototype.processTemplate = function(primaryColor, secondaryColor) { - var primary = this.getColor(primaryColor, '500'); - var primaryDark = this.getColor(primaryColor, '700'); - var accent = this.getColor(secondaryColor, 'A200'); - - return this.replaceDict(this.template, { - '\\$color-primary-dark': primaryDark, - '\\$color-primary-contrast': this.calculateTextColor(primary), - '\\$color-accent-contrast': this.calculateTextColor(accent), - '\\$color-primary': primary, - '\\$color-accent': accent - }); - }; - - MaterialCustomizer.prototype.calculateChannel = function(component) { - component = component / 255; - - return component < 0.03928 ? - component / 12.92 : Math.pow((component + 0.055) / 1.055, 2.4); - }; - - MaterialCustomizer.prototype.calculateLuminance = function(color) { - var components = color.split(','); - var red = this.calculateChannel(parseInt(components[0])); - var green = this.calculateChannel(parseInt(components[1])); - var blue = this.calculateChannel(parseInt(components[2])); - - return (0.2126 * red) + (0.7152 * green) + (0.0722 * blue); - }; - - MaterialCustomizer.prototype.calculateContrast = - function(background, foreground) { - var backLum = this.calculateLuminance(background) + 0.05; - var foreLum = this.calculateLuminance(foreground) + 0.05; - - return Math.max(backLum, foreLum) / Math.min(backLum, foreLum); - }; - - MaterialCustomizer.prototype.calculateTextColor = function(background) { - var minimumContrast = 3.1; - var light = '255,255,255'; - var dark = '66,66,66'; - - // Most colors will be dark, so check light text color first. - var whiteContrast = this.calculateContrast(background, light); - - if (whiteContrast >= minimumContrast) { - return light; - } else { - var blackContrast = this.calculateContrast(background, dark); - return blackContrast > whiteContrast ? dark : light; - } - }; - - MaterialCustomizer.prototype.replaceKeyword = function(str, key, val) { - return str.replace(new RegExp(key, 'g'), val); - }; - - MaterialCustomizer.prototype.updateStylesheet = function() { - var oldStyle = document.getElementById('main-stylesheet'); - var newStyle = document.createElement('style'); - newStyle.id = 'main-stylesheet'; - - var style = this.processTemplate( - this.getSelectedPrimary(), - this.getSelectedSecondary()); - if (oldStyle && oldStyle.parentNode) { - oldStyle.parentNode.removeChild(oldStyle); - } - newStyle.textContent = style; - document.head.appendChild(newStyle); - this.prepareDownload(style); - }; - - MaterialCustomizer.prototype.prepareDownload = function(content) { - var link = document.getElementById('download'); - var blob = new Blob([content], {type: 'text/css'}); - this.blob = blob; - var url = URL.createObjectURL(blob); - link.setAttribute('href', url); - link.setAttribute('download', 'material.min.css'); - }; - - return MaterialCustomizer; -})(); - -// For NodeJS usage -if (typeof module !== 'undefined') { - module.exports = MaterialCustomizer; -} diff --git a/docs/_assets/customizer.png b/docs/_assets/customizer.png deleted file mode 100644 index b17c3fa49..000000000 Binary files a/docs/_assets/customizer.png and /dev/null differ diff --git a/docs/_assets/demos/dog.png b/docs/_assets/demos/dog.png deleted file mode 100644 index 07743e51d..000000000 Binary files a/docs/_assets/demos/dog.png and /dev/null differ diff --git a/docs/_assets/demos/image_card.jpg b/docs/_assets/demos/image_card.jpg deleted file mode 100644 index 23a5822f6..000000000 Binary files a/docs/_assets/demos/image_card.jpg and /dev/null differ diff --git a/docs/_assets/demos/transparent.jpg b/docs/_assets/demos/transparent.jpg deleted file mode 100644 index 1364c2f89..000000000 Binary files a/docs/_assets/demos/transparent.jpg and /dev/null differ diff --git a/docs/_assets/demos/welcome_card.jpg b/docs/_assets/demos/welcome_card.jpg deleted file mode 100644 index af7f15f31..000000000 Binary files a/docs/_assets/demos/welcome_card.jpg and /dev/null differ diff --git a/docs/_assets/faq/subscribe-single-issue.png b/docs/_assets/faq/subscribe-single-issue.png deleted file mode 100644 index 275235012..000000000 Binary files a/docs/_assets/faq/subscribe-single-issue.png and /dev/null differ diff --git a/docs/_assets/favicon.png b/docs/_assets/favicon.png deleted file mode 100644 index 6ebb80943..000000000 Binary files a/docs/_assets/favicon.png and /dev/null differ diff --git a/docs/_assets/github_white_24.svg b/docs/_assets/github_white_24.svg deleted file mode 100644 index 14625a56e..000000000 --- a/docs/_assets/github_white_24.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - Shape - Created with Sketch. - - - - - - - - - - - \ No newline at end of file diff --git a/docs/_assets/google-services.png b/docs/_assets/google-services.png deleted file mode 100755 index 116579b77..000000000 Binary files a/docs/_assets/google-services.png and /dev/null differ diff --git a/docs/_assets/header.jpg b/docs/_assets/header.jpg deleted file mode 100644 index c84886759..000000000 Binary files a/docs/_assets/header.jpg and /dev/null differ diff --git a/docs/_assets/header_2x.jpg b/docs/_assets/header_2x.jpg deleted file mode 100644 index 335129eea..000000000 Binary files a/docs/_assets/header_2x.jpg and /dev/null differ diff --git a/docs/_assets/icons.svg b/docs/_assets/icons.svg deleted file mode 100644 index 6348ae44b..000000000 --- a/docs/_assets/icons.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - Shape - Created with Sketch. - - - - - - - - - - - \ No newline at end of file diff --git a/docs/_assets/ie.css b/docs/_assets/ie.css deleted file mode 100644 index caad6ea9e..000000000 --- a/docs/_assets/ie.css +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /* Header navigation fix to ensure display */ - .docs-layout .docs-layout-header.mdl-layout__header { - display: block; - } - - body > div.mdl-layout__container > div > main > div > section.about-panel.about-panel--components.mdl-color-text--white.mdl-cell.mdl-cell--6-col, - body > div.mdl-layout__container > div > main > div > section.about-panel.about-panel--styles.mdl-color-text--white.mdl-cell.mdl-cell--6-col { - width: 50%; - float: left; - } diff --git a/docs/_assets/img-1.png b/docs/_assets/img-1.png deleted file mode 100755 index ae3a83829..000000000 Binary files a/docs/_assets/img-1.png and /dev/null differ diff --git a/docs/_assets/img-2.png b/docs/_assets/img-2.png deleted file mode 100755 index 1242e078a..000000000 Binary files a/docs/_assets/img-2.png and /dev/null differ diff --git a/docs/_assets/ios-desktop.png b/docs/_assets/ios-desktop.png deleted file mode 100644 index de5d8fa1a..000000000 Binary files a/docs/_assets/ios-desktop.png and /dev/null differ diff --git a/docs/_assets/logo.png b/docs/_assets/logo.png deleted file mode 100644 index 23fd0454e..000000000 Binary files a/docs/_assets/logo.png and /dev/null differ diff --git a/docs/_assets/logo.svg b/docs/_assets/logo.svg deleted file mode 100644 index 812961b88..000000000 --- a/docs/_assets/logo.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - Shape - Created with Sketch. - - - - - \ No newline at end of file diff --git a/docs/_assets/main.css b/docs/_assets/main.css deleted file mode 100644 index ff1c026ef..000000000 --- a/docs/_assets/main.css +++ /dev/null @@ -1,1350 +0,0 @@ -html > body { - font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif !important; - background-color: #FAFAFA; -} -.docs-layout .docs-layout-header.mdl-layout__header { - height: 560px; - max-height: 50%; - flex-shrink: 0; - background-size: auto; - background-repeat: no-repeat; - background-position: center center; - box-shadow: none !important; - align-items: flex-start; - padding: 40px; - flex-shrink: 0; - position: relative; - display: flex !important; -} -body.about .docs-layout.is-small-screen .docs-layout-header.mdl-layout__header { - height: 280px; -} -body.about .docs-layout.is-small-screen .docs-layout-header.mdl-layout__header { - background-size: auto 58px, cover; - background-repeat: no-repeat, no-repeat; - background-position: center center, center center; -} -.docs-layout-header .mdl-textfield { - padding-top: 0; -} -.docs-layout-header > .mdl-layout__header-row { - padding: 0px; - align-items: flex-start; - height: auto; -} -.docs-layout-header .docs-navigation .github, -.docs-layout-header .docs-navigation .download { - text-transform: none; -} -.docs-layout-title { - font-weight: 500; - text-transform: uppercase; - line-height: 1.5em; - font-size: 1rem; -} -.docs-layout .docs-layout-title a { - font-weight: inherit; - color: white; -} -.docs-layout-header .mdl-textfield .mdl-button { - right: 0; -} -.docs-layout-header .mdl-textfield .mdl-textfield__expandable-holder { - margin-right: 32px; -} -.docs-layout-header .mdl-textfield label:after { - background-color: rgba(255, 255, 255, 0.12); -} -.about .docs-layout-header.mdl-layout__header { - background-color: #37474f; - background: url('logo.svg'), url('header.jpg'); - background-size: auto 118px, cover; - background-repeat: no-repeat, no-repeat; - background-position: center center, center center; -} -@media (max-height: 600px){ - .about .docs-layout-header.mdl-layout__header { - background-size: auto 80px, cover; - } -} -body:not(.about) .docs-layout .docs-layout-header.mdl-layout__header { - background-repeat: no-repeat; - background-position: center center; -} -.templates .docs-layout-header.mdl-layout__header { - background-color: #263238; - background-image: url('templates.png'); - background-size: auto 29px; -} -.showcase .docs-layout-header.mdl-layout__header { - background-color: #3E82F7; - background-image: url('templates.png'); - background-size: auto 29px; -} -.started .docs-layout-header.mdl-layout__header, -.faq .docs-layout-header.mdl-layout__header { - background-color: #2E2E2E; - background-image: url('logo.png'); - background-size: auto 32px; -} -.components .docs-layout-header.mdl-layout__header { - background-color: #C2185B; - background-image: url('components.png'); - background-size: auto 34px; -} -.styles .docs-layout-header.mdl-layout__header { - background-color: #8E24AA; - background-image: url('styles.png'); - background-size: auto 41px; -} -.customize .docs-layout-header.mdl-layout__header { - background-color: #1A237E; - background-image: url('customize.png'); - background-size: auto 36px; -} -body:not(.about) .docs-layout .docs-layout-header.mdl-layout__header { - box-sizing: border-box; - height: 144px; - background-position: 40px 32px; -} -body:not(.about) .docs-layout-title { - display: none; -} -.docs-navigation__container { - overflow: hidden; - position: absolute; - height: 64px; - width: 100%; - bottom: 0; - left: 0; -} -.docs-navigation { - box-shadow: none !important; - border: 0 !important; - padding: 0 16px; - width: 100%; - height: 85px; - flex-shrink: 0; - padding-left: 24px; - overflow-x: auto; - overflow-y: hidden; - user-select: none; - margin-bottom: -16px; -} -.docs-layout.is-small-screen .docs-navigation { - padding: 0; -} -.docs-layout.is-small-screen .docs-navigation .mdl-navigation__link .material-icons { - display: none; -} -.docs-navigation::-webkit-scrollbar { - display: none; -} -body:not(.about) .docs-layout.is-small-screen .docs-layout-header { - background-image: none; -} -.docs-layout.mdl-layout.is-small-screen .docs-layout-header.mdl-layout__header { - padding: 0; - height: 64px; -} -.docs-layout.is-small-screen .docs-layout-header .docs-layout-title, -.docs-layout.is-small-screen .docs-layout-header .mdl-textfield { - display: none; -} -.docs-layout.is-small-screen .docs-navigation__container { - top: 0; - bottom: auto; - left: 48px; - width: calc(100% - 2 * 48px); - padding: 0 !important; -} -.docs-layout .scrollindicator { - position: absolute; - top: 0; - line-height: 64px; - height: 64px; - width: 48px; - display: none; - margin-right: 0; - text-align: center; - cursor: pointer; - user-select: none; -} -.docs-layout .scrollindicator.disabled { - opacity: 0.12; - cursor: default; -} -.docs-layout .scrollindicator.scrollindicator--right { - right: 0; -} -.docs-layout .scrollindicator.scrollindicator--left { - left: 0; -} -.docs-layout.is-small-screen .scrollindicator.scrollindicator.scrollindicator { - display: block; -} -.mdl-navigation__link--icon > span, .mdl-navigation__link--icon > .material-icons { - line-height: 64px; - margin-right: 8px; - line-height: inherit; -} -.docs-navigation .mdl-navigation__link { - display: flex; - flex-shrink: 0; - user-select: inherit; - height: 64px; -} -.docs-navigation .mdl-navigation__link:hover, -.docs-navigation .mdl-navigation__link.download:hover > span, -.docs-navigation .mdl-navigation__link.download:hover > .material-icons { - background-color: inherit; - opacity: 1 !important; -} -.docs-navigation .mdl-navigation__link:not(.download), -.docs-navigation .mdl-navigation__link.download > span, -.docs-navigation .mdl-navigation__link.download > .material-icons { - opacity: 0.65; -} -.docs-navigation .mdl-navigation__link, section.download { - font-weight: 500; - font-size: 13px; - text-transform: uppercase; - line-height: 64px; - padding: 0 16px; - color: white; - box-sizing: border-box; - border-bottom: 3px solid transparent; -} -.docs-layout.is-small-screen .docs-navigation .mdl-navigation__link, -.docs-layouy.is-small-screen section.download { - padding: 0 12px; -} -.about .docs-layout:not(.is-small-screen) .mdl-navigation__link.download > .material-icons { - display: none; -} -.about .docs-layout.is-small-screen .mdl-navigation__link.download > button, -body:not(.about) .mdl-navigation__link.download > button { - display: none; -} -.docs-navigation .download button .material-icons { - color: black; - opacity: 0.54; -} -.about .docs-navigation .about, -.templates .docs-navigation .templates, -.showcase .docs-navigation .showcase, -.started .docs-navigation .started, -.styles .docs-navigation .styles, -.components .docs-navigation .components, -.faq .docs-navigation .faq, -.customize .docs-navigation .customize { - opacity: 1; - border-bottom-color: #18FFFF; -} -.mdl-layout__content.docs-layout-content { - overflow: visible; -} -.docs-layout-content > .download { - width: 100%; - height: 6rem; - display: flex; - justify-content: center; - align-items: center; -} -.docs-layout-content > .download > a { - font-weight: 500; - text-transform: uppercase; -} -.docs-footer.mdl-mini-footer { - flex-direction: column; - align-items: stretch; - justify-content: center; - height: 120px; -} -.docs-footer.mdl-mini-footer ul { - padding: 0; - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; -} -.docs-footer.mdl-mini-footer ul > li > a { - margin: 0 8px; - font-weight: 400; - font-size: 12px; -} - -.docs-footer .docs-link-list li { - margin-left: 0.5em; - margin-right: 0.5em; -} - -.about-panel { - box-sizing: border-box; - width: 100%; - flex-grow: 1; -} -.about-panel--text { - padding: 100px; -} -.about-panel--text p { - width: 640px; - margin: 0 auto; - line-height: 2em; -} -.about-panel--text dl { - width: 100%; - display: flex; - flex-direction: row; - justify-content: center; - align-items: stretch; -} -.about-panel--text dl dt { - text-align: right; - vertical-align: top; - display: inline-table; - margin-right: 24px; - line-height: 2em; -} -.about-panel--text dl dd { - text-align: left; - line-height: 2em; - vertical-align: top; - width: 700px; - margin: 0; - margin-left: 24px; -} -.docs-layout.is-small-screen .about-panel { - padding: 40px; -} -.docs-layout.is-small-screen .about-panel--text:not(:first-of-type) { - display: none; -} -.docs-layout.is-small-screen .about-panel--text dl { - flex-direction: column; -} -.docs-layout.is-small-screen .about-panel--text dd, -.docs-layout.is-small-screen .about-panel--text dt { - margin: 0; - padding: 0; - text-align: left; - width: 100%; -} -.about-panel--components, -.about-panel--styles, -.about-panel--customize, -.about-panel--templates { - height: 500px; - display: flex; - flex-direction: column; - align-items: center; - justify-content: flex-end; - padding: 40px; - color: white; - text-transform: uppercase; - font-size: 1.4rem; - width: auto; - background-repeat: no-repeat; - background-position: center center; - cursor: pointer; -} -.docs-layout-content .about-panel--start > p { - color: rgb(66,66,66); - text-transform: uppercase; - font-size: 1.6rem; - margin-top: 20px; - margin-bottom: 0px; -} -.about-panel--templates { - background-color: #B3E0E1; - background-image: url(templates.svg); - background-size: 287px auto; -} -.about-panel--templates:hover { - background-image: url(templates_mo.svg); -} -.about-panel--components { - background-color: #E90974; - background-image: url(components.svg); - background-size: 174px auto; -} -.about-panel--components:hover { - background-image: url(components_mo.svg); -} -.about-panel--styles { - background-color: #8F4099; - background-image: url(styles.svg); - background-size: 252px auto; -} -.about-panel--styles:hover { - background-image: url(styles_mo.svg); - background-size: 331px auto; - background-position-x: calc(50% + 40px); -} -.about-panel--customize { - height: 400px; - background-color: #191E80; - background-image: url(customize.svg); - background-size: 156px auto; -} -.about-panel--customize:hover { - background-image: url(customize_mo.svg); -} - -.image-preloader { - position: fixed; - visibility: hidden; - width: 0px; - height: 0px; - top: -100px; - left: -100px; - background-image: url(templates_mo.svg), url(components_mo.svg), url(styles_mo.svg), url(customize_mo.svg); -} -.templates .content { - padding-left: 24px !important; - max-width: 960px; -} -.templates .docs-layout-content .content { - padding: 40px 0; -} -.templates .docs-layout .template { - margin-left: -16px; -} - -.showcase .content { - padding-left: 24px !important; - max-width: 960px; -} -.showcase .docs-layout-content .content { - padding: 40px 0; -} -.showcase .docs-layout .template { - margin-left: -16px; -} -.template { - width: 100%; - margin-bottom: 72px; - align-items: flex-start; -} -.template > .template__meta { - align-content: flex-start; - padding-left: 24px; -} -.templates .docs-layout.is-small-screen .template > .template__meta { - padding-left: 0; -} -.showcase .docs-layout.is-small-screen .template > .template__meta { - padding-left: 0; -} -.template > .template__meta.template__meta > * { - margin-bottom: 24px; -} -.template > .template__meta > *:last-child { - margin-bottom: 0px; -} -.template > .template__meta a { - color:inherit; - margin-left: -8px !important; -} -.template > .template__preview { - height: auto; -} -.docs-layout-content dd { - font-size: 13px; -} -.docs-layout-content p { - font-size: 13px; - margin-bottom: 32px; - max-width: 640px; - - /* Override */ - font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif; -} -.docs-text-styling ol li { - font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif; -} - -.docs-text-styling h1 { - color: #c2185b; - font-size: 2.5em; - margin: .67em 0; -} - - -.docs-text-styling h2 { - padding-top: 48px; - font-size: 24px; - font-weight: 400; - line-height: 32px; - margin-bottom: 30px; - color: #c2185b; -} - -.docs-text-styling h1, -.docs-text-styling h2, -.docs-text-styling h3, -.docs-text-styling h4 { - font-size: 16px; - color: rgba(0, 0, 0, 0.54); - font-weight: 500; - text-transform: uppercase; -} -.docs-layout-content h2.mdl-card__title-text { - padding-top: 0; - margin-bottom: 0; -} - -.docs-text-styling a { - text-decoration: none; -} - -.docs-layout-content .mdl-download { - color: #000; - font-weight: normal; -} - -.docs-layout-title a { - color: inherit; - text-decoration: none; -} - -.component-description { - max-width: 720px; - padding: 40px; -} -.component-description .mdl-button:first-of-type { - margin-top: 8px; -} -.docs-footer.mdl-mini-footer .mdl-mini-footer--social-btn { - background-color: transparent; - margin: 0 16px; - width: 24px; - height: 24px; -} -.docs-footer.mdl-mini-footer .social-btn { - display: block; - background-position: center; - background-size: contain; - background-repeat: no-repeat; - width: 24px; - height: 24px; - cursor: pointer; -} -.social-btn__twitter { - background-image: url('https://www.gstatic.com/images/icons/material/system/2x/post_twitter_white_24dp.png'); -} -.social-btn__github { - background-image: url('github_white_24.svg'); - width: 22px; - height: 22px; -} -.social-btn__gplus { - background-image: url('https://www.gstatic.com/images/icons/material/system/2x/post_gplus_white_24dp.png'); -} -.subpageheader { - margin-top: 60px; - margin-bottom: 40px; - display: flex; - color: rgba(0, 0, 0, .54); - align-items: center; - flex-shrink: 0; - text-transform: uppercase; - font-size: 16px; - font-weight: 500; -} -.about .subpageheader, -.components .subpageheader { - display: none; -} -.started .subpageheader, -.customize .subpageheader, -.styles .subpageheader, -.faq .subpageheader, -.templates .subpageheader, -.showcase .subpageheader { - width: 960px; - margin: 40px auto; -} -/* Components Snippets */ -.snippet-group { - margin-left: -16px; - margin-right: -16px; - margin-bottom: 84px; -} -.snippet-group .snippet-header { - display: table; - border-collapse:collapse; - border-spacing: 0; - width: 100%; -} -.snippet-group .snippet-demos, -.snippet-group .snippet-captions { - display: table-row; -} -.snippet-group .snippet-demo .snippet-demo-container { - text-align: left; - display: inline-block; -} -.snippet-group .snippet-captions { - background-color: white; - height: 48px; -} -.snippet-group .snippet-demo, -.snippet-group .snippet-demo-padding, -.snippet-group .snippet-caption, -.snippet-group .snippet-caption-padding { - display: table-cell; - text-align: center; - vertical-align: middle; - margin: 0; - padding: 0; -} - -.snippet-group .snippet-caption { - font-size: 13px; - padding: 0px 40px; - white-space: nowrap; - text-align: center; - position: relative; -} - -.snippet-group .snippet-demo { - padding: 0px 40px 40px 40px; -} -.snippet-group .snippet-demos .snippet-demo-padding { - width: 50%; -} -_:-ms-input-placeholder, :root .snippet-group .snippet-demo { - width: 1px; -} -_:-ms-input-placeholder, :root .snippet-group .snippet-demos .snippet-demo-padding { - width: auto; -} -.snippet-group .snippet-code { - position: relative; - overflow: hidden; -} -.snippet-group .snippet-code pre { - margin: 0; - border-radius: 0; - display: block; - padding: 0; - overflow: hidden; -} -.snippet-group .snippet-code code { - padding: 8px 16px; - position: relative; - max-height: none; - width: 100%; - box-sizing: border-box; -} -.snippet-group .snippet-code pre[class*=language-]>code[data-language] { - max-height: none; -} -.snippet-group .snippet-code code:first-of-type { - padding-top: 16px; -} -.snippet-group .snippet-code code:last-of-type { - padding-bottom: 16px; -} -.snippet-group .snippet-code code:hover { - background-color: rgba(0,0,0,0.05); -} -.snippet-group .snippet-code code:hover:only-of-type { - background-color: transparent; -} -.snippet-group .snippet-code code::before, -.snippet-group .snippet-code code::after { - display: none; -} -.snippet-group .snippet-code code:hover::before { - display: inline-block; - content: 'click to copy'; - color: rgba(0,0,0,0.5); - font-size: 13px; - background-color: rgba(0,0,0,0.1); - border-top-left-radius: 5px; - position: absolute; - right: 0; - bottom: 0; - padding: 3px 10px; -} -.snippet-group .snippet-code code:active::before { - content: ''; -} -.snippet-group .snippet-code code.copied::before { - content: 'copied'; - color: rgba(255,255,255,0.5); - background-color: rgba(0,0,0,0.6); -} -.snippet-group .snippet-code code.nosupport::before { - content: "browser not supported :'("; - color: rgba(255,255,255,0.5); - background-color: rgba(0,0,0,0.6); -} -.snippet-group .snippet-code .codepen-extra-css { - display:none; -} -@media (max-width: 850px) { - .snippet-group .snippet-demo { - padding-left: 5px; - padding-right: 5px; - } -} -.snippet-group.is-full-width .snippet-demo-container { - width: 100%; -} -.snippet-group.is-full-width .snippet-demos > .snippet-demo { - width: 100%; - padding-left: 0; - padding-right: 0; -} -.snippet-group.is-full-width .snippet-demo-padding { - width: 0; - padding: 8px; - margin: 0; -} -/* Open with CodePen Button */ -.codepen-button { - z-index: 50; - cursor: pointer; - background-image: url('codepen-logo.png'); - background-repeat: no-repeat; - background-position: 5px center; - background-size: 26px 26px; - position: absolute; - top: 0; - right: -125px; - width: 165px; - height: 46px; - display: none; - opacity: 0.6; - overflow: hidden; - box-sizing: border-box; - white-space: nowrap; - color: black; - padding: 13px 15px 5px 50px; - transition: right 0.5s, background-color 0.5s, opacity 0.5s, background-size 0.3s; -} -.codepen-button::after { - content: 'Open in CodePen'; -} -.codepen-button:hover { - opacity: 1; - right: 0; - background-size: 36px 36px; - background-color: rgb(248,248,248); - border-bottom-left-radius: 10px; -} -.docs-layout .docs-text-styling pre[class*=language-markup] { - max-width: calc(100vw - 32px); -} -.docs-layout pre[class*=language-markup] { - max-width: 100vw; - box-sizing: border-box; - overflow: hidden; -} -.docs-layout pre[class*=language-markup].codepen-button-enabled { - padding-right: 0; -} -.docs-layout pre[class*=language-markup].codepen-button-enabled code { - padding-right: 50px; -} -.codepen-button-enabled .codepen-button { - display: inline-block; -} -/* Prism and code blocks styling and overrides */ -.token.attr-name, .token.builtin, .token.selector, .token.string { - color: #E91E63; -} -.token.boolean, .token.constant, .token.number, .token.property, .token.symbol, .token.tag { - color: #9D1DB3; -} -.token.atrule, .token.attr-value, .token.keyword { - color: #00BCD4; -} -.docs-layout code, -.docs-layout pre { - display: inline-block; - background-color: rgba(0,0,0,0.06); - border-radius: 3px; - font-size: 85%; - white-space: pre-wrap; -} -.docs-layout pre { - padding: 16px; - font-size: 87%; - box-sizing: border-box; -} -.docs-layout code:before, -.docs-layout code:after { - letter-spacing: -0.2em; - content: "\00a0"; -} -.docs-layout pre > code:before, -.docs-layout pre > code:after { - letter-spacing: 0; - content: ""; -} -.docs-layout pre > code { - background-color: rgba(0,0,0,0); - padding: 0px; - font-size: 100%; - width: 100%; - box-sizing: border-box; - word-break: break-word; -} -.docs-layout pre[class*=language-]>code[data-language] { - overflow: hidden; -} -pre[class*=language-]>code[data-language]::before { - content: ""; - background: none; -} -.token.cr:before, -.token.lf:before { - display: none; -} -.language-css .token.string, -.style .token.string, -.token.entity, -.token.operator, -.token.url, -.token.variable { - color: #9D1DB3; - background: none; -} -code[class*=language-], pre[class*=language-] { - color: rgba(0,0,0,0.87); - text-shadow: none; -} -.token.function { - color: #009688; -} -.code-with-text { - position: relative; - width: auto; - display: block; - border-spacing: 0; - border-collapse: collapse; - background-color: white; - padding: 15px; - border-radius: 3px; - font-size: 13px; -} -.code-with-text pre { - margin: 15px -15px -15px -15px; - border-top-left-radius: 0; - border-top-right-radius: 0; - display: block; - width: auto; -} -/* Table of content widget */ -.docs-toc ul { - border-left: solid 3px #C0EbF1; - padding-left: 20px; - line-height: 28px; -} -.docs-toc a { - font-weight: 400; - color: #00BCD4; -} -.docs-toc li { - font-size: 16px; - list-style: none; -} -/* Getting started guide */ -.started .mdl-tabs__tab-bar { - justify-content: flex-start; - border-bottom: 0; -} -.started .download-button-container { - text-align: center; - margin-bottom: 20px; -} -.started .mdl-tabs.is-upgraded .mdl-tabs__tab.is-active { - color: #00ACC1; -} -.started .mdl-tabs.is-upgraded .mdl-tabs__tab.is-active:after { - background-color: #00ACC1; -} -.started .docs-layout-content { - text-align: center; -} -.started .chapter-toc { - display: table; -} -.started .code-with-text { - width: 640px; - box-sizing: border-box; -} -.started .docs-layout .content section { - max-width: 960px; - margin: 0 auto; -} -.started a, -.about a, -.faq a, -.customize a { - color: #00BCD4; -} -.customize .docs-layout .content { - max-width: 960px; - margin: 0 auto; - display: block; - margin-bottom: 120px; - padding: 40px; -} -.started .content h3, -.started .content h4 { - display: table-cell; - font-size: 15px; - padding-right: 60px; - line-height: 25px; - text-transform: none; -} -.started .content h3 { - width: 140px; -} -.started .content section { - margin-bottom: 30px; -} -.started .section-content { - display: table-cell; -} -.started .content, -.styles .content, -.faq .content { - padding: 40px; - display: inline-block; - text-align: left; - width: 100%; - box-sizing: border-box; -} -.docs-layout ul { - list-style-type: none; -} -.docs-layout li { - position: relative; -} -.styles .content li:before, -.docs-readme .content li:before { - position: absolute; - top: 2px; - left: -28px; - content: '•'; - font-size: 32px; -} -.started .content p { - margin-top: 10px; - margin-bottom: 15px; -} -.started .mdl-tabs { - margin-bottom: 22px; -} -.started .content .mdl-tabs__panel { - padding-top: 10px; -} -.started .caption { - font-size: 13px; - max-width: 640px; - box-sizing: border-box; - margin-top: 15px; - padding: 15px; - background-color: rgb(255, 255, 255); - border-radius: 3px; -} -.started .caption h4 { - font-size: 13px; - font-weight: normal; - font-style: italic; - margin-top: 0; -} -.started .use-components pre { - margin-top: 0; -} -.started .component-example { - margin: 30px 0; -} -.started ol { - padding-left: 18px; - font-size: 13px; - max-width: 640px; - box-sizing: border-box; -} -.started pre { - width: 640px; - box-sizing: border-box; - position: relative; -} -.started .snippet-group { - max-width: 640px; - margin: 60px 0 40px 0; -} -@media (max-width: 850px) { - .started .chapter-toc { - display: block; - } - .started .content h3, - .started .content h4 { - display: block; - width: auto; - } - .started .section-content { - display: block; - } - .started pre { - width: auto; - margin-left: -40px; - margin-right: -40px; - padding: 15px 40px; - box-sizing: content-box; - display: block; - max-width: none; - } - .started .caption { - margin-left: -40px; - margin-right: -40px; - max-width: none; - box-sizing: content-box; - padding: 15px 40px; - } - .started .mdl-tabs__tab-bar { - margin-left: -40px; - margin-right: -40px; - justify-content: center; - } - .started .mdl-tabs__tab { - padding: 0 3%; - } - .started .content { - display: block; - } - .started .snippet-group { - margin-left: -40px; - margin-right: -40px; - max-width: none; - } - .started .snippet-group code { - padding-left: 40px; - padding-right: 40px; - } -} -/*Styles page*/ -.styles a { - color: #00BCD4; -} -.styles .styles__content h2 { - text-transform: none; -} -.styles .typo-styles { - margin-bottom: 40px; -} -.styles .typo-styles dt { - display: block; - float: left; - color: white; - background-color: rgba(0, 0, 0, 0.24); - width: 32px; - height: 32px; - border-radius: 16px; - line-height: 32px; - text-align: center; - font-weight: 500; - margin-top: 5px; -} -.styles .typo-styles dd { - display: block; - margin-left: 60px; - margin-bottom: 20px; -} -.styles .typo-styles .typo-styles__demo { - margin-bottom: 8px; -} -.styles .typo-styles .typo-styles__desc { - font-weight: 300; -} -.styles .typo-styles .typo-styles__desc .typo-styles__name { - margin-right: 8px; - font-weight: 400; -} -.styles .download-btn { - color: rgba(0, 0, 0, 0.54); - line-height: 20px; - display: flex; - font-weight: 300; - margin-bottom: 20px; -} -.styles .download-btn.download-btn--customizer .material-icons { - margin-top: -2px; -} -.styles .download-btn > * { - margin-right: 8px; -} -.styles .styles__ribbon { - background-color: #4A148C; - width: 100vw; - margin: 80px 0; - margin-left: -40px; - height: 320px; - display: flex; - flex-direction: row; - justify-content: center; - align-items: stretch; -} -.styles .styles__ribbon > .ribbon__imagecontainer { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -} -.styles .styles__ribbon > .ribbon__imagecontainer > .ribbon__image { - display: block; - margin-bottom: 48px; - border: 0; -} -.styles .styles__ribbon > .ribbon__imagecontainer > .ribbon__caption { - color: white; - text-transform: uppercase; - font-size: 16px; - font-weight: 500; - height: 24px; - line-height: 24px; - text-align: center; -} -.styles .styles__ribbon > .ribbon__imagecontainer > .ribbon__caption.ribbon__caption--split { - width: 100%; - text-align: left; -} -.styles .styles__ribbon > .ribbon__imagecontainer > .ribbon__caption > .material-icons { - height: 24px; - line-height: 24px; - vertical-align: middle; - margin-top: -1px; -} -.styles .styles__ribbon > .ribbon__imagecontainer > .ribbon__caption.ribbon__caption--split > .material-icons { - float: right; -} -.styles .content .docs-text-styling h3 { - text-transform: none; - margin: 0; - font-size: 14px; - font-weight: 700; -} -.styles .content .docs-text-styling p { - margin-top: 0; -} -.styles img.customizer { - max-width: 450px; -} -.styles .code-with-text { - margin-right: 40px; -} -.styles .docs-layout.is-small-screen .code-with-text pre[class*=language-markup]{ - width: 100vw; - max-width: none; -} -.styles .content ul, -.components .content ul { - font-size: 13px; -} -.styles .content li:before { - font-size: 16px; -} -.styles .content .mdl-cell.left-col { - padding-right: 40px; -} -.styles .content .mdl-cell.right-col { - margin-bottom: 40px; -} -.styles .code-with-text { - margin-bottom: 20px; -} -.styles .content .styles__content { - max-width: 960px; - margin: 0 auto; -} -.styles .styles__download { - display: flex; -} -.styles .styles__download a { - font-weight: 500; - margin-right: 16px; -} -.styles .styles__content a .customizer { - border: 0; -} - -@media (max-width: 850px) { - .started .docs-layout .docs-text-styling pre[class*=language-markup] { - max-width: none; - } - .docs-layout .code-with-text { - width: 100%; - margin-left: -40px; - margin-right: -40px; - padding: 15px 40px; - display: block; - box-sizing: content-box; - } - .docs-layout .code-with-text pre { - width: auto; - padding-left: 40px; - padding-right: 40px; - margin-left: -40px; - margin-right: -40px; - } -} -@media (-webkit-min-device-pixel-ratio: 2), /* Webkit-based browsers */ - (min--moz-device-pixel-ratio: 2), /* Older Firefox browsers (prior to Firefox 16) */ - (min-resolution: 2dppx), /* The standard way */ - (min-resolution: 192dpi) /* dppx fallback */ { - .social-btn__twitter { - background-image: url('https://www.gstatic.com/images/icons/material/system/2x/post_twitter_white_24dp.png'); - } - .social-btn__gplus { - background-image: url('https://www.gstatic.com/images/icons/material/system/2x/post_gplus_white_24dp.png'); - } - .templates .docs-layout-header { - background-image: url('templates_2x.png'); - } - .showcase .docs-layout-header { - background-image: url('templates_2x.png'); - } - .components .docs-layout-header { - background-image: url('components_2x.png'); - } - .styles .docs-layout-header { - background-image: url('styles_2x.png'); - } - .customize .docs-layout-header { - background-image: url('customize_2x.png'); - } - .about .docs-layout-header { - background: url('logo.svg'), url('header_2x.jpg'); - background-size: auto 30%, cover; - background-repeat: no-repeat, no-repeat; - background-position: center center, center center; - } -} -.docs-navigation .spacer { - flex-grow: 1; -} -.components .docs-layout.is-small-screen .docs-text-styling pre { - margin: 0 -16px; - width: 100vw; - max-width: 640px; -} -.docs-text-styling p { - margin-top: 16px; - margin-bottom: 16px; -} -.components .content blockquote { - font-size: 13px; - max-width: 640px; - box-sizing: border-box; - margin-top: 15px; - padding: 15px; - background-color: rgb(255, 255, 255); - border-radius: 3px; - margin-left: 0; -} -.components .content blockquote:before, -.components .content blockquote:after { - display: none; -} -/* .started .caption h4 { - font-size: 13px; - font-weight: normal; - font-style: italic; - margin-top: 0; -} - */ - -/* faq */ -.faq .docs-text-styling > section { - max-width: 960px; - margin: 0 auto; -} -.faq img { - max-width: 100%; -} -.faq .mdl-tabs__tab-bar { - justify-content: flex-start; - border-bottom: 0; -} -.faq .mdl-tabs.is-upgraded .mdl-tabs__tab.is-active { - color: #00ACC1; -} -.faq .mdl-tabs.is-upgraded .mdl-tabs__tab.is-active:after { - background-color: #00ACC1; -} -.faq .docs-layout-content { - text-align: center; -} -.faq .chapter-toc { - display: table; -} -.faq .content h3 { - display: table-cell; - width: 140px; - font-size: 15px; - font-weight: bold; - padding-right: 60px; - line-height: 25px; -} -.faq .content section { - margin-bottom: 30px; -} -.faq .section-content { - display: table-cell; -} -.faq .content p { - margin-top: 10px; - margin-bottom: 15px; -} -.faq .mdl-tabs { - margin-bottom: 22px; -} -.faq .content h4 { - font-size: 15px; - font-weight: bold; - margin-bottom: 5px; - margin-top: 20px; -} -.faq .content .mdl-tabs__panel { - padding-top: 10px; -} -.faq .docs-layout.is-small-screen .docs-toc > * { - display: block; -} -.faq .caption { - font-size: 13px; - max-width: 640px; - box-sizing: border-box; - margin-top: 15px; - padding: 15px; - background-color: rgb(255, 255, 255); - border-radius: 3px; -} -.faq .caption h4 { - font-size: 13px; - font-weight: normal; - font-style: italic; - margin-top: 0; -} -.faq ol { - padding-left: 18px; - font-size: 13px; - max-width: 640px; - box-sizing: border-box; -} -.faq pre { - width: 640px; - box-sizing: border-box; - word-wrap: break-word; -} -.faq .snippet-group { - max-width: 640px; - margin: 60px 0 40px 0; -} diff --git a/docs/_assets/main.js b/docs/_assets/main.js deleted file mode 100644 index 62fdddff7..000000000 --- a/docs/_assets/main.js +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/*global MaterialCustomizer:true,Prism:true,ga:true*/ - -// Navbar scroll buttons -(function() { - 'use strict'; - - var rightScroll = document.querySelector('.scrollindicator.scrollindicator--right'); - var leftScroll = document.querySelector('.scrollindicator.scrollindicator--left'); - var menuBar = document.querySelector('.docs-navigation'); - var delta = 40; - - function updateScrollIndicator() { - leftScroll.classList.remove('disabled'); - rightScroll.classList.remove('disabled'); - if (menuBar.scrollLeft <= 0) { - leftScroll.classList.add('disabled'); - } - // 5px tolerance because browsers! - if (menuBar.scrollLeft + menuBar.clientWidth + 5 >= menuBar.scrollWidth) { - rightScroll.classList.add('disabled'); - } - } - menuBar.addEventListener('scroll', updateScrollIndicator); - updateScrollIndicator(); - - function scrollMenuBar(delta) { - menuBar.scrollLeft += delta; - } - - rightScroll.addEventListener('click', scrollMenuBar.bind(null, delta)); - rightScroll.addEventListener('tap', scrollMenuBar.bind(null, delta)); - leftScroll.addEventListener('click', scrollMenuBar.bind(null, -delta)); - leftScroll.addEventListener('tap', scrollMenuBar.bind(null, -delta)); -})(); - -(function() { - 'use strict'; - - var downloadButton = document.querySelector('.download-button-container'); - if (downloadButton) { - downloadButton.addEventListener('click', function() { - ga('send', { - hitType: 'event', - eventCategory: 'click', - eventAction: 'mdl-download' - }); - }); - } - -})(); - -// Disable empty links in demo's to prevent refresh page -(function () { - 'use strict'; - var emptyLinks = document.querySelectorAll('[href=""]'); - Array.prototype.forEach.call(emptyLinks, function(link) { - link.addEventListener('click', function (event){ - event.preventDefault(); - }); - }); -})(); \ No newline at end of file diff --git a/docs/_assets/mo.svg b/docs/_assets/mo.svg deleted file mode 100644 index bf26f8966..000000000 --- a/docs/_assets/mo.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - mo - Created with Sketch. - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/_assets/rich-media-gallery.png b/docs/_assets/rich-media-gallery.png deleted file mode 100755 index 92266c164..000000000 Binary files a/docs/_assets/rich-media-gallery.png and /dev/null differ diff --git a/docs/_assets/shapes.svg b/docs/_assets/shapes.svg deleted file mode 100644 index e78fec291..000000000 --- a/docs/_assets/shapes.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - 03 - Created with Sketch. - - - - - \ No newline at end of file diff --git a/docs/_assets/showcase/contributor.jpg b/docs/_assets/showcase/contributor.jpg deleted file mode 100644 index 43c6bc25b..000000000 Binary files a/docs/_assets/showcase/contributor.jpg and /dev/null differ diff --git a/docs/_assets/showcase/contributor_2x.jpg b/docs/_assets/showcase/contributor_2x.jpg deleted file mode 100644 index 5b8ea9a0a..000000000 Binary files a/docs/_assets/showcase/contributor_2x.jpg and /dev/null differ diff --git a/docs/_assets/showcase/developers.jpg b/docs/_assets/showcase/developers.jpg deleted file mode 100644 index 3421956ae..000000000 Binary files a/docs/_assets/showcase/developers.jpg and /dev/null differ diff --git a/docs/_assets/showcase/developers_2x.jpg b/docs/_assets/showcase/developers_2x.jpg deleted file mode 100644 index 03d3ff754..000000000 Binary files a/docs/_assets/showcase/developers_2x.jpg and /dev/null differ diff --git a/docs/_assets/showcase/rework.jpg b/docs/_assets/showcase/rework.jpg deleted file mode 100644 index 01cc55b4e..000000000 Binary files a/docs/_assets/showcase/rework.jpg and /dev/null differ diff --git a/docs/_assets/showcase/rework_2x.jpg b/docs/_assets/showcase/rework_2x.jpg deleted file mode 100644 index 9b9c1f6d4..000000000 Binary files a/docs/_assets/showcase/rework_2x.jpg and /dev/null differ diff --git a/docs/_assets/showcase/sunroof.jpg b/docs/_assets/showcase/sunroof.jpg deleted file mode 100644 index ceb2b2289..000000000 Binary files a/docs/_assets/showcase/sunroof.jpg and /dev/null differ diff --git a/docs/_assets/showcase/sunroof_2x.jpg b/docs/_assets/showcase/sunroof_2x.jpg deleted file mode 100644 index a6f4ec2d2..000000000 Binary files a/docs/_assets/showcase/sunroof_2x.jpg and /dev/null differ diff --git a/docs/_assets/showcase/wallet.jpg b/docs/_assets/showcase/wallet.jpg deleted file mode 100644 index 7a9a6c476..000000000 Binary files a/docs/_assets/showcase/wallet.jpg and /dev/null differ diff --git a/docs/_assets/showcase/wallet_2x.jpg b/docs/_assets/showcase/wallet_2x.jpg deleted file mode 100644 index f4c455634..000000000 Binary files a/docs/_assets/showcase/wallet_2x.jpg and /dev/null differ diff --git a/docs/_assets/showcase/work_partners.jpg b/docs/_assets/showcase/work_partners.jpg deleted file mode 100644 index e765169b4..000000000 Binary files a/docs/_assets/showcase/work_partners.jpg and /dev/null differ diff --git a/docs/_assets/showcase/work_partners_2x.jpg b/docs/_assets/showcase/work_partners_2x.jpg deleted file mode 100644 index afc515bb0..000000000 Binary files a/docs/_assets/showcase/work_partners_2x.jpg and /dev/null differ diff --git a/docs/_assets/sliders_degradation.png b/docs/_assets/sliders_degradation.png deleted file mode 100644 index c64beac37..000000000 Binary files a/docs/_assets/sliders_degradation.png and /dev/null differ diff --git a/docs/_assets/snippets.js b/docs/_assets/snippets.js deleted file mode 100644 index a518c0a57..000000000 --- a/docs/_assets/snippets.js +++ /dev/null @@ -1,115 +0,0 @@ -/** - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -function MaterialComponentsSnippets() { - 'use strict'; - - // Find all code snippets. - this.snippets = document.querySelectorAll('code.language-markup'); - this.init(); -} - -/** - * Initializes the MaterialComponentsSnippets components. - */ -MaterialComponentsSnippets.prototype.init = function() { - 'use strict'; - - [].slice.call(this.snippets).forEach(function(snippet) { - snippet.addEventListener('click', this.onMouseClickHandler(snippet)); - snippet.addEventListener('mouseout', this.onMouseOutHandler(snippet)); - }, this); -}; - -/** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * @enum {string} - * @private - */ -MaterialComponentsSnippets.prototype.CssClasses_ = { - COPIED: 'copied', - NOT_SUPPORTED: 'nosupport' -}; - -/** - * Copies content of a element into the system clipboard. - * Not all browsers may be supported. See the following for details: - * http://caniuse.com/clipboard - * https://developers.google.com/web/updates/2015/04/cut-and-copy-commands - * @param {HTMLElement} snippet The element containing the snippet code - * @return {bool} whether the copy operation is succeeded - */ -MaterialComponentsSnippets.prototype.copyToClipboard = function(snippet) { - 'use strict'; - - var sel = window.getSelection(); - var snipRange = document.createRange(); - snipRange.selectNodeContents(snippet); - sel.removeAllRanges(); - sel.addRange(snipRange); - var res = false; - try { - res = document.execCommand('copy'); - } catch (err) { - // copy command is not available - console.error(err); - } - sel.removeAllRanges(); - return res; -}; - -/** - * Returns a mouseClickHandler for a snippet element. - * @param {HTMLElement} snippet The element containing the snippet code - * @return {function} the click handler - */ -MaterialComponentsSnippets.prototype.onMouseClickHandler = function(snippet) { - 'use strict'; - - return function() { - if (window.getSelection().toString().length > 0) { - // user has selected some text manually - // don't do anything - return; - } - var cls = this.CssClasses_.COPIED; - if (!this.copyToClipboard(snippet)) { - cls = this.CssClasses_.NOT_SUPPORTED; - } - snippet.classList.add(cls); - }.bind(this); -}; - -/** - * Returns a mouseOutHandler for a snippet element. - * @param {HTMLElement} snippet The element containing the snippet code - * @return {function} the click handler - */ -MaterialComponentsSnippets.prototype.onMouseOutHandler = function(snippet) { - 'use strict'; - - return function() { - snippet.classList.remove(this.CssClasses_.COPIED); - }.bind(this); -}; - -window.addEventListener('load', function() { - 'use strict'; - - new MaterialComponentsSnippets(); -}); diff --git a/docs/_assets/styles.png b/docs/_assets/styles.png deleted file mode 100755 index 58f4abb48..000000000 Binary files a/docs/_assets/styles.png and /dev/null differ diff --git a/docs/_assets/styles.svg b/docs/_assets/styles.svg deleted file mode 100644 index da1cc22b7..000000000 --- a/docs/_assets/styles.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - styles - Created with Sketch. - - - - - - - - - - \ No newline at end of file diff --git a/docs/_assets/styles_2x.png b/docs/_assets/styles_2x.png deleted file mode 100755 index 86af59afa..000000000 Binary files a/docs/_assets/styles_2x.png and /dev/null differ diff --git a/docs/_assets/styles_mo.svg b/docs/_assets/styles_mo.svg deleted file mode 100644 index 553a4ae82..000000000 --- a/docs/_assets/styles_mo.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - styles - Created with Sketch. - - - - - - - - - - \ No newline at end of file diff --git a/docs/_assets/table_degradation.png b/docs/_assets/table_degradation.png deleted file mode 100644 index 6a5171a1b..000000000 Binary files a/docs/_assets/table_degradation.png and /dev/null differ diff --git a/docs/_assets/template-preview.png b/docs/_assets/template-preview.png deleted file mode 100755 index 80a010c0f..000000000 Binary files a/docs/_assets/template-preview.png and /dev/null differ diff --git a/docs/_assets/templates.png b/docs/_assets/templates.png deleted file mode 100755 index b41fd54bc..000000000 Binary files a/docs/_assets/templates.png and /dev/null differ diff --git a/docs/_assets/templates.svg b/docs/_assets/templates.svg deleted file mode 100644 index 910d8a35d..000000000 --- a/docs/_assets/templates.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - templates_mo - Created with Sketch. - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/_assets/templates/android-dot-com.jpg b/docs/_assets/templates/android-dot-com.jpg deleted file mode 100644 index 0bbebe13b..000000000 Binary files a/docs/_assets/templates/android-dot-com.jpg and /dev/null differ diff --git a/docs/_assets/templates/android-dot-com_2x.jpg b/docs/_assets/templates/android-dot-com_2x.jpg deleted file mode 100644 index 23c16b1e8..000000000 Binary files a/docs/_assets/templates/android-dot-com_2x.jpg and /dev/null differ diff --git a/docs/_assets/templates/article.jpg b/docs/_assets/templates/article.jpg deleted file mode 100644 index e2d5cb0f8..000000000 Binary files a/docs/_assets/templates/article.jpg and /dev/null differ diff --git a/docs/_assets/templates/article_2x.jpg b/docs/_assets/templates/article_2x.jpg deleted file mode 100644 index 89b2e8c38..000000000 Binary files a/docs/_assets/templates/article_2x.jpg and /dev/null differ diff --git a/docs/_assets/templates/blog.jpg b/docs/_assets/templates/blog.jpg deleted file mode 100644 index 24f9c534d..000000000 Binary files a/docs/_assets/templates/blog.jpg and /dev/null differ diff --git a/docs/_assets/templates/blog_2x.jpg b/docs/_assets/templates/blog_2x.jpg deleted file mode 100644 index 41885efe5..000000000 Binary files a/docs/_assets/templates/blog_2x.jpg and /dev/null differ diff --git a/docs/_assets/templates/dashboard.jpg b/docs/_assets/templates/dashboard.jpg deleted file mode 100644 index 432be9837..000000000 Binary files a/docs/_assets/templates/dashboard.jpg and /dev/null differ diff --git a/docs/_assets/templates/dashboard_2x.jpg b/docs/_assets/templates/dashboard_2x.jpg deleted file mode 100644 index ac2ba0795..000000000 Binary files a/docs/_assets/templates/dashboard_2x.jpg and /dev/null differ diff --git a/docs/_assets/templates/general.jpg b/docs/_assets/templates/general.jpg deleted file mode 100644 index 94346a165..000000000 Binary files a/docs/_assets/templates/general.jpg and /dev/null differ diff --git a/docs/_assets/templates/general_2x.jpg b/docs/_assets/templates/general_2x.jpg deleted file mode 100644 index d30257dd2..000000000 Binary files a/docs/_assets/templates/general_2x.jpg and /dev/null differ diff --git a/docs/_assets/templates/portfolio.jpg b/docs/_assets/templates/portfolio.jpg deleted file mode 100644 index c58320de3..000000000 Binary files a/docs/_assets/templates/portfolio.jpg and /dev/null differ diff --git a/docs/_assets/templates/portfolio_2x.jpg b/docs/_assets/templates/portfolio_2x.jpg deleted file mode 100644 index 69f2218d6..000000000 Binary files a/docs/_assets/templates/portfolio_2x.jpg and /dev/null differ diff --git a/docs/_assets/templates/product.jpg b/docs/_assets/templates/product.jpg deleted file mode 100644 index c63c80a65..000000000 Binary files a/docs/_assets/templates/product.jpg and /dev/null differ diff --git a/docs/_assets/templates/product_2x.jpg b/docs/_assets/templates/product_2x.jpg deleted file mode 100644 index 1c4cbfae8..000000000 Binary files a/docs/_assets/templates/product_2x.jpg and /dev/null differ diff --git a/docs/_assets/templates/text-only.jpg b/docs/_assets/templates/text-only.jpg deleted file mode 100644 index f2e219ac8..000000000 Binary files a/docs/_assets/templates/text-only.jpg and /dev/null differ diff --git a/docs/_assets/templates/text-only_2x.jpg b/docs/_assets/templates/text-only_2x.jpg deleted file mode 100644 index d49f542b8..000000000 Binary files a/docs/_assets/templates/text-only_2x.jpg and /dev/null differ diff --git a/docs/_assets/templates_2x.png b/docs/_assets/templates_2x.png deleted file mode 100755 index d417c67e0..000000000 Binary files a/docs/_assets/templates_2x.png and /dev/null differ diff --git a/docs/_assets/templates_mo.svg b/docs/_assets/templates_mo.svg deleted file mode 100644 index 3f74cf225..000000000 --- a/docs/_assets/templates_mo.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - templates_mo - Created with Sketch. - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/_pages/components.md b/docs/_pages/components.md deleted file mode 100644 index fdd699828..000000000 --- a/docs/_pages/components.md +++ /dev/null @@ -1,387 +0,0 @@ ---- -layout: components -title: Components -bodyclass: components -include_prefix: ../ -categories: - - name: badges - title: Badges - description: Small status descriptors for UI elements. - components: - - name: badge - class: mdl-badge - snippets: - - snippet_group: - - caption: Number - file: badge-on-icon-text.html - demo_file: badge-on-icon-text-demo.html - - caption: Icon - file: badge-on-icon-icon.html - demo_file: badge-on-icon-icon-demo.html - - snippet_group: - - caption: Number - file: badge-on-text-text.html - demo_file: badge-on-text-text-demo.html - - caption: Icon - file: badge-on-text-icon.html - demo_file: badge-on-text-icon-demo.html - - name: buttons - title: Buttons - description: Variations on Material Design buttons. - components: - - name: button - class: mdl-button - snippets: - - snippet_group: - - caption: Colored FAB - file: fab-colored.html - - caption: With ripple - file: fab-colored-ripple.html - - snippet_group: - - caption: Plain FAB - file: fab.html - - caption: With ripple - file: fab-ripple.html - - caption: Disabled - file: fab-disabled.html - - snippet_group: - - caption: Raised Button - file: raised.html - - caption: With ripple - file: raised-ripple.html - - caption: Disabled - file: raised-disabled.html - - snippet_group: - - caption: Colored button - file: raised-colored.html - - caption: Accent colored - file: raised-accent.html - - caption: With Ripples - file: raised-ripple-accent.html - - snippet_group: - - caption: Flat button - file: flat.html - - caption: With ripple - file: flat-ripple.html - - caption: Disabled - file: flat-disabled.html - - snippet_group: - - caption: Primary colored flat - file: flat-primary.html - - caption: Accent colored flat - file: flat-accent.html - - snippet_group: - - caption: Icon button - file: icon.html - - caption: Colored - file: icon-colored.html - - snippet_group: - - caption: Mini FAB - file: fab-mini.html - - caption: Colored - file: fab-mini-colored.html - - name: cards - title: Cards - description: Self-contained pieces of paper with data. - components: - - name: card - class: mdl-card - snippets: - - snippet_group: - - caption: Wide - file: wide.html - - snippet_group: - - caption: Square - file: square.html - - snippet_group: - - caption: Image - file: image.html - - caption: Event - file: event.html - - name: dialog - title: Dialogs - description: Modal windows for dedicated user input. - components: - - name: dialog - class: mdl-dialog - warning: Dialogs use the HTML element, which currently has very - limited cross-browser support. To ensure support across all modern - browsers, please consider using a polyfill or creating your own. - There is no polyfill included with MDL. - - name: layout - title: Layout - description: Building blocks for constructing a page layout. - components: - - name: layout - caption: Navigation layouts - class: mdl-layout - snippets: - - snippet_group: - - caption: Transparent header - file: transparent.html - demo_file: transparent-demo.html - full_width: true - - snippet_group: - - caption: Fixed drawer, no header - file: fixed-drawer.html - demo_file: fixed-drawer-demo.html - full_width: true - - snippet_group: - - caption: Fixed header - file: fixed-header.html - demo_file: fixed-header-demo.html - full_width: true - - snippet_group: - - caption: Fixed header and drawer - file: fixed-header-drawer.html - demo_file: fixed-header-drawer-demo.html - full_width: true - - snippet_group: - - caption: Scrolling header - file: scrolling-header.html - demo_file: scrolling-header-demo.html - full_width: true - - snippet_group: - - caption: Waterfall header - file: waterfall-header.html - demo_file: waterfall-header-demo.html - full_width: true - - snippet_group: - - caption: Scrollable tabs - file: scrollable-tabs.html - demo_file: scrollable-tabs-demo.html - full_width: true - - snippet_group: - - caption: Fixed tabs - file: fixed-tabs.html - demo_file: fixed-tabs-demo.html - full_width: true - - name: grid - caption: Grid - class: mdl-grid - snippets: - - snippet_group: - - caption: Responsive grid - file: grid.html - demo_file: grid-demo.html - extra_codepen_css: codepen-grid.css - full_width: true - - name: tabs - caption: Tabs - class: mdl-tabs - snippets: - - snippet_group: - - caption: Content tabs - file: tabs.html - - name: footer - caption: Footer - class: mdl-mega-footer / mdl-mini-footer - snippets: - - snippet_group: - - caption: Mega footer - file: mega-footer.html - full_width: true - - snippet_group: - - caption: Mini footer - file: mini-footer.html - full_width: true - - name: lists - title: Lists - description: Customizable scrollable lists. - components: - - name: list - class: mdl-list - snippets: - - snippet_group: - - caption: Simple list - file: list-item.html - - snippet_group: - - caption: Icons - file: icon.html - - snippet_group: - - caption: Avatars and actions - file: action.html - - snippet_group: - - caption: Avatars and controls - file: list-control.html - - snippet_group: - - caption: Two line - file: two-line.html - - snippet_group: - - caption: Three line - file: three-line.html - - name: loading - title: Loading - description: Indicate loading and progress states. - components: - - name: progress - caption: Progress bar - class: mdl-progress - snippets: - - snippet_group: - - caption: Default - file: progress-default.html - demo_file: progress-default-demo.html - - snippet_group: - - caption: Indeterminate - file: progress-indeterminate.html - demo_file: progress-indeterminate-demo.html - - snippet_group: - - caption: Buffering - file: progress-buffering.html - demo_file: progress-buffering-demo.html - - name: spinner - caption: Spinner - class: mdl-spinner - snippets: - - snippet_group: - - caption: Default - file: spinner-default.html - - caption: Single color - file: spinner-single-color.html - - name: menus - title: Menus - description: Lists of clickable actions. - components: - - name: menu - class: mdl-menu - snippets: - - snippet_group: - - caption: Lower left - file: lower-left.html - demo_file: lower-left-demo.html - extra_codepen_css: codepen-lower-buttons.css - - caption: Lower right - file: lower-right.html - demo_file: lower-right-demo.html - - snippet_group: - - caption: Top left - file: top-left.html - demo_file: top-left-demo.html - extra_codepen_css: codepen-top-buttons.css - - caption: Top right - file: top-right.html - demo_file: top-right-demo.html - - name: sliders - title: Sliders - description: Selecting a value out of a range. - components: - - name: slider - class: mdl-slider - snippets: - - snippet_group: - - caption: Default slider - file: slider-default.html - demo_file: slider-default-demo.html - - caption: Starting value - file: slider-starting-value.html - demo_file: slider-starting-value-demo.html - - name: snackbar - title: Snackbar - description: Transient popup notifications. - components: - - name: snackbar - class: mdl-snackbar - snippets: - - snippet_group: - - caption: Snackbar - file: snackbar.html - - snippet_group: - - caption: Toast - file: toast.html - - name: toggles - title: Toggles - description: Choose between states. - components: - - name: checkbox - caption: Checkbox - class: mdl-checkbox - snippets: - - snippet_group: - - caption: Check on - file: check-on.html - - caption: Check off - file: check-off.html - - name: radio - caption: Radio button - class: mdl-radio - snippets: - - snippet_group: - - caption: Radio on - file: radio-on.html - - caption: Radio off - file: radio-off.html - - name: icon-toggle - caption: Icon toggle - class: mdl-icon-toggle - snippets: - - snippet_group: - - caption: Icon on - file: icon-on.html - - caption: Icon off - file: icon-off.html - - name: switch - caption: Switch - class: mdl-switch - snippets: - - snippet_group: - - caption: Switch on - file: switch-on.html - - caption: Switch off - file: switch-off.html - - name: tables - title: Tables - description: Organize data. - components: - - name: data-table - class: mdl-data-table - snippets: - - snippet_group: - - caption: Data table - file: data-table.html - - name: textfields - title: Text Fields - description: Textual input components. - components: - - name: textfield - class: mdl-textfield - snippets: - - snippet_group: - - caption: Text - file: textfield-text.html - demo_file: textfield-text-demo.html - - caption: Numeric - file: textfield-numeric.html - demo_file: textfield-numeric-demo.html - - snippet_group: - - caption: Text with floating label - file: textfield-floating-text.html - demo_file: textfield-floating-text-demo.html - - caption: Numeric with floating label - file: textfield-floating-numeric.html - demo_file: textfield-floating-numeric-demo.html - - snippet_group: - - caption: Multiple line - file: textfield-multi-line.html - demo_file: textfield-multi-line-demo.html - - caption: Expanding - file: textfield-expanding.html - demo_file: textfield-expanding-demo.html - - name: tooltips - title: Tooltips - description: Useful information on hover. - components: - - name: tooltip - class: mdl-tooltip - snippets: - - snippet_group: - - caption: Simple - file: tooltip-simple.html - - caption: Large - file: tooltip-large.html - - snippet_group: - - caption: Rich - file: tooltip-rich.html - - caption: Multiple lines - file: tooltip-multiline.html ---- diff --git a/docs/_pages/customize.md b/docs/_pages/customize.md deleted file mode 100644 index 9c6f00ab3..000000000 --- a/docs/_pages/customize.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -layout: customize -title: Customize & Download -bodyclass: customize -include_prefix: ../ ---- diff --git a/docs/_pages/faq.md b/docs/_pages/faq.md deleted file mode 100644 index 113d45aee..000000000 --- a/docs/_pages/faq.md +++ /dev/null @@ -1,200 +0,0 @@ ---- -layout: styles -title: FAQ -bodyclass: faq -include_prefix: ../ ---- - -
-
-

Contents

- -
- -

Where should I use Material Design Lite (MDL)?

- -If you’re interested in a [Material Design](https://www.google.com/design/spec/material-design/introduction.html) experience using vanilla Web technologies like CSS, JavaScript and HTML, MDL might be a useful option to consider. We optimise for websites heavy on content, such as marketing pages, articles, blogs and general web content that isn’t particularly app-y. If you just want to pick some colors, customise a template and ship a Material experience, we try to help make that process simpler. - -Whilst there exist several community-driven options for Material Design, our experience has shown that there are several gaps in the Material specification when it comes to the web. Rather than guessing how these gaps should be filled (something we know the community has struggled with), we’ve opted for a close collaboration with the Material Design team to provide a Material library that is both spec compatible for today and provides guidance on aspects of the spec still being evolved. - -

What CSS naming conventions does MDL use?

- -MDL was written using [BEM](https://en.bem.info/method/). BEM stands for Block, Element, Modifier. It is a method used to construct CSS class-names so they are consistent, isolated, and expressive. A few good resources for learning more about BEM methods are: - -* [CSSWizardry](http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/) -* [CSS-Tricks](https://css-tricks.com/bem-101/) -* [Smashing Magazine](http://www.smashingmagazine.com/2012/04/16/a-new-front-end-methodology-bem/) - -These are great resources that simplify the data needed to understand BEM. If you want to read the methodology from the inventors, [Yandex provides the resource](https://en.bem.info/). This reference goes way beyond just the CSS and into the full JavaScript setup they use as well. - -Our [wiki](https://github.com/google/material-design-lite/wiki/Understanding-BEM) includes a section on the namespacing used for MDL specifically. - -

Does MDL support progressive enhancement?

- -MDL’s components were designed from the ground up with progressive enhancement in mind. We attempt to build on native HTML elements as much as possible, relying on JavaScript where absolutely necessary for ‘enhancements’. - -One example of this is our ‘Text only’ Material Design template. Switching JavaScript off in Chrome DevTools, the page still renders CSS fine: - -![A preview of a template rendering in an older version of IE](../assets/template-preview.png) - -This allows us to render important content first and then ‘enhance’ the page with things like Material Design button ripples and pop-out menu components. - -MDL will degrade to a no-JavaScript experience on IE9, though you can pull in polyfills for an enhanced experience. If components require JavaScript to function, such as Layout, these will otherwise need to be planned for in development. IE10+ and evergreen browsers are fully supported. For more details on our browser support, see ‘Which browsers does MDL support?’. - -Note: the MDL site itself attempts to use progressive enhancement where possible. We do however have aspects of the site (e.g our component page) that rely more heavily on JS. The MDL Templates and Components otherwise try to render as well as they can with JS off. - -

Which browsers does MDL support?

- -The complete MDL experience should work in the last two versions of all evergreen browsers, whilst we gracefully degrade to CSS-only in browsers like IE9 that don’t pass our [Cutting-the-mustard](https://github.com/google/material-design-lite/blob/9e6c6ec9237715bfa04b307f786e9073f943e6be/src/mdlComponentHandler.js#L333) test. - -Our [browser compatibility matrix](https://github.com/google/material-design-lite/#browser-support) has the most up to date information on the browsers we officially support. For components, at minimum we require support for [querySelector](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector), [classList](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList) and [addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener), which can be [polyfilled](https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills) as needed. Our Templates will work in IE10+, primarily due to our use of Flexbox. - -The polyfills that we’re currently using for the MDL site to improve support in oldIE are the following: - -```html - -``` - -IE10 standards mode [removes](http://bit.ly/1dypChT) support for conditional comments, so the above will only get interpreted by older versions of IE, such as IE9. - -We do not officially support IE8. That said, some components will degrade using the CSS-only (or native HTML element) experience there better than others. For example: - -**Buttons** - -Buttons rendering in IE8 - -**Tables** - -Tables gracefully degrading in IE8 - -**Sliders (degrade to input fields)** - -Sliders degrading in IE8 to input fields - -

Does MDL play nicely with Polymer? Is it a replacement for the Paper elements?

- -MDL focuses on delivering an experience that is optimised for static content sites, like blogs, marketing pages and more traditional text-based web pages. - -The Paper elements built with Polymer are fully encapsulated components that can be used individually or composed together to create a material design-style site, and support more advanced user interaction. - -That said, MDL can be used alongside the Polymer element counterparts. Polymer uses the power of Web Components to encapsulate the designs used for those components. MDL does not affect the styling within custom components. - -

Is MDL comparable to Bootstrap?

- -*If we're using it instead of Bootstrap, can we expect the same level of component styling?* - -Material Design can replace many parts of Bootstrap. However, it does not intend to feature-match everything Bootstrap offers. Instead MDL intends to implement the components specified by the Material Design specification. This allows it to provide the most comprehensive and accurate solution available. - -

How does it compare to existing Material CSS implementations?

- -*Materialize, Material Bootstrap, etc* - -We think the community does a great job offering their own take on how Material Design should be implemented for CSS libraries. - -That said, the large, diverse number of implementations available are often quite liberal with their interpretation of the spec (not their fault!) and their opinions don’t always reflect what the Material Design team would consider ‘correct’. MDL was developed in close collaboration with the Material Design and Chrome UX teams and undergoes regular reviews for spec compliance. When we run into an area of the spec that isn’t yet fully fleshed out, MDL is able to offer reviewed opinions on how these should be solved in a way that tries to stay true to Material Design. - -

Should I use the minified, CDN or Sass versions of MDL?

- -*Should I build my own version or download the minified version or simply refer to CDN objects?* - -**Minified: **If it’s your first time using MDL, we recommend downloading one of the default packages from the ‘Getting Started’ page that include a minified version of our CSS/JS and optionally our pre-made Templates. - -**CDN: **If you’re just prototyping or want to avoid hosting your own copy of the MDL CSS and JS files, you can use our CDN to pull down a heavily edge-cached version. - -**Customiser: **If you’re creating a new site with MDL and are using a custom color scheme, we recommend downloading the default package then generating a custom build using the Customiser tool. You can use this to override the material.min.css file for your own needs. - -**Sass: **If you would prefer to go all in, you can get the Sass version of MDL, which includes our original sources, docs and templates. This version allows maximum customisation using CSS variables and the rest of the Sass goodness you’re used to. - -

What service does the official CDN use?

- -The official CDN is hosted using [Google Cloud Storage](https://cloud.google.com/storage/). - -

How does MDL relate to Web Starter Kit?

- -MDL is an evolutionary step from the styleguide provided in Web Starter Kit. The more [Web Starter Kit](https://developers.google.com/web/tools/starter-kit/) was used, the more it became clear that many developers simply wanted Material Design in their sites. - -The WSK Styleguide also did not align to Material Design fully, it was simply based on the idea. From the WSK project, MDL was born to try and fill this need for developers. In the process making the implementation as faithful as possible to the specification. - -

Do any Google properties use MDL in production?

- -MDL is used in production by a few different Google properties. These use an older, incomplete version but demonstrate what deployed experiences can look like. Examples include: - -The [Google Services](https://developers.google.com/mobile/add) site: - -![Google Services site screenshot](../assets/google-services.png) - -[RichMediaGallery](http://www.richmediagallery.com/) by DoubleClick: - -![RichMediaGallery screenshot](../assets/rich-media-gallery.png) - -and is being used by many other teams on upcoming projects, including Google Shopping. - -

Is there a showcase available of sites using MDL?

- -See the Showcase for an early list of Google sites using MDL in production. - -To request your site be added, please file a [new issue](https://github.com/Google/material-design-lite/issues/new?title=Site%20Showcase%20Request&body=Please%20include:%0A*%20Description%0A*%20Primary%20Link%0A*%20Screenshot) on our GitHub issue tracker. The issue should include a link, a description of the site and a suggested screenshot. - -We hope to add a properly polished showcase to the site in the near future. - -

Can I build or use individual MDL components (e.g a button)?

- -For V1 of MDL we are focused on the use-case of folks who are likely to need a few different components on their page and will want to include most of the MDL library. This means that support and docs around just plucking single components on their own is minimal. - -That said, if you need to generate a build using just a single (or smaller number of) components, you will need to use Gulp with our Sass build. You can [comment out](https://github.com/google/material-design-lite/blob/master/src/material-design-lite.scss) those components you don’t need in material-design-lite.scss, [comment out](https://github.com/google/material-design-lite/blob/master/gulpfile.js#L191) the scripts you don’t need in the Gulpfile and then run `gulp` to create your build. - -We have talked about offering up components in a more modular fashion but will be exploring this in the post V1 timeline. - -

How do I report an issue with MDL?

- -Please let us know about any problems by opening an issue on our [GitHub repo](https://github.com/google/material-design-lite/issues). - -

Where can I get help with questions about using MDL?

- -We encourage the MDL user and developer community to ask questions, and help answer questions, on [Stack Overflow](http://stackoverflow.com), using the `Material-Design-Lite` tag. - -

Are there any presentations or slide-decks available on MDL?

- -We did a preview talk at Google I/O 2015 on MDL and the slides for that talk can be found on [SpeakerDeck](https://speakerdeck.com/gauntface/material-design-lite-preview). - -

Can I request or contribute components to MDL?

- -Sure! There may be components or templates you would like to see implemented in MDL that we don't yet provide. Please feel free to propose them on the Issue Tracker. While we can't guarantee we'll be able to implement them all, we will consider requests and review them at regular intervals. - -

Will MDL support non-Sass preprocessors?

- -*Stylus, Less, PostCSS, etc.* - -MDL is implemented using Sass and there are no current plans to change this. If you wish to maintain a port to another preprocessor, you are more than welcome to. - -

How do I keep updated with issues I'm interested in?

- -Watching the whole repository can introduce a lot of extra noise in your stream. To keep updated with just issues you are interested in you only need to subscribe to that issue. This is done on the issue page by clicking the "Subscribe" button in the right hand sidebar. - -Subscribing to a single issue diff --git a/docs/_pages/index.md b/docs/_pages/index.md deleted file mode 100644 index 3a6271b9b..000000000 --- a/docs/_pages/index.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -layout: layout -bodyclass: about -include_prefix: ./ ---- - -
-
-
Material Design Lite
-
- Material Design Lite lets you add a [Material Design](http://google.com/design/spec) look and feel to your websites. It doesn’t rely on any JavaScript frameworks and aims to optimize for cross-device use, gracefully degrade in older browsers, and offer an experience that is immediately accessible. [Get started now](started/index.html). -
-
-
- -
- Templates -
- -
-

- The MDL components are created with CSS, JavaScript, and HTML. You can use the components to construct web pages and web apps that are attractive, consistent, and functional. Pages developed with MDL will adhere to modern web design principles like browser portability, device independence, and graceful degradation. -

-
- -
- Components -
-
- Styles -
-
- Customize -
- -
-

- The MDL component library includes new versions of common user interface controls such as buttons, check boxes, and text fields, adapted to follow Material Design concepts. The library also includes enhanced and specialized features like cards, column layouts, sliders, spinners, tabs, typography, and more. MDL is free to download and use, and may be used with or without any library or development environment (such as [Web Starter Kit](https://developers.google.com/web/starter-kit/)). It is a cross-browser, cross-OS web developer's toolkit that can be used by anyone who wants to write more productive, portable, and — most importantly — usable web pages. -

-
- diff --git a/docs/_pages/showcase.md b/docs/_pages/showcase.md deleted file mode 100644 index a1f579bf6..000000000 --- a/docs/_pages/showcase.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -layout: showcase -title: 'Showcase: sites using MDL' -bodyclass: showcase -include_prefix: ../ -sites: - - name: wallet - title: Google Wallet - description: Google Wallet allows you to send money to anyone in the US with an email address. It's fast, easy, and free to send directly from your debit card, bank account, or Wallet Balance. - url: https://www.google.com/wallet/ - - name: contributor - title: Google Contributor - description: Contribute a few dollars each month. See fewer ads. It's that simple. The money you contribute helps fund the sites you visit. - url: https://www.google.com/contributor/welcome/ - - name: work_partners - title: Google for Work - description: The Google for Work Partner Program enables you to sell, service, and innovate by leveraging our products and platforms across the Google for Work suite. - url: https://www.google.com/work/partners/ - - name: rework - title: reWork with Google - description: Practices, research, and ideas from Google and other organizations to put people first. - url: https://rework.withgoogle.com/ - - name: developers - title: Google Developers - description: Web Fundamentals is a comprehensive resource for multi-device web development hosted by Google Developers. - url: https://developers.google.com/web/fundamentals/ - - name: sunroof - title: Google Project Sunroof - description: Project Sunroof puts Google's expansive data in mapping and computing resources to use, helping calculate the best solar plan for you. - url: https://www.google.com/get/sunroof/about/ ---- -
-

Material Design Lite is used on a wide range of sites. Below are just a small selection of the Google.com sites that have launched using us. We hope to expand the showcase to cover third-party and community sites built using MDL in the near future. To request your site be added, please file a new issue on our GitHub issue tracker.

-
- diff --git a/docs/_pages/started.md b/docs/_pages/started.md deleted file mode 100644 index fa62d57db..000000000 --- a/docs/_pages/started.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -layout: started -title: Getting started -bodyclass: started -include_prefix: ../ -snippets: - - component_name: button - snippet_group: - - caption: Raised button - file: raised-ripple-accent.html - - caption: Colored FAB - file: fab-colored.html ---- diff --git a/docs/_pages/styles.md b/docs/_pages/styles.md deleted file mode 100644 index d30d59331..000000000 --- a/docs/_pages/styles.md +++ /dev/null @@ -1,223 +0,0 @@ ---- -layout: styles -title: Styles -bodyclass: styles -include_prefix: ../ ---- - -
-

- Material Design Lite is a light-weight implementation of Material Design, - specifically crafted for the web. For more detailed guidelines and - specifications for other platforms please refer to the - - Material Design site - -

- -

Typography

-
-
h1
-
-
Light 112sp
-
- display-4 - font weight 300 -
-
-
h2
-
-
Regular 56sp
-
- display-3 - font weight 400 -
-
-
h3
-
-
Regular 45sp
-
- display-2 - font weight 400 -
-
-
h4
-
-
Regular 34sp
-
- display-1 - font weight 400 -
-
-
h5
-
-
Regular 24sp
-
- headline - font weight 400 -
-
-
h6
-
-
Regular 20sp
-
- title - font weight 500 -
-
-
-
- Note: This portion is only to demonstrate header and display styles for out CSS. For more typography guidelines, please refer to the Material Design spec. -
- -
- To embed Roboto into your web page, copy the code as the first element in the <head> of your HTML document. -
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:300,400,500,700" type="text/css">
-
-
- - - -
-
-

Icons

-

Material Design Icons are the official open-source icons featured in the Google Material Design specification. What’s included:

-
-
-
    -
  • SVG versions of all icons in both 24px and 48px flavours
  • -
  • SVG and CSS sprites of all icons
  • -
  • 1x, 2x icons targeted at the Web (PNG)
  • -
  • 1x, 2x, 3x icons targeted at iOS (PNG)
  • -
  • Hi-dpi version of all icons (hdpi, mdpi, xhdpi, xxhdpi, xxxhdpi) (PNG)
  • -
-
-
-

Getting Started

-

You have a few options for getting the icons.

-

Download the Zip

-

Grab the latest stable zip archive (~57MB) of all icons of the bleeding-edge version from master.

- -
-
-

Bower

-
- Install the icons using the Bower package manager. -
$ bower install material-design-icons --save
-
-

npm

-
- You can also find all the icons on npm. -
$ npm install material-design-icons --save
-
-

Usage

-

Take a look at the included index.html file for a preview of all icons included in the set. You are free to use the icons in the way that makes most sense to your project.

-

Structure

-

In general, an icon category (e.g. action) will include the following directories, containing multiple resolutions of our icons.

-
    -
  • 1x, 2x Web
  • -
  • 1x, 2x, 3x iOS
  • -
  • drawable hdpi, mdpi, xhdpi, xxhdpi, xxxhdpi
  • -
  • svg
  • -
-

Decide on the icon resolution required for your project and copy, then reference the icons you wish to use.

-
-
-

Spritesheets

-

Material Design icons come with SVG and CSS sprites for each category of icon we include. These can be found in the sprites directory, under svg-sprite and css-sprite.

-

Using CSS Sprites

-

To use a CSS spritesheet, reference the stylesheet for the icon category you wish to use, then include the icon definition in your markup. E.g. to use one of the play icons in css-sprite-av.

-

That’s it! Don’t forget to publish the corresponding CSS and SVG/PNG files when deploying your project.

-
-
-
- Reference the stylesheet: -
<link href="css-sprite/sprite-av-black.css" rel="stylesheet">
-
-
- Create an element which will use the icon as a background: -
<div></div>
-
-
- Add a class referencing the icon spritesheet and specific icon icon-ic_play-circle_outline_black_24dp, which you can get from the above stylesheet. -
<div class="icon icon-ic_play-circle_outline_black_24dp"></div>
-
-
-
-

Using SVG Sprites

-

Similarly, to use an SVG spritesheet, reference the stylesheet for the icon category, then include the icon definition in your markup.

-
-
-
- E.g: to use one of the play icons in svg-sprite-av, reference the stylesheet: -
<link href="svg-sprite/svg-sprite-av.css" rel="stylesheet">
-
-
- Create an element which will use the icon as a background: -
<div></div>
-
-
- Next, make sure to set a dimension for the icon. This can either be done inline or via a class. We’ll use a class for this example. -
<style>
-  .svg-ic_play_circle_outline_24px-dims { width: 24px; height: 24px; }
-</style>
-
-
- Finally, set the dimension and specific ifcon svg-ic_play_circle_outline_24px, which you can get from the above stylesheet. -
<div class="svg-ic_play_circle_outline_24px svg-ic_play_circle_outline_24px-dims"> </div>
-
-

Polymer Icons

-

If you wish to use the icon set with Polymer, we recommend consuming them via the <iron-icons>-element. -

License

-

All icons are released under Attribution 4.0 International license.

-
-
- -
-
-

Color palette

-

If you’re using the extended color palette, use the first color as the primary color in your app and the other colors as accents.

-

See all colors and their accessibility ratios. This resource includes info on the appropriate contrast ratios and alpha values when using white or black text on a colored background.

- - -
-
- -
-
diff --git a/docs/_pages/templates.md b/docs/_pages/templates.md deleted file mode 100644 index 892051762..000000000 --- a/docs/_pages/templates.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -layout: templates -title: Templates -bodyclass: templates -include_prefix: ../ -templates: - - name: blog - title: Blog - description: A mobile focused responsive template that showcases image or text based blog entries, a subscription CTA, search & share links, and an expanded article page with comments, counters and bookmarking capabilities built-in. - - name: android-dot-com - title: Android.com MDL skin - description: A Material Design Lite version of the current android.com site, using the same content with a horizontal navigation, feature carousel and long form scrolling sub pages. - - name: dashboard - title: Dashboard - description: A modular responsive template built to display data visualizations and information with a clear vertical nav, user profile, search and dedicated space for updates and filters. - - name: portfolio - title: Portfolio - description: A modern and clean looking template for a portfolio/blog build with Material Design Lite. Included are a top nav bar that comes with the waterfall header component, cards to display different types of content and a footer. - - name: text-only - title: Text-heavy webpage - description: Built for presenting content that is information dense, easily updatable, and optimized for legibility, this template has a sticky horizontal top nav on mobile, feature callouts, cards and a site map footer with a deep-linked table of contents. - - name: article - title: Stand-alone article - description: A clean layout optimized for presenting text-based content with a breadcrumb nav, search, clear headers and a footer that utilizes a card-like structure to showcase the content. ---- diff --git a/docs/_templates/component.html b/docs/_templates/component.html deleted file mode 100644 index 231d0a1c5..000000000 --- a/docs/_templates/component.html +++ /dev/null @@ -1,5 +0,0 @@ - -{% block content %} - -{{content|safe}} -{% endblock %} diff --git a/docs/_templates/components.html b/docs/_templates/components.html deleted file mode 100644 index 551a9e896..000000000 --- a/docs/_templates/components.html +++ /dev/null @@ -1,100 +0,0 @@ -{% extends 'layout.html' %} - -{% block content %} - - - - - -
- -
-
-
-
-
-
COMPONENTS
-
- Material Design Lite (MDL) is a library of components for web developers - based on Google's Material Design Philosophy: "A visual language for our - users that synthesizes the classic principles of good design with the - innovation and possibility of technology and science." Understanding the - goals and principles of Material Design is critical to the proper use of - the Material Design Lite components. If you have not yet read the - Material Design Introduction - you should do so before attempting to use the components. -
-
-
-
-
-
- - {% for category in page.categories -%} -
-
-
-

{{ category.title }}

-

{{ category.description }}

-
- - {% if category.components.length > 1 %} -
- -
- {%- endif %} - - {% for component in category.components %} - - {% if component.caption %} - -

{{ component.caption }}

-
- {%- endif %} - - {% if component.warning %} -
Note: {{ component.warning }}
- {%- endif %} - - {% for snippet_group in component.snippets %} - {% set snippet_group["component_name"] = component.name %} - {% include "./snippets.html" with snippet_group only %} - {%- endfor %} - - {% set demo_css = "../../dist/components/" + component.name + "/demo.css" %} - - {% set demo_js = "../../dist/components/" + component.name + "/demo.js" %} - - {% set demo = "../../src/" + component.name + "/demo.html" %} - {% include demo ignore missing %} -
- {% set doc = "../../dist/components/" + component.name + "/index.html" %} - {% include doc ignore missing %} -
- {%- endfor %} -
-
- {%- endfor %} -
-
- -{% endblock %} diff --git a/docs/_templates/customize.html b/docs/_templates/customize.html deleted file mode 100644 index 1fa911f21..000000000 --- a/docs/_templates/customize.html +++ /dev/null @@ -1,79 +0,0 @@ -{% extends 'layout.html' %} - -{% block content %} - -
-
-
-
- - - - - - - - - - - - - - - - -
-
-
-
- Custom CSS theme builder -

Click on the color wheel to choose a primary (1) and accent (2) color to preview the theme below. When you’ve selected a color combination you like, either reference our hosted CSS or download the CSS by clicking the white button in the middle. You will need to include MDL’s JavaScript alongside your customised CSS to get the full experience. This is included in our default Download from the Getting Started guide.

-
-
-
-
- - - - - - - -
- Theme Preview -
-
-
- Theme Preview - -
-
-

Try it out

-

- Lorem ipsum dolor sit amet. -

- - -
-
-
-
-
-
- CSS hosted on our CDN (17.6kB gzipped): -
 <link rel="stylesheet" href="$$hosted_libs_prefix$$/$$version$$/material.$primary-$accent.min.css" /> 
-
-
-
-
- - -{% endblock %} diff --git a/docs/_templates/demo.html b/docs/_templates/demo.html deleted file mode 100644 index 53f32a92f..000000000 --- a/docs/_templates/demo.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - {{ page.component }} test - - - - - - - - - - - - {% set demo_css = "../../dist/components/" + page.component + "/demo.css" %} - - - - - -
- {% block content %} - {{content|safe}} - {% endblock %} -
- - - {% set demo_js = "../../dist/components/" + page.component + "/demo.js" %} - - - diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html deleted file mode 100644 index 6a60b01d1..000000000 --- a/docs/_templates/layout.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - - Material Design Lite - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - - - -
-
-
-
{{page.title}}
- {% block content %} - {{content|safe}} - {% endblock %} -
-
- Download Kit -
- -
-
- - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_templates/page.html b/docs/_templates/page.html deleted file mode 100644 index 786bf400b..000000000 --- a/docs/_templates/page.html +++ /dev/null @@ -1,7 +0,0 @@ -{% extends 'layout.html' %} - -{% block content %} - -{{content|safe}} - -{% endblock %} diff --git a/docs/_templates/showcase.html b/docs/_templates/showcase.html deleted file mode 100644 index f49cc2d12..000000000 --- a/docs/_templates/showcase.html +++ /dev/null @@ -1,29 +0,0 @@ -{% extends 'layout.html' %} -{% block content %} -{{content|safe}} -{% for template in page.sites %} -
- -
-

{{ template.title }}

-

- {{ template.description }} -

- - - Screenshot - - - - Visit - -
-
-{% endfor %} -{% endblock %} diff --git a/docs/_templates/snippets.html b/docs/_templates/snippets.html deleted file mode 100644 index b185be165..000000000 --- a/docs/_templates/snippets.html +++ /dev/null @@ -1,42 +0,0 @@ -{% if snippet_group.length === 1 && snippet_group[0].full_width %} -
-{% else %} -
-{% endif %} -
-
-
- {% for snippet in snippet_group %} - {% if snippet.demo_file %} - {% set snippet_file = "../../src/" + component_name + "/snippets/" + snippet.demo_file %} - {% else %} - {% set snippet_file = "../../src/" + component_name + "/snippets/" + snippet.file %} - {% endif %} -
-
- {% include snippet_file ignore missing %} -
-
- {%- endfor %} -
-
-
-
- {% for snippet in snippet_group %} -
- {{ snippet.caption }} -
- {%- endfor %} -
-
-
-
-
{% for snippet in snippet_group %}{% set snippet_file = "../../src/" + component_name + "/snippets/" + snippet.file %}{% filter e('html') %}{% include snippet_file ignore missing %}{% endfilter %}
<style>{% set extra_css_file = "../../src/" + component_name + "/snippets/" + snippet.extra_codepen_css %}{% include extra_css_file ignore missing %}</style>
{%- endfor %}{% if snippet_group.length !== 1 || !snippet_group[0].full_width %}
<style> -body { - padding: 20px; - background: #fafafa; - position: relative; -} -</style>
{% endif %}
-
-
diff --git a/docs/_templates/started.html b/docs/_templates/started.html deleted file mode 100644 index 0004272c5..000000000 --- a/docs/_templates/started.html +++ /dev/null @@ -1,260 +0,0 @@ -{% extends 'layout.html' %} - -{% block content %} - - -
-
-

Contents

- -
- -
-

Include the master CSS & JavaScript

-
-

- Include the Material Lite CSS and JavaScript files in each HTML page in your project. We recommend that you use the files hosted on our CDN. You can also customize and download them to host them yourself, build them from our source code or install them in your npm/Bower project. -

- -
-
- Hosted - Download - Build - Bower - npm -
-
-
- Just add the following <link> and <script> elements into your HTML pages (27kB gzipped): -
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
-<link rel="stylesheet" href="$$hosted_libs_prefix$$/$$version$$/material.indigo-pink.min.css">
-<script defer src="$$hosted_libs_prefix$$/$$version$$/material.min.js"></script>
-
-

Choose color scheme

-

- Color schemes used in Material Design are based on a primary and an accent colors which you may want to personalize. These colors are specified in the CSS file name by following this pattern: material.{primary}-{accent}.min.css (e.g. material.indigo-pink.min.css). Our CDN hosts a number of color combinations based on common Material Design colors. To discover and preview available color combinations use our Customize and Preview tool. -

-
-
-

- Download the minified CSS and Javascript now (27kB gzipped): -

- -
- Refer to these files by adding a <link> and a <script> elements into your HTML pages and also include the Material Icon font: -
<link rel="stylesheet" href="./material.min.css">
-<script src="./material.min.js"></script>
-<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
-
-

Choose color scheme

-

- Color schemes used in Material Design are based on a primary and an accent colors which you may want to personalize. Use the Customize and Preview tool to select and preview primary and accent colors combinations for your site. Then download your customized Material Design Lite CSS using the button and simply replace the `material.min.css` with the customized one. -

-
-
-

- Our source code is hosted on GitHub. You'll need to download the code and build it. -

-
- Run the following commands in a shell: -
# Clone/copy the Material Design lite source code.
-git clone https://github.com/google/material-design-lite.git
-# Go into the newly created folder containing the source code.
-cd material-design-lite
-# Install necessary dependencies.
-npm install && npm install -g gulp
-# Build a production version of the components.
-gulp
-
-

You'll find the Material Design Lite library's file in the dist folder. Copy them to your project. -

-
- Refer to these files by adding a <link> and a <script> element into your HTML pages and also include the Material Icon font: -
<link rel="stylesheet" href="./material.min.css">
-<script src="./material.min.js"></script>
-<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
-
-
-

- Note: -

- Using this method you will not be able to customize the color scheme of the MDL elements. If you'd like to customize the color scheme prefer the CDN hosted or downloadable libraries. In this case use our Customize and Preview tool. -
-
-
-

- Simply install Material Design Lite files in your Bower enabled project using: -

-
- Run the following command in a shell: -
bower install material-design-lite --save
-
-

- This will install the Material Design Lite library files in your project's bower_components folder. -

-
- Refer to these files by adding a <link> and a <script> element into your HTML pages and also include the Material Icon font: -
<link rel="stylesheet" href="/bower_components/material-design-lite/material.min.css">
-<script src="/bower_components/material-design-lite/material.min.js"></script>
-<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
-
-
-

- Note: -

- Using this method you will not be able to customize the color scheme of the MDL elements. If you'd like to customize the color scheme prefer the CDN hosted or downloadable libraries. In this case use our Customize and Preview tool. -
-
-
-

- Simply install Material Design Lite files in your npm enabled project using: -

-
- Run the following command in a shell: -
npm install material-design-lite --save
-
-

- This will install the Material Design Lite library files in your project's node_modules folder. -

-
- Refer to these files by adding a <link> and a <script> element into your HTML pages and also include the Material Icon font: -
<link rel="stylesheet" href="/node_modules/material-design-lite/material.min.css">
-<script src="/node_modules/material-design-lite/material.min.js"></script>
-<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
-
-
-

- Note: -

- Using this method you will not be able to customize the color scheme of the MDL elements. If you'd like to customize the color scheme prefer the CDN hosted or downloadable libraries. In this case use our Customize and Preview tool. -
-
-
-

- That's it! You are now ready to add MDL components on your site. -

-
-
- -
-

Use the components

-
- -

- You'll find below a couple of examples of MDL Button elements: a Button with ripples and a FAB Button. Just copy & paste the corresponding source code in the <body> of an HTML page of your project and the elements will render as shown below. -

- - - {% for snippet_group in page.snippets %} - {% include "./snippets.html" with snippet_group only %} - {%- endfor %} - -

- MDL elements can be tweaked and configured by adding CSS classes. For example adding mdl-js-ripple-effect to an MDL Button will add a Ripple effect when the button is clicked and adding mdl-button--fab will change the style of the button to a FAB button. -

-

- There are many other elements available such as Card containers, Sliders, Tables, Menus... For the complete set of MDL elements and options have a look at the components page. -

-

- We also recommend that you check out our templates. These are ready to use website templates using MDL components. Feel free to have a look at them to get started quickly on your next project. -

-
-
- -
-

General rules and principles

-
-

- In general, follow these basic steps to use an MDL component in your HTML page: -

-
    -
  1. Start with a standard HTML element, such as <button>, <div>, or <ul>, depending on the MDL component you want to use. This establishes the element in the page and readies it for MDL modification.
  2. - -
  3. Add one or more MDL-specific CSS classes to the element, such as mdl-button or mdl-tabs__panel, again depending on the component. The classes apply the MDL enhancements to the element and turn it into an MDL component.
  4. -
- -

- Remember to include the meta viewport tag in your document so mobile devices will render correctly. -

-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
- -
-

- A note about HTML elements and MDL CSS classes -

- Material Design Lite uses namespaced BEM classes—which can apply to almost any HTML element—to construct components. For some components you can use almost any element. The examples in each component's documentation use elements that perform well as that component. If you must use elements other than those shown in the examples, we encourage you to experiment to find the best combination of HTML elements and MDL CSS classes for your application. -
-
-
- -
-

Use MDL on dynamic websites

-
-

- Material Design Lite will automatically register and render all elements marked with MDL classes upon page load. - However in the case where you are creating DOM elements dynamically you need to register new elements using the upgradeElement function. Here is how you can dynamically create the same raised button with ripples shown in the section above: -

-
<div id="container"/>
-<script>
-  var button = document.createElement('button');
-  var textNode = document.createTextNode('Click Me!');
-  button.appendChild(textNode);
-  button.className = 'mdl-button mdl-js-button mdl-js-ripple-effect';
-  componentHandler.upgradeElement(button);
-  document.getElementById('container').appendChild(button);
-</script>
-
-
- -
-

What are MDL's responsibilities?

-
-

- Material Design Lite is built to provide a lightweight and basic set of Material Design components and templates for web sites. - The project does not intend to provide structures to create all possible UX needs, but to provide a low-friction Material Design implementation you can build on. - Even within Material Design itself, cards specifically, it is unfeasible to provide every combination in a seamless manner. - When you find something not provided, such as dropdowns in the drawer, you may need to code your own component. -

-

- The team is committed to providing a great experience to developers while staying true to the promise of lite. -

-
-
- -
-

What's next?

-
-

- Detailed instructions for using the components, including MDL classes and their effects, coding considerations, and configuration options, can be found in the components page. Example of sites using MDL elements together can be found in the templates page. -

-
-
- -
-

License

-
-

- Copyright Google, 2015. Licensed under an Apache-2 license. -

-
-
-
- -{% endblock %} diff --git a/docs/_templates/styles.html b/docs/_templates/styles.html deleted file mode 100644 index fad9f242e..000000000 --- a/docs/_templates/styles.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'layout.html' %} - -{% block content %} - -
-
- {{content|safe}} -
-
- -{% endblock %} diff --git a/docs/_templates/templates.html b/docs/_templates/templates.html deleted file mode 100644 index 76f1f5c68..000000000 --- a/docs/_templates/templates.html +++ /dev/null @@ -1,28 +0,0 @@ -{% extends 'layout.html' %} -{% block content %} -{% for template in page.templates %} -
- -
-

{{ template.title }}

-

- {{ template.description }} -

- - - Download - - - - Preview - -
-
-{% endfor %} -{% endblock %} diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 000000000..13b7959e7 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,6 @@ +# NOTE: Not currently functional. + +We've recently [changed our architecture]() such that these examples are outdated and probably don't +work. We will fix them up before our beta release, as things may still change until then. + +Working framework examples for v2 can be found on our [POC branch](https://github.com/google/material-design-lite/tree/experimental/v2-architecture-poc/examples). diff --git a/.editorconfig b/examples/angular2/.editorconfig similarity index 63% rename from .editorconfig rename to examples/angular2/.editorconfig index 5d1263484..82da0b16e 100644 --- a/.editorconfig +++ b/examples/angular2/.editorconfig @@ -1,13 +1,15 @@ -# editorconfig.org +# http://editorconfig.org + root = true [*] +charset = utf-8 indent_style = space indent_size = 2 end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true insert_final_newline = true +trim_trailing_whitespace = true [*.md] -trim_trailing_whitespace = false +insert_final_newline = false +trim_trailing_whitespace = false \ No newline at end of file diff --git a/examples/angular2/.gitignore b/examples/angular2/.gitignore new file mode 100644 index 000000000..5bd24dc33 --- /dev/null +++ b/examples/angular2/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/dist/ +/npm-debug.log +/typings/ diff --git a/examples/angular2/README.md b/examples/angular2/README.md new file mode 100644 index 000000000..1ccad948d --- /dev/null +++ b/examples/angular2/README.md @@ -0,0 +1,17 @@ +# MDL Checkbox Example - Angular2 + +This folder contains a POC for using mdl-checkbox within Angular2. + +It is based off of [angular2-seed](https://github.com/angular/angular2-seed) + +## Setup + +1. Run `npm install` within this folder +2. Run `npm start` to start the demo server +3. Navigate to http://localhost:3000 to view the demo. + +## Notes + +The checkbox wrapper is implemented within `src/app/components/checkbox/checkbox.ts`. There are also +simple wrapper components for both the checkbox wrapper classes and the checkbox label (which is +implemented as a directive). diff --git a/examples/angular2/package.json b/examples/angular2/package.json new file mode 100644 index 000000000..dbebc7709 --- /dev/null +++ b/examples/angular2/package.json @@ -0,0 +1,68 @@ +{ + "name": "angular2-seed", + "version": "1.0.0", + "description": "A simple starter Angular2 project", + "scripts": { + "typings-install": "typings install", + "postinstall": "npm run typings-install", + "build": "webpack --inline --colors --progress --display-error-details --display-cached", + "watch": "npm run build -- --watch", + "server": "webpack-dev-server --inline --colors --progress --display-error-details --display-cached --port 3000 --content-base src", + "start": "npm run server" + }, + "contributors": [ + "Rob Wormald ", + "PatrickJS " + ], + "license": "MIT", + "devDependencies": { + "autoprefixer": "^6.3.6", + "awesome-typescript-loader": "~0.16.2", + "babel-core": "^6.9.1", + "babel-loader": "^6.2.4", + "babel-preset-es2015": "^6.9.0", + "css-loader": "^0.23.1", + "es6-promise": "3.0.2", + "es6-shim": "0.35.0", + "node-sass": "^3.7.0", + "postcss-loader": "^0.9.1", + "reflect-metadata": "0.1.2", + "sass-loader": "^3.2.0", + "source-map-loader": "^0.1.5", + "typescript": "~1.8.9", + "typings": "~1.0.3", + "webpack": "^1.12.9", + "webpack-dev-server": "^1.14.0", + "webpack-merge": "^0.8.4" + }, + "dependencies": { + "@angular/http": "2.0.0-rc.1", + "@angular/common": "2.0.0-rc.1", + "@angular/compiler": "2.0.0-rc.1", + "@angular/core": "2.0.0-rc.1", + "@angular/platform-browser": "2.0.0-rc.1", + "@angular/platform-browser-dynamic": "2.0.0-rc.1", + "@angular/platform-server": "2.0.0-rc.1", + "@angular/router": "2.0.0-rc.1", + "core-js": "^2.2.0", + "rxjs": "5.0.0-beta.6", + "zone.js": "~0.6.12" + }, + "keywords": [ + "Angular2", + "angular2-seed", + "official angular 2 seed", + "official angular2 seed" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/angular/angular2-seed.git" + }, + "bugs": { + "url": "https://github.com/angular/angular2-seed/issues" + }, + "homepage": "https://github.com/angular/angular2-seed#readme", + "babel": { + "presets": ["es2015"] + } +} diff --git a/test/unit/slider.js b/examples/angular2/src/app.ts similarity index 50% rename from test/unit/slider.js rename to examples/angular2/src/app.ts index 71c5de920..d86a0563d 100644 --- a/test/unit/slider.js +++ b/examples/angular2/src/app.ts @@ -1,5 +1,5 @@ /** - * Copyright 2015 Google Inc. All Rights Reserved. + * Copyright 2016 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,21 +14,20 @@ * limitations under the License. */ -describe('MaterialSlider', function () { +import {LocationStrategy, HashLocationStrategy} from '@angular/common'; +import {bootstrap} from '@angular/platform-browser-dynamic'; +import {provide, enableProdMode} from '@angular/core'; +import {HTTP_PROVIDERS} from '@angular/http'; +import {ROUTER_PROVIDERS} from '@angular/router'; - it('should be globally available', function () { - expect(MaterialSlider).to.be.a('function'); - }); +import {SeedApp} from './app/seed-app'; - it('should upgrade successfully', function () { - var el = document.createElement('input'); - el.type = 'range'; - var parent = document.createElement('div'); - parent.appendChild(el); +// enableProdMode() - componentHandler.upgradeElement(el, 'MaterialSlider'); - expect($(el)).to.have.data('upgraded', ',MaterialSlider'); - }); - -}); +bootstrap(SeedApp, [ + HTTP_PROVIDERS, + ROUTER_PROVIDERS, + provide(LocationStrategy, {useClass: HashLocationStrategy}) +]) +.catch(err => console.error(err)); diff --git a/examples/angular2/src/app/components/checkbox/checkbox-label.ts b/examples/angular2/src/app/components/checkbox/checkbox-label.ts new file mode 100644 index 000000000..16dd75f4e --- /dev/null +++ b/examples/angular2/src/app/components/checkbox/checkbox-label.ts @@ -0,0 +1,25 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {Directive, HostBinding, Input} from 'angular2/core'; + +@Directive({ + selector: '[md-checkbox-label]' +}) +export class CheckboxLabelDirective { + @HostBinding('class') className: string = 'md-checkbox-label'; + @Input() id: string; +} diff --git a/src/animation/_animation.scss b/examples/angular2/src/app/components/checkbox/checkbox-wrapper.ts similarity index 52% rename from src/animation/_animation.scss rename to examples/angular2/src/app/components/checkbox/checkbox-wrapper.ts index 26df66950..d2fb5a963 100644 --- a/src/animation/_animation.scss +++ b/examples/angular2/src/app/components/checkbox/checkbox-wrapper.ts @@ -1,5 +1,5 @@ /** - * Copyright 2015 Google Inc. All Rights Reserved. + * Copyright 2016 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,21 +14,18 @@ * limitations under the License. */ -@import "../variables"; +import {Component, HostBinding, ViewEncapsulation} from 'angular2/core'; - -.mdl-animation--default { - transition-timing-function: $animation-curve-default; -} - -.mdl-animation--fast-out-slow-in { - transition-timing-function: $animation-curve-fast-out-slow-in; -} - -.mdl-animation--linear-out-slow-in { - transition-timing-function: $animation-curve-linear-out-slow-in; -} - -.mdl-animation--fast-out-linear-in { - transition-timing-function: $animation-curve-fast-out-linear-in; -} +@Component({ + selector: 'md-checkbox-wrapper', + template: ` +
+ +
+ `, + // Style URLs are pulled in by md-checkbox, which we assume we are using. + encapsulation: ViewEncapsulation.None +}) +export class CheckboxWrapperComponent { + @HostBinding('class') className: string = 'md-checkbox-wrapper'; +}; diff --git a/examples/angular2/src/app/components/checkbox/checkbox.html b/examples/angular2/src/app/components/checkbox/checkbox.html new file mode 100644 index 000000000..f111bac3f --- /dev/null +++ b/examples/angular2/src/app/components/checkbox/checkbox.html @@ -0,0 +1,20 @@ + +
+
+ + + +
+
diff --git a/examples/angular2/src/app/components/checkbox/checkbox.ts b/examples/angular2/src/app/components/checkbox/checkbox.ts new file mode 100644 index 000000000..4fa22369d --- /dev/null +++ b/examples/angular2/src/app/components/checkbox/checkbox.ts @@ -0,0 +1,176 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + AfterViewInit, + ChangeDetectionStrategy, + Component, + ElementRef, + EventEmitter, + HostBinding, + Input, + OnDestroy, + Output, + Provider, + Renderer, + ViewChild, + ViewEncapsulation, + forwardRef +} from '@angular/core'; +import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/common'; +// Since we don't have typings (yet) we require mdl-checkbox manually. +const {default: MDLCheckbox} = require('mdl-checkbox'); +// Use webpack's require function to load the css +const MDL_CHECKBOX_STYLES = require('mdl-checkbox-styles'); + +// Needed for ngModel to work properly. +const MD_CHECKBOX_CONTROL_VALUE_ACCESSOR = new Provider( + NG_VALUE_ACCESSOR, { + useExisting: forwardRef(() => CheckboxComponent), + multi: true + }); + +type UnlistenerMap = WeakMap; + +@Component({ + moduleId: module.id, + selector: 'md-checkbox', + templateUrl: 'app/components/checkbox/checkbox.html', + styles: [String(MDL_CHECKBOX_STYLES)], + encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush, + providers: [MD_CHECKBOX_CONTROL_VALUE_ACCESSOR] +}) +export class CheckboxComponent implements AfterViewInit, OnDestroy { + @Input() checked: boolean = false; + @Input() indeterminate: boolean = false; + @Input() labelId: string; + @Output() change: EventEmitter = new EventEmitter(); + @HostBinding('class') className: string = 'md-checkbox'; + @ViewChild('nativeCb') nativeCb: ElementRef; + // value accessor stuff + onTouched: () => any = () => {}; + + private _controlValueAccessorChangeFn: (value: any) => void = (value) => {}; + private _unlisteners: Map = new Map(); + + constructor(private _renderer: Renderer, private _root: ElementRef) {} + + ngAfterViewInit() { + (this).initMdlCheckbox_(); + } + + ngOnDestroy() { + // inherited from MDLCheckbox + (this).removeEventListeners(); + } + + handleChange(evt: Event) { + // Stop native checkbox change event from bubbling. + evt.stopPropagation(); + this._controlValueAccessorChangeFn((evt.target).checked); + this.change.emit(evt); + } + + // ControlValueAccessor stuff below, for ngModel. + + writeValue(value: any) { + this.checked = !!value; + } + + registerOnChange(fn: (value: any) => void) { + this._controlValueAccessorChangeFn = fn; + } + + registerOnTouched(fn: any) { + this.onTouched = fn; + } +} +// NOTE: We can make this better by providing type definitions for MixInto +MDLCheckbox.mixInto(CheckboxComponent, { + addClass(className: string) { + const {_renderer: renderer, _root: root} = this; + renderer.setElementClass(root.nativeElement, className, true); + }, + + removeClass(className: string) { + const {_renderer: renderer, _root: root} = this; + renderer.setElementClass(root.nativeElement, className, false); + }, + + addEventListener(type: string, listener: EventListener) { + const self = this; + if (self._root) { + listen.call(self, self._root, type, listener); + } + }, + + removeEventListener(type: string, listener: EventListener) { + unlisten.call(this, type, listener); + }, + + getNativeCheckbox() { + const {nativeCb} = this; + if (!nativeCb) { + throw new Error('Invalid state'); + } + return nativeCb.nativeElement; + }, + + addNativeCheckboxListener(type: string, listener: EventListener) { + const self = this; + if (self.nativeCb) { + listen.call(self, self.nativeCb, type, listener); + } + }, + + removeNativeCheckboxListener(type, listener) { + unlisten.call(this, type, listener); + }, + + forceLayout() { + const {_root: root} = this; + // Return to prevent optimizers thinking this is dead code. + return root.offsetWidth; + }, + + isAttachedToDOM() { + const self = this; + return !!self._root && !!self._root.nativeElement; + } +}); + +function listen(ref: ElementRef, type: string, listener: EventListener) { + const self = this; + if (!self._unlisteners.has(type)) { + self._unlisteners.set(type, new WeakMap()); + } + const unlistener = self._renderer.listen(ref.nativeElement, type, listener); + self._unlisteners.get(type).set(listener, unlistener); +} + +function unlisten(type: string, listener: EventListener) { + const self = this; + if (!self._unlisteners.has(type)) { + return; + } + const unlisteners = self._unlisteners.get(type); + if (!unlisteners.has(listener)) { + return; + } + unlisteners.get(listener)(); + unlisteners.delete(listener); +} diff --git a/examples/angular2/src/app/components/home/home.css b/examples/angular2/src/app/components/home/home.css new file mode 100644 index 000000000..e69de29bb diff --git a/examples/angular2/src/app/components/home/home.html b/examples/angular2/src/app/components/home/home.html new file mode 100644 index 000000000..852095819 --- /dev/null +++ b/examples/angular2/src/app/components/home/home.html @@ -0,0 +1,10 @@ + + + + +
+ +
+

{{changeEventCount}} change events so far

diff --git a/examples/angular2/src/app/components/home/home.ts b/examples/angular2/src/app/components/home/home.ts new file mode 100644 index 000000000..cf9996442 --- /dev/null +++ b/examples/angular2/src/app/components/home/home.ts @@ -0,0 +1,51 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {Component} from '@angular/core'; +import {CheckboxComponent} from '../checkbox/checkbox'; +import {CheckboxWrapperComponent} from '../checkbox/checkbox-wrapper'; +import {CheckboxLabelDirective} from '../checkbox/checkbox-label'; + +@Component({ + selector: 'home', + templateUrl: 'app/components/home/home.html', + styleUrls: ['app/components/home/home.css'], + providers: [], + directives: [ + CheckboxComponent, + CheckboxLabelDirective, + CheckboxWrapperComponent + ], + pipes: [] +}) +export class Home { + public isChecked: boolean = false; + public isIndeterminate: boolean = false; + public labelId: string = 'my-checkbox-label'; + public changeEventCount: number = 0; + + public get status(): string { + if (this.isIndeterminate) { + return 'indeterminate'; + } + return this.isChecked ? 'checked' : 'unchecked'; + } + + handleChange() { + this.isIndeterminate = false; + this.changeEventCount++; + } +} diff --git a/examples/angular2/src/app/seed-app.html b/examples/angular2/src/app/seed-app.html new file mode 100644 index 000000000..efe589e58 --- /dev/null +++ b/examples/angular2/src/app/seed-app.html @@ -0,0 +1,6 @@ +

+ MDL Checkbox - Angular2 Example +

+
+ +
diff --git a/examples/angular2/src/app/seed-app.ts b/examples/angular2/src/app/seed-app.ts new file mode 100644 index 000000000..5c18e1a99 --- /dev/null +++ b/examples/angular2/src/app/seed-app.ts @@ -0,0 +1,36 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {Component} from '@angular/core'; +import {Routes, ROUTER_DIRECTIVES} from '@angular/router'; + +import {Home} from './components/home/home'; + +@Component({ + selector: 'seed-app', + providers: [], + pipes: [], + directives: [ROUTER_DIRECTIVES, Home], + templateUrl: 'app/seed-app.html', +}) +@Routes([ + { path: '/', component: Home, } +]) +export class SeedApp { + + constructor() {} + +} diff --git a/examples/angular2/src/favicon.ico b/examples/angular2/src/favicon.ico new file mode 100644 index 000000000..8081c7cea Binary files /dev/null and b/examples/angular2/src/favicon.ico differ diff --git a/examples/angular2/src/index.html b/examples/angular2/src/index.html new file mode 100644 index 000000000..a21c5a365 --- /dev/null +++ b/examples/angular2/src/index.html @@ -0,0 +1,34 @@ + + + + + + Angular2 Seed + + + + + + Loading... + + + + + + + + diff --git a/src/demos.css b/examples/angular2/src/polyfills.ts similarity index 61% rename from src/demos.css rename to examples/angular2/src/polyfills.ts index d0cfefbfd..c0276e724 100644 --- a/src/demos.css +++ b/examples/angular2/src/polyfills.ts @@ -1,5 +1,5 @@ /** - * Copyright 2015 Google Inc. All Rights Reserved. + * Copyright 2016 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,26 +14,14 @@ * limitations under the License. */ -.demo-page { - width: 100%; - height: auto; +// Polyfills +// These modules are what's in angular 2 bundle polyfills so don't include them +// import 'es6-shim'; +// import 'es6-promise'; +// import 'reflect-metadata'; - margin: 0; - padding: 0; +// CoreJS has all the polyfills you need - padding: 24px; - box-sizing: border-box; -} - -.demo-preview-block { - padding: 20px; - padding-bottom: 0; - margin-bottom: 0; - box-sizing: border-box; - width: 100%; -} - -.demo-code { - width: 100%; - box-sizing: border-box; -} +import 'core-js'; +require('zone.js/dist/zone'); +require('zone.js/dist/long-stack-trace-zone'); diff --git a/examples/angular2/src/typings.d.ts b/examples/angular2/src/typings.d.ts new file mode 100644 index 000000000..2c194480c --- /dev/null +++ b/examples/angular2/src/typings.d.ts @@ -0,0 +1,67 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Custom Type Definitions + * When including 3rd party modules you also need to include the type definition for the module + * if they don't provide one within the module. You can try to install it with typings + +typings install node --save + + * If you can't find the type definition in the registry we can make an ambient definition in + * this file for now. For example + +declare module "my-module" { + export function doesSomething(value: string): string; +} + + * + * If you're prototying and you will fix the types later you can also declare it as type any + * + +declare var assert: any; + + * + * If you're importing a module that uses Node.js modules which are CommonJS you need to import as + * + +import * as _ from 'lodash' + + * You can include your type definitions in this file until you create one for the typings registry + * see https://github.com/typings/registry + * + */ + +// Alias legacy import/exports pre rc +declare module "angular2/core" { + export * from '@angular/core'; +} + +declare module "angular2/http" { + export * from '@angular/http'; +} + +declare module 'angular2/platform/browser' { + export * from '@angular/platform-browser'; +} + +declare module 'angular2/testing' { + export * from '@angular/core/testing'; +} + +declare module 'angular2/http/testing' { + export * from '@angular/http/testing'; +} diff --git a/src/resets/_mobile.scss b/examples/angular2/src/vendor.ts similarity index 56% rename from src/resets/_mobile.scss rename to examples/angular2/src/vendor.ts index efa20dd11..7d7209921 100644 --- a/src/resets/_mobile.scss +++ b/examples/angular2/src/vendor.ts @@ -1,5 +1,5 @@ /** - * Copyright 2015 Google Inc. All Rights Reserved. + * Copyright 2016 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,19 @@ * limitations under the License. */ +// Vendors -/* Remove the unwanted box around FAB buttons */ -/* More info: http://goo.gl/IPwKi */ -a, .mdl-accordion, .mdl-button, .mdl-card, .mdl-checkbox, .mdl-dropdown-menu, -.mdl-icon-toggle, .mdl-item, .mdl-radio, .mdl-slider, .mdl-switch, .mdl-tabs__tab { +// Angular 2 +import '@angular/platform-browser-dynamic'; +import '@angular/platform-browser'; +import '@angular/core'; +import '@angular/http'; +import '@angular/router'; - -webkit-tap-highlight-color: transparent; - -webkit-tap-highlight-color: rgba(255, 255, 255, 0); -} + +// RxJS 5 +// import 'rxjs/Rx'; + + +// For vendors for example jQuery, Lodash, angular2-jwt import them here +// Also see src/typings.d.ts as you also need to run `typings install x` where `x` is your module diff --git a/examples/angular2/tsconfig.json b/examples/angular2/tsconfig.json new file mode 100644 index 000000000..2a36be44a --- /dev/null +++ b/examples/angular2/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "outDir": "dist", + "rootDir": ".", + "sourceMap": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "moduleResolution": "node" + }, + "exclude": [ + "typings/main.d.ts", + "typings/main", + "node_modules", + "src/app/components/checkbox/vendored-*" + ], + "compileOnSave": false, + "buildOnSave": false, + "atom": { "rewriteTsconfig": false } +} diff --git a/examples/angular2/typings.json b/examples/angular2/typings.json new file mode 100644 index 000000000..ede26fa18 --- /dev/null +++ b/examples/angular2/typings.json @@ -0,0 +1,8 @@ +{ + "name": "angular2-seed", + "version": false, + "dependencies": {}, + "globalDependencies": { + "node": "registry:dt/node#4.0.0+20160423143914" + } +} diff --git a/examples/angular2/webpack.config.js b/examples/angular2/webpack.config.js new file mode 100644 index 000000000..8268ac9e1 --- /dev/null +++ b/examples/angular2/webpack.config.js @@ -0,0 +1,121 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* eslint-disable */ +var webpack = require('webpack'); +var path = require('path'); + + +// Webpack Config +var webpackConfig = { + entry: { + 'polyfills': './src/polyfills.ts', + 'vendor': './src/vendor.ts', + 'app': './src/app.ts', + }, + + output: { + path: './dist', + }, + + plugins: [ + new webpack.optimize.CommonsChunkPlugin({ name: ['app', 'vendor', 'polyfills'], minChunks: Infinity }), + ], + + module: { + loaders: [ + // .ts files for TypeScript + { test: /\.ts$/, loader: 'babel-loader!awesome-typescript-loader' }, + { + test: /\.js$/, + loader: 'babel-loader', + include: [ + path.resolve('../../packages') + ] + }, + { + test: /\.scss$/, + loader: 'css-loader!postcss-loader!sass-loader', + include: [ + path.resolve('../../packages') + ] + } + ] + }, + + sassLoader: { + includePaths: [path.resolve('../../packages')] + }, + + resolve: { + alias: { + 'mdl-checkbox': path.resolve('../../packages/mdl-checkbox/index.js'), + 'mdl-checkbox-styles': path.resolve('../../packages/mdl-checkbox/mdl-checkbox.scss') + } + } +}; + + +// Our Webpack Defaults +var defaultConfig = { + devtool: 'cheap-module-source-map', + cache: true, + debug: true, + output: { + filename: '[name].bundle.js', + sourceMapFilename: '[name].map', + chunkFilename: '[id].chunk.js' + }, + + module: { + noParse: [ + path.join(__dirname, 'node_modules', 'zone.js', 'dist'), + path.join(__dirname, 'node_modules', 'angular2', 'bundles') + ] + }, + + resolve: { + root: [ path.join(__dirname, 'src') ], + extensions: ['', '.ts', '.js'], + alias: { + 'angular2/testing': path.join(__dirname, 'node_modules', '@angular', 'core', 'testing.js'), + '@angular/testing': path.join(__dirname, 'node_modules', '@angular', 'core', 'testing.js'), + 'angular2/core': path.join(__dirname, 'node_modules', '@angular', 'core', 'index.js'), + 'angular2/platform/browser': path.join(__dirname, 'node_modules', '@angular', 'platform-browser', 'index.js'), + 'angular2/testing': path.join(__dirname, 'node_modules', '@angular', 'testing', 'index.js'), + 'angular2/router': path.join(__dirname, 'node_modules', '@angular', 'router', 'index.js'), + 'angular2/http': path.join(__dirname, 'node_modules', '@angular', 'http', 'index.js'), + 'angular2/http/testing': path.join(__dirname, 'node_modules', '@angular', 'http', 'testing.js') + }, + }, + + devServer: { + historyApiFallback: true, + watchOptions: { aggregateTimeout: 300, poll: 1000 } + }, + + node: { + global: 1, + crypto: 'empty', + module: 0, + Buffer: 0, + clearImmediate: 0, + setImmediate: 0 + }, +} + +var webpackMerge = require('webpack-merge'); +module.exports = webpackMerge(defaultConfig, webpackConfig); diff --git a/examples/react/.babelrc b/examples/react/.babelrc new file mode 100644 index 000000000..9b7d435ad --- /dev/null +++ b/examples/react/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["es2015", "stage-0", "react"] +} diff --git a/examples/react/README.md b/examples/react/README.md new file mode 100644 index 000000000..d7bca0cf9 --- /dev/null +++ b/examples/react/README.md @@ -0,0 +1,17 @@ +# MDL Checkbox Example - React + +This folder contains a POC for using mdl-checkbox within React. + +It is based off of [react-hot-boilerplate](https://github.com/gaearon/react-hot-boilerplate) + +## Setup + +1. Run `npm install` within this folder +2. Run `npm start` to start the demo server +3. Navigate to http://localhost:3000 to view the demo. + +## Notes + +The checkbox wrapper is implemented within `src/Checkbox.js`. There are also +simple wrapper components for both the checkbox wrapper classes and the checkbox label (both +implemented as pure functions). diff --git a/examples/react/index.html b/examples/react/index.html new file mode 100644 index 000000000..d2df58eec --- /dev/null +++ b/examples/react/index.html @@ -0,0 +1,26 @@ + + + + + Sample App + + +
+
+ + + diff --git a/examples/react/package.json b/examples/react/package.json new file mode 100644 index 000000000..91bb2a48d --- /dev/null +++ b/examples/react/package.json @@ -0,0 +1,56 @@ +{ + "name": "react-hot-boilerplate", + "version": "1.0.0", + "description": "Boilerplate for ReactJS project with hot code reloading", + "scripts": { + "start": "node server.js", + "lint": "eslint src" + }, + "repository": { + "type": "git", + "url": "https://github.com/gaearon/react-hot-boilerplate.git" + }, + "keywords": [ + "react", + "reactjs", + "boilerplate", + "hot", + "reload", + "hmr", + "live", + "edit", + "webpack" + ], + "author": "Dan Abramov (http://github.com/gaearon)", + "license": "MIT", + "bugs": { + "url": "https://github.com/gaearon/react-hot-boilerplate/issues" + }, + "homepage": "https://github.com/gaearon/react-hot-boilerplate", + "devDependencies": { + "autoprefixer": "^6.3.6", + "babel-core": "^6.0.20", + "babel-eslint": "^4.1.3", + "babel-loader": "^6.0.1", + "babel-preset-es2015": "^6.0.15", + "babel-preset-react": "^6.0.15", + "babel-preset-stage-0": "^6.0.15", + "css-loader": "^0.23.1", + "node-sass": "^3.7.0", + "postcss-loader": "^0.9.1", + "react-hot-loader": "^1.3.0", + "sass-loader": "^3.2.0", + "style-loader": "^0.13.1", + "webpack": "^1.12.2", + "webpack-dev-server": "^1.12.1" + }, + "dependencies": { + "immutable": "^3.8.1", + "react": "^15.1.0", + "react-addons-pure-render-mixin": "^15.1.0", + "react-dom": "^15.1.0" + }, + "babel": { + "presets": ["es2015", "stage-0", "react"] + } +} diff --git a/examples/react/server.js b/examples/react/server.js new file mode 100644 index 000000000..7ca454fee --- /dev/null +++ b/examples/react/server.js @@ -0,0 +1,31 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var webpack = require('webpack'); +var WebpackDevServer = require('webpack-dev-server'); +var config = require('./webpack.config'); + +new WebpackDevServer(webpack(config), { + publicPath: config.output.publicPath, + hot: true, + historyApiFallback: true +}).listen(3000, 'localhost', function (err, result) { + if (err) { + return console.log(err); + } + + console.log('Listening at http://localhost:3000/'); +}); diff --git a/examples/react/src/App.js b/examples/react/src/App.js new file mode 100644 index 000000000..c18290762 --- /dev/null +++ b/examples/react/src/App.js @@ -0,0 +1,62 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* eslint-disable */ + +import React, {Component, PropTypes} from 'react'; +import PureRenderMixin from 'react-addons-pure-render-mixin'; + +import Checkbox from './Checkbox'; +import CheckboxLabel from './CheckboxLabel'; +import CheckboxWrapper from './CheckboxWrapper'; + +export default class App extends Component { + state = { + checked: false, + indeterminate: false, + changeEventCount: 0 + } + shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this) + + render() { + const {checked, indeterminate, status, changeEventCount} = this.state; + return ( +
+

MDL Checkbox - React Example

+ + this.setState({ + changeEventCount: changeEventCount + 1, + checked: target.checked, + indeterminate: false + })}/> + The checkbox is currently {this.status()} + +
+ +
+

{changeEventCount} change events so far

+
+ ); + } + + status() { + if (this.state.indeterminate) { + return 'indeterminate'; + } + return this.state.checked ? 'checked' : 'unchecked'; + } +} diff --git a/examples/react/src/Checkbox.js b/examples/react/src/Checkbox.js new file mode 100644 index 000000000..0917a18d7 --- /dev/null +++ b/examples/react/src/Checkbox.js @@ -0,0 +1,151 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* eslint-disable */ + +import React, {Component, PropTypes} from 'react'; +import PureRenderMixin from 'react-addons-pure-render-mixin'; +import {Set as ImmutableSet} from 'immutable'; +// lol super hack +import MDLCheckbox from '../../../packages/mdl-checkbox'; +import '../../../packages/mdl-checkbox/mdl-checkbox.scss'; + +export default class Checkbox extends Component { + static propTypes = { + checked: PropTypes.bool, + indeterminate: PropTypes.bool, + onChange: PropTypes.func, + labelId: PropTypes.string + } + + static defaultProps = { + checked: false, + indeterminate: false, + onChange: () => {} + } + + state = { + classes: new ImmutableSet(), + checkedInternal: false, + indeterminateInternal: false + } + classesToAdd = new ImmutableSet(); + classesToRemove = new ImmutableSet(); + shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this); + + render() { + return ( +
+ { + this.setState({ + checkedInternal: this.refs.nativeCb.checked, + indeterminateInternal: false + }); + this.props.onChange(evt); + }}/> +
+
+ + + +
+
+
+ ); + } + + componentDidMount() { + this.initMdlCheckbox_(); + } + + componentWillUnmount() { + // From MDLCheckboxMixin + this.removeEventListeners(); + } + + componentWillReceiveProps(props) { + if (props.checked !== this.props.checked) { + this.setState({checkedInternal: props.checked, indeterminateInternal: false}); + } + if (props.indeterminate !== this.props.indeterminate) { + this.setState({indeterminateInternal: props.indeterminate}); + } + } + + componentDidUpdate() { + if (this.refs.nativeCb) { + this.refs.nativeCb.indeterminate = this.state.indeterminateInternal; + } + } +} +MDLCheckbox.mixInto(Checkbox, { + addClass(className) { + this.setState(prevState => ({ + classes: prevState.classes.add(className) + })); + }, + removeClass(className) { + this.setState(prevState => ({ + classes: prevState.classes.remove(className) + })); + }, + addEventListener(type, listener) { + if (this.refs.root) { + this.refs.root.addEventListener(type, listener); + } + }, + removeEventListener(type, listener) { + if (this.refs.root) { + this.refs.root.removeEventListener(type, listener); + } + }, + addNativeCheckboxListener(type, listener) { + if (this.refs.nativeCb) { + this.refs.nativeCb.addEventListener(type, listener); + } + }, + removeNativeCheckboxListener(type, listener) { + if (this.refs.nativeCb) { + this.refs.nativeCb.removeEventListener(type, listener); + } + }, + getNativeCheckbox() { + if (!this.refs.nativeCb) { + throw new Error('Invalid state for operation'); + } + return this.refs.nativeCb; + }, + forceLayout() { + if (this.refs.nativeCb) { + this.refs.nativeCb.offsetWidth; + } + }, + isAttachedToDOM() { + // Return true?? + return Boolean(this.refs.nativeCb); + } +}); diff --git a/src/material-design-lite-grid.scss b/examples/react/src/CheckboxLabel.js similarity index 70% rename from src/material-design-lite-grid.scss rename to examples/react/src/CheckboxLabel.js index 060dad26a..853213539 100644 --- a/src/material-design-lite-grid.scss +++ b/examples/react/src/CheckboxLabel.js @@ -1,5 +1,5 @@ /** - * Copyright 2015 Google Inc. All Rights Reserved. + * Copyright 2016 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,8 +14,12 @@ * limitations under the License. */ -/* Material Design Lite Grid*/ +/* eslint-disable */ -@import "variables"; -@import "mixins"; -@import "grid/grid"; \ No newline at end of file +import React from 'react'; + +export default function CheckboxLabel({id, children}) { + return ( + + ); +} diff --git a/examples/react/src/CheckboxWrapper.js b/examples/react/src/CheckboxWrapper.js new file mode 100644 index 000000000..8af248073 --- /dev/null +++ b/examples/react/src/CheckboxWrapper.js @@ -0,0 +1,29 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* eslint-disable */ + +import React from 'react'; + +export default function CheckboxWrapper({children}) { + return ( +
+
+ {children} +
+
+ ); +} diff --git a/test/unit/ripple.js b/examples/react/src/index.js similarity index 72% rename from test/unit/ripple.js rename to examples/react/src/index.js index 92cce2c0d..cd9a93b91 100644 --- a/test/unit/ripple.js +++ b/examples/react/src/index.js @@ -1,5 +1,5 @@ /** - * Copyright 2015 Google Inc. All Rights Reserved. + * Copyright 2016 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,9 @@ * limitations under the License. */ -describe('MaterialRipple', function () { +/* eslint-disable */ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; - it('should be globally available', function () { - expect(MaterialRipple).to.be.a('function'); - }); - -}); +ReactDOM.render(, document.getElementById('root')); diff --git a/examples/react/webpack.config.js b/examples/react/webpack.config.js new file mode 100644 index 000000000..be74024d6 --- /dev/null +++ b/examples/react/webpack.config.js @@ -0,0 +1,61 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const path = require('path'); +const webpack = require('webpack'); + +module.exports = { + devtool: 'source-map', + entry: [ + 'webpack-dev-server/client?http://localhost:3000', + 'webpack/hot/only-dev-server', + './src/index' + ], + output: { + path: path.join(__dirname, 'dist'), + filename: 'bundle.js', + publicPath: '/static/' + }, + plugins: [ + new webpack.HotModuleReplacementPlugin() + ], + module: { + loaders: [{ + test: /\.js$/, + loaders: ['react-hot', 'babel'], + include: [ + path.join(__dirname, 'src') + ] + }, { + test: /\.js$/, + loaders: ['babel'], + include: [ + path.resolve('../../packages') + ] + }, { + test: /\.scss$/, + loaders: ['style', 'css', 'postcss', 'sass'] + }] + }, + sassLoader: { + includePaths: [path.resolve('../../packages')] + }, + postcss: function() { + return [ + require('autoprefixer') + ]; + } +}; diff --git a/gulpfile.babel.js b/gulpfile.babel.js deleted file mode 100644 index 6bd08c948..000000000 --- a/gulpfile.babel.js +++ /dev/null @@ -1,807 +0,0 @@ -/** - * - * Material Design Lite - * Copyright 2015 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - * - */ - - // jscs:disable jsDoc - -'use strict'; - -// Include Gulp & Tools We'll Use -import fs from 'fs'; -import path from 'path'; -import mergeStream from 'merge-stream'; -import del from 'del'; -import vinylPaths from'vinyl-paths'; -import runSequence from 'run-sequence'; -import browserSync from 'browser-sync'; -import through from 'through2'; -import swig from 'swig'; -import gulp from 'gulp'; -import closureCompiler from 'gulp-closure-compiler'; -import gulpLoadPlugins from 'gulp-load-plugins'; -import uniffe from './utils/uniffe.js'; -import pkg from './package.json'; - -const $ = gulpLoadPlugins(); -const reload = browserSync.reload; -const hostedLibsUrlPrefix = 'https://code.getmdl.io'; -const templateArchivePrefix = 'mdl-template-'; -const bucketProd = 'gs://www.getmdl.io'; -const bucketStaging = 'gs://mdl-staging'; -const bucketCode = 'gs://code.getmdl.io'; -const banner = ['/**', - ' * <%= pkg.name %> - <%= pkg.description %>', - ' * @version v<%= pkg.version %>', - ' * @license <%= pkg.license %>', - ' * @copyright 2015 Google, Inc.', - ' * @link https://github.com/google/material-design-lite', - ' */', - ''].join('\n'); - -let codeFiles = ''; - -const AUTOPREFIXER_BROWSERS = [ - 'ie >= 10', - 'ie_mob >= 10', - 'ff >= 30', - 'chrome >= 34', - 'safari >= 7', - 'opera >= 23', - 'ios >= 7', - 'android >= 4.4', - 'bb >= 10' -]; - -const SOURCES = [ - // Component handler - 'src/mdlComponentHandler.js', - // Polyfills/dependencies - 'src/third_party/**/*.js', - // Base components - 'src/button/button.js', - 'src/checkbox/checkbox.js', - 'src/icon-toggle/icon-toggle.js', - 'src/menu/menu.js', - 'src/progress/progress.js', - 'src/radio/radio.js', - 'src/slider/slider.js', - 'src/snackbar/snackbar.js', - 'src/spinner/spinner.js', - 'src/switch/switch.js', - 'src/tabs/tabs.js', - 'src/textfield/textfield.js', - 'src/tooltip/tooltip.js', - // Complex components (which reuse base components) - 'src/layout/layout.js', - 'src/data-table/data-table.js', - // And finally, the ripples - 'src/ripple/ripple.js' -]; - -// ***** Development tasks ****** // - -// Lint JavaScript -gulp.task('lint', () => { - return gulp.src([ - 'src/**/*.js', - 'gulpfile.babel.js' - ]) - .pipe(reload({stream: true, once: true})) - .pipe($.jshint()) - .pipe($.jscs()) - .pipe($.jshint.reporter('jshint-stylish')) - .pipe($.jscs.reporter()) - .pipe($.if(!browserSync.active, $.jshint.reporter('fail'))) - .pipe($.if(!browserSync.active, $.jscs.reporter('fail'))); -}); - -// ***** Production build tasks ****** // - -// Optimize Images -// TODO: Update image paths in final CSS to match root/images -gulp.task('images', () => { - return gulp.src('src/**/*.{svg,png,jpg}') - .pipe($.flatten()) - .pipe($.cache($.imagemin({ - progressive: true, - interlaced: true - }))) - .pipe(gulp.dest('dist/images')) - .pipe($.size({title: 'images'})); -}); - -// Compile and Automatically Prefix Stylesheets (dev) -gulp.task('styles:dev', () => { - return gulp.src('src/**/*.scss') - .pipe($.sass({ - precision: 10, - onError: console.error.bind(console, 'Sass error:') - })) - .pipe($.cssInlineImages({ - webRoot: 'src' - })) - .pipe($.autoprefixer(AUTOPREFIXER_BROWSERS)) - .pipe(gulp.dest('.tmp/styles')) - .pipe($.size({title: 'styles'})); -}); - -// Compile and Automatically Prefix Stylesheet Templates (production) -gulp.task('styletemplates', () => { - // For best performance, don't add Sass partials to `gulp.src` - return gulp.src('src/template.scss') - // Generate Source Maps - .pipe($.sourcemaps.init()) - .pipe($.sass({ - precision: 10, - onError: console.error.bind(console, 'Sass error:') - })) - .pipe($.cssInlineImages({webRoot: 'src'})) - .pipe($.autoprefixer(AUTOPREFIXER_BROWSERS)) - .pipe(gulp.dest('.tmp')) - // Concatenate Styles - .pipe($.concat('material.css.template')) - .pipe(gulp.dest('dist')) - // Minify Styles - .pipe($.if('*.css.template', $.csso())) - .pipe($.concat('material.min.css.template')) - .pipe($.header(banner, {pkg})) - .pipe($.sourcemaps.write('.')) - .pipe(gulp.dest('dist')) - .pipe($.size({title: 'styles'})); -}); - -// Compile and Automatically Prefix Stylesheets (production) -gulp.task('styles', () => { - // For best performance, don't add Sass partials to `gulp.src` - return gulp.src('src/material-design-lite.scss') - // Generate Source Maps - .pipe($.sourcemaps.init()) - .pipe($.sass({ - precision: 10, - onError: console.error.bind(console, 'Sass error:') - })) - .pipe($.cssInlineImages({webRoot: 'src'})) - .pipe($.autoprefixer(AUTOPREFIXER_BROWSERS)) - .pipe(gulp.dest('.tmp')) - // Concatenate Styles - .pipe($.concat('material.css')) - .pipe($.header(banner, {pkg})) - .pipe(gulp.dest('dist')) - // Minify Styles - .pipe($.if('*.css', $.csso())) - .pipe($.concat('material.min.css')) - .pipe($.header(banner, {pkg})) - .pipe($.sourcemaps.write('.')) - .pipe(gulp.dest('dist')) - .pipe($.size({title: 'styles'})); -}); - -// Only generate CSS styles for the MDL grid -gulp.task('styles-grid', () => { - return gulp.src('src/material-design-lite-grid.scss') - .pipe($.sass({ - precision: 10, - onError: console.error.bind(console, 'Sass error:') - })) - .pipe($.autoprefixer(AUTOPREFIXER_BROWSERS)) - .pipe(gulp.dest('.tmp')) - // Concatenate Styles - .pipe($.concat('material-grid.css')) - .pipe($.header(banner, {pkg})) - .pipe(gulp.dest('dist')) - // Minify Styles - .pipe($.if('*.css', $.csso())) - .pipe($.concat('material-grid.min.css')) - .pipe($.header(banner, {pkg})) - .pipe(gulp.dest('dist')) - .pipe($.size({title: 'styles-grid'})); -}); - -// Build with Google's Closure Compiler, requires Java 1.7+ installed. -gulp.task('closure', () => { - return gulp.src(SOURCES) - .pipe(closureCompiler({ - compilerPath: 'node_modules/google-closure-compiler/compiler.jar', - fileName: 'material.closure.min.js', - compilerFlags: { - // jscs:disable closureCamelCase - compilation_level: 'ADVANCED_OPTIMIZATIONS', - language_in: 'ECMASCRIPT6_STRICT', - language_out: 'ECMASCRIPT5_STRICT', - warning_level: 'VERBOSE' - // jscs:enable closureCamelCase - } - })) - .pipe(gulp.dest('./dist')); -}); - -// Concatenate And Minify JavaScript -gulp.task('scripts', ['lint'], () => { - return gulp.src(SOURCES) - .pipe($.if(/mdlComponentHandler\.js/, $.util.noop(), uniffe())) - .pipe($.sourcemaps.init()) - // Concatenate Scripts - .pipe($.concat('material.js')) - .pipe($.iife({useStrict: true})) - .pipe(gulp.dest('dist')) - // Minify Scripts - .pipe($.uglify({ - sourceRoot: '.', - sourceMapIncludeSources: true - })) - .pipe($.header(banner, {pkg})) - .pipe($.concat('material.min.js')) - // Write Source Maps - .pipe($.sourcemaps.write('.')) - .pipe(gulp.dest('dist')) - .pipe($.size({title: 'scripts'})); -}); - -// Clean Output Directory -gulp.task('clean', () => del(['dist', '.publish'])); - -// Copy package manger and LICENSE files to dist -gulp.task('metadata', () => { - return gulp.src([ - 'package.json', - 'bower.json', - 'LICENSE' - ]) - .pipe(gulp.dest('dist')); -}); - -// Build Production Files, the Default Task -gulp.task('default', ['clean'], cb => { - runSequence( - ['styles', 'styles-grid'], - ['scripts'], - ['mocha'], - cb); -}); - -// Build production files and microsite -gulp.task('all', ['clean'], cb => { - runSequence( - ['styletemplates'], - ['styles-grid', 'styles:gen'], - ['scripts'], - ['mocha'], - ['assets', 'pages', - 'templates', 'images', 'metadata'], - ['zip'], - cb); -}); - -// ***** Testing tasks ***** // - -gulp.task('mocha', ['styles'], () => { - return gulp.src('test/index.html') - .pipe($.mochaPhantomjs({reporter: 'tap'})); -}); - -gulp.task('mocha:closure', ['closure'], () => { - return gulp.src('test/index.html') - .pipe($.replace('src="../dist/material.js"', - 'src="../dist/material.closure.min.js"')) - .pipe($.rename('temp.html')) - .pipe(gulp.dest('test')) - .pipe($.mochaPhantomjs({reporter: 'tap'})) - .on('finish', () => del.sync('test/temp.html')) - .on('error', () => del.sync('test/temp.html')); -}); - -gulp.task('test', [ - 'lint', - 'mocha', - 'mocha:closure' -]); - -gulp.task('test:visual', () => { - browserSync({ - notify: false, - server: '.', - startPath: 'test/visual/index.html' - }); - - gulp.watch('test/visual/**', reload); -}); - -// ***** Landing page tasks ***** // - -/** - * Site metadata for use with templates. - * @type {Object} - */ -const site = {}; - -/** - * Generates an HTML file based on a template and file metadata. - */ -function applyTemplate() { - return through.obj((file, enc, cb) => { - const data = { - site, - page: file.page, - content: file.contents.toString() - }; - - const templateFile = path.join( - __dirname, 'docs', '_templates', `${file.page.layout}.html`); - const tpl = swig.compileFile(templateFile, {cache: false}); - - file.contents = new Buffer(tpl(data)); - cb(null, file); - }); -} - -/** - * Generates an index.html file for each README in MDL/src directory. - */ -gulp.task('components', ['demos'], () => { - return gulp.src('src/**/README.md', {base: 'src'}) - // Add basic front matter. - .pipe($.header('---\nlayout: component\nbodyclass: component\ninclude_prefix: ../../\n---\n\n')) - .pipe($.frontMatter({ - property: 'page', - remove: true - })) - .pipe($.marked()) - .pipe((() => { - return through.obj((file, enc, cb) => { - file.page.component = file.relative.split('/')[0]; - cb(null, file); - }); - })()) - .pipe(applyTemplate()) - .pipe($.rename(path => path.basename = 'index')) - .pipe(gulp.dest('dist/components')); -}); - -/** - * Copies demo files from MDL/src directory. - */ -gulp.task('demoresources', () => { - return gulp.src([ - 'src/**/demos.css', - 'src/**/demo.css', - 'src/**/demo.js' - ], {base: 'src'}) - .pipe($.if('*.scss', $.sass({ - precision: 10, - onError: console.error.bind(console, 'Sass error:') - }))) - .pipe($.cssInlineImages({webRoot: 'src'})) - .pipe($.if('*.css', $.autoprefixer(AUTOPREFIXER_BROWSERS))) - .pipe(gulp.dest('dist/components')); -}); - -/** - * Generates demo files for testing made of all the snippets and the demo file - * put together. - */ -gulp.task('demos', ['demoresources'], () => { - /** - * Retrieves the list of component folders. - */ - function getComponentFolders() { - return fs.readdirSync('src') - .filter(file => fs.statSync(path.join('src', file)).isDirectory()); - } - - const tasks = getComponentFolders().map(component => { - return gulp.src([ - path.join('src', component, 'snippets', '*.html'), - path.join('src', component, 'demo.html') - ]) - .pipe($.concat('/demo.html')) - // Add basic front matter. - .pipe($.header('---\nlayout: demo\nbodyclass: demo\ninclude_prefix: ../../\n---\n\n')) - .pipe($.frontMatter({ - property: 'page', - remove: true - })) - .pipe($.marked()) - .pipe((() => { - return through.obj((file, enc, cb) => { - file.page.component = component; - cb(null, file); - }); - })()) - .pipe(applyTemplate()) - .pipe(gulp.dest(path.join('dist', 'components', component))); - }); - - return mergeStream(tasks); -}); - -/** - * Generates an HTML file for each md file in _pages directory. - */ -gulp.task('pages', ['components'], () => { - return gulp.src('docs/_pages/*.md') - .pipe($.frontMatter({ - property: 'page', - remove: true - })) - .pipe($.marked()) - .pipe(applyTemplate()) - .pipe($.replace('$$version$$', pkg.version)) - .pipe($.replace('$$hosted_libs_prefix$$', hostedLibsUrlPrefix)) - .pipe($.replace('$$template_archive_prefix$$', templateArchivePrefix)) - /* Replacing code blocks class name to match Prism's. */ - .pipe($.replace('class="lang-', 'class="language-')) - /* Translate html code blocks to "markup" because that's what Prism uses. */ - .pipe($.replace('class="language-html', 'class="language-markup')) - .pipe($.rename(path => { - if (path.basename !== 'index') { - path.dirname = path.basename; - path.basename = 'index'; - } - })) - .pipe(gulp.dest('dist')); -}); - -/** - * Copies assets from MDL and _assets directory. - */ -gulp.task('assets', () => { - return gulp.src([ - 'docs/_assets/**/*', - 'node_modules/clippy/build/clippy.swf', - 'node_modules/swfobject-npm/swfobject/src/swfobject.js', - 'node_modules/prismjs/prism.js', - 'node_modules/prismjs/components/prism-markup.min.js', - 'node_modules/prismjs/components/prism-javascript.min.js', - 'node_modules/prismjs/components/prism-css.min.js', - 'node_modules/prismjs/components/prism-bash.min.js', - 'node_modules/prismjs/dist/prism-default/prism-default.css' - ]) - .pipe($.if(/\.js/i, $.replace('$$version$$', pkg.version))) - .pipe($.if(/\.js/i, $.replace('$$hosted_libs_prefix$$', hostedLibsUrlPrefix))) - .pipe($.if(/\.(svg|jpg|png)$/i, $.imagemin({ - progressive: true, - interlaced: true - }))) - .pipe($.if(/\.css/i, $.autoprefixer(AUTOPREFIXER_BROWSERS))) - .pipe($.if(/\.css/i, $.csso())) - .pipe($.if(/\.js/i, $.uglify({ - preserveComments: 'some', - sourceRoot: '.', - sourceMapIncludeSources: true - }))) - .pipe(gulp.dest('dist/assets')); -}); - -/** - * Defines the list of resources to watch for changes. - */ -function watch() { - gulp.watch(['src/**/*.js', '!src/**/README.md'], - ['scripts', 'demos', 'components', reload]); - gulp.watch(['src/**/*.{scss,css}'], - ['styles', 'styles-grid', 'styletemplates', reload]); - gulp.watch(['src/**/*.html'], ['pages', reload]); - gulp.watch(['src/**/*.{svg,png,jpg}'], ['images', reload]); - gulp.watch(['src/**/README.md'], ['pages', reload]); - gulp.watch(['templates/**/*'], ['templates', reload]); - gulp.watch(['docs/**/*'], ['pages', 'assets', reload]); - gulp.watch(['package.json', 'bower.json', 'LICENSE'], ['metadata']); -} - -/** - * Serves the landing page from "out" directory. - */ -gulp.task('serve:browsersync', () => { - browserSync({ - notify: false, - server: { - baseDir: ['dist'] - } - }); - - watch(); -}); - -gulp.task('serve', () => { - $.connect.server({ - root: 'dist', - port: 5000, - livereload: true - }); - - watch(); - - gulp.src('dist/index.html') - .pipe($.open({uri: 'http://localhost:5000'})); -}); - -// Generate release archive containing just JS, CSS, Source Map deps -gulp.task('zip:mdl', () => { - return gulp.src([ - 'dist/material?(.min)@(.js|.css)?(.map)', - 'LICENSE', - 'bower.json', - 'package.json' - ]) - .pipe($.zip('mdl.zip')) - .pipe(gulp.dest('dist')); -}); - -/** - * Returns the list of children directories inside the given directory. - * @param {string} dir the parent directory - * @return {Array} list of child directories - */ -function getSubDirectories(dir) { - return fs.readdirSync(dir) - .filter(file => fs.statSync(path.join(dir, file)).isDirectory()); -} - -// Generate release archives containing the templates and assets for templates. -gulp.task('zip:templates', () => { - const templates = getSubDirectories('dist/templates'); - - // Generate a zip file for each template. - const generateZips = templates.map(template => { - return gulp.src([ - `dist/templates/${template}/**/*.*`, - 'LICENSE' - ]) - .pipe($.rename(path => { - path.dirname = path.dirname.replace(`dist/templates/${template}`, ''); - })) - .pipe($.zip(`${templateArchivePrefix}${template}.zip`)) - .pipe(gulp.dest('dist')); - }); - - return mergeStream(generateZips); -}); - -gulp.task('zip', [ - 'zip:templates', - 'zip:mdl' -]); - -gulp.task('genCodeFiles', () => { - return gulp.src([ - 'dist/material.*@(js|css)?(.map)', - 'dist/mdl.zip', - `dist/${templateArchivePrefix}*.zip` - ], {read: false}) - .pipe($.tap(file => { - codeFiles += ` dist/${path.basename(file.path)}`; - })); -}); - -// Push the latest version of code resources (CSS+JS) to Google Cloud Storage. -// Public-read objects in GCS are served by a Google provided and supported -// global, high performance caching/content delivery network (CDN) service. -// This task requires gsutil to be installed and configured. -// For info on gsutil: https://cloud.google.com/storage/docs/gsutil. -gulp.task('pushCodeFiles', () => { - const dest = bucketCode; - console.log(`Publishing ${pkg.version} to CDN (${dest})`); - - // Build cache control and gsutil cmd to copy - // each object into a GCS bucket. The dest is a version specific path. - // The gsutil -m option requests parallel copies. - // The gsutil -h option is used to set metadata headers - // (cache control, in this case). - // Code files should NEVER be touched after uploading, therefore - // 30 days caching is a safe value. - const cacheControl = '-h "Cache-Control:public,max-age=2592000"'; - const gsutilCpCmd = 'gsutil -m cp -z js,css,map '; - const gsutilCacheCmd = `gsutil -m setmeta -R ${cacheControl}`; - - // Upload the goodies to a separate GCS bucket with versioning. - // Using a sep bucket avoids the risk of accidentally blowing away - // old versions in the microsite bucket. - return gulp.src('') - .pipe($.shell([ - `${gsutilCpCmd}${codeFiles} ${dest}/${pkg.version}`, - `${gsutilCacheCmd} ${dest}/${pkg.version}` - ])); -}); - -gulp.task('publish:code', cb => { - runSequence( - ['zip:mdl', 'zip:templates'], - 'genCodeFiles', - 'pushCodeFiles', - cb); -}); - -/** - * Function to publish staging or prod version from local tree, - * or to promote staging to prod, per passed arg. - * @param {string} pubScope the scope to publish to. - */ -function mdlPublish(pubScope) { - let cacheTtl = null; - let src = null; - let dest = null; - - if (pubScope === 'staging') { - // Set staging specific vars here. - cacheTtl = 0; - src = 'dist/*'; - dest = bucketStaging; - } else if (pubScope === 'prod') { - // Set prod specific vars here. - cacheTtl = 60; - src = 'dist/*'; - dest = bucketProd; - } else if (pubScope === 'promote') { - // Set promote (essentially prod) specific vars here. - cacheTtl = 60; - src = `${bucketStaging}/*`; - dest = bucketProd; - } - - let infoMsg = `Publishing ${pubScope}/${pkg.version} to GCS (${dest})`; - if (src) { - infoMsg += ` from ${src}`; - } - console.log(infoMsg); - - // Build gsutil commands: - // The gsutil -h option is used to set metadata headers. - // The gsutil -m option requests parallel copies. - // The gsutil -R option is used for recursive file copy. - const cacheControl = `-h "Cache-Control:public,max-age=${cacheTtl}"`; - const gsutilCacheCmd = `gsutil -m setmeta ${cacheControl} ${dest}/**`; - const gsutilCpCmd = `gsutil -m cp -r -z html,css,js,svg ${src} ${dest}`; - - gulp.src('').pipe($.shell([gsutilCpCmd, gsutilCacheCmd])); -} - -// Push the local build of the MDL microsite and release artifacts to the -// production Google Cloud Storage bucket for general serving to the web. -// Public-read objects in GCS are served by a Google provided and supported -// global, high performance caching/content delivery network (CDN) service. -// This task requires gsutil to be installed and configured. -// For info on gsutil: https://cloud.google.com/storage/docs/gsutil. -// -gulp.task('publish:prod', () => { - mdlPublish('prod'); -}); - -// Promote the staging version of the MDL microsite and release artifacts -// to the production Google Cloud Storage bucket for general serving. -// Public-read objects in GCS are served by a Google provided and supported -// global, high performance caching/content delivery network (CDN) service. -// This task requires gsutil to be installed and configured. -// For info on gsutil: https://cloud.google.com/storage/docs/gsutil. -// -gulp.task('publish:promote', () => { - mdlPublish('promote'); -}); - -// Push the staged version of the MDL microsite and release artifacts -// to a production Google Cloud Storage bucket for staging and pre-production testing. -// -// This task requires gsutil to be installed and configured. -// For info on gsutil: https://cloud.google.com/storage/docs/gsutil. -// -gulp.task('publish:staging', () => { - mdlPublish('staging'); -}); - -gulp.task('_release', () => { - return gulp.src([ - 'dist/material?(.min)@(.js|.css)?(.map)', - 'LICENSE', - 'README.md', - 'bower.json', - 'package.json', - '.jscsrc', - '.jshintrc', - './sr?/**/*', - 'gulpfile.babel.js', - './util?/**/*' - ]) - .pipe(gulp.dest('_release')); -}); - -gulp.task('publish:release', ['_release'], () => { - return gulp.src('_release') - .pipe($.subtree({ - remote: 'origin', - branch: 'release' - })) - .pipe(vinylPaths(del)); -}); - -gulp.task('templates:styles', () => { - return gulp.src('templates/**/*.css') - .pipe($.autoprefixer(AUTOPREFIXER_BROWSERS)) - // FIXME: This crashes. It's a bug in gulp-csso, - // not csso itself. - //.pipe($.csso()) - .pipe(gulp.dest('dist/templates')); -}); - -gulp.task('templates:static', () => { - return gulp.src('templates/**/*.html') - .pipe($.replace('$$version$$', pkg.version)) - .pipe($.replace('$$hosted_libs_prefix$$', hostedLibsUrlPrefix)) - .pipe(gulp.dest('dist/templates')); -}); - -// This task can be used if you want to test the templates against locally -// built version of the MDL libraries. -gulp.task('templates:localtestingoverride', () => { - return gulp.src('templates/**/*.html') - .pipe($.replace('$$version$$', '.')) - .pipe($.replace('$$hosted_libs_prefix$$', '')) - .pipe(gulp.dest('dist/templates')); -}); - -gulp.task('templates:images', () => { - return gulp.src('templates/*/images/**/*') - .pipe($.imagemin({ - progressive: true, - interlaced: true - })) - .pipe(gulp.dest('dist/templates')); -}); - -gulp.task('templates:fonts', () => { - return gulp.src('templates/*/fonts/**/*') - .pipe(gulp.dest('dist/templates/')); -}); - -gulp.task('templates', [ - 'templates:static', - 'templates:images', - 'templates:fonts', - 'templates:styles' -]); - -gulp.task('styles:gen', ['styles'], () => { - const MaterialCustomizer = require('./docs/_assets/customizer.js'); - const templatePath = path.join(__dirname, 'dist', 'material.min.css.template'); - // TODO: This task needs refactoring once we turn MaterialCustomizer - // into a proper Node module. - const mc = new MaterialCustomizer(); - mc.template = fs.readFileSync(templatePath).toString(); - - let stream = gulp.src(''); - - mc.paletteIndices.forEach(primary => { - mc.paletteIndices.forEach(accent => { - if (primary === accent) { - return; - } - - if (mc.forbiddenAccents.indexOf(accent) !== -1) { - return; - } - - const primaryName = primary.toLowerCase().replace(' ', '_'); - const accentName = accent.toLowerCase().replace(' ', '_'); - - stream = stream.pipe($.file( - `material.${primaryName}-${accentName}.min.css`, - mc.processTemplate(primary, accent) - )); - }); - }); - - stream.pipe(gulp.dest('dist')); -}); diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 000000000..6a3f14974 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,160 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const path = require('path'); +const webpackConfig = require('./webpack.config')[0]; + +const USING_TRAVISCI = Boolean(process.env.TRAVIS); +const USING_SL = Boolean(process.env.SAUCE_USERNAME && process.env.SAUCE_ACCESS_KEY); + +const SL_LAUNCHERS = { + 'sl-chrome-stable': { + base: 'SauceLabs', + browserName: 'chrome', + version: 'latest', + platform: 'OS X 10.11' + }, + 'sl-chrome-beta': { + base: 'SauceLabs', + browserName: 'chrome', + version: 'beta' + }, + 'sl-chrome-previous': { + base: 'SauceLabs', + browserName: 'chrome', + version: 'latest-1', + platform: 'OS X 10.11' + }, + 'sl-firefox-stable': { + base: 'SauceLabs', + browserName: 'firefox', + version: 'latest', + platform: 'Windows 10' + }, + 'sl-firefox-previous': { + base: 'SauceLabs', + browserName: 'firefox', + version: 'latest-1', + platform: 'Windows 10' + }, + 'sl-ie': { + base: 'SauceLabs', + browserName: 'internet explorer', + version: '11', + platform: 'Windows 8.1' + }, + 'sl-android-stable': { + base: 'SauceLabs', + browserName: 'android', + version: '5.0' + } + // NOTE(traviskaufman): Temporarily disabling these browsers as they are consistently flaky using + // Sauce Labs and almost always yield false negatives. + // 'sl-edge': { + // base: 'SauceLabs', + // browserName: 'microsoftedge', + // version: 'latest', + // platform: 'Windows 10' + // }, + // 'sl-safari-stable': { + // base: 'SauceLabs', + // browserName: 'safari', + // version: '9', + // platform: 'OS X 10.11' + // }, + // 'sl-safari-previous': { + // base: 'SauceLabs', + // browserName: 'safari', + // version: '8', + // platform: 'OS X 10.10' + // }, + // 'sl-ios-safari-latest': { + // base: 'SauceLabs', + // browserName: 'iphone', + // platform: 'OS X 10.10', + // version: '9.1' + // }, + // 'sl-ios-safari-previous': { + // base: 'SauceLabs', + // browserName: 'iphone', + // version: '8.4' + // } +}; + +module.exports = function(config) { + config.set({ + basePath: '', + frameworks: ['tap'], + files: [ + 'test/unit/index.js' + ], + preprocessors: { + 'test/unit/index.js': ['webpack', 'sourcemap'] + }, + reporters: ['dots', 'coverage'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + browsers: USING_SL ? Object.keys(SL_LAUNCHERS) : ['Chrome'], + browserDisconnectTimeout: 20000, + browserNoActivityTimeout: 240000, + captureTimeout: 120000, + concurrency: USING_SL ? 4 : Infinity, + customLaunchers: SL_LAUNCHERS, + + coverageReporter: { + dir: 'coverage', + reporters: [ + {type: 'json', subdir: '.', file: 'coverage.json'}, + {type: 'html'} + ] + }, + + webpack: Object.assign({}, webpackConfig, { + devtool: 'inline-source-map', + node: { + fs: 'empty' + }, + module: Object.assign({}, webpackConfig.module, { + // Cover source files when not debugging tests. Otherwise, omit coverage instrumenting to get + // uncluttered source maps. + loaders: webpackConfig.module.loaders.concat([config.singleRun ? { + test: /\.js$/, + include: path.resolve('./packages'), + loader: 'isparta' + } : undefined]).filter(Boolean) + }) + }), + + webpackMiddleware: { + noInfo: true + } + }); + + // See https://github.com/karma-runner/karma-sauce-launcher/issues/73 + if (USING_TRAVISCI) { + config.set({ + sauceLabs: { + testName: 'Material Design Lite Unit Tests - CI', + tunnelIdentifier: process.env.TRAVIS_JOB_NUMBER, + startConnect: false + }, + // Attempt to de-flake Sauce Labs tests on TravisCI. + transports: ['polling'], + browserDisconnectTolerance: 3 + }); + } +}; diff --git a/lerna.json b/lerna.json new file mode 100644 index 000000000..ea35f7205 --- /dev/null +++ b/lerna.json @@ -0,0 +1,4 @@ +{ + "lerna": "2.0.0-beta.18", + "version": "independent" +} diff --git a/package.json b/package.json index 6a4021fc8..92ad8e842 100644 --- a/package.json +++ b/package.json @@ -1,72 +1,93 @@ { - "name": "material-design-lite", - "version": "1.1.3", - "description": "Material Design Components in CSS, JS and HTML", "private": true, - "license": "Apache-2.0", - "author": "Google", - "repository": "google/material-design-lite", - "main": "dist/material.min.js", - "devDependencies": { - "acorn": "^2.2.0", - "babel-core": "^5.8.25", - "browser-sync": "^2.2.3", - "chai": "^3.3.0", - "chai-jquery": "^2.0.0", - "del": "^2.0.2", - "drool": "^0.3.1", - "escodegen": "^1.6.1", - "google-closure-compiler": "", - "gulp": "^3.9.0", - "gulp-autoprefixer": "^3.0.2", - "gulp-cache": "^0.3.0", - "gulp-closure-compiler": "^0.3.1", - "gulp-concat": "^2.4.1", - "gulp-connect": "^2.2.0", - "gulp-css-inline-images": "^0.1.1", - "gulp-csso": "1.0.0", - "gulp-file": "^0.2.0", - "gulp-flatten": "^0.2.0", - "gulp-front-matter": "^1.2.2", - "gulp-header": "^1.2.2", - "gulp-if": "^2.0.0", - "gulp-iife": "^0.1.0", - "gulp-imagemin": "^2.2.1", - "gulp-jscs": "^3.0.1", - "gulp-jshint": "^1.6.3", - "gulp-load-plugins": "^0.10.0", - "gulp-marked": "^1.0.0", - "gulp-mocha-phantomjs": "^0.10.1", - "gulp-open": "^1.0.0", - "gulp-rename": "^1.2.0", - "gulp-replace": "^0.5.3", - "gulp-sass": "2.0.*", - "gulp-shell": "^0.4.2", - "gulp-size": "^2.0.0", - "gulp-sourcemaps": "^1.3.0", - "gulp-subtree": "^0.1.0", - "gulp-tap": "^0.1.3", - "gulp-uglify": "^1.0.1", - "gulp-util": "^3.0.4", - "gulp-zip": "^3.0.2", - "humanize": "0.0.9", - "jquery": "^2.1.3", - "jshint-stylish": "^2.0.1", - "merge-stream": "^1.0.0", - "mocha": "^2.1.0", - "prismjs": "0.0.1", - "run-sequence": "^1.0.2", - "swig": "^1.4.2", - "through2": "^2.0.0", - "vinyl-paths": "^2.0.0" - }, - "engines": { - "node": ">=0.12.0" - }, + "description": "Material Design Lite", + "version": "2.0.0", + "license": "MIT", "scripts": { - "test": "gulp && git status | grep 'working directory clean' >/dev/null || (echo 'Please commit all changes generated by building'; exit 1)" + "clean": "del-cli build/**", + "build": "mkdirp build && webpack", + "build:min": "mkdirp build && cross-env MDL_ENV=production webpack -p", + "dist": "npm run clean && npm run build && npm run build:min", + "dev": "npm run clean && cross-env MDL_ENV=development webpack-dev-server --content-base demos --inline --hot", + "fix:js": "eslint --fix packages test webpack.config.js karma.conf.js", + "fix:css": "stylefmt -R packages", + "fix": "npm-run-all --parallel fix:*", + "lint:js": "eslint packages test webpack.config.js karma.conf.js", + "lint:css": "stylelint packages/**/*.scss", + "lint": "npm-run-all --parallel lint:*", + "postinstall": "lerna bootstrap", + "pretest": "npm run lint", + "test": "karma start --single-run", + "posttest": "istanbul report --root coverage text-summary && istanbul check-coverage --lines 85 --statements 85 --branches 85 --functions 85", + "test:watch": "karma start --auto-watch" + }, + "devDependencies": { + "autoprefixer": "^6.3.6", + "babel-loader": "^6.2.4", + "babel-plugin-transform-object-assign": "^6.8.0", + "babel-preset-es2015": "^6.9.0", + "bel": "^4.4.3", + "cross-env": "^2.0.0", + "css-loader": "^0.23.1", + "cz-conventional-changelog": "^1.1.6", + "del-cli": "^0.2.0", + "dom-compare": "^0.2.1", + "dom-events": "^0.1.1", + "es6-promise": "^3.2.1", + "eslint": "^2.12.0", + "eslint-config-google": "^0.5.0", + "eslint-plugin-tape": "^1.1.0", + "extract-text-webpack-plugin": "^1.0.1", + "ghooks": "^1.3.2", + "isparta-loader": "^2.0.0", + "istanbul": "^0.4.4", + "json-loader": "^0.5.4", + "karma": "^1.1.1", + "karma-chrome-launcher": "^1.0.1", + "karma-coverage": "^1.1.0", + "karma-firefox-launcher": "^1.0.0", + "karma-sauce-launcher": "^1.0.0", + "karma-sourcemap-loader": "^0.3.7", + "karma-tap": "^2.0.1", + "karma-webpack": "^1.7.0", + "lerna": "2.0.0-beta.18", + "lolex": "^1.5.0", + "mkdirp": "^0.5.1", + "node-sass": "^3.7.0", + "npm-run-all": "^2.3.0", + "postcss-custom-properties": "^5.0.1", + "postcss-loader": "^0.9.1", + "raw-loader": "^0.5.1", + "sass-loader": "^3.2.0", + "style-loader": "^0.13.1", + "stylefmt": "^4.1.1", + "stylelint": "^7.1.0", + "stylelint-config-standard": "^11.0.0", + "stylelint-scss": "^1.2.1", + "stylelint-selector-bem-pattern": "^1.0.0", + "tape": "^4.6.0", + "testdouble": "^1.6.0", + "validate-commit-msg": "^2.6.1", + "webpack": "^1.13.1", + "webpack-dev-server": "^1.14.1" }, "babel": { - "only": "gulpfile.babel.js" + "presets": [ + "es2015" + ], + "plugins": [ + "transform-object-assign" + ] + }, + "config": { + "ghooks": { + "commit-msg": "validate-commit-msg" + }, + "validate-commit-msg": { + "helpMessage": "\nNOTE: Please see angular's commit message guidelines (https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit) for information on how to format commit messages.\n\nAs an example, here is a valid commit message: 'docs(slider): Document slider public api'\n\nIf this commit is on a development / WIP branch, you can disable this by running `git commit --no-verify`." + }, + "commitizen": { + "path": "./node_modules/cz-conventional-changelog" + } } } diff --git a/src/shadow/_shadow.scss b/packages/material-design-lite/index.js similarity index 57% rename from src/shadow/_shadow.scss rename to packages/material-design-lite/index.js index 708f921cc..7ad5f3411 100644 --- a/src/shadow/_shadow.scss +++ b/packages/material-design-lite/index.js @@ -1,5 +1,5 @@ /** - * Copyright 2015 Google Inc. All Rights Reserved. + * Copyright 2016 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,33 +14,22 @@ * limitations under the License. */ -@import "../variables"; -@import "../mixins"; - -.mdl-shadow--2dp { - @include shadow-2dp(); -} - -.mdl-shadow--3dp { - @include shadow-3dp(); -} - -.mdl-shadow--4dp { - @include shadow-4dp(); -} - -.mdl-shadow--6dp { - @include shadow-6dp(); -} - -.mdl-shadow--8dp { - @include shadow-8dp(); -} - -.mdl-shadow--16dp { - @include shadow-16dp(); -} - -.mdl-shadow--24dp { - @include shadow-24dp(); -} +import BaseComponent from 'mdl-base'; +import Checkbox from 'mdl-checkbox'; +import Radio from 'mdl-radio'; +import Ripple from 'mdl-ripple'; +import autoInit from 'mdl-auto-init'; + +console.info('Hello, MDL!!!'); + +// Register all components +autoInit.register('MDLCheckbox', Checkbox); + +// Export all components. +export { + BaseComponent, + Checkbox, + Radio, + Ripple, + autoInit +}; diff --git a/packages/material-design-lite/material-design-lite.scss b/packages/material-design-lite/material-design-lite.scss new file mode 100644 index 000000000..3b077a30b --- /dev/null +++ b/packages/material-design-lite/material-design-lite.scss @@ -0,0 +1,25 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "mdl-animation/mdl-animation"; +@import "mdl-button/mdl-button"; +@import "mdl-card/mdl-card"; +@import "mdl-checkbox/mdl-checkbox"; +@import "mdl-fab/mdl-fab"; +@import "mdl-radio/mdl-radio"; +@import "mdl-ripple/mdl-ripple"; +@import "mdl-toolbar/mdl-toolbar"; +@import "mdl-typography/mdl-typography"; diff --git a/packages/material-design-lite/package.json b/packages/material-design-lite/package.json new file mode 100644 index 000000000..6f046ee01 --- /dev/null +++ b/packages/material-design-lite/package.json @@ -0,0 +1,19 @@ +{ + "name": "material-design-lite", + "description": "The canonical material design implementation for the web platform", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "mdl-animation": "^1.0.0", + "mdl-auto-init": "^1.0.0", + "mdl-base": "^1.0.0", + "mdl-button": "^1.0.0", + "mdl-card": "^1.0.0", + "mdl-checkbox": "^1.0.0", + "mdl-fab": "^1.0.0", + "mdl-radio": "^1.0.0", + "mdl-ripple": "^1.0.0", + "mdl-toolbar": "^1.0.0", + "mdl-typography": "^1.0.0" + } +} diff --git a/packages/mdl-animation/README.md b/packages/mdl-animation/README.md new file mode 100644 index 000000000..be5e6a1d6 --- /dev/null +++ b/packages/mdl-animation/README.md @@ -0,0 +1,57 @@ +# mdl-animation + +mdl-animation is a sass / css library which provides variables, mixins, and classes for Material Design animation, based off of the [motion guidelines](https://material.google.com/motion/duration-easing.html#duration-easing-common-durations). Currently, it only covers easing curves. + +## Installation + +> Note: Installation via the npm registry will be available after alpha. + +## Usage + +We currently have variables for the following 3 animation curves: + +| Variable name | timing function | use case | +| --- | --- | --- | +| `$mdl-animation-fast-out-slow-in-timing-function` | `cubic-bezier(.4, 0, .2, 1)` | Standard curve; any animations that are visible from start to finish (e.g. a FAB transforming into a toolbar) | +| `$mdl-animation-linear-out-slow-in-timing-function` | `cubic-bezier(0, 0, .2, 1)` | Animations that cause objects to enter the screen (e.g. a fade in) | +| `$mdl-animation-fast-out-linear-in-timing-function` | `cubic-bezier(.4, 0, ``, 1)` | Animations that cause objects to leave the screen (e.g. a fade out) | + +### SCSS + +Simply drop `mdl-animation` into your build and start using the variables: + +```scss +.mdl-thing--animating { + animation: foo 175ms $mdl-animation-fast-out-slow-in-timing-function; +} +``` + +or the mixins, which simply assign their corresponding variables to the `animation-timing-function` +property: + +```scss +.mdl-thing--on-screen { + @include mdl-animation-fast-out-linear-in; +} +``` + +Every mixin has the same name as its corresponding variable, without the `-timing-function` suffix. + +### CSS Classes + +> NOTE: dist/ will be available when installing via NPM. + +Alternatively, you can include the built stylesheet and use the classes it exports within your HTML + +```html + + +
hi
+``` + +CSS Classes have the exact same name as their mixin counterparts. + +### Overriding the default curves. + +All animation variables are marked with `!default`, thus they can be overridden should the need +arise. diff --git a/packages/mdl-animation/_mixins.scss b/packages/mdl-animation/_mixins.scss new file mode 100644 index 000000000..413c44610 --- /dev/null +++ b/packages/mdl-animation/_mixins.scss @@ -0,0 +1,29 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "./variables"; + +@mixin mdl-animation-linear-out-slow-in { + animation-timing-function: $mdl-animation-linear-out-slow-in-timing-function; +} + +@mixin mdl-animation-fast-out-slow-in { + animation-timing-function: $mdl-animation-fast-out-slow-in-timing-function; +} + +@mixin mdl-animation-fast-out-linear-in { + animation-timing-function: $mdl-animation-fast-out-linear-in-timing-function; +} diff --git a/docs/_assets/index.js b/packages/mdl-animation/_variables.scss similarity index 64% rename from docs/_assets/index.js rename to packages/mdl-animation/_variables.scss index 6fa1519d7..d9af5134d 100644 --- a/docs/_assets/index.js +++ b/packages/mdl-animation/_variables.scss @@ -1,5 +1,5 @@ /** - * Copyright 2015 Google Inc. All Rights Reserved. + * Copyright 2016 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,11 +14,6 @@ * limitations under the License. */ -(function() { - Array.prototype.forEach.call(document.querySelectorAll('[data-target]'), function(el) { - var target = el.getAttribute('data-target'); - el.addEventListener('click', function() { - location.href = target; - }); - }); -})(); +$mdl-animation-linear-out-slow-in-timing-function: cubic-bezier(0, 0, .2, 1) !default; +$mdl-animation-fast-out-slow-in-timing-function: cubic-bezier(.4, 0, .2, 1) !default; +$mdl-animation-fast-out-linear-in-timing-function: cubic-bezier(.4, 0, 1, 1) !default; diff --git a/packages/mdl-animation/mdl-animation.scss b/packages/mdl-animation/mdl-animation.scss new file mode 100644 index 000000000..414c6243b --- /dev/null +++ b/packages/mdl-animation/mdl-animation.scss @@ -0,0 +1,31 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "./mixins"; + +.mdl-animation { + &-linear-out-slow-in { + @include mdl-animation-linear-out-slow-in; + } + + &-fast-out-slow-in { + @include mdl-animation-fast-out-slow-in; + } + + &-fast-out-linear-in { + @include mdl-animation-fast-out-linear-in; + } +} diff --git a/packages/mdl-animation/package.json b/packages/mdl-animation/package.json new file mode 100644 index 000000000..1be705a67 --- /dev/null +++ b/packages/mdl-animation/package.json @@ -0,0 +1,7 @@ +{ + "name": "mdl-animation", + "description": "Animation Variables and Mixins for Material Design", + "version": "1.0.0", + "license": "Apache-2.0", + "devDependencies": {} +} diff --git a/packages/mdl-auto-init/index.js b/packages/mdl-auto-init/index.js new file mode 100644 index 000000000..688e06f8f --- /dev/null +++ b/packages/mdl-auto-init/index.js @@ -0,0 +1,72 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const registry = Object.create(null); + +const CONSOLE_WARN = console.warn.bind(console); + +/** + * Auto-initializes all mdl components on a page. + */ +export default function mdlAutoInit(root = document, warn = CONSOLE_WARN) { + const nodes = root.querySelectorAll('[data-mdl-auto-init]'); + for (let i = 0, node; (node = nodes[i]); i++) { + const ctorName = node.dataset.mdlAutoInit; + if (!ctorName) { + throw new Error('(mdl-auto-init) Constructor name must be given.'); + } + + const Ctor = registry[ctorName]; + if (typeof Ctor !== 'function') { + throw new Error( + `(mdl-auto-init) Could not find constructor in registry for ${ctorName}`); + } + + if (node[ctorName]) { + warn(`(mdl-auto-init) Component already initialized for ${node}. Skipping...`); + continue; + } + + // TODO: Should we make an eslint rule for an attachTo() static method? + const component = Ctor.attachTo(node); + Object.defineProperty(node, ctorName, { + value: component, + writable: false, + enumerable: false, + configurable: true + }); + } +} + +mdlAutoInit.register = function(componentName, Ctor, warn = CONSOLE_WARN) { + if (typeof Ctor !== 'function') { + throw new Error(`(mdl-auto-init) Invalid Ctor value ${Ctor}. Expected function`); + } + if (registry[componentName]) { + warn( + `(mdl-auto-init) Overriding registration for ${componentName} with ${Ctor}. ` + + `Was: ${registry[componentName]}`); + } + registry[componentName] = Ctor; +}; + +mdlAutoInit.deregister = function(componentName) { + delete registry[componentName]; +}; + +mdlAutoInit.deregisterAll = function() { + Object.keys(registry).forEach(this.deregister, this); +}; diff --git a/packages/mdl-auto-init/package.json b/packages/mdl-auto-init/package.json new file mode 100644 index 000000000..bf41b6c00 --- /dev/null +++ b/packages/mdl-auto-init/package.json @@ -0,0 +1,7 @@ +{ + "name": "mdl-auto-init", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "description": "data-mdl-auto-init=" +} diff --git a/packages/mdl-base/README.md b/packages/mdl-base/README.md new file mode 100644 index 000000000..afbc31192 --- /dev/null +++ b/packages/mdl-base/README.md @@ -0,0 +1,241 @@ +# mdl-base + +> NOTE: Please do not use or rely on `adapter.js`. It is deprecated and in the process of being +> removed. + +MDL base contains core foundation and component classes that serve as the base classes for all of MDL's foundation classes and components (respectively). + +Most of the time, you shouldn't need to depend on `mdl-base` directly. It is useful however if you'd like to write custom components that follow MDL's pattern and elegantly integrate with the MDL ecosystem. + +## Installation + +First install the module: + +> NOTE: Installation via the npm registry will be available after alpha. + +Then include it in your code in one of the following ways: + +#### ES2015+ + +```javascript +import MDLComponent, {MDLFoundation} from 'mdl-base'; +``` +#### CommonJS + +```javascript +const MDLComponent = require('mdl-base').default; +const MDLFoundation = require('mdl-base').MDLFoundation; +``` + +#### AMD + +```javascript +require(['path/to/mdl-base'], function(mdlBase) { + const MDLComponent = mdlBase.default; + const MDLFoundation = mdlBase.MDLFoundation; +}); +``` + +#### Vanilla + +```javascript +const MDLComponent = mdl.Base.default; +const MDLFoundation = mdl.Base.MDLFoundation; +``` + +## Usage + +mdl-base exposes two classes: `MDLComponent` (the default export) which all components extend from, and `MDLFoundation`, which all foundation classes extend from. To learn more about foundation classes vs. components, check out our [developer guide](https://github.com/google/material-design-lite/blob/master/docs/DEVELOPER.md) (_WIP_). + +### MDLFoundation + +MDLFoundation provides the basic mechanisms for implementing a foundation classes. Subclasses are expected to: + +- Provide implementations of the proper static getters where necessary. +- Provide `init()` and `destroy()` lifecycle methods + +```javascript +import {MDLFoundation} from 'mdl-base'; + +export default class MyFoundation extends MDLFoundation { + static get cssClasses() { + return { + ROOT: 'my-component', + MESSAGE: 'my-component__message', + BUTTON: 'my-component__button', + TOGGLED: 'my-component--toggled' + }; + } + + static get defaultAdapter() { + return { + toggleClass: (/* className: string */) => {}, + registerBtnClickHandler: (/* handler: Function */) => {}, + deregisterBtnClickHandler: (/* handler: Function */) => {} + }; + } + + constructor(adapter) { + super(Object.assign(MyFoundation.defaultAdapter, adapter)); + const {TOGGLED} = MyFoundation.cssClasses; + this.clickHandler_ = () => this.adapter_.toggleClass(TOGGLED); + } + + init() { + this.adapter_.registerBtnClickHandler(this.clickHandler_); + } + + destroy() { + this.adapter_.deregisterBtnClickHandler(this.clickHandler_); + } +} +``` + +#### Static Getters + +The static getters specify constants that can be used within the foundation class, its component, and by 3rd-party code. _It's important to remember to always put constants into these getters_. This will ensure your component can interop in as many environments as possible, including those where CSS classes need to be overwritten by the host library (e.g., Closure Stylesheets), or strings need to be modified (for i18n, for example). + +Note that you do not have to explicitly provide getters for constants if your component has none. + +The getters which should be provided are specified below: + +| getter | description | +| --- | --- | +| cssClasses | returns an object where each key identifies a css class that some code will rely on. | +| strings | returns an object where each key identifies a string constant, e.g. `ARIA_ROLE` | +| numbers | returns an object where each key identifies a numeric constant, e.g. `TRANSITION_DELAY_MS` | +| defaultAdapter | returns an object specifying the shape of the adapter. Can be used as sensible defaults for an adapter as well as a way to specify your adapter's "schema" | + +#### Lifecycle Methods + +Each foundation class has two lifecycle methods: `init()` and `destroy()`, which are described below: + +| method | time of invocation | use case | +| --- | --- | --- | +| init() | called by a host class when a component is ready to be initialized | add event listeners, query for info via adapters, etc. | +| destroy() | called by a host class when a component is no longer in use | remove event listeners, reset any transient state, etc. | + +> Please note: _the lifecycle methods are **not** a safe place to perform DOM reads/writes that would invalidate layout or cause a repaint_. If this needs to be done within these methods, it should be put into a `requestAnimationFrame()` call so that it's synchronized with the browser's refresh cycle and does not [cause jank](http://www.html5rocks.com/en/tutorials/speed/rendering/). + +### MDLComponent + +MDLComponent provides the basic mechanisms for implementing component classes. + +```javascript +import MyComponentFoundation from './foundation'; + +export default class MyComponent extends MDLComponent { + static buildDom() { + const {ROOT, MESSAGE, BUTTON} = MyComponentFoundation.cssClasses; + const root = document.createElement('div'); + root.classList.add(ROOT); + + const message = document.createElement('p'); + message.classList.add(MESSAGE); + root.appendChild(message); + + const button = document.createElement('button'); + button.type = 'button'; + button.classList.add(BUTTON); + root.appendChild(button); + + return root; + } + + static attachTo(root) { + return new MyComponent(root); + } + + getDefaultFoundation() { + const btn = this.root.querySelector(`.${MyComponentFoundation.cssClasses.BUTTON}`); + return new MyComponentFoundation({ + toggleClass: className => { + if (this.root.classList.contains(className)) { + this.root.classList.remove(className); + return; + } + this.root.classList.add(className); + }, + registerBtnClickHandler: handler => btn.addEventListener('click', handler), + deregisterBtnClickHandler: handler => btn.removeEventListener('click', handler) + }); + } +} +``` + +#### Properties + +`MDLComponent` provides the following "private" properties to subclasses: + +| property | description | +| --- | --- | +| `root_` | The root element passed into the constructor as the first argument. | +| `foundation_` | The foundation class for this component. This is either passed in as an optional second argument to the constructor, or assigned the result of calling `getDefaultFoundation()` | + +#### Methods + +`MDLComponent` provides the following methods to subclasses: + +| method | description | +| --- | --- | +| `getDefaultFoundation()` | Returns an instance of a foundation class properly configured for the component. Called when no foundation instance is given within the constructor. Subclasses **must** implement this method. | +| `initialSyncWithDOM()` | Called within the constructor. Subclasses may override this method if they wish to perform initial synchronization of state with the host DOM element. For example, a slider may want to check if its host element contains a pre-set value, and adjust its internal state accordingly. Note that the same caveats apply to this method as to foundation class lifecycle methods. Defaults to a no-op. | +| `destroy()` | Subclasses may override this method if they wish to perform any additional cleanup work when a component is destroyed. For example, a component may want to deregister a window resize listener. | + +#### Static Methods + +In addition to methods inherited, subclasses should implement the following two static methods within their code: + +| method | description | +| --- | --- | +| `buildDom(...any) => HTMLElement` | Subclasses may implement this as a convenience method to construct the proper DOM for a component. Users could then rely on this as an alternative to having to construct the DOM themselves. However, it should exist purely for convenience and _never_ be used as a dependency for the component itself. | +| `attachTo(root) => ` | Subclasses must implement this as a convenience method to instantiate and return an instance of the class using the root element provided. This will be used within `mdl-auto-init`, and in the future its presence may be enforced via a custom lint rule.| + +#### Foundation Lifecycle handling + +`MDLComponent` calls its foundation's `init()` function within its _constructor_, and its foundation's `destroy()` function within its own _destroy()_ function. Therefore it's important to remember to _always call super() when overriding destroy()_. Not doing so can lead to leaked resources. + +#### Best Practice: Keep your adapters simple + +If you find your adapters getting too complex, you should consider refactoring the complex parts out into their own implementations. + +```javascript +import MyComponentFoundation from './foundation'; +import {toggleClass} from './util'; + +class MyComponent { + // ... + getDefaultFoundation() { + return new MyComponentFoundation({ + toggleClass: className => util.toggleClass(this.root_, className), + // ... + }); + } +} +``` + +Where `./util` could look like: + +```javascript +export function toggleClass(element, className) { + if (root.classList.contains(className)) { + root.classList.remove(className); + return; + } + root.classList.add(className); +} +``` + +This not only reduces the complexity of your component class, but allows for the functionality of complex adapters to be adequately tested: + +```javascript +test('toggleClass() removes a class when present on an element', t => { + const root = document.createElement('div'); + root.classList.add('foo'); + + util.toggleClass(root, 'foo'); + + t.false(root.classList.contains('foo')); + t.end(); +}); +``` diff --git a/packages/mdl-base/adapter.js b/packages/mdl-base/adapter.js new file mode 100644 index 000000000..e98889c38 --- /dev/null +++ b/packages/mdl-base/adapter.js @@ -0,0 +1,75 @@ +// TODO: Remove this file once mdl-radio and mdl-ripple have been converted. + +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * A basic component adapter. + */ +export const MDLBaseAdapter = { + getBoundingClientRect(id) { + return this.elements_[id].getBoundingClientRect(); + }, + + setStyles(id, styles) { + Object.assign(this.elements_[id].style, styles); + }, + + forceLayout(id) { + return this.elements_[id].offsetWidth; + }, + + addClass(id, cls) { + this.elements_[id].classList.add(cls); + }, + + removeClass(id, cls) { + this.elements_[id].classList.remove(cls); + }, + + get(...symbolPath) { + return ref(...symbolPath); + }, + + getComputedValue(id, property) { + return window.getComputedStyle(this.elements_[id]).getPropertyValue(property); + }, + + addEventListener(id, event, listener) { + return this.elements_[id].addEventListener(event, listener); + }, + + removeEventListener(id, event, listener) { + this.elements_[id].removeEventListener(event, listener); + }, + + setProperty(id, name, value) { + this.elements_[id][name] = value; + }, + + getProperty(id, name) { + return this.elements_[id][name]; + } +}; + +/** + * Element refs are concatenated symbol paths of arbitrary length. + * e.g. + * get('md-ripple__foreground', 0) = `md-ripple__foreground|0` + */ +export function ref(...symbolPath) { + return symbolPath.join('|'); +} diff --git a/packages/mdl-base/component.js b/packages/mdl-base/component.js new file mode 100644 index 000000000..33c833207 --- /dev/null +++ b/packages/mdl-base/component.js @@ -0,0 +1,61 @@ +/** + * Copyright 2016 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import MDLFoundation from './foundation'; + +export default class MDLComponent { + static buildDom() { + // Classes which extend MDLBase should provide a buildDom() method which returns a node containing the basic + // DOM needed for rendering the component. Clients can then opt to use buildDom() as a convenience method + // rather than having to write the DOM themselves. + return document.createElement('div'); + } + + static attachTo(root) { + // Subclasses which extend MDLBase should provide an attachTo() method that takes a root element and + // returns an instantiated component with its root set to that element. Also note that in the cases of + // subclasses, an explicit foundation class will not have to be passed in; it will simply be initialized + // from getDefaultFoundation(). + return new MDLComponent(root, new MDLFoundation()); + } + + constructor(root, foundation) { + this.root_ = root; + this.foundation_ = foundation === undefined ? this.getDefaultFoundation() : foundation; + this.foundation_.init(); + this.initialSyncWithDOM(); + } + + getDefaultFoundation() { + // Subclasses must override this method to return a properly configured foundation class for the + // component. + throw new Error('Subclasses must override getDefaultFoundation to return a properly configured ' + + 'foundation class'); + } + + initialSyncWithDOM() { + // Subclasses should override this method if they need to perform work to synchronize with a host DOM + // object. An example of this would be a form control wrapper that needs to synchronize its internal state + // to some property or attribute of the host DOM. Please note: this is *not* the place to perform DOM + // reads/writes that would cause layout / paint, as this is called synchronously from within the constructor. + } + + destroy() { + // Subclasses may implement this method to release any resources / deregister any listeners they have + // attached. An example of this might be deregistering a resize event from the window object. + this.foundation_.destroy(); + } +} diff --git a/packages/mdl-base/foundation.js b/packages/mdl-base/foundation.js new file mode 100644 index 000000000..395b01e1e --- /dev/null +++ b/packages/mdl-base/foundation.js @@ -0,0 +1,54 @@ +/** + * Copyright 2016 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default class MDLFoundation { + static get cssClasses() { + // Classes extending MDLBaseFoundation should implement this method to return an object which exports every + // CSS class the foundation class needs as a property. e.g. {ACTIVE: 'mdl-component--active'} + return {}; + } + + static get strings() { + // Classes extending MDLBaseFoundation should implement this method to return an object which exports all + // semantic strings as constants. e.g. {ARIA_ROLE: 'tablist'} + return {}; + } + + static get numbers() { + // Classes extending MDLBaseFoundation should implement this method to return an object which exports all + // of its semantic numbers as constants. e.g. {ANIMATION_DELAY_MS: 350} + return {}; + } + + static get defaultAdapter() { + // Classes extending MDLBaseFoundation may choose to implement this getter in order to provide a convenient + // way of viewing the necessary methods of an adapter. In the future, this could also be used for adapter + // validation. + return {}; + } + + constructor(adapter = {}) { + this.adapter_ = adapter; + } + + init() { + // Subclasses should override this method to perform initialization routines (registering events, etc.) + } + + destroy() { + // Subclasses should override this method to perform de-initialization routines (de-registering events, etc.) + } +} diff --git a/templates/android-dot-com/material.scss b/packages/mdl-base/index.js similarity index 64% rename from templates/android-dot-com/material.scss rename to packages/mdl-base/index.js index 3c14caa21..b46318d98 100644 --- a/templates/android-dot-com/material.scss +++ b/packages/mdl-base/index.js @@ -1,11 +1,11 @@ /** - * Copyright 2015 Google Inc. All Rights Reserved. + * Copyright 2016 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -14,4 +14,7 @@ * limitations under the License. */ -@import '../../src/material-design-lite'; +import MDLComponent from './component'; +export {default as MDLFoundation} from './foundation'; +export {MDLBaseAdapter as MDLBaseAdapterLegacy, ref as refLegacy} from './adapter'; +export default MDLComponent; diff --git a/packages/mdl-base/package.json b/packages/mdl-base/package.json new file mode 100644 index 000000000..291ba4886 --- /dev/null +++ b/packages/mdl-base/package.json @@ -0,0 +1,7 @@ +{ + "name": "mdl-base", + "description": "The set of base classes for Material Design Lite", + "version": "1.0.0", + "license": "Apache-2.0", + "main": "index.js" +} diff --git a/packages/mdl-button/README.md b/packages/mdl-button/README.md new file mode 100644 index 000000000..3058e5962 --- /dev/null +++ b/packages/mdl-button/README.md @@ -0,0 +1,65 @@ +# MDL Button + +The MDL Button component is a spec-aligned button component adhering to the + [Material Design button requirements](https://material.google.com/components/buttons.html). + It works without JavaScript with basic functionality for all states. + If you initiate the JavaScript object for a button, then it will be enhanced with ripple effects. (Not yet implemented) + +## Installation + +> Note: Installation via the npm registry will be available after alpha. + +## Usage + +### Flat + +```html + +``` + +### Colored + +```html + +``` + +### Raised + +```html + +``` + +### Disabled + +```html + +``` + +## Classes + +### Block + +The block class is `mdl-button`. This defines the top-level button element. + +### Element + +The button component has no inner elements. + +### Modifier + +The provided modifiers are: + +| Class | Description | +| --------------------- | ------------------------------------------------------| +| `mdl-button--dense` | Compresses the button to make it slightly smaller. | +| `mdl-button--raised` | Elevates the button and creates a colored background. | +| `mdl-button--primary` | Colors the button with the primary color. | +| `mdl-button--accent` | Colors the button with the accent color. | diff --git a/src/template.scss b/packages/mdl-button/_variables.scss similarity index 74% rename from src/template.scss rename to packages/mdl-button/_variables.scss index 4515a807b..940c2de88 100644 --- a/src/template.scss +++ b/packages/mdl-button/_variables.scss @@ -1,5 +1,5 @@ /** - * Copyright 2015 Google Inc. All Rights Reserved. + * Copyright 2016 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,8 +14,8 @@ * limitations under the License. */ -/* Material Design Lite */ - -$styleguide-generate-template: true; - -@import "styleguide"; +/* @TODO(Garbee) Remove these once we have theming land */ +:root { + --mdl-theme-color-primary: #3f51b5; + --mdl-theme-color-accent: #ff4081; +} diff --git a/packages/mdl-button/mdl-button.scss b/packages/mdl-button/mdl-button.scss new file mode 100644 index 000000000..7d41b38fe --- /dev/null +++ b/packages/mdl-button/mdl-button.scss @@ -0,0 +1,147 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "variables"; +@import "mdl-typography/mixins"; + +/* postcss-bem-linter: define button */ +/* stylelint-disable declaration-property-unit-whitelist */ +.mdl-button { + @include mdl-typography(body2); + display: inline-block; + position: relative; + min-width: 64px; + height: 36px; + padding: 0 16px; + border: none; + border-radius: 2px; + outline: none; + background: transparent; + color: rgba(0, 0, 0, .87); + font-size: 14px; /* Override font to specifically be px as spec defined pt */ + font-weight: 500; + line-height: 36px; /* Override line-height so text aligns centered */ + text-align: center; + text-transform: uppercase; + vertical-align: middle; + box-sizing: border-box; + -webkit-appearance: none; + + /* postcss-bem-linter: ignore */ + &::before { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + transition: opacity 120ms cubic-bezier(0, 0, .2, 1); + border-radius: inherit; + background: currentColor; + content: ""; + opacity: 0; + } + + &:focus::before { + opacity: .12; + } + + &:active::before { + opacity: .18; + } + + &:active { + outline: none; + } + + &:hover { + cursor: pointer; + } + + &::-moz-focus-inner { + padding: 0; + border: 0; + } + + &--dense { + height: 32px; + font-size: .8125rem; /* 13sp */ + line-height: 32px; + } + + &--raised { + min-width: 88px; + transition: box-shadow 280ms cubic-bezier(.4, 0, .2, 1); + box-shadow: + 0 3px 1px -2px rgba(0, 0, 0, .2), + 0 2px 2px 0 rgba(0, 0, 0, .14), + 0 1px 5px 0 rgba(0, 0, 0, .12); + will-change: box-shadow; + + &:active { + box-shadow: + 0 5px 5px -3px rgba(0, 0, 0, .2), + 0 8px 10px 1px rgba(0, 0, 0, .14), + 0 3px 14px 2px rgba(0, 0, 0, .12); + } + } + + &--primary { + color: var(--mdl-theme-color-primary); + + /* postcss-bem-linter: ignore */ + &.mdl-button--raised { + background-color: var(--mdl-theme-color-primary); + color: rgba(0, 0, 0, .87); + + /* postcss-bem-linter: ignore */ + &::before { + color: black; + } + } + } + + &--accent { + color: var(--mdl-theme-color-accent); + + /* postcss-bem-linter: ignore */ + &.mdl-button--raised { + background-color: var(--mdl-theme-color-accent); + color: rgba(0, 0, 0, .87); + + /* postcss-bem-linter: ignore */ + &::before { + color: black; + } + } + } + + /* stylelint-disable selector-no-type */ + fieldset:disabled &, + &:disabled { + color: rgba(0, 0, 0, .26); + cursor: default; + pointer-events: none; + } + + fieldset:disabled &--raised, + &--raised:disabled { + background-color: rgba(0, 0, 0, .12); + pointer-events: none; + box-shadow: none; + } +} + +/* postcss-bem-linter: end */ diff --git a/packages/mdl-button/package.json b/packages/mdl-button/package.json new file mode 100644 index 000000000..35624514f --- /dev/null +++ b/packages/mdl-button/package.json @@ -0,0 +1,5 @@ +{ + "name": "mdl-button", + "version": "1.0.0", + "license": "Apache 2.0" +} diff --git a/packages/mdl-card/README.md b/packages/mdl-card/README.md new file mode 100644 index 000000000..fef792fe4 --- /dev/null +++ b/packages/mdl-card/README.md @@ -0,0 +1,129 @@ +# mdl-card + +MDL card is a component that implements the +[Material Design card component](https://material.google.com/components/cards.html), and makes it available to +developers as a set of CSS classes. + +## Installation + +> Note: Installation via the npm registry will be available after alpha. + + +## Usage + +```html +
+
+

Title goes here

+

Subtitle here

+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim + veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea + commodo consequat. +
+
+ + +
+
+``` + +Cards don't come with a predefined width or height. They expand horizontally to fill all available space, and vertically +to fit their contents. + +If you'd like to maintain a consistent height and width across cards, you'll need to set it in your styles: + +```css +.my-card-container .mdl-card { + height: 350px; + width: 350px; +} +``` + +Content will be bottom-aligned if it's smaller than the height of the card. + + +### Content blocks + +Cards are composed of different content blocks, which are typically laid out in vertical succession. + + +#### Rich media + +```css +#example .mdl-card__media { + background-image: url("pretty.jpg"); + background-size: cover; + background-repeat: no-repeat; + height: 90px; +} +``` + +```html +
+``` + +This area is used for showing rich media in cards. Use the `mdl-card__media` CSS class. + + +#### Actions + +```html +
+ + +
+``` + +This area is used for showing different actions the user can take. It's typically used with buttons, as in the example +above, or with icon buttons, as below: + +> TODO(sgomes): Add icon button support and example. + +You can use the `mdl-card__actions--vertical` option to lay actions out vertically instead of horizontally: + +```html +
+ + +
+``` + +Be sure to include the `mdl-card__action` class on every action for correct positioning. + +#### Primary title / text + +```html +
+

Title goes here

+

Subtitle here

+
+``` + +This area is used for titles and subtitles: + +| Class | Description | +| ------------------------ | ----------------------------------------------- | +| `mdl-card__primary` | Defines the primary text / title content block. | +| `mdl-card__title` | A title block. | +| `mdl-card__title--large` | An option for the title, to make it larger. | +| `mdl-card__subtitle` | A subtitle block. | + +Note that the title and subtitle classes can also be used outside of the primary title / text content block. + + +#### Supporting text + +```html +
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim + veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea + commodo consequat. +
+``` + +This area is used for displaying the bulk of the textual content of the card. Use the `mdl-card__supporting-text` CSS +class. diff --git a/packages/mdl-card/mdl-card.scss b/packages/mdl-card/mdl-card.scss new file mode 100644 index 000000000..7d4bf6167 --- /dev/null +++ b/packages/mdl-card/mdl-card.scss @@ -0,0 +1,147 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "mdl-typography/mixins"; + +/* postcss-bem-linter: define card */ +.mdl-card { + display: flex; + flex-direction: column; + justify-content: flex-end; + padding: 0; + + /* TODO(sgomes): replace with elevation mixin once mdl-elevation is in. */ + box-shadow: + 0 3px 1px -2px rgba(0, 0, 0, .2), + 0 2px 2px 0 rgba(0, 0, 0, .14), + 0 1px 5px 0 rgba(0, 0, 0, .12); + + overflow: hidden; + box-sizing: border-box; + + &__primary { + padding: 16px; + + /* Add extra space before large title. */ + .mdl-card__title--large { + padding-top: 8px; + } + + /* Add extra padding if this is the last block. */ + &:last-child { + padding-bottom: 24px; + } + } + + &__supporting-text { + padding: 8px 16px; + + @include mdl-typography(body1); + @include mdl-typography-color(primary, true); + + /* Adjust text color for dark theme. */ + .mdl-card--dark-theme > &, + .mdl-theme--dark & { + @include mdl-typography-color(primary, false); + } + + /* Remove top padding if immediately preceded by a primary block. */ + .mdl-card__primary + & { + margin-top: -8px; + padding-top: 0; + } + + /* Add extra padding if this is the last block. */ + &:last-child { + padding-bottom: 24px; + } + } + + &__actions { + display: flex; + padding: 8px; + box-sizing: border-box; + + /* Adjust text color for dark theme. */ + .mdl-card--dark-theme > &, + .mdl-theme--dark & { + @include mdl-typography-color(primary, false); + } + + /* Tweak button paddings and margins when they're used as actions */ + .mdl-card__action { + margin: 0 8px 0 0; + } + .mdl-card__action:last-child { + margin-right: 0; + } + + /* Vertical actions (one per line) */ + &--vertical { + flex-flow: column; + align-items: flex-start; + + .mdl-card__action { + margin: 0 0 4px; + } + .mdl-card__action:last-child { + margin-bottom: 0; + } + } + } + + &__media { + display: flex; + flex-direction: column; + justify-content: flex-end; + padding: 16px; + box-sizing: border-box; + } + + &__title { + @include mdl-typography(body2); + @include mdl-typography-color(primary, true); + + /* Adjust text color for dark theme. */ + .mdl-card--dark-theme &, + .mdl-theme--dark & { + @include mdl-typography-color(primary, false); + } + + margin: -.063rem 0; /* -1sp 0 */ + } + + &__title--large { + @include mdl-typography(headline); + + margin: 0; + } + + &__subtitle { + @include mdl-typography(body1); + @include mdl-typography-color(secondary, true); + + /* Adjust text color for dark theme. */ + .mdl-card--dark-theme &, + .mdl-theme--dark & { + @include mdl-typography-color(primary, false); + } + + margin: -.063rem 0; /* -1sp 0 */ + } +} + +/* postcss-bem-linter: end */ diff --git a/packages/mdl-card/package.json b/packages/mdl-card/package.json new file mode 100644 index 000000000..a46b3d9e6 --- /dev/null +++ b/packages/mdl-card/package.json @@ -0,0 +1,12 @@ +{ + "name": "mdl-card", + "version": "1.0.0", + "description": "The Material Design Lite card component", + "license": "Apache-2.0", + "dependencies": { + "mdl-typography": "^1.0.0" + }, + "devDependencies": { + "mdl-button": "^1.0.0" + } +} diff --git a/packages/mdl-checkbox/README.md b/packages/mdl-checkbox/README.md new file mode 100644 index 000000000..aecf59837 --- /dev/null +++ b/packages/mdl-checkbox/README.md @@ -0,0 +1,179 @@ +# MDL Checkbox + +The MDL Checkbox component is a spec-aligned checkbox component adhering to the +[Material Design checkbox requirements](https://material.google.com/components/selection-controls.html#selection-controls-checkbox). +It works without JavaScript with basic functionality for all states. If you use the JavaScript object for a checkbox, then it will be add more intricate animation effects when switching between states. + +## Installation + +> Note: Installation via the npm registry will be available after alpha. + +## Usage + +### Standalone Checkbox + +```html +
+ +
+ + + +
+
+ +``` + +The checkbox component is driven by an underlying native checkbox element. This element is sized and +positioned the same way as the checkbox component itself, allowing for proper behavior of assistive +devices. + +You can also add an `mdl-checkbox--theme-dark` modifier class to the component to use the dark theme +checkbox styles. + +### Checkbox wrapper class + +MDL Checkbox comes with an `mdl-checkbox-wrapper` class which you can use to easily lay out a +checkbox / label combo side-by-side. The wrapper is RTL-aware and supports start and end alignment. + +```html +
+
+
+ +
+ + + +
+
+ +
+
+``` + +To switch the order of the checkbox and label, no DOM modification is necessary. Simply add a +`mdl-checkbox-wrapper--align-end` modifier class the the wrapper block. + +```html +
+
+ +
+
+``` + +### Using the JS Component + +MDL Checkbox ships with a Component / Foundation combo which progressively enhances the checkbox +state transitions to achieve full parity with the material design motion for switching checkbox +states. + +#### Including in code + +##### ES2015 + +```javascript +import MDLCheckbox, {MDLCheckboxFoundation} from 'mdl-checkbox'; +``` + +##### CommonJS + +```javascript +const mdlCheckbox = require('mdl-checkbox'); +const MDLCheckbox = mdlCheckbox.default; +const MDLCheckboxFoundation = mdlCheckbox.MDLCheckboxFoundation; +``` + +##### AMD + +```javascript +require(['path/to/mdl-checkbox'], mdlCheckbox => { + const MDLCheckbox = mdlCheckbox.default; + const MDLCheckboxFoundation = mdlCheckbox.MDLCheckboxFoundation; +}); +``` + +##### Global + +```javascript +const MDLCheckbox = mdl.Checkbox.default; +const MDLCheckboxFoundation = mdl.Checkbox.MDLCheckboxFoundation; +``` + +#### Fully-automatic: DOM Rendering + Initialization + +```javascript +const root = MDLCheckbox.buildDom({id: 'my-checkbox', labelId: 'my-checkbox-label'}); +const checkbox = MDLCheckbox.attachTo(root); +// append root to element, etc... +``` + +You can use `MDLCheckbox.buildDom` to dynamically construct checkbox DOM for you. +`MDLCheckbox.buildDom` takes an options object with values described below: + +| Option | Type | Default | Description | +| --- | --- | --- | --- | +| `id` | `string` | `mdl-checkbox-` | The id for the native checkbox control. | +| `labelId` | `string` | `mdl-checkbox-label-` | The id of the element which label's this checkbox. The default will use the `id` param and prefix it with `mdl-checkbox-label`. This value is +attached to the `aria-labelledby` attribute on the native control. | + +> **NOTE**: Regardless of how you instantiate a checkbox element, you should always strive to +> provide an id for the checkbox that's used within its label's `for` attribute, as well as an id +> for its label which is used in the native control's `aria-labelledby` attribute. This will ensure +> that assistive devices function properly when using this component. + +#### Using an existing element. + +If you do not care about retaining the component instance for the checkbox, simply call `attachTo()` +and pass it a DOM element. + +```javascript +mdl.Checkbox.attachTo(document.querySelector('.mdl-checkbox')); +``` + +#### Manual Instantiation + +Checkboxes can easily be initialized using their default constructors as well, similar to `attachTo`. + +```javascript +import MDLCheckbox from 'mdl-checkbox'; + +const checkbox = new MDLCheckbox(document.querySelector('.mdl-checkbox')); +``` + +### Using the Foundation Class + +MDL Checkbox ships with an `MDLCheckboxFoundation` class that external frameworks and libraries can +use to integrate the component. As with all foundation classes, an adapter object must be provided. +The adapter for checkboxes must provide the following functions, with correct signatures: + +| Method Signature | Description | +| --- | --- | +| `addClass(className: string) => void` | Adds a class to the root element. | +| `removeClass(className: string) => void` | Removes a class from the root element. | +| `registerAnimationEndHandler(handler: EventListener) => void` | Registers an event handler to be called when an `animationend` event is triggered on the root element. Note that you must account for +vendor prefixes in order for this to work correctly. | +| `deregisterAnimationEndHandler(handler: EventListener) => void` | Deregisters an event handler from an `animationend` event listener. This will only be called with handlers that have previously been passed to `registerAnimationEndHandler` calls. | +| `registerChangeHandler(handler: EventListener) => void` | Registers an event handler to be called when a `change` event is triggered on the native control (_not_ the root element). | +| `deregisterChangeHandler(handler: EventListener) => void` | Deregisters an event handler that was previously passed to `registerChangeHandler`. | +| `getNativeControl() => HTMLInputElement?` | Returns the native checkbox control, if available. Note that if this control is not available, the methods that rely on it will exit gracefully.| +| `forceLayout() => void` | Force-trigger a layout on the root element. This is needed to restart +animations correctly. If you find that you do not need to do this, you can simply make it a no-op. | +| `isAttachedToDOM() => boolean` | Returns true if the component is currently attached to the DOM, false otherwise.` | + +## Theming + +> TK once mdl-theming lands. diff --git a/packages/mdl-checkbox/_keyframes.scss b/packages/mdl-checkbox/_keyframes.scss new file mode 100644 index 000000000..99bf109f0 --- /dev/null +++ b/packages/mdl-checkbox/_keyframes.scss @@ -0,0 +1,178 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "./variables"; + +@keyframes mdl-checkbox-fade-in-background { + 0% { + border-color: $mdl-checkbox-border-color; + background-color: transparent; + } + + 50% { + border-color: $mdl-checkbox-background-color; + background-color: $mdl-checkbox-background-color; + } +} + +@keyframes mdl-checkbox-fade-out-background { + 0%, + 80% { + border-color: $mdl-checkbox-background-color; + background-color: $mdl-checkbox-background-color; + } + + 100% { + border-color: $mdl-checkbox-border-color; + background-color: transparent; + } +} + +@keyframes mdl-checkbox-fade-in-background-dark { + 0% { + border-color: $mdl-checkbox-border-color-dark; + background-color: transparent; + } + + 50% { + border-color: $mdl-checkbox-background-color; + background-color: $mdl-checkbox-background-color; + } +} + +@keyframes mdl-checkbox-fade-out-background-dark { + 0%, + 80% { + border-color: $mdl-checkbox-background-color; + background-color: $mdl-checkbox-background-color; + } + + 100% { + border-color: $mdl-checkbox-border-color-dark; + background-color: transparent; + } +} + +@keyframes mdl-checkbox-unchecked-checked-checkmark-path { + 0%, + 50% { + stroke-dashoffset: $_mdl-checkbox-mark-path-length; + } + + 50% { + @include mdl-animation-linear-out-slow-in; + } + + 100% { + stroke-dashoffset: 0; + } +} + +@keyframes mdl-checkbox-unchecked-indeterminate-mixedmark { + 0%, + 68.2% { + transform: scaleX(0); + } + + 68.2% { + animation-timing-function: cubic-bezier(0, 0, 0, 1); + } + + 100% { + transform: scaleX(1); + } +} + +@keyframes mdl-checkbox-checked-unchecked-checkmark-path { + from { + @include mdl-animation-fast-out-linear-in; + opacity: 1; + stroke-dashoffset: 0; + } + + to { + opacity: 0; + stroke-dashoffset: $_mdl-checkbox-mark-path-length * -1; + } +} + +@keyframes mdl-checkbox-checked-indeterminate-checkmark { + from { + transform: rotate(0deg); + opacity: 1; + + @include mdl-animation-linear-out-slow-in; + } + + to { + transform: rotate(45deg); + opacity: 0; + } +} + +@keyframes mdl-checkbox-indeterminate-checked-checkmark { + from { + transform: rotate(45deg); + opacity: 0; + animation-timing-function: $_mdl-checkbox-indeterminate-checked-easing-function; + } + + to { + transform: rotate(360deg); + opacity: 1; + } +} + +@keyframes mdl-checkbox-checked-indeterminate-mixedmark { + from { + transform: rotate(-45deg); + opacity: 0; + + @include mdl-animation-linear-out-slow-in; + } + + to { + transform: rotate(0deg); + opacity: 1; + } +} + +@keyframes mdl-checkbox-indeterminate-checked-mixedmark { + from { + transform: rotate(0deg); + opacity: 1; + animation-timing-function: $_mdl-checkbox-indeterminate-checked-easing-function; + } + + to { + transform: rotate(315deg); + opacity: 0; + } +} + +@keyframes mdl-checkbox-indeterminate-unchecked-mixedmark { + 0% { + transform: scaleX(1); + opacity: 1; + animation-timing-function: linear; + } + + 32.8%, + 100% { + transform: scaleX(0); + opacity: 0; + } +} diff --git a/packages/mdl-checkbox/_variables.scss b/packages/mdl-checkbox/_variables.scss new file mode 100644 index 000000000..c722acbeb --- /dev/null +++ b/packages/mdl-checkbox/_variables.scss @@ -0,0 +1,33 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* TODO: Revisit once MDL theming lands */ +$mdl-checkbox-background-color: #3f51b5 !default; +$mdl-checkbox-mark-color: white !default; +$mdl-checkbox-border-color: rgba(black, .54) !default; +$mdl-checkbox-border-color-dark: white !default; +$mdl-checkbox-disabled-color: rgba(black, .26) !default; +$mdl-checkbox-disabled-color-dark: rgba(white, .3) !default; + +$mdl-checkbox-size: 18px; +$mdl-checkbox-mark-stroke-size: 2/15 * $mdl-checkbox-size; +$mdl-checkbox-border-width: 2px; +$mdl-checkbox-transition-duration: 90ms; +$mdl-checkbox-item-spacing: 4px; + +/* Manual calculation done on SVG */ +$_mdl-checkbox-mark-path-length: 29.7833385; +$_mdl-checkbox-indeterminate-checked-easing-function: cubic-bezier(.14, 0, 0, 1); diff --git a/packages/mdl-checkbox/constants.js b/packages/mdl-checkbox/constants.js new file mode 100644 index 000000000..44edc5a28 --- /dev/null +++ b/packages/mdl-checkbox/constants.js @@ -0,0 +1,50 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const ROOT = 'mdl-checkbox'; +const ANIM = `${ROOT}--anim`; + +export const cssClasses = { + ROOT, + CHECKED: `${ROOT}--checked`, + INDETERMINATE: `${ROOT}--indeterminate`, + ANIM_UNCHECKED_CHECKED: `${ANIM}-unchecked-checked`, + ANIM_UNCHECKED_INDETERMINATE: `${ANIM}-unchecked-indeterminate`, + ANIM_CHECKED_UNCHECKED: `${ANIM}-checked-unchecked`, + ANIM_CHECKED_INDETERMINATE: `${ANIM}-checked-indeterminate`, + ANIM_INDETERMINATE_CHECKED: `${ANIM}-indeterminate-checked`, + ANIM_INDETERMINATE_UNCHECKED: `${ANIM}-indeterminate-unchecked` +}; + +export const strings = { + ANIM_END_EVENT_NAME: (() => { + const el = document.createElement('div'); + // NOTE: We can immediately assume that the prefix is 'webkit' in browsers that don't + // support unprefixed animations since the only browsers up to two major versions back that + // don't support unprefixed names are mobile Safari and Android native browser, both of + // which use the 'webkit' prefix. + return 'animation' in el.style ? 'animationend' : 'webkitAnimationEnd'; + })(), + NATIVE_CONTROL_SELECTOR: `.${ROOT}__native-control`, + TRANSITION_STATE_INIT: 'init', + TRANSITION_STATE_CHECKED: 'checked', + TRANSITION_STATE_UNCHECKED: 'unchecked', + TRANSITION_STATE_INDETERMINATE: 'indeterminate' +}; + +export const numbers = { + ANIM_END_LATCH_MS: 100 +}; diff --git a/packages/mdl-checkbox/foundation.js b/packages/mdl-checkbox/foundation.js new file mode 100644 index 000000000..8189ebe4b --- /dev/null +++ b/packages/mdl-checkbox/foundation.js @@ -0,0 +1,194 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {MDLFoundation} from 'mdl-base'; +import {cssClasses, strings, numbers} from './constants'; + +const CB_PROTO_PROPS = ['checked', 'indeterminate']; + +export default class MDLCheckboxFoundation extends MDLFoundation { + static get cssClasses() { + return cssClasses; + } + + static get strings() { + return strings; + } + + static get numbers() { + return numbers; + } + + static get defaultAdapter() { + return { + addClass: (/* className: string */) => {}, + removeClass: (/* className: string */) => {}, + registerAnimationEndHandler: (/* handler: EventListener */) => {}, + deregisterAnimationEndHandler: (/* handler: EventListener */) => {}, + registerChangeHandler: (/* handler: EventListener */) => {}, + deregisterChangeHandler: (/* handler: EventListener */) => {}, + getNativeControl: () => /* HTMLInputElement */ {}, + forceLayout: () => {}, + isAttachedToDOM: () => /* boolean */ {} + }; + } + + constructor(adapter) { + super(Object.assign(MDLCheckboxFoundation.defaultAdapter, adapter)); + + this.currentCheckState_ = strings.TRANSITION_STATE_INIT; + this.currentAnimationClass_ = ''; + this.animEndLatchTimer_ = 0; + this.animEndHandler_ = () => { + clearTimeout(this.animEndLatchTimer_); + this.animEndLatchTimer_ = setTimeout(() => { + this.adapter_.removeClass(this.currentAnimationClass_); + this.adapter_.deregisterAnimationEndHandler(this.animEndHandler_); + }, numbers.ANIM_END_LATCH_MS); + }; + this.changeHandler_ = () => this.transitionCheckState_(); + } + + init() { + this.adapter_.registerChangeHandler(this.changeHandler_); + this.installPropertyChangeHooks_(); + } + + destroy() { + this.adapter_.deregisterChangeHandler(this.changeHandler_); + this.uninstallPropertyChangeHooks_(); + } + + installPropertyChangeHooks_() { + const nativeCb = this.adapter_.getNativeControl(); + if (!nativeCb) { + return; + } + const cbProto = Object.getPrototypeOf(nativeCb); + + CB_PROTO_PROPS.forEach(controlState => { + const desc = Object.getOwnPropertyDescriptor(cbProto, controlState); + // We have to check for this descriptor, since some browsers (Safari) don't support its return. + // See: https://bugs.webkit.org/show_bug.cgi?id=49739 + if (validDescriptor(desc)) { + Object.defineProperty(nativeCb, controlState, { + get: desc.get, + set: state => { + desc.set.call(nativeCb, state); + this.transitionCheckState_(); + }, + configurable: desc.configurable, + enumerable: desc.enumerable + }); + } + }); + } + + uninstallPropertyChangeHooks_() { + const nativeCb = this.adapter_.getNativeControl(); + if (!nativeCb) { + return; + } + const cbProto = Object.getPrototypeOf(nativeCb); + + CB_PROTO_PROPS.forEach(controlState => { + const desc = Object.getOwnPropertyDescriptor(cbProto, controlState); + if (validDescriptor(desc)) { + Object.defineProperty(nativeCb, controlState, desc); + } + }); + } + + transitionCheckState_() { + const nativeCb = this.adapter_.getNativeControl(); + if (!nativeCb) { + return; + } + const oldState = this.currentCheckState_; + const newState = this.determineCheckState_(nativeCb); + if (oldState === newState) { + return; + } + + // Check to ensure that there isn't a previously existing animation class, in case for example + // the user interacted with the checkbox before the animation was finished. + if (this.currentAnimationClass_.length > 0) { + clearTimeout(this.animEndLatchTimer_); + this.adapter_.forceLayout(); + this.adapter_.removeClass(this.currentAnimationClass_); + } + + this.currentAnimationClass_ = this.getTransitionAnimationClass_(oldState, newState); + this.currentCheckState_ = newState; + + // Check for parentNode so that animations are only run when the element is attached + // to the DOM. + if (this.adapter_.isAttachedToDOM() && this.currentAnimationClass_.length > 0) { + this.adapter_.addClass(this.currentAnimationClass_); + this.adapter_.registerAnimationEndHandler(this.animEndHandler_); + } + } + + determineCheckState_(nativeCb) { + const { + TRANSITION_STATE_INDETERMINATE, + TRANSITION_STATE_CHECKED, + TRANSITION_STATE_UNCHECKED + } = strings; + + if (nativeCb.indeterminate) { + return TRANSITION_STATE_INDETERMINATE; + } + return nativeCb.checked ? TRANSITION_STATE_CHECKED : TRANSITION_STATE_UNCHECKED; + } + + getTransitionAnimationClass_(oldState, newState) { + const { + TRANSITION_STATE_INIT, + TRANSITION_STATE_CHECKED, + TRANSITION_STATE_UNCHECKED + } = strings; + + const { + ANIM_UNCHECKED_CHECKED, + ANIM_UNCHECKED_INDETERMINATE, + ANIM_CHECKED_UNCHECKED, + ANIM_CHECKED_INDETERMINATE, + ANIM_INDETERMINATE_CHECKED, + ANIM_INDETERMINATE_UNCHECKED + } = MDLCheckboxFoundation.cssClasses; + + switch (oldState) { + case TRANSITION_STATE_INIT: + if (newState === TRANSITION_STATE_UNCHECKED) { + return ''; + } + // fallthrough + case TRANSITION_STATE_UNCHECKED: + return newState === TRANSITION_STATE_CHECKED ? ANIM_UNCHECKED_CHECKED : ANIM_UNCHECKED_INDETERMINATE; + case TRANSITION_STATE_CHECKED: + return newState === TRANSITION_STATE_UNCHECKED ? ANIM_CHECKED_UNCHECKED : ANIM_CHECKED_INDETERMINATE; + // TRANSITION_STATE_INDETERMINATE + default: + return newState === TRANSITION_STATE_CHECKED ? + ANIM_INDETERMINATE_CHECKED : ANIM_INDETERMINATE_UNCHECKED; + } + } +} + +function validDescriptor(inputPropDesc) { + return inputPropDesc && typeof inputPropDesc.set === 'function'; +} diff --git a/packages/mdl-checkbox/index.js b/packages/mdl-checkbox/index.js new file mode 100644 index 000000000..3678031f7 --- /dev/null +++ b/packages/mdl-checkbox/index.js @@ -0,0 +1,70 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import MDLComponent from 'mdl-base'; +import MDLCheckboxFoundation from './foundation'; + +let idCounter = 0; + +export default class MDLCheckbox extends MDLComponent { + static buildDom({id = `mdl-checkbox-${++idCounter}`, labelId = `mdl-checkbox-label-${id}`} = {}) { + const {ROOT: CSS_ROOT} = MDLCheckboxFoundation.cssClasses; + + const root = document.createElement('div'); + root.classList.add(CSS_ROOT); + root.innerHTML = ` + +
+
+ + + +
+
+ `; + + return root; + } + + static attachTo(root) { + return new MDLCheckbox(root); + } + + getDefaultFoundation() { + const {ANIM_END_EVENT_NAME, NATIVE_CONTROL_SELECTOR} = MDLCheckboxFoundation.strings; + const nativeCb = this.root_.querySelector(NATIVE_CONTROL_SELECTOR); + return new MDLCheckboxFoundation({ + addClass: className => this.root_.classList.add(className), + removeClass: className => this.root_.classList.remove(className), + registerAnimationEndHandler: handler => this.root_.addEventListener(ANIM_END_EVENT_NAME, handler), + deregisterAnimationEndHandler: handler => this.root_.removeEventListener(ANIM_END_EVENT_NAME, handler), + registerChangeHandler: handler => nativeCb.addEventListener('change', handler), + deregisterChangeHandler: handler => nativeCb.removeEventListener('change', handler), + getNativeControl: () => nativeCb, + forceLayout: () => this.root_.offsetWidth, + isAttachedToDOM: () => Boolean(this.root_.parentNode) + }); + } +} diff --git a/packages/mdl-checkbox/mdl-checkbox.scss b/packages/mdl-checkbox/mdl-checkbox.scss new file mode 100644 index 000000000..b403e06a7 --- /dev/null +++ b/packages/mdl-checkbox/mdl-checkbox.scss @@ -0,0 +1,357 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "mdl-animation/mixins"; +@import "./variables"; +@import "./keyframes"; + +// TODO: Docs +// TODO: x-browser test! + +@function mdl-checkbox-transition($property, $timing-function, $delay: 0ms, $duration: $mdl-checkbox-transition-duration) { + @return $property $duration $timing-function $delay; +} + +@function mdl-checkbox-transition-enter($property, $delay: 0ms, $duration: $mdl-checkbox-transition-duration) { + @return mdl-checkbox-transition( + $property, $mdl-animation-linear-out-slow-in-timing-function, $delay, $duration); +} + +@function mdl-checkbox-transition-exit($property, $delay: 0ms, $duration: $mdl-checkbox-transition-duration) { + @return mdl-checkbox-transition( + $property, $mdl-animation-fast-out-linear-in-timing-function, $delay, $duration); +} + +@mixin mdl-checkbox-cover-element { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; +} + +@mixin mdl-checkbox-outer-box { + border-radius: 2px; + + @include mdl-checkbox-cover-element; + box-sizing: border-box; + pointer-events: none; +} + +@mixin mdl-checkbox-focus-ring-transition($timing-fn) { + transition: + mdl-checkbox-transition(opacity, $timing-fn, 0ms, 80ms), + mdl-checkbox-transition(transform, $timing-fn, 0ms, 80ms); +} + +/* postcss-bem-linter: define checkbox-wrapper */ +.mdl-checkbox-wrapper { + display: inline-block; + + &__layout { + display: inline-flex; + align-items: baseline; + vertical-align: middle; + } + + /* postcss-bem-linter: ignore */ + .mdl-checkbox { + order: 0; + margin: auto; + margin-right: $mdl-checkbox-item-spacing; + + /* postcss-bem-linter: ignore */ + [dir="rtl"] & { + margin-right: auto; + margin-left: $mdl-checkbox-item-spacing; + } + } +} + +.mdl-checkbox-wrapper--align-end { + /* postcss-bem-linter: ignore */ + .mdl-checkbox { + order: 1; + margin-right: auto; + margin-left: $mdl-checkbox-item-spacing; + + /* postcss-bem-linter: ignore */ + [dir="rtl"] & { + margin-right: $mdl-checkbox-item-spacing; + margin-left: auto; + } + } +} + +/* postcss-bem-linter: end */ + +/* postcss-bem-linter: define checkbox */ +.mdl-checkbox { + display: inline-block; + position: relative; + width: $mdl-checkbox-size; + height: $mdl-checkbox-size; + line-height: 0; + white-space: nowrap; + cursor: pointer; + vertical-align: bottom; + + &__background { + @include mdl-checkbox-outer-box; + + display: inline-flex; + align-items: center; + justify-content: center; + transition: + mdl-checkbox-transition-exit(background-color), + mdl-checkbox-transition-exit(border-color); + + border: $mdl-checkbox-border-width solid $mdl-checkbox-border-color; + background-color: transparent; + will-change: background-color, border-color; + + .mdl-checkbox--dark-theme & { + border-color: $mdl-checkbox-border-color-dark; + } + + /** The frame's ::before element is used as a focus indicator for the checkbox */ + &::before { + @include mdl-checkbox-cover-element; + + transform: scale(0, 0); + transition: mdl-checkbox-transition-exit(opacity), mdl-checkbox-transition-exit(transform); + border-radius: 50%; + background: $mdl-checkbox-background-color; + content: ""; + opacity: 0; + pointer-events: none; + will-change: opacity, transform; + } + } + + &__native-control { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + margin: 0; + padding: 0; + cursor: inherit; + opacity: 0; + } + + &__checkmark { + @include mdl-checkbox-cover-element; + + width: 100%; + transition: mdl-checkbox-transition-exit(opacity, 0ms, $mdl-checkbox-transition-duration * 2); + opacity: 0; + fill: $mdl-checkbox-mark-color; + + &__path { + transition: + mdl-checkbox-transition-exit( + stroke-dashoffset, + 0ms, + $mdl-checkbox-transition-duration * 2 + ); + // !important is needed here because a stroke must be set as an attribute on the SVG in order + // for line animation to work properly. + stroke: $mdl-checkbox-mark-color !important; + stroke-width: $mdl-checkbox-mark-stroke-size * 1.3; + stroke-dashoffset: $_mdl-checkbox-mark-path-length; + stroke-dasharray: $_mdl-checkbox-mark-path-length; + } + } + + &__mixedmark { + width: 100%; + height: floor($mdl-checkbox-mark-stroke-size); + transform: scaleX(0) rotate(0deg); + transition: mdl-checkbox-transition-exit(opacity), mdl-checkbox-transition-exit(transform); + background-color: $mdl-checkbox-mark-color; + opacity: 0; + } +} + +.mdl-checkbox__native-control:focus { + ~ .mdl-checkbox__background::before { + @include mdl-checkbox-focus-ring-transition($mdl-animation-linear-out-slow-in-timing-function); + transform: scale(2.75, 2.75); + opacity: .26; + } +} + +.mdl-checkbox__native-control:checked { + ~ .mdl-checkbox__background { + transition: + mdl-checkbox-transition-enter(border-color), + mdl-checkbox-transition-enter(background-color); + border-color: $mdl-checkbox-background-color; + background-color: $mdl-checkbox-background-color; + + .mdl-checkbox__checkmark { + transition: + mdl-checkbox-transition-enter(opacity, 0ms, $mdl-checkbox-transition-duration * 2), + mdl-checkbox-transition-enter(transform, 0ms, $mdl-checkbox-transition-duration * 2); + opacity: 1; + + &__path { + stroke-dashoffset: 0; + } + } + + .mdl-checkbox__mixedmark { + transform: scaleX(1) rotate(-45deg); + } + } +} + +.mdl-checkbox__native-control:indeterminate { + ~ .mdl-checkbox__background { + border-color: $mdl-checkbox-background-color; + background-color: $mdl-checkbox-background-color; + + .mdl-checkbox__checkmark { + transform: rotate(45deg); + transition: + mdl-checkbox-transition-exit(opacity, 0ms, $mdl-checkbox-transition-duration), + mdl-checkbox-transition-exit(transform, 0ms, $mdl-checkbox-transition-duration); + opacity: 0; + + &__path { + stroke-dashoffset: 0; + } + } + + .mdl-checkbox__mixedmark { + transform: scaleX(1) rotate(0deg); + opacity: 1; + } + } +} + +.mdl-checkbox__native-control:disabled, +fieldset:disabled .mdl-checkbox__native-control, +[aria-disabled="true"] .mdl-checkbox__native-control { + cursor: default; + + /* postcss-bem-linter: ignore */ + ~ .mdl-checkbox__background { + border-color: $mdl-checkbox-disabled-color; + + .mdl-checkbox--dark-theme & { + border-color: $mdl-checkbox-disabled-color-dark; + } + } + + &:checked, + &:indeterminate { + ~ .mdl-checkbox__background { + border-color: transparent; + background-color: $mdl-checkbox-disabled-color; + /* stylelint-disable selector-max-compound-selectors, selector-max-specificity */ + .mdl-checkbox--dark-theme & { + background-color: $mdl-checkbox-disabled-color-dark; + } + /* stylelint-enable selector-max-compound-selectors, selector-max-specificity */ + } + } +} + +.mdl-checkbox--anim { + $_mdl-checkbox-indeterminate-change-duration: 500ms; + + &-unchecked-checked, + &-unchecked-indeterminate { + .mdl-checkbox__background { + animation: mdl-checkbox-fade-in-background $mdl-checkbox-transition-duration * 2 linear; + + .mdl-checkbox--dark-theme & { + animation-name: mdl-checkbox-fade-in-background-dark; + } + } + } + + &-checked-unchecked, + &-indeterminate-unchecked { + .mdl-checkbox__background { + animation: mdl-checkbox-fade-out-background $mdl-checkbox-transition-duration * 2 linear; + + .mdl-checkbox--dark-theme & { + animation-name: mdl-checkbox-fade-out-background-dark; + } + } + } + + &-unchecked-checked { + .mdl-checkbox__checkmark__path { + // Instead of delaying the animation, we simply multiply its length by 2 and begin the + // animation at 50% in order to prevent a flash of styles applied to a checked checkmark + // as the background is fading in before the animation begins. + animation: $mdl-checkbox-transition-duration * 2 linear 0s mdl-checkbox-unchecked-checked-checkmark-path; + transition: none; + } + } + + &-unchecked-indeterminate { + .mdl-checkbox__mixedmark { + animation: $mdl-checkbox-transition-duration linear 0s mdl-checkbox-unchecked-indeterminate-mixedmark; + transition: none; + } + } + + &-checked-unchecked { + .mdl-checkbox__checkmark__path { + animation: $mdl-checkbox-transition-duration linear 0s mdl-checkbox-checked-unchecked-checkmark-path; + transition: none; + } + } + + &-checked-indeterminate { + .mdl-checkbox__checkmark { + animation: $mdl-checkbox-transition-duration linear 0s mdl-checkbox-checked-indeterminate-checkmark; + transition: none; + } + + .mdl-checkbox__mixedmark { + animation: $mdl-checkbox-transition-duration linear 0s mdl-checkbox-checked-indeterminate-mixedmark; + transition: none; + } + } + + &-indeterminate-checked { + .mdl-checkbox__checkmark { + animation: $_mdl-checkbox-indeterminate-change-duration linear 0s mdl-checkbox-indeterminate-checked-checkmark; + transition: none; + } + + .mdl-checkbox__mixedmark { + animation: $_mdl-checkbox-indeterminate-change-duration linear 0s mdl-checkbox-indeterminate-checked-mixedmark; + transition: none; + } + } + + &-indeterminate-unchecked { + .mdl-checkbox__mixedmark { + animation: $_mdl-checkbox-indeterminate-change-duration * .6 linear 0s mdl-checkbox-indeterminate-unchecked-mixedmark; + transition: none; + } + } +} + +/* postcss-bem-linter: end */ diff --git a/packages/mdl-checkbox/mixin.js b/packages/mdl-checkbox/mixin.js new file mode 100644 index 000000000..52ee11fbb --- /dev/null +++ b/packages/mdl-checkbox/mixin.js @@ -0,0 +1,198 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {cssClasses, strings, numbers} from './constants'; + +/** + * AOP! Frameworks can define their own methods of doing these things should they choose to! + * @param {!Object} options Options which won't work in advanced compilation mode...yet. + */ +export default function MDLCheckboxMixin(options = {}) { + if (!this || typeof this !== 'object') { + throw new Error('You must call MDLCheckboxMixin with a prototype object as its receiver'); + } + + options = Object.assign({ + addClass: () => {}, + removeClass: () => {}, + addEventListener: () => {}, + removeEventListener: () => {}, + addNativeCheckboxListener: () => {}, + removeNativeCheckboxListener: () => {}, + getNativeCheckbox: () => { + throw new Error('I will not work properly without getNativeCheckbox!'); + }, + forceLayout: () => {}, + isAttachedToDOM: () => {} + }, options); + + Object.assign(this, { + initMdlCheckbox_() { + this.currentCheckState_ = strings.TRANSITION_STATE_INIT; + this.currentAnimationClass_ = ''; + this.animEndLatchTimer_ = 0; + this.animEndListener_ = () => { + clearTimeout(this.animEndLatchTimer_); + this.animEndLatchTimer_ = setTimeout(() => { + options.removeClass.call(this, this.currentAnimationClass_); + options.removeEventListener.call( + this, strings.ANIM_END_EVENT_NAME, this.animEndListener_); + }, numbers.ANIM_END_LATCH_MS); + }; + + this.eventListeners_ = { + nativeCheckboxFocus: () => options.addClass.call(this, cssClasses.FOCUSED), + nativeCheckboxBlur: () => options.removeClass.call(this, cssClasses.FOCUSED), + nativeCheckboxChange: () => this.transitionCheckState_() + }; + this.addEventListeners(); + }, + + addEventListeners() { + const { + nativeCheckboxFocus, + nativeCheckboxBlur, + nativeCheckboxChange + } = this.eventListeners_; + options.addNativeCheckboxListener.call(this, 'focus', nativeCheckboxFocus); + options.addNativeCheckboxListener.call(this, 'blur', nativeCheckboxBlur); + options.addNativeCheckboxListener.call(this, 'change', nativeCheckboxChange); + this.installPropertyChangeHooks(); + }, + + removeEventListeners() { + const { + nativeCheckboxFocus, + nativeCheckboxBlur, + nativeCheckboxChange + } = this.eventListeners_; + options.removeNativeCheckboxListener.call(this, 'focus', nativeCheckboxFocus); + options.removeNativeCheckboxListener.call(this, 'blur', nativeCheckboxBlur); + options.removeNativeCheckboxListener.call(this, 'change', nativeCheckboxChange); + this.uninstallPropertyChangeHooks(); + }, + + installPropertyChangeHooks() { + const nativeCb = options.getNativeCheckbox.call(this); + const cbProto = Object.getPrototypeOf(nativeCb); + // We override "checked" as change events only fire on interactions. We + // want animations to be run when properties change as well. + ['checked', 'indeterminate'].forEach(controlState => { + const desc = Object.getOwnPropertyDescriptor(cbProto, controlState); + Object.defineProperty(nativeCb, controlState, { + get: desc.get, + set: state => { + desc.set.call(nativeCb, state); + this.transitionCheckState_(); + }, + configurable: desc.configurable, + enumerable: desc.enumerable + }); + }); + + // NOTE: should we defineProperty indicator hooks are installed onto the nativeCb? This way + // frameworks can check if hooks are already installed. + }, + + uninstallPropertyChangeHooks() { + const nativeCb = options.getNativeCheckbox.call(this); + const cbProto = Object.getPrototypeOf(nativeCb); + ['checked', 'indeterminate'].forEach(controlState => { + const desc = Object.getOwnPropertyDescriptor(cbProto, controlState); + Object.defineProperty(nativeCb, controlState, desc); + }); + }, + + transitionCheckState_() { + const oldState = this.currentCheckState_; + const newState = this.determineCheckState_(); + if (oldState === newState) { + return; + } + + // Check to ensure that there isn't a previously existing animation class, in case for example + // the user interacted with the checkbox before the animation was finished. + if (this.currentAnimationClass_.length > 0) { + clearTimeout(this.animEndLatchTimer_); + options.forceLayout.call(this); + options.removeClass.call(this, this.currentAnimationClass_); + } + + this.currentAnimationClass_ = this.getTransitionAnimationClass_(oldState, newState); + this.currentCheckState_ = newState; + + // Check for parentNode so that animations are only run when the element is attached + // to the DOM. + if (options.isAttachedToDOM.call(this) && this.currentAnimationClass_.length > 0) { + options.addClass.call(this, this.currentAnimationClass_); + options.addEventListener.call( + this, strings.ANIM_END_EVENT_NAME, this.animEndListener_); + } + }, + + determineCheckState_() { + const nativeCb = options.getNativeCheckbox.call(this); + const { + TRANSITION_STATE_INDETERMINATE, + TRANSITION_STATE_CHECKED, + TRANSITION_STATE_UNCHECKED + } = strings; + + if (nativeCb.indeterminate) { + return TRANSITION_STATE_INDETERMINATE; + } + return nativeCb.checked ? + TRANSITION_STATE_CHECKED : TRANSITION_STATE_UNCHECKED; + }, + + getTransitionAnimationClass_(oldState, newState) { + const { + TRANSITION_STATE_INIT, + TRANSITION_STATE_CHECKED, + TRANSITION_STATE_UNCHECKED, + TRANSITION_STATE_INDETERMINATE + } = strings; + + const { + ANIM_UNCHECKED_CHECKED, + ANIM_UNCHECKED_INDETERMINATE, + ANIM_CHECKED_UNCHECKED, + ANIM_CHECKED_INDETERMINATE, + ANIM_INDETERMINATE_CHECKED, + ANIM_INDETERMINATE_UNCHECKED + } = cssClasses; + + switch (oldState) { + case TRANSITION_STATE_INIT: + if (newState === TRANSITION_STATE_UNCHECKED) { + return ''; + } + // fallthrough + case TRANSITION_STATE_UNCHECKED: + return newState === TRANSITION_STATE_CHECKED ? + ANIM_UNCHECKED_CHECKED : ANIM_UNCHECKED_INDETERMINATE; + case TRANSITION_STATE_CHECKED: + return newState === TRANSITION_STATE_UNCHECKED ? + ANIM_CHECKED_UNCHECKED : ANIM_CHECKED_INDETERMINATE; + case TRANSITION_STATE_INDETERMINATE: + return newState === TRANSITION_STATE_CHECKED ? + ANIM_INDETERMINATE_CHECKED : ANIM_INDETERMINATE_UNCHECKED; + default: + return ''; + } + } + }); +} diff --git a/packages/mdl-checkbox/package.json b/packages/mdl-checkbox/package.json new file mode 100644 index 000000000..8deff943c --- /dev/null +++ b/packages/mdl-checkbox/package.json @@ -0,0 +1,9 @@ +{ + "name": "mdl-checkbox", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "mdl-animation": "^1.0.0", + "mdl-base": "^1.0.0" + } +} diff --git a/packages/mdl-fab/README.md b/packages/mdl-fab/README.md new file mode 100644 index 000000000..ce2493f7b --- /dev/null +++ b/packages/mdl-fab/README.md @@ -0,0 +1,93 @@ +# MDL FAB + +The MDL FAB component is a spec-aligned button component adhering to the + [Material Design FAB requirements](https://material.google.com/components/buttons-floating-action-button.html). + It works without JavaScript with basic functionality for all states. + If you initiate the JavaScript object for a button, then it will be enhanced with ripple effects. (Not yet implemented) + +## Installation + +> Note: Installation via the npm registry will be available after alpha. + +## Usage + +The demonstrations use the [Material Design Icon Font](https://design.google.com/icons/). +You may include this to use them as shown or use any other icon method you wish. + +### Default + +```html + +``` + +### Mini + +```html + +``` + +### Plain + +```html + +``` + +### Absolutely positioned + +By default the FAB rests in the page where it sits in the content flow. +Developers must position it as-needed within their applications designs. + +```html + + + + +``` + +## Classes + +### Block + +The block class is `mdl-fab`. This defines the top-level button element. + +### Element + +The button component has no inner elements. + +### Modifier + +The provided modifiers are: + +| Class | Description | +| ------------------| --------------------------------------- | +| `mdl-fab--mini` | Makes the fab smaller (40 x 40 pixels). | +| `mdl-fab--plain` | Makes the FAB have a white background. | diff --git a/src/_functions.scss b/packages/mdl-fab/_variables.scss similarity index 76% rename from src/_functions.scss rename to packages/mdl-fab/_variables.scss index 80e7ca479..c92d391d4 100644 --- a/src/_functions.scss +++ b/packages/mdl-fab/_variables.scss @@ -1,5 +1,5 @@ /** - * Copyright 2015 Google Inc. All Rights Reserved. + * Copyright 2016 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ * limitations under the License. */ -@function strip-units($number) { - @return $number / ($number * 0 + 1); +/* @TODO Remove this internally once the theme base is in place. */ +:root { + --mdl-theme-color-accent: rgb(255, 64, 129); } diff --git a/packages/mdl-fab/mdl-fab.scss b/packages/mdl-fab/mdl-fab.scss new file mode 100644 index 000000000..441a7d2c0 --- /dev/null +++ b/packages/mdl-fab/mdl-fab.scss @@ -0,0 +1,106 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "variables"; + +/* postcss-bem-linter: define fab */ +.mdl-fab { + display: inline-flex; + position: relative; + justify-content: center; + width: 56px; + height: 56px; + padding: 0; + transition: box-shadow 280ms cubic-bezier(.4, 0, .2, 1); + border: none; + border-radius: 50%; + background-color: var(--mdl-theme-color-accent); + color: white; + box-shadow: + 0 3px 5px -1px rgba(0, 0, 0, .2), + 0 6px 10px 0 rgba(0, 0, 0, .14), + 0 1px 18px 0 rgba(0, 0, 0, .12); + cursor: pointer; + overflow: hidden; + user-select: none; + box-sizing: border-box; + fill: currentColor; + -moz-appearance: none; + -webkit-appearance: none; + + &--mini { + width: 40px; + height: 40px; + } + + &--plain { + background-color: white; + color: rgba(0, 0, 0, .87); + } + + &::before { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + transition: opacity 120ms cubic-bezier(0, 0, .2, 1); + border-radius: inherit; + background: black; + content: ""; + opacity: 0; + } + + &:focus::before { + opacity: .12; + } + + &:active::before { + opacity: .18; + } + + &:active, + &:focus { + outline: none; + } + + &:active { + box-shadow: + 0 7px 8px -4px rgba(0, 0, 0, .2), + 0 12px 17px 2px rgba(0, 0, 0, .14), + 0 5px 22px 4px rgba(0, 0, 0, .12); + } + + &:hover { + cursor: pointer; + } + + &::-moz-focus-inner { + padding: 0; + border: 0; + } + + /* stylelint-disable selector-no-type */ + fieldset:disabled &, + &:disabled { + background-color: rgba(0, 0, 0, .12); + color: rgba(0, 0, 0, .26); + cursor: default; + pointer-events: none; + } +} + +/* postcss-bem-linter: end */ diff --git a/packages/mdl-fab/package.json b/packages/mdl-fab/package.json new file mode 100644 index 000000000..f4a9fc571 --- /dev/null +++ b/packages/mdl-fab/package.json @@ -0,0 +1,6 @@ +{ + "name": "mdl-fab", + "description": "A simple FAB component provided by Material Design Lite", + "version": "1.0.0", + "license": "Apache-2.0" +} diff --git a/packages/mdl-radio/index.js b/packages/mdl-radio/index.js new file mode 100644 index 000000000..4383c516a --- /dev/null +++ b/packages/mdl-radio/index.js @@ -0,0 +1,42 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import MDLComponent, {MDLBaseAdapterLegacy as MDLBaseAdapter} from 'mdl-base'; +import MDLRadioMixin, { + Identifier +} from './mixin'; + +export default class MDLRadio extends MDLComponent { + static attachTo(root) { + return new MDLRadio(root); + } + + constructor(root) { + super(root); + + const nativeInput = root.getElementsByClassName(Identifier.NATIVE_INPUT)[0]; + const elements = { + [Identifier.ROOT]: root, + [Identifier.NATIVE_INPUT]: nativeInput + }; + + this.elements_ = elements; + + this.initMdlRadio_(); + } +} + +MDLRadioMixin.call(MDLRadio.prototype, MDLBaseAdapter); diff --git a/packages/mdl-radio/mdl-radio.scss b/packages/mdl-radio/mdl-radio.scss new file mode 100644 index 000000000..4ed4e502f --- /dev/null +++ b/packages/mdl-radio/mdl-radio.scss @@ -0,0 +1,133 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +$mdl-radio-size: 20px !default; +$mdl-radio-foreground-color: #333 !default; +$mdl-radio-accent-color: rgba(255, 82, 82, .87) !default; +$mdl-radio-disabled-color: gray !default; +$mdl-radio-timing-fn: ease 280ms !default; + +// Top-level host container. +// postcss-bem-linter: define radio +.mdl-radio { + display: inline-block; + transition: color $mdl-radio-timing-fn; + color: $mdl-radio-foreground-color; + + // Container for radio circles and ripple. + &__container { + display: inline-block; + position: relative; + width: $mdl-radio-size; + height: $mdl-radio-size; + cursor: pointer; + box-sizing: border-box; + } + // The outer circle for the radio, always present. + &__outer-circle { + position: absolute; + top: 0; + left: 0; + width: $mdl-radio-size; + height: $mdl-radio-size; + transition: border-color $mdl-radio-timing-fn; + border: 2px solid $mdl-radio-foreground-color; + border-radius: 50%; + box-sizing: border-box; + will-change: border-color; + } + // The inner circle for the radio, shown when checked. + &__inner-circle { + position: absolute; + top: 0; + left: 0; + width: $mdl-radio-size; + height: $mdl-radio-size; + transform: scale(0); + transition: transform $mdl-radio-timing-fn, background-color $mdl-radio-timing-fn; + border-radius: 50%; + background-color: $mdl-radio-accent-color; + box-sizing: border-box; + will-change: transform; + } + // Underlying native input element. + // Visually hidden but still able to respond to focus. + &__input { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + border: 0; + text-transform: none; + overflow: hidden; + clip: rect(0 0 0 0); + } +} + +.mdl-radio__input:checked { + ~ .mdl-radio__container { + .mdl-radio__outer-circle { + border-color: $mdl-radio-accent-color; + } + + .mdl-radio__inner-circle { + transform: scale(.5); + } + } +} + +// Basic disabled state. +.mdl-radio__input:disabled { + ~ .mdl-radio__container { + cursor: default; + + .mdl-radio__outer-circle { + border-color: $mdl-radio-disabled-color; + } + + .mdl-radio__inner-circle { + background-color: $mdl-radio-disabled-color; + } + } +} + +.mdl-radio__input:focus { + ~ .mdl-radio__container { + .mdl-ink-ripple { + background-color: rgba(255, 82, 82, .26); + // Fade in when radio focused. + opacity: 1; + } + } +} + +// TODO(mtlin): This is temporary and will be removed once the ripple is integrated. +// postcss-bem-linter: ignore +.mdl-ink-ripple { + position: absolute; + top: 50%; + left: 50%; + width: 48px; + height: 48px; + transform: translate(-50%, -50%); + transition: opacity $mdl-radio-timing-fn, background-color $mdl-radio-timing-fn; + border-radius: 50%; + opacity: 0; + overflow: hidden; + pointer-events: none; +} +// postcss-bem-linter: end diff --git a/packages/mdl-radio/mixin.js b/packages/mdl-radio/mixin.js new file mode 100644 index 000000000..d06600a29 --- /dev/null +++ b/packages/mdl-radio/mixin.js @@ -0,0 +1,60 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const Identifier = { + ROOT: 'mdl-radio', + NATIVE_INPUT: 'mdl-radio__input' +}; + +export default function MDLRadioMixin(renderer) { + Object.assign(this, { + initMdlRadio_() { + this.renderer_ = bindAll(renderer, this); + } + }); + + Object.defineProperty(this, 'checked', { + get: function() { + return Boolean(this.renderer_.getProperty(Identifier.NATIVE_INPUT, 'checked')); + }, + + set: function(value) { + this.renderer_.setProperty(Identifier.NATIVE_INPUT, 'checked', value); + } + }); + + Object.defineProperty(this, 'disabled', { + get: function() { + return Boolean(this.renderer_.getProperty(Identifier.NATIVE_INPUT, 'disabled')); + }, + + set: function(value) { + this.renderer_.setProperty(Identifier.NATIVE_INPUT, 'disabled', value); + } + }); +} + +/** + * Create a cloned object with functions bound to the given this parameter. + */ +// TODO(mtlin): Make a shared mixin package or utils equivalent. +function bindAll(obj, self) { + const boundObj = {}; + Object.keys(obj).forEach(key => { + boundObj[key] = obj[key].bind(self); + }); + return boundObj; +} diff --git a/packages/mdl-radio/package.json b/packages/mdl-radio/package.json new file mode 100644 index 000000000..ae92bd74d --- /dev/null +++ b/packages/mdl-radio/package.json @@ -0,0 +1,8 @@ +{ + "name": "mdl-radio", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "mdl-base": "^1.0.0" + } +} diff --git a/packages/mdl-ripple/animation.js b/packages/mdl-ripple/animation.js new file mode 100644 index 000000000..3550ff68d --- /dev/null +++ b/packages/mdl-ripple/animation.js @@ -0,0 +1,88 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Create a sequential animation/transition from a list of class names. + */ +export default class SequentialAnimation { + constructor(ref, renderer, isAnimation = false) { + this.elementRef_ = ref; + + this.renderer_ = renderer; + + this.eventName_ = isAnimation ? 'animationend' : 'transitionend'; + + this.isAnimation_ = isAnimation; + + this.onFinish = null; + + /** + * Store the promise rejection function for use later. + */ + this.reject_ = null; + } + + start(...sequence) { + const promise = sequence.reduce((acc, cur) => { + let clsName; + const useNamedFinish = Array.isArray(cur); + if (useNamedFinish) { + clsName = cur[0]; + } else { + clsName = cur; + } + + let listener; + let rejecter; + const promise = new Promise((resolve, reject) => { + rejecter = reject; + listener = ev => { + if (!this.isAnimation_ && (!useNamedFinish || useNamedFinish && ev.propertyName === cur[1]) || + this.isAnimation_ && ev.animationName === cur[1]) { + // Cleanup current animation and trigger next. + this.renderer_.removeEventListener(this.elementRef_, this.eventName_, listener); + this.renderer_.removeClass(this.elementRef_, clsName); + resolve(); + } + }; + }).catch(() => { + // Animation chain was canceled - remove current class. + this.renderer_.removeEventListener(this.elementRef_, this.eventName_, listener); + this.renderer_.removeClass(this.elementRef_, clsName); + }); + return acc.then(() => { + this.reject_ = rejecter; + this.renderer_.addEventListener(this.elementRef_, this.eventName_, listener); + // Begin the next animation. + this.renderer_.addClass(this.elementRef_, clsName); + return promise; + }); + }, Promise.resolve()); + + promise.then(() => { + if (this.onFinish) { + this.onFinish(); + } + }); + } + + stop() { + if (this.reject_) { + this.reject_(); + this.reject_ = null; + } + } +} diff --git a/packages/mdl-ripple/index.js b/packages/mdl-ripple/index.js new file mode 100644 index 000000000..ff7b174a2 --- /dev/null +++ b/packages/mdl-ripple/index.js @@ -0,0 +1,119 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import MDLComponent, { + MDLBaseAdapterLegacy as MDLBaseAdapter, + refLegacy as ref +} from 'mdl-base'; +import MDLRippleMixin, { + Class, + Identifier, + MAX_RIPPLES, + getNormalizedEventCoords +} from './mixin'; + +export default class MDLRipple extends MDLComponent { + /** + * Convenience helper to build required DOM. + */ + static buildDom() { + // Create the DOM. + const root = document.createElement('div'); + root.classList.add(Class.ROOT); + + const background = document.createElement('div'); + background.classList.add(Class.BACKGROUND); + root.appendChild(background); + + for (let i = 0; i < MAX_RIPPLES; i++) { + const foreground = document.createElement('div'); + foreground.classList.add(Class.FOREGROUND); + const foregroundCircle = document.createElement('div'); + foregroundCircle.classList.add(Class.FOREGROUND_CIRCLE); + foreground.appendChild(foregroundCircle); + root.appendChild(foreground); + } + return root; + } + + /** + * Bind to a root element and parent surface. + */ + static attachTo(surface, root) { + const elements = { + [Identifier.SURFACE]: surface, + [Identifier.ROOT]: root, + [Identifier.BACKGROUND]: root.getElementsByClassName(Class.BACKGROUND)[0] + }; + + const foregrounds = root.getElementsByClassName(Class.FOREGROUND); + const foregroundCircles = root.getElementsByClassName(Class.FOREGROUND_CIRCLE); + for (let i = 0; i < foregrounds.length; i++) { + elements[ref(Identifier.FOREGROUND, i)] = foregrounds[i]; + elements[ref(Identifier.FOREGROUND_CIRCLE, i)] = foregroundCircles[i]; + } + + const options = { + bounded: surface.getAttribute('bounded') !== 'false' + }; + + if (surface.hasAttribute('max-radius')) { + options.maxRadius = parseFloat(surface.getAttribute('max-radius'), 10); + } + + return new MDLRipple(elements, options); + } + + constructor(elements, options = {}) { + super(elements[Identifier.ROOT]); + + this.elements_ = elements; + + this.initMdlRipple_(); + + this.isBounded = options.bounded !== false; + + this.maxRadius = typeof options.maxRadius === 'number' ? options.maxRadius : 0; + + // TODO(mtlin): Might not be the best place for this.. + this.addEventListeners(); + } + + getDefaultFoundation() { + // TODO(traviskaufman): Implement once ripple is ported over from mixin pattern. + return {init: () => {}}; + } + + addEventListeners() { + const surface = this.elements_[Identifier.SURFACE]; + + surface.addEventListener('mousedown', ev => { + const {top, left} = getNormalizedEventCoords(ev, surface); + + this.startTouchBeganAnimationAtPoint(top, left); + }); + surface.addEventListener('mouseup', ev => { + const {top, left} = getNormalizedEventCoords(ev, surface); + + this.startTouchEndedAnimationAtPoint(top, left); + }); + surface.addEventListener('mouseout', () => { + this.cancelAnimations(); + }); + } +} + +MDLRippleMixin.call(MDLRipple.prototype, MDLBaseAdapter); diff --git a/packages/mdl-ripple/mdl-ripple.scss b/packages/mdl-ripple/mdl-ripple.scss new file mode 100644 index 000000000..1a8270f0b --- /dev/null +++ b/packages/mdl-ripple/mdl-ripple.scss @@ -0,0 +1,92 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@keyframes radius-in { + from { + transform: scale(0); + animation-timing-function: cubic-bezier(.157, .72, .386, .987); + } + + to { + // This differs slightly from spec. + transform: scale(1.5); + } +} + +@keyframes opacity-out { + from { + opacity: 1; + animation-timing-function: linear; + } + + to { + opacity: 0; + } +} + +// postcss-bem-linter: define ripple +.mdl-ripple { + visibility: hidden; + pointer-events: none; + + &, + &__foreground, + &__foreground-circle, + &__background { + position: absolute; + width: 100%; + height: 100%; + } +} + +.mdl-ripple__foreground { + &-circle { + transform: scale(0); + border-radius: 50%; + background-color: rgba(0, 0, 0, .06); + opacity: 0; + } + + &--bounded-active { + transition: transform 300ms cubic-bezier(.157, .72, .386, .987); + } + + &--bounded-circle-active { + animation-fill-mode: forwards; + animation: 800ms radius-in, 400ms opacity-out; + } +} + +.mdl-ripple__background { + transform: scale(1); + transition: opacity 480ms linear; + border-radius: 50%; + background-color: rgba(0, 0, 0, .06); + opacity: 0; + + &--active { + transition: opacity 600ms linear; + // In order for the fill class's duration to be taken into account, the target + // opacity value must be different between the two classes. + opacity: .99999; + } + + &--bounded-active-fill { + transition-duration: 120ms; + opacity: 1; + } +} +// postcss-bem-linter: end diff --git a/packages/mdl-ripple/mixin.js b/packages/mdl-ripple/mixin.js new file mode 100644 index 000000000..13119f0f7 --- /dev/null +++ b/packages/mdl-ripple/mixin.js @@ -0,0 +1,274 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import SequentialAnimation from './animation'; + +export const Class = { + ROOT: 'mdl-ripple', + BACKGROUND: 'mdl-ripple__background', + BACKGROUND_ACTIVE: 'mdl-ripple__background--active', + BACKGROUND_BOUNDED_ACTIVE_FILL: 'mdl-ripple__background--bounded-active-fill', + FOREGROUND: 'mdl-ripple__foreground', + FOREGROUND_CIRCLE: 'mdl-ripple__foreground-circle', + FOREGROUND_BOUNDED_ACTIVE: 'mdl-ripple__foreground--bounded-active', + FOREGROUND_BOUNDED_CIRCLE_ACTIVE: 'mdl-ripple__foreground--bounded-circle-active' +}; + +export const Identifier = { + ROOT: Class.ROOT, + SURFACE: 'mdl-ripple__surface', + FOREGROUND: Class.FOREGROUND, + FOREGROUND_CIRCLE: Class.FOREGROUND_CIRCLE, + BACKGROUND: Class.BACKGROUND +}; + +const LOG_DECELERATE = 'cubic-bezier(0.157, 0.72, 0.386, 0.987)'; + +const TRANSITION_DELTA = 1e-8; + +const UNBOUNDED_EXPAND_DELAY_MS = 80; + +export const MAX_RIPPLES = 4; + +export default function MDLRippleMixin(renderer) { + Object.assign(this, { + initMdlRipple_() { + this.renderer_ = bindAll(renderer, this); + + this.isBounded = true; + + this.boundingRect_ = null; + + this.fgIndex_ = 0; + + this.maxRadius_ = 0; + + this.needsLayout_ = true; + }, + + layout(force = false) { + if (!this.needsLayout_ && !force) { + return; + } + + const surface = this.renderer_.get(Identifier.SURFACE); + const root = this.renderer_.get(Identifier.ROOT); + + this.boundingRect_ = this.renderer_.getBoundingClientRect(surface); + + // Ensure that the ripple container is a square and is visible. + const maxDim = this.maxRadius * 2; + this.renderer_.setStyles(root, { + height: maxDim + 'px', + width: maxDim + 'px', + top: -((maxDim - this.boundingRect_.height) / 2.0) + 'px', + left: -((maxDim - this.boundingRect_.width) / 2.0) + 'px', + visibility: 'visible' + }); + + this.needsLayout_ = false; + }, + + startTouchBeganAnimationAtPoint(top, left) { + this.layout(); + + const background = this.renderer_.get(Identifier.BACKGROUND); + + this.renderer_.addClass(background, Class.BACKGROUND_ACTIVE); + + if (!this.isBounded) { + const foreground = this.renderer_.get(Identifier.FOREGROUND, this.fgIndex_); + const fgCircle = this.renderer_.get(Identifier.FOREGROUND_CIRCLE, this.fgIndex_); + + // Center the ripple at the touch point. + const origin = this.computeOriginTranslate_(top, left); + this.renderer_.setStyles(foreground, { + transform: `translate3d(${origin.left}px, ${origin.top}px, 0)` + }); + + // Force apply transform immediately. + this.renderer_.forceLayout(foreground); + + const duration = 1000 * Math.sqrt(this.maxRadius / 1024); + + // Expand and fade in the circle. + this.renderer_.setStyles(fgCircle, { + transition: `opacity 110ms linear, transform ${duration}ms linear ${UNBOUNDED_EXPAND_DELAY_MS}ms`, + opacity: 1, + transform: 'scale(1)' + }); + + // Gravitate towards the center. + this.renderer_.setStyles(foreground, { + transition: `transform ${duration}ms linear ${UNBOUNDED_EXPAND_DELAY_MS}ms`, + transform: 'translate3d(0.01px,0,0)' + }); + } + }, + + computeOriginTranslate_(top, left) { + return { + top: (top - this.boundingRect_.height / 2), + left: (left - this.boundingRect_.width / 2) + }; + }, + + startTouchEndedAnimationAtPoint(top, left) { + this.layout(); + + const background = this.renderer_.get(Identifier.BACKGROUND); + const foreground = this.renderer_.get(Identifier.FOREGROUND, this.fgIndex_); + const fgCircle = this.renderer_.get(Identifier.FOREGROUND_CIRCLE, this.fgIndex_); + + this.renderer_.removeClass(background, Class.BACKGROUND_ACTIVE); + + if (this.isBounded) { + const bgAnim = new SequentialAnimation(background, this.renderer_); + + bgAnim.start(Class.BACKGROUND_BOUNDED_ACTIVE_FILL); + // Center the ripple at the touch point. + const origin = this.computeOriginTranslate_(top, left); + this.renderer_.setStyles(foreground, { + transform: `translate3d(${origin.left}px, ${origin.top}px, 0)` + }); + + // Force apply transform immediately. + this.renderer_.forceLayout(foreground); + + this.renderer_.addClass(foreground, Class.FOREGROUND_BOUNDED_ACTIVE); + + // Translate 1/3 of the way to the origin. + const finalTop = origin.top * 2 / 3; + const finalLeft = origin.left * 2 / 3; + this.renderer_.setStyles(foreground, { + transform: `translate3d(${finalLeft}px, ${finalTop}px, 0)` + }); + + const anim = new SequentialAnimation(fgCircle, this.renderer_, true); + anim.start([Class.FOREGROUND_BOUNDED_CIRCLE_ACTIVE, 'radius-in']); + anim.onFinish = () => { + this.renderer_.removeClass(foreground, Class.FOREGROUND_BOUNDED_ACTIVE); + }; + } else { + // 'opacity' lookup only forces style recalc, not layout. + // https://gist.github.com/paulirish/5d52fb081b3570c81e3a + let circleOpacity = parseFloat(this.renderer_.getComputedValue(fgCircle, 'opacity'), 10); + + // Special case: when touch end is called programmatically (without touch + // start) for unbounded, we set an initial starting point for the ripple. + if (circleOpacity === 0) { + circleOpacity = 1.0; + this.renderer_.setStyles(fgCircle, { + opacity: circleOpacity, + transform: 'scale(.5)' + }); + } + + // Hack to get the current transform value for the radius, without parsing the complicated + // computed style. + const currentRadius = this.renderer_.getBoundingClientRect(fgCircle).height / 2; + + const remainingRadius = this.maxRadius - currentRadius; + const radiusDuration = 1000 * Math.sqrt(remainingRadius / 4424); + const originDuration = radiusDuration; + + const opacityDuration = 1000 * circleOpacity / 3; + this.renderer_.setStyles(fgCircle, { + transition: `opacity ${opacityDuration}ms linear, transform ${radiusDuration}ms ${LOG_DECELERATE}`, + transform: `scale(${1 + TRANSITION_DELTA})`, + opacity: '0' + }); + + this.renderer_.setStyles(foreground, { + transition: `transform ${originDuration}ms ${LOG_DECELERATE}`, + transform: 'translate3d(0,0,0)' + }); + + // Since we know the duration already, no need to listen for transition end. + setTimeout(() => { + this.resetStyles_(foreground, fgCircle); + }, opacityDuration); + } + + this.fgIndex_ = (this.fgIndex_ + 1) % MAX_RIPPLES; + }, + + resetStyles_(...eles) { + eles.forEach(each => { + this.renderer_.setStyles(each, { + transition: '', + transform: '', + opacity: '' + }); + }); + }, + + cancelAnimations() { + const background = this.renderer_.get(Identifier.BACKGROUND); + this.renderer_.removeClass(background, Class.BACKGROUND_ACTIVE); + + const foreground = this.renderer_.get(Identifier.FOREGROUND, this.fgIndex_); + const fgCircle = this.renderer_.get(Identifier.FOREGROUND_CIRCLE, this.fgIndex_); + this.resetStyles_(foreground, fgCircle); + } + }); + + Object.defineProperty(this, 'maxRadius', { + get: function() { + if (this.maxRadius_ || !this.boundingRect_) { + return this.maxRadius_; + } + + const maxDim = Math.max(this.boundingRect_.height, this.boundingRect_.width); + // Sqrt(2) * square length == diameter + return Math.sqrt(2) * maxDim / 2; + }, + + set: function(value) { + this.maxRadius_ = value; + } + }); +} + +export function getNormalizedEventCoords(ev, container) { + const rect = container.getBoundingClientRect(); + const documentLeft = window.pageXOffset + rect.left; + const documentTop = window.pageYOffset + rect.top; + + let normalizedLeft; + let normalizedTop; + // Determine touch point relative to the ripple container. + if (ev.type === 'touchstart') { + normalizedLeft = ev.touches[0].pageX - documentLeft; + normalizedTop = ev.touches[0].pageY - documentTop; + } else { + normalizedLeft = ev.pageX - documentLeft; + normalizedTop = ev.pageY - documentTop; + } + + return {left: normalizedLeft, top: normalizedTop}; +} + +/** + * Create a cloned object with functions bound to the given this parameter. + */ +function bindAll(obj, self) { + const boundObj = {}; + Object.keys(obj).forEach(key => { + boundObj[key] = obj[key].bind(self); + }); + return boundObj; +} diff --git a/packages/mdl-ripple/package.json b/packages/mdl-ripple/package.json new file mode 100644 index 000000000..0c8b7c080 --- /dev/null +++ b/packages/mdl-ripple/package.json @@ -0,0 +1,8 @@ +{ + "name": "mdl-ripple", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "mdl-base": "^1.0.0" + } +} diff --git a/packages/mdl-toolbar/_variables.scss b/packages/mdl-toolbar/_variables.scss new file mode 100644 index 000000000..e69de29bb diff --git a/packages/mdl-toolbar/mdl-toolbar.scss b/packages/mdl-toolbar/mdl-toolbar.scss new file mode 100644 index 000000000..7f57dcd67 --- /dev/null +++ b/packages/mdl-toolbar/mdl-toolbar.scss @@ -0,0 +1,119 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* postcss-bem-linter: define toolbar */ +.mdl-toolbar { + + &__row { + display: flex; + position: static; + position: sticky; + top: 0; /* stylelint-disable-line declaration-block-no-ignored-properties */ + width: 100%; + height: 54px; + background: transparent; + color: white; + + @media (min-width: 1024px) { + height: 64px; + } + } + + &__action { + display: inline-flex; + position: relative; + flex-basis: auto; + width: auto; + height: 100%; + padding: 0 16px; + border: none; + background: transparent; + -webkit-appearance: none; + color: white; + fill: currentColor; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + + @media (min-width: 1024px) { + padding: 0 24px; + } + + &::before { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + transition: opacity 120ms cubic-bezier(0, 0, .2, 1); + border-radius: inherit; + background: black; + content: ""; + opacity: 0; + } + + &:focus::before { + opacity: .12; + } + + &:active::before { + opacity: .18; + } + + &:focus, + &:active { + outline: none; + } + } + + &__title { + display: flex; + flex-direction: column; + justify-content: center; + padding-left: 16px; + color: currentColor; + font-family: Roboto, sans-serif; + fill: currentColor; + font-size: 1.25rem; /* 20sp */ + + @media (min-width: 1024px) { + padding-left: 24px; + } + } + + &__actions { + display: flex; + justify-content: flex-end; + height: 100%; + margin-left: auto; + } + + &--primary { + background: indigo; + } + + &--dark { + background: black; + } + + /* + Appbar modifier so it sits on top of the + content area so no other toolbars overlap. + */ + &--appbar { + z-index: 2; + } +} + +/* postcss-bem-linter: end */ diff --git a/packages/mdl-toolbar/package.json b/packages/mdl-toolbar/package.json new file mode 100644 index 000000000..88d8a2fc3 --- /dev/null +++ b/packages/mdl-toolbar/package.json @@ -0,0 +1,7 @@ +{ + "name": "mdl-toolbar", + "description": "Simple Material Design toolbar component.", + "version": "1.0.0", + "license": "Apache-2.0" +} + diff --git a/packages/mdl-typography/README.md b/packages/mdl-typography/README.md new file mode 100644 index 000000000..e626abfc2 --- /dev/null +++ b/packages/mdl-typography/README.md @@ -0,0 +1,120 @@ +# mdl-typography + +MDL typography is a CSS-only component that implements the +[Material Design typography guidelines](https://material.google.com/style/typography.html), and makes them available to +developers as CSS classes. + +## Installation + +> Note: Installation via the npm registry will be available after alpha. + + +## Usage + +```html + + + + +

Big header

+ +``` + +Material Design typography uses the Roboto font, which we're loading from Google Fonts in the example above. + +> Note: You can load more font weights and styles if you wish, but `mdl-typography` only uses 300, 400 and 500. + +The `mdl-typography` class defines basic properties for text, such as the typeface and antialiasing settings. + +### Formatting your text + +#### Style + +Simply add the corresponding style class to format your text: + +```html + +

Big header

+ +

+ A paragraph with emphasis. +

+ +``` + +The full list of styles: + +- `mdl-typography--display4` +- `mdl-typography--display3` +- `mdl-typography--display2` +- `mdl-typography--display1` +- `mdl-typography--headline` +- `mdl-typography--title` +- `mdl-typography--subheading` +- `mdl-typography--body2` +- `mdl-typography--body1` +- `mdl-typography--caption` + +#### Margins and positioning + +In order to minimize unexpected behavior, the style classes only specify font properties, such as size, weight and line +height. + +This means that while text will be correctly styled, it may not be correctly positioned. If you include the +`mdl-typography--adjust-margin` class, though, positioning will be adjusted according to the style: + +```html + +

+ Big header +

+ +

+ A paragraph with + + emphasis + . +

+ +``` + +> Note: as the name implies, `mdl-typography--adjust-margin` will change the margin properties of the element it's +applied to, in order to align text correctly. Because of this, it should only be used in a text context; using this +property on UI elements such as buttons may cause them to be positioned incorrectly. + +#### Color + +Most Material Design text is either black or white, but can have different opacity values depending on usage. The color +classes help you apply the right color depending on context: + +```html + +

+ + Some dark primary text. + + + Followed by some dark secondary text. + +

+ +
+ This div has a dark background, so we use a light color for text. +
+ +``` + +The full list of color classes: + +| Class | Description | +| --------------------------------- | ---------------------------------------------- | +| `mdl-typography--primary-dark` | Primary text, in a dark color. | +| `mdl-typography--secondary-dark` | Secondary text, in a dark color. | +| `mdl-typography--hint-dark` | Hint text, in a dark color. | +| `mdl-typography--disabled-dark` | Disabled text, in a dark color. | +| `mdl-typography--icon-dark` | Icon, in a dark color (used with icon fonts). | +| `mdl-typography--primary-light` | Primary text, in a light color. | +| `mdl-typography--secondary-light` | Secondary text, in a light color. | +| `mdl-typography--hint-light` | Hint text, in a light color. | +| `mdl-typography--disabled-light` | Disabled text, in a light color. | +| `mdl-typography--icon-light` | Icon, in a light color (used with icon fonts). | diff --git a/packages/mdl-typography/_mixins.scss b/packages/mdl-typography/_mixins.scss new file mode 100644 index 000000000..902af6886 --- /dev/null +++ b/packages/mdl-typography/_mixins.scss @@ -0,0 +1,55 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// All variables are local, so disable pattern checking. +// stylelint-disable scss/dollar-variable-pattern + +@import "./variables"; + +@mixin mdl-typography-base { + font-family: $mdl-typography-font-family; + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; +} + +@mixin mdl-typography($style) { + $style-props: map-get($mdl-typography-styles, $style); + + @if not map-has-key($mdl-typography-styles, $style) { + @error "Invalid style specified! Choose one of #{map-keys($mdl-typography-styles)}"; + } + + @include mdl-typography-base; + + font-size: map-get($style-props, font-size); + font-weight: #{map-get($style-props, font-weight)}; + letter-spacing: map-get($style-props, letter-spacing); + line-height: map-get($style-props, line-height); +} + +@mixin mdl-typography-adjust-margin($style) { + margin: map-get(map-get($mdl-typography-styles, $style), margin); +} + +@mixin mdl-typography-color($color-style, $dark: false) { + $color-map: if($dark, $mdl-typography-colors-dark, $mdl-typography-colors-light); + + color: map-get($color-map, $color-style); + + @if not map-has-key($color-map, $color-style) { + @error "Invalid typography style. Specify one of #{map-keys($color-map)}"; + } +} diff --git a/packages/mdl-typography/_variables.scss b/packages/mdl-typography/_variables.scss new file mode 100644 index 000000000..e2ce36be0 --- /dev/null +++ b/packages/mdl-typography/_variables.scss @@ -0,0 +1,125 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +$mdl-typography-font-family: Roboto, sans-serif; + +$mdl-typography-font-weight-values: ( + thin: 100, + light: 300, + regular: 400, + medium: 500, + bold: 700, + black: 900 +); + +/* TODO(sgomes): Figure out what to do about desktop font sizes. */ + +/* TODO(sgomes): Figure out what to do about i18n and i18n font sizes. */ + +$mdl-typography-styles: ( + display4: ( + font-size: 7rem, /* 112sp */ + line-height: 7rem, /* 112sp */ + font-weight: map-get($mdl-typography-font-weight-values, light), + letter-spacing: -.04em, + margin: -1rem 0 3.5rem -.085em /* -16sp 0 56sp -.085em */ + ), + display3: ( + font-size: 3.5rem, /* 56px */ + line-height: 3.5rem, /* 56px */ + font-weight: map-get($mdl-typography-font-weight-values, regular), + letter-spacing: -.02em, + margin: -8px 0 64px -.07em + ), + display2: ( + font-size: 2.813rem, /* 45px */ + line-height: 3rem, /* 48px */ + font-weight: map-get($mdl-typography-font-weight-values, regular), + letter-spacing: normal, + margin: -.5rem 0 4rem -.07em /* -8sp 0 64sp -.07em */ + ), + display1: ( + font-size: 2.125rem, /* 34sp */ + line-height: 2.5rem, /* 40sp */ + font-weight: map-get($mdl-typography-font-weight-values, regular), + letter-spacing: normal, + margin: -.5rem 0 4rem -.07em /* -8sp 0 64sp -.07em */ + ), + headline: ( + font-size: 1.5rem, /* 24sp */ + line-height: 2rem, /* 32sp */ + font-weight: map-get($mdl-typography-font-weight-values, regular), + letter-spacing: normal, + margin: -.5rem 0 1rem -.06em /* -8sp 0 16sp -.06em */ + ), + title: ( + font-size: 1.25rem, /* 20sp */ + line-height: 2rem, /* 32sp */ + font-weight: map-get($mdl-typography-font-weight-values, medium), + letter-spacing: .02em, + margin: -.5rem 0 1rem -.05em /* -8sp 0 16sp -.05em */ + ), + subheading2: ( + font-size: 1rem, /* 16sp */ + line-height: 1.75rem, /* 28sp */ + font-weight: map-get($mdl-typography-font-weight-values, regular), + letter-spacing: .04em, + margin: -.5rem 0 1rem -.06em /* -8sp 0 16sp -.06em */ + ), + subheading1: ( + font-size: .938rem, /* 15sp */ + line-height: 1.5rem, /* 24sp */ + font-weight: map-get($mdl-typography-font-weight-values, regular), + letter-spacing: .04em, + margin: -.313rem 0 .813rem -.06em /* -5sp 0 13sp -.06em */ + ), + body2: ( + font-size: .875rem, /* 14sp */ + line-height: 1.5rem, /* 24sp */ + font-weight: map-get($mdl-typography-font-weight-values, medium), + letter-spacing: .04em, + margin: -.25rem 0 .75rem 0 /* -4sp 0 12sp 0 */ + ), + body1: ( + font-size: .875rem, /* 14sp */ + line-height: 1.25rem, /* 20sp */ + font-weight: map-get($mdl-typography-font-weight-values, regular), + letter-spacing: .04em, + margin: -.25rem 0 .75rem 0 /* -4sp 0 12sp 0 */ + ), + caption: ( + font-size: .75rem, /* 12sp */ + line-height: 1.25rem, /* 20sp */ + font-weight: map-get($mdl-typography-font-weight-values, regular), + letter-spacing: .08em, + margin: -.5rem 0 1rem -.04em /* -8sp 0 16sp -.04em */ + ) +); + +$mdl-typography-colors-dark: ( + primary: rgba(black, .87), + secondary: rgba(black, .54), + hint: rgba(black, .38), + disabled: rgba(black, .38), + icon: rgba(black, .38) +); + +$mdl-typography-colors-light: ( + primary: white, + secondary: rgba(white, .7), + hint: rgba(white, .5), + disabled: rgba(white, .5), + icon: rgba(white, .5) +); diff --git a/packages/mdl-typography/mdl-typography.scss b/packages/mdl-typography/mdl-typography.scss new file mode 100644 index 000000000..cc5a05475 --- /dev/null +++ b/packages/mdl-typography/mdl-typography.scss @@ -0,0 +1,46 @@ +/** + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "./variables"; +@import "./mixins"; + +.mdl-typography { + @include mdl-typography-base; +} + +@each $style in map-keys($mdl-typography-styles) { + .mdl-typography--#{$style} { + @include mdl-typography($style); + } + + .mdl-typography--adjust-margin.mdl-typography--#{$style} { + @include mdl-typography-adjust-margin($style); + } +} + +// TODO(sgomes): Reconsider the below approach when we decide how to do dark theming. + +@each $color-style in map-keys($mdl-typography-colors-light) { + .mdl-typography--color-#{$color-style}-light { + @include mdl-typography-color($color-style); + } +} + +@each $color-style in map-keys($mdl-typography-colors-dark) { + .mdl-typography--color-#{$color-style}-dark { + @include mdl-typography-color($color-style, true); + } +} diff --git a/packages/mdl-typography/package.json b/packages/mdl-typography/package.json new file mode 100644 index 000000000..120171b42 --- /dev/null +++ b/packages/mdl-typography/package.json @@ -0,0 +1,4 @@ +{ + "name": "mdl-typography", + "version": "1.0.0" +} diff --git a/src/INTRODUCTION.md b/src/INTRODUCTION.md deleted file mode 100755 index e27dfb2f7..000000000 --- a/src/INTRODUCTION.md +++ /dev/null @@ -1,44 +0,0 @@ -# Material Design Lite - -## Introduction -**Material Design Light (MDL)** is a library of components for web developers based on Google's **Material Design** philosophy: "A visual language for our users that synthesizes the classic principles of good design with the innovation and possibility of technology and science." Understanding the goals and principles of Material Design is critical to the proper use of the MDL components. If you have not yet read the [Material Design Introduction](http://www.google.com/design/spec/material-design/introduction.html), you should do so before attempting to use the components. - -The MDL components are created with CSS, JavaScript, and HTML. You can use the components to construct web pages and web apps that are attractive, consistent, and functional. Pages developed with MDL will adhere to modern web design principles like browser portability, device independence, and graceful degradation. - -The MDL component library includes new versions of common user interface controls such as buttons, check boxes, and text fields, adapted to follow Material Design concepts. The library also includes enhanced and specialized features like cards, column layouts, sliders, spinners, tabs, typography, and more. - -MDL is free to download and use, and may be used with or without any build library or development environment (such as [Material Design Lite](http://www.getmdl.io/)). It is a cross-browser, cross-OS web developer's toolkit that can be used by anyone who wants to write more productive, portable, and — most importantly — usable web pages. - -## Getting started - -### Get the components -To obtain the components, clone or download the [GitHub MDL repository](https://github.com/google/material-design-lite). Copy the entire package (the top-level folder and everything below it) to the project folder where you will write your HTML pages. This ensures that your project can access all of MDL's components and assets, and that you always have the original files for reference in case you break something. :-) - -### Include the master CSS and JavaScript -In each HTML page in your project, include the minified (compressed) CSS and JavaScript files using standard relative-path references and the Material Icon font. This example assumes that a copy of the MDL package folders resides in your project folder. - - -```html - - - -``` - -That's it! You are now ready to use the MDL components. - -### Use the components -In general, follow these basic steps to use an MDL component in your HTML page. - -1. Start with a standard HTML element, such as ` -``` - 2. Add one or more MDL classes, separated by spaces, to the button using the `class` attribute. -```html - -``` - -The button component is ready for use. - -#### Examples - -A button with the "raised" effect. -```html - -``` - -A button with the "fab" effect. -```html - -``` - -A button with the "icon" and "colored" effects. -```html - -``` - - -## Configuration options - -The MDL CSS classes apply various predefined visual and behavioral enhancements to the button. The table below lists the available classes and their effects. - -| MDL class | Effect | Remarks | -|-----------|--------|---------| -| `mdl-button` | Defines button as an MDL component | Required | -| `mdl-js-button` | Assigns basic MDL behavior to button | Required | -| (none) | Applies *flat* display effect to button (default) | | -| `mdl-button--raised` | Applies *raised* display effect | Mutually exclusive with *fab*, *mini-fab*, and *icon* | -| `mdl-button--fab` | Applies *fab* (circular) display effect | Mutually exclusive with *raised*, *mini-fab*, and *icon* | -| `mdl-button--mini-fab` | Applies *mini-fab* (small fab circular) display effect | Mutually exclusive with *raised*, *fab*, and *icon* | -| `mdl-button--icon` | Applies *icon* (small plain circular) display effect | Mutually exclusive with *raised*, *fab*, and *mini-fab* | -| `mdl-button--colored` | Applies *colored* display effect (primary or accent color, depending on the type of button) | Colors are defined in `material.min.css` | -| `mdl-button--primary` | Applies *primary* color display effect | Colors are defined in `material.min.css` | -| `mdl-button--accent` | Applies *accent* color display effect | Colors are defined in `material.min.css` | -| `mdl-js-ripple-effect` | Applies *ripple* click effect | May be used in combination with any other classes | - ->**Note:** Disabled versions of all the available button types are provided, and are invoked with the standard HTML boolean attribute `disabled`. ``. Alternatively, the `mdl-button--disabled` class can be used to achieve the same style but it does not disable the functionality of the element. ->This attribute may be added or removed programmatically via scripting. diff --git a/src/button/_button.scss b/src/button/_button.scss deleted file mode 100644 index 25bb3b364..000000000 --- a/src/button/_button.scss +++ /dev/null @@ -1,305 +0,0 @@ -/** - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@import "../variables"; -@import "../mixins"; - -// The button component. Defaults to a flat button. -.mdl-button { - background: transparent; - border: none; - border-radius: $button-border-radius; - color: $button-secondary-color; - position: relative; - height: $button-height; - margin: 0; - min-width: $button-min-width; - padding: 0 $button-padding; - display: inline-block; - @include typo-button(); - overflow: hidden; - will-change: box-shadow; - transition: box-shadow 0.2s $animation-curve-fast-out-linear-in, - background-color 0.2s $animation-curve-default, - color 0.2s $animation-curve-default; - outline: none; - cursor: pointer; - text-decoration: none; - text-align: center; - line-height: $button-height; - vertical-align: middle; - - &::-moz-focus-inner { - border: 0; - } - - &:hover { - background-color: $button-hover-color; - } - - &:focus:not(:active) { - background-color: $button-focus-color; - } - - &:active { - background-color: $button-active-color; - } - - &.mdl-button--colored { - color: $button-primary-color-alt; - - &:focus:not(:active) { - background-color: $button-focus-color-alt; - } - } -} - -input.mdl-button[type="submit"] { - -webkit-appearance:none; -} - - // Raised buttons - .mdl-button--raised { - background: $button-primary-color; - @include shadow-2dp(); - - &:active { - @include shadow-4dp(); - background-color: $button-active-color; - } - - &:focus:not(:active) { - @include focus-shadow(); - background-color: $button-active-color; - } - - &.mdl-button--colored { - background: $button-primary-color-alt; - color: $button-secondary-color-alt; - - &:hover { - background-color: $button-hover-color-alt; - } - - &:active { - background-color: $button-active-color-alt; - } - - &:focus:not(:active) { - background-color: $button-active-color-alt; - } - - & .mdl-ripple { - background: $button-ripple-color-alt; - } - } - } - - - // FABs - .mdl-button--fab { - border-radius: 50%; - font-size: $button-fab-font-size; - height: $button-fab-size; - margin: auto; - min-width: $button-fab-size; - width: $button-fab-size; - padding: 0; - overflow: hidden; - background: $button-primary-color; - box-shadow: 0 1px 1.5px 0 rgba(0,0,0,0.12), 0 1px 1px 0 rgba(0,0,0,0.24); - position: relative; - line-height: normal; - - & .material-icons { - position: absolute; - top: 50%; - left: 50%; - transform: translate(- $button-fab-font-size / 2, - $button-fab-font-size / 2); - line-height: $button-fab-font-size; - width: $button-fab-font-size; - } - - &.mdl-button--mini-fab { - height: $button-fab-size-mini; - min-width: $button-fab-size-mini; - width: $button-fab-size-mini; - } - - & .mdl-button__ripple-container { - border-radius: 50%; - // Fixes clipping bug in Safari. - -webkit-mask-image: -webkit-radial-gradient(circle, white, black); - } - - &:active { - @include shadow-4dp(); - background-color: $button-active-color; - } - - &:focus:not(:active) { - @include focus-shadow(); - background-color: $button-active-color; - } - - &.mdl-button--colored { - background: $button-fab-color-alt; - color: $button-fab-text-color-alt; - - &:hover { - background-color: $button-fab-hover-color-alt; - } - - &:focus:not(:active) { - background-color: $button-fab-active-color-alt; - } - - &:active { - background-color: $button-fab-active-color-alt; - } - - & .mdl-ripple { - background: $button-fab-ripple-color-alt; - } - } - } - - - // Icon buttons - .mdl-button--icon { - border-radius: 50%; - font-size: $button-fab-font-size; - height: $button-icon-size; - margin-left: 0; - margin-right: 0; - min-width: $button-icon-size; - width: $button-icon-size; - padding: 0; - overflow: hidden; - color: inherit; - line-height: normal; - - & .material-icons { - position: absolute; - top: 50%; - left: 50%; - transform: translate(- $button-fab-font-size / 2, - $button-fab-font-size / 2); - line-height: $button-fab-font-size; - width: $button-fab-font-size; - } - - &.mdl-button--mini-icon { - height: $button-icon-size-mini; - min-width: $button-icon-size-mini; - width: $button-icon-size-mini; - - & .material-icons { - top: ($button-icon-size-mini - $button-fab-font-size) / 2; - left: ($button-icon-size-mini - $button-fab-font-size) / 2; - } - } - - & .mdl-button__ripple-container { - border-radius: 50%; - // Fixes clipping bug in Safari. - -webkit-mask-image: -webkit-radial-gradient(circle, white, black); - } - } - - - // Ripples - .mdl-button__ripple-container { - display: block; - height: 100%; - left: 0px; - position: absolute; - top: 0px; - width: 100%; - z-index: 0; - overflow: hidden; - - .mdl-button[disabled] & .mdl-ripple, - .mdl-button.mdl-button--disabled & .mdl-ripple { - background-color: transparent; - } - } - -// Colorized buttons - -.mdl-button--primary.mdl-button--primary { - color: $button-primary-color-alt; - & .mdl-ripple { - background: $button-secondary-color-alt; - } - &.mdl-button--raised, &.mdl-button--fab { - color: $button-secondary-color-alt; - background-color: $button-primary-color-alt; - } -} - -.mdl-button--accent.mdl-button--accent { - color: $button-fab-color-alt; - & .mdl-ripple { - background: $button-fab-text-color-alt; - } - &.mdl-button--raised, &.mdl-button--fab { - color: $button-fab-text-color-alt; - background-color: $button-fab-color-alt; - } -} - -// Disabled buttons - -.mdl-button { - // Bump up specificity by using [disabled] twice. - &[disabled][disabled], - &.mdl-button--disabled.mdl-button--disabled { - color: $button-secondary-color-disabled; - cursor: default; - background-color: transparent; - } - - &--fab { - // Bump up specificity by using [disabled] twice. - &[disabled][disabled], - &.mdl-button--disabled.mdl-button--disabled { - background-color: $button-primary-color-disabled; - color: $button-secondary-color-disabled; - } - } - - &--raised { - // Bump up specificity by using [disabled] twice. - &[disabled][disabled], - &.mdl-button--disabled.mdl-button--disabled { - background-color: $button-primary-color-disabled; - color: $button-secondary-color-disabled; - box-shadow: none; - } - } - &--colored { - // Bump up specificity by using [disabled] twice. - &[disabled][disabled], - &.mdl-button--disabled.mdl-button--disabled { - color: $button-secondary-color-disabled; - } - } -} - -// Align icons inside buttons with text -.mdl-button .material-icons { - vertical-align: middle; -} diff --git a/src/button/button.js b/src/button/button.js deleted file mode 100644 index cc9ba8d09..000000000 --- a/src/button/button.js +++ /dev/null @@ -1,123 +0,0 @@ -/** - * @license - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -(function() { - 'use strict'; - - /** - * Class constructor for Button MDL component. - * Implements MDL component design pattern defined at: - * https://github.com/jasonmayes/mdl-component-design-pattern - * - * @param {HTMLElement} element The element that will be upgraded. - */ - var MaterialButton = function MaterialButton(element) { - this.element_ = element; - - // Initialize instance. - this.init(); - }; - window['MaterialButton'] = MaterialButton; - - /** - * Store constants in one place so they can be updated easily. - * - * @enum {string | number} - * @private - */ - MaterialButton.prototype.Constant_ = { - // None for now. - }; - - /** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * - * @enum {string} - * @private - */ - MaterialButton.prototype.CssClasses_ = { - RIPPLE_EFFECT: 'mdl-js-ripple-effect', - RIPPLE_CONTAINER: 'mdl-button__ripple-container', - RIPPLE: 'mdl-ripple' - }; - - /** - * Handle blur of element. - * - * @param {Event} event The event that fired. - * @private - */ - MaterialButton.prototype.blurHandler_ = function(event) { - if (event) { - this.element_.blur(); - } - }; - - // Public methods. - - /** - * Disable button. - * - * @public - */ - MaterialButton.prototype.disable = function() { - this.element_.disabled = true; - }; - MaterialButton.prototype['disable'] = MaterialButton.prototype.disable; - - /** - * Enable button. - * - * @public - */ - MaterialButton.prototype.enable = function() { - this.element_.disabled = false; - }; - MaterialButton.prototype['enable'] = MaterialButton.prototype.enable; - - /** - * Initialize element. - */ - MaterialButton.prototype.init = function() { - if (this.element_) { - if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) { - var rippleContainer = document.createElement('span'); - rippleContainer.classList.add(this.CssClasses_.RIPPLE_CONTAINER); - this.rippleElement_ = document.createElement('span'); - this.rippleElement_.classList.add(this.CssClasses_.RIPPLE); - rippleContainer.appendChild(this.rippleElement_); - this.boundRippleBlurHandler = this.blurHandler_.bind(this); - this.rippleElement_.addEventListener('mouseup', this.boundRippleBlurHandler); - this.element_.appendChild(rippleContainer); - } - this.boundButtonBlurHandler = this.blurHandler_.bind(this); - this.element_.addEventListener('mouseup', this.boundButtonBlurHandler); - this.element_.addEventListener('mouseleave', this.boundButtonBlurHandler); - } - }; - - // The component registers itself. It can assume componentHandler is available - // in the global scope. - componentHandler.register({ - constructor: MaterialButton, - classAsString: 'MaterialButton', - cssClass: 'mdl-js-button', - widget: true - }); -})(); diff --git a/src/button/snippets/fab-colored-ripple.html b/src/button/snippets/fab-colored-ripple.html deleted file mode 100644 index df2d39a41..000000000 --- a/src/button/snippets/fab-colored-ripple.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/fab-colored.html b/src/button/snippets/fab-colored.html deleted file mode 100644 index b25e8da0a..000000000 --- a/src/button/snippets/fab-colored.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/fab-disabled.html b/src/button/snippets/fab-disabled.html deleted file mode 100644 index 3dc9cb46b..000000000 --- a/src/button/snippets/fab-disabled.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/fab-mini-colored.html b/src/button/snippets/fab-mini-colored.html deleted file mode 100644 index 3e35a1599..000000000 --- a/src/button/snippets/fab-mini-colored.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/fab-mini.html b/src/button/snippets/fab-mini.html deleted file mode 100644 index 8b5c5ca30..000000000 --- a/src/button/snippets/fab-mini.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/fab-ripple.html b/src/button/snippets/fab-ripple.html deleted file mode 100644 index 02c42f9ec..000000000 --- a/src/button/snippets/fab-ripple.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/fab.html b/src/button/snippets/fab.html deleted file mode 100644 index 0874925bd..000000000 --- a/src/button/snippets/fab.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/flat-accent.html b/src/button/snippets/flat-accent.html deleted file mode 100644 index b650bc2f4..000000000 --- a/src/button/snippets/flat-accent.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/flat-disabled.html b/src/button/snippets/flat-disabled.html deleted file mode 100644 index 9139038d3..000000000 --- a/src/button/snippets/flat-disabled.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/flat-primary.html b/src/button/snippets/flat-primary.html deleted file mode 100644 index 780ce4893..000000000 --- a/src/button/snippets/flat-primary.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/flat-ripple.html b/src/button/snippets/flat-ripple.html deleted file mode 100644 index c8c37a8a4..000000000 --- a/src/button/snippets/flat-ripple.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/flat.html b/src/button/snippets/flat.html deleted file mode 100644 index 19da6130f..000000000 --- a/src/button/snippets/flat.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/icon-colored.html b/src/button/snippets/icon-colored.html deleted file mode 100644 index cabcb5af6..000000000 --- a/src/button/snippets/icon-colored.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/icon.html b/src/button/snippets/icon.html deleted file mode 100644 index 122023a52..000000000 --- a/src/button/snippets/icon.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/raised-accent.html b/src/button/snippets/raised-accent.html deleted file mode 100644 index cb547f194..000000000 --- a/src/button/snippets/raised-accent.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/raised-colored.html b/src/button/snippets/raised-colored.html deleted file mode 100644 index 713c2f582..000000000 --- a/src/button/snippets/raised-colored.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/raised-disabled.html b/src/button/snippets/raised-disabled.html deleted file mode 100644 index 02f747428..000000000 --- a/src/button/snippets/raised-disabled.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/raised-ripple-accent.html b/src/button/snippets/raised-ripple-accent.html deleted file mode 100644 index 9d33d8be0..000000000 --- a/src/button/snippets/raised-ripple-accent.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/raised-ripple.html b/src/button/snippets/raised-ripple.html deleted file mode 100644 index 6b38c0bf2..000000000 --- a/src/button/snippets/raised-ripple.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/button/snippets/raised.html b/src/button/snippets/raised.html deleted file mode 100644 index a9397331c..000000000 --- a/src/button/snippets/raised.html +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/src/card/README.md b/src/card/README.md deleted file mode 100755 index 567c5b37e..000000000 --- a/src/card/README.md +++ /dev/null @@ -1,127 +0,0 @@ -## Introduction - -The Material Design Lite (MDL) **card** component is a user interface element representing a virtual piece of paper that contains related data — such as a photo, some text, and a link — that are all about a single subject. - -Cards are a convenient means of coherently displaying related content that is composed of different types of objects. They are also well-suited for presenting similar objects whose size or supported actions can vary considerably, like photos with captions of variable length. Cards have a constant width and a variable height, depending on their content. - -Cards are a fairly new feature in user interfaces, and allow users an access point to more complex and detailed information. Their design and use is an important factor in the overall user experience. See the card component's [Material Design specifications page](http://www.google.com/design/spec/components/cards.html) for details. - -### To include an MDL **card** component: - - 1. Code a `
` element; this is the "outer" container, intended to hold all of the card's content. -```html -
-
-``` - 2. Inside the div, code one or more "inner" divs, one for each desired content block. A card containing a title, an image, some text, and an action bar would contain four "inner" divs, all siblings. -```html -
-
- ... -
-
- ... -
-
- ... -
-
- ... -
-
-``` - 3. Add one or more MDL classes, separated by spaces, to the "outer" div and the "inner" divs (depending on their intended use) using the `class` attribute. -```html -
-
- ... -
-
- ... -
-
- ... -
-
- ... -
-
-``` - 4. Add content to each "inner" div, again depending on its intended use, using standard HTML elements and, optionally, additional MDL classes. -```html -
-
-

title Text Goes Here

-
-
- -
-
- This text might describe the photo and provide further information, such as where and - when it was taken. -
- -
-``` - -The card component is ready for use. - -#### Examples - -A card (no shadow) with a title, image, text, and action. - -```html -
-
-

Auckland Sky Tower
Auckland, New Zealand

-
-
- -
-
- The Sky Tower is an observation and telecommunications tower located in Auckland, - New Zealand. It is 328 metres (1,076 ft) tall, making it the tallest man-made structure - in the Southern Hemisphere. -
- -
-``` - -Card (level-3 shadow) with an image, caption, and text: - -```html -
-
-
-
- Auckland Sky Tower, taken March 24th, 2014 -
-
- The Sky Tower is an observation and telecommunications tower located in Auckland, - New Zealand. It is 328 metres (1,076 ft) tall, making it the tallest man-made structure - in the Southern Hemisphere. -
-
-``` - -## Configuration options - -The MDL CSS classes apply various predefined visual and behavioral enhancements to the card. The table below lists the available classes and their effects. - -| MDL class | Effect | Remarks | -|-----------|--------|---------| -| `mdl-card` | Defines div element as an MDL card container | Required on "outer" div | -| `mdl-card--border` | Adds a border to the card section that it's applied to | Used on the "inner" divs | -| `mdl-shadow--2dp through mdl-shadow--16dp` | Assigns variable shadow depths (2, 3, 4, 6, 8, or 16) to card | Optional, goes on "outer" div; if omitted, no shadow is present | -| `mdl-card__title` | Defines div as a card title container | Required on "inner" title div | -| `mdl-card__title-text` | Assigns appropriate text characteristics to card title | Required on head tag (H1 - H6) inside title div | -| `mdl-card__subtitle-text` | Assigns text characteristics to a card subtitle | Optional. Should be a child of the title element. | -| `mdl-card__media` | Defines div as a card media container | Required on "inner" media div | -| `mdl-card__supporting-text` | Defines div as a card body text container and assigns appropriate text characteristics to body text | Required on "inner" body text div; text goes directly inside the div with no intervening containers | -| `mdl-card__actions` | Defines div as a card actions container and assigns appropriate text characteristics to actions text | Required on "inner" actions div; content goes directly inside the div with no intervening containers | diff --git a/src/card/_card.scss b/src/card/_card.scss deleted file mode 100644 index 8bd7cbd43..000000000 --- a/src/card/_card.scss +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@import "../variables"; - -.mdl-card { - display: flex; - flex-direction: column; - font-size: $card-font-size; - font-weight: 400; - min-height: $card-height; - overflow: hidden; - width: $card-width; - z-index: $card-z-index; - position: relative; - background: $card-background-color; - border-radius: 2px; - box-sizing: border-box; -} - -.mdl-card__media { - background-color: $card-image-placeholder-color; - background-repeat: repeat; - background-position: 50% 50%; - background-size: cover; - background-origin: padding-box; - background-attachment: scroll; - box-sizing: border-box; -} - -.mdl-card__title { - align-items: center; - color: $card-text-color; - display: block; - display: flex; - justify-content: stretch; - line-height: normal; - padding: $card-vertical-padding $card-horizontal-padding; - perspective-origin: $card-title-perspective-origin-x $card-title-perspective-origin-y; - transform-origin: $card-title-transform-origin-x $card-title-transform-origin-y; - box-sizing: border-box; - - &.mdl-card--border { - border-bottom: 1px solid $card-border-color; - } -} - -.mdl-card__title-text { - align-self: flex-end; - color: inherit; - display: block; - display: flex; - font-size: $card-title-font-size; - font-weight: $card-title-text-font-weight; - line-height: normal; - overflow: hidden; - transform-origin: $card-title-text-transform-origin-x $card-title-text-transform-origin-y; - margin: 0; -} - -.mdl-card__subtitle-text { - font-size: $card-subtitle-font-size; - color: $card-subtitle-color; - margin: 0; -} - -.mdl-card__supporting-text { - color: $card-supporting-text-text-color; - font-size: $card-supporting-text-font-size; - line-height: $card-supporting-text-line-height; - overflow: hidden; - padding: $card-vertical-padding $card-horizontal-padding; - width: 90%; -} - -.mdl-card__actions { - font-size: $card-actions-font-size; - line-height: normal; - width: 100%; - background-color: rgba(0,0,0,0); - padding: 8px; - box-sizing: border-box; - - &.mdl-card--border { - border-top: 1px solid $card-border-color; - } -} - -.mdl-card--expand { - flex-grow: 1; -} - - -.mdl-card__menu { - position: absolute; - right: 16px; - top: 16px; -} diff --git a/src/card/snippets/event.html b/src/card/snippets/event.html deleted file mode 100644 index b5407c319..000000000 --- a/src/card/snippets/event.html +++ /dev/null @@ -1,47 +0,0 @@ - - - -
-
-

- Featured event:
- May 24, 2016
- 7-11pm -

-
-
- - Add to Calendar - -
- event -
-
diff --git a/src/card/snippets/image.html b/src/card/snippets/image.html deleted file mode 100644 index f9cb6454b..000000000 --- a/src/card/snippets/image.html +++ /dev/null @@ -1,25 +0,0 @@ - - - -
-
-
- Image.jpg -
-
diff --git a/src/card/snippets/square.html b/src/card/snippets/square.html deleted file mode 100644 index 93d13f503..000000000 --- a/src/card/snippets/square.html +++ /dev/null @@ -1,27 +0,0 @@ - - - -
-
-

Update

-
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. - Aenan convallis. -
- -
diff --git a/src/card/snippets/wide.html b/src/card/snippets/wide.html deleted file mode 100644 index 0ee92408a..000000000 --- a/src/card/snippets/wide.html +++ /dev/null @@ -1,34 +0,0 @@ - - - -
-
-

Welcome

-
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. - Mauris sagittis pellentesque lacus eleifend lacinia... -
- -
- -
-
diff --git a/src/checkbox/README.md b/src/checkbox/README.md deleted file mode 100755 index 2a000e756..000000000 --- a/src/checkbox/README.md +++ /dev/null @@ -1,64 +0,0 @@ -## Introduction - -The Material Design Lite (MDL) **checkbox** component is an enhanced version of the standard HTML `` element. A checkbox consists of a small square and, typically, text that clearly communicates a binary condition that will be set or unset when the user clicks or touches it. Checkboxes typically, but not necessarily, appear in groups, and can be selected and deselected individually. The MDL checkbox component allows you to add display and click effects. - -Checkboxes are a common feature of most user interfaces, regardless of a site's content or function. Their design and use is therefore an important factor in the overall user experience. See the checkbox component's [Material Design specifications page](https://www.google.com/design/spec/components/selection-controls.html#selection-controls-checkbox) for details. - -The enhanced checkbox component has a more vivid visual look than a standard checkbox, and may be initially or programmatically *disabled*. - -### To include an MDL **checkbox** component: - - 1. Code a `