├── .gitignore ├── .travis.yml ├── .zuul.yml ├── LICENSE ├── README.md ├── bower.json ├── demo ├── index-source.html └── index-source.js ├── index.js ├── input.js ├── package.json └── test ├── build.js ├── source.html ├── test.js └── transform-build.js /.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | demo/index.html 3 | demo/index-browserify.js 4 | test/build.html 5 | 6 | # Logs 7 | logs 8 | *.log 9 | 10 | # Runtime data 11 | pids 12 | *.pid 13 | *.seed 14 | 15 | # Directory for instrumented libs generated by jscoverage/JSCover 16 | lib-cov 17 | 18 | # Coverage directory used by tools like istanbul 19 | coverage 20 | 21 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 22 | .grunt 23 | 24 | # Compiled binary addons (http://nodejs.org/api/addons.html) 25 | build/Release 26 | 27 | # Dependency directory 28 | # Commenting this out is preferred by some people, see 29 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 30 | node_modules 31 | bower_components 32 | 33 | # Users Environment Variables 34 | .lock-wscript 35 | 36 | # ========================= 37 | # Operating System Files 38 | # ========================= 39 | 40 | # OSX 41 | # ========================= 42 | 43 | .DS_Store 44 | .AppleDouble 45 | .LSOverride 46 | 47 | # Thumbnails 48 | ._* 49 | 50 | # Files that might appear on external disk 51 | .Spotlight-V100 52 | .Trashes 53 | 54 | # Directories potentially created on remote AFP share 55 | .AppleDB 56 | .AppleDesktop 57 | Network Trash Folder 58 | Temporary Items 59 | .apdisk 60 | 61 | # Windows 62 | # ========================= 63 | 64 | # Windows image file caches 65 | Thumbs.db 66 | ehthumbs.db 67 | 68 | # Folder config file 69 | Desktop.ini 70 | 71 | # Recycle Bin used on file shares 72 | $RECYCLE.BIN/ 73 | 74 | # Windows Installer files 75 | *.cab 76 | *.msi 77 | *.msm 78 | *.msp 79 | 80 | # Windows shortcuts 81 | *.lnk 82 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - node 4 | before_script: 5 | - npm install -g bower 6 | - bower install 7 | env: 8 | global: 9 | - secure: BF+PWkYE4iUPjC5T/mRaGWZC35s9euU+GGBPq9dUFmsBRFCdHcPNn4huvOZgEO2vAzzTIgP5bnU/29hlQcp30Np40O38eBf3anikH9dYPemYiiZ/Ud+mDQKFp14hv287kt0FPlRq59Ev/XfRPzCJPaq1RfNmbyb+KuU0VdSXluRNnGBdyJWJ51Zjqg1te6fgznjBMBsQ5CSfxBJ4D0wDr3fxxnIogeRVdsfNlh9LUwH/dx9uDSh1vjjJ7g742lEotpYPCNGbAPofrzw8qCXX6oEUbEbxPE8FKFvAnf/vmZveR65+tCE2Kcgmfsk4M3bIm5XIjMXRKeV15v2TBHRSQeWjPI/6XRUFwuNXEFtiW7YXo1VdqixHE+LT91T5MdNakQ6exqL6W6yg1CqXDBHdxQHoIPgu0pkKEcaNQuDXKrArUSnXhQIdiKjLdbYbT0bvmXQguYWzWh7kXyL0fjaOZBD47EZ1sBJxdIekvYszEDj4xuypyCH7yAYhD83wD8ztIevT4gMEaUBI6tefSD6q9z9E1h4tHMQ0aDyCrXvtheFlw9SzWuldX4CN5uX1UF6A9gQc4/HP3Q81NyswkXBaOgcnIHdA4vM620vHpvjuCX8H3Uphj/B1E0PR7YH8KkxYh42vYrclvuqvyipjgS3ELMQjfAmEn/Cg0XDWblvZ87c= 10 | - secure: mDd4uwODnHgXc+rV8A4eJ4kSv+K4cgVXPMZ0HEBk08LYEjTwLPH+iAsGDktK1PMdHo+sT7Pv2VGsBe/JoIEZcSy4VRB4ZmqStokV3R9QzNF+vIvIAhZUay2c4YfEikoVPFOBgrR6We8YdIBF14NhoIzg4AI5VdvlcZzYxz2h0ixFBIu5Lowq5UFSStxPiJI3SGd9shsW3FWi9Me0SXtOtUpFp6Cj0CCJ0AX2u7pt1J9AW49n/GsIJlf6d7lDedb67lW6h9Tk7qSdHRuLNnScXiYKp5jAMbE/zZ9rmZWitR0SFu+/zoJ3jEj8alCwYZfEaq5lGawyBI8VlXuAxpA3xdNgoJYFtU0Y24lUFRiGoTeitX6FVcSnLBHdD6BJeVFOd4XrJnRuCKjHc1bZvTjkjL2U5omst/+NsBq6bqtlPL9XK1iogE5M9ukY/6hJXhs+tyhsR+mEEjV+3IwOR51tGrBJrT+rEbP9+iAdU9Mv2DQSkKzUt9Ut6JlcAyAhNOnDbOanawRE0wNux+dbJBh57/77BGUlNDyd+gZ7szitr3pSuWEsFbtKQQOmNvn9VsobMd7EZtfS8KDd0vRXkZY6m3vqRp2DtDtyy+vUJ66ZbHtlBN2pcNba/r7G9k4GXPkpbiVjXSwLKa9VUp+xMjVzrX+m2W2X1+OwzJf1vlM6Zyk= 11 | script: | 12 | if [ "$TRAVIS_PULL_REQUEST" == "false" ] 13 | then 14 | npm test 15 | else 16 | npm run pretest 17 | fi 18 | branches: 19 | only: 20 | - master 21 | -------------------------------------------------------------------------------- /.zuul.yml: -------------------------------------------------------------------------------- 1 | ui: tape 2 | browserify: 3 | - transform: 4 | name: babelify 5 | presets: 6 | - es2015 7 | - react 8 | html: test/build.html 9 | browsers: 10 | - name: chrome 11 | version: [latest, beta] 12 | - name: firefox 13 | version: latest 14 | - name: safari 15 | version: latest 16 | - name: ie 17 | version: latest 18 | - name: microsoftedge 19 | version: latest 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Jan Schär 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-polymer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][npm-url] 2 | 3 | [travis-image]: https://img.shields.io/travis/jscissr/react-polymer/master.svg 4 | [travis-url]: https://travis-ci.org/jscissr/react-polymer 5 | [npm-image]: https://img.shields.io/npm/v/react-polymer.svg 6 | [npm-url]: https://npmjs.org/package/react-polymer 7 | [downloads-image]: https://img.shields.io/npm/dm/react-polymer.svg 8 | 9 | *Use Polymer elements in React* 10 | 11 | react-polymer now supports Polymer 2.0! If you need to use Polymer 1.0 please use v3 12 | 13 | Since [this change](https://github.com/facebook/react/pull/1551) you can put 14 | Polymer elements into React components and at first glance it just works: 15 | 16 | ```js 17 | click me 18 | ``` 19 | 20 | However, when you then start using custom attributes and events, it doesn't work 21 | anymore. 22 | 23 | Now you need react-polymer: 24 | 25 | ```js 26 | import reactPolymer from 'react-polymer' // Must be imported before React 27 | import React from 'react' 28 | 29 | reactPolymer.registerAttribute('drawer') // Note: this is only needed for custom attributes on standard elements like div 30 | reactPolymer.registerAttribute('main') 31 | reactPolymer.registerEvent('color-picker-selected', 'onColorPickerSelected') 32 | 33 | 34 | 35 |
Drawer panel...
36 |
Main panel...
37 |
38 | 39 | ``` 40 | 41 | Also, all the form elements don't work like the native ones. 42 | That's because React internally has wrappers to make controlled components. 43 | We have our own wrapper for the Polymer form elements: 44 | 45 | ```js 46 | import reactPolymer from 'react-polymer' 47 | import React from 'react' 48 | import { 49 | PaperCheckbox, 50 | PaperToggleButton, 51 | PaperInput, 52 | PaperTextarea, 53 | IronAutogrowTextarea, 54 | PaperSlider, 55 | PaperMenu, 56 | PaperListbox, 57 | PaperRadioGroup, 58 | PaperTabs, 59 | IronSelector 60 | } from 'react-polymer/input' 61 | 62 | 63 | 64 | 65 | ``` 66 | 67 | Another problem that is solved automatically by react-polymer is that 68 | `className` doesn't work on Polymer elements. 69 | 70 | See [more examples](https://github.com/jscissr/react-polymer/blob/master/demo/index-source.js). 71 | 72 | ## ES6 73 | 74 | This module uses some ES6 features, so you should run it through a transpiler like [babel](https://babeljs.io/). If you use [browserify](http://browserify.org/), you don't need to do anything. If you use [webpack](https://webpack.github.io/), you have to [enable transpiling](https://webpack.js.org/loaders/#transpiling), but replace the default `exclude` config with `exclude: s => /node_modules/.test(s) && !/react-polymer/.test(s)`. (If you know how to make webpack do this automatically like it works with browserify, please tell me!) 75 | 76 | ## Testing 77 | 78 | ```shell 79 | npm install 80 | bower install 81 | npm run test-local 82 | ``` 83 | 84 | ## Caveats 85 | 86 | `gold-*` elements are not yet supported. 87 | 88 | Polymer elements can have properties with `notify` attribute, which trigger 89 | `{property}-changed` events. However these events don't bubble, so you have to 90 | manually call `addEventListener` yourself. 91 | 92 | This module does a lot of monkey patching on internal APIs of react-dom, so it only works with React 15. It is recommended to pin React to a fixed version, and always test new versions before updating. There is no guarantee that it will still work, even after patch-level updates of React. 93 | 94 | ## Notes 95 | 96 | A React issue that might simplify this once solved: 97 | 98 | - https://github.com/facebook/react/issues/4751 99 | 100 | ## Similar Libraries 101 | 102 | For mixing Polymer and React, there is [Maple](https://github.com/Wildhoney/Maple.js), which doesn't seem to be maintained anymore. However, if all you are looking for is a way to incorporate pre-built Material Design components into React, there are also [Material-UI](https://github.com/callemall/material-ui) and [React-Materialize](https://github.com/react-materialize/react-materialize). 103 | 104 | ## License 105 | 106 | MIT. 107 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-polymer", 3 | "devDependencies": { 4 | "paper-slider": "PolymerElements/paper-slider#^2.0.0", 5 | "paper-input": "PolymerElements/paper-input#^2.0.0", 6 | "paper-checkbox": "PolymerElements/paper-checkbox#^2.0.0", 7 | "paper-toggle-button": "PolymerElements/paper-toggle-button#^2.0.0", 8 | "paper-radio-button": "PolymerElements/paper-radio-button#^2.0.0", 9 | "paper-radio-group": "PolymerElements/paper-radio-group#^2.0.0", 10 | "paper-progress": "PolymerElements/paper-progress#^2.0.0", 11 | "paper-dropdown-menu": "PolymerElements/paper-dropdown-menu#^2.0.0", 12 | "paper-item": "PolymerElements/paper-item#^2.0.0", 13 | "paper-tabs": "PolymerElements/paper-tabs#^2.0.0", 14 | "paper-listbox": "PolymerElements/paper-listbox#^2.0.0", 15 | "iron-selector": "PolymerElements/iron-selector#^2.0.0", 16 | "paper-swatch-picker": "PolymerElements/paper-swatch-picker#^2.0.0", 17 | "web-animations-js": "web-animations/web-animations-js#^2.2.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /demo/index-source.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | react-polymer demo 4 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 48 | 49 | 50 |
51 | 52 | -------------------------------------------------------------------------------- /demo/index-source.js: -------------------------------------------------------------------------------- 1 | import reactPolymer from '../' 2 | 3 | import React from 'react' 4 | import {render} from 'react-dom' 5 | 6 | import { 7 | IronAutogrowTextarea, 8 | PaperToggleButton, 9 | PaperCheckbox, 10 | PaperInput, 11 | PaperTextarea, 12 | PaperSlider, 13 | PaperListbox, 14 | PaperRadioGroup, 15 | PaperTabs, 16 | IronSelector 17 | } from '../input' 18 | 19 | reactPolymer.registerEvent('color-picker-selected', 'onColorPickerSelected') 20 | 21 | function App () { 22 | const c = new React.Component() 23 | c.state = { 24 | text: 'Hello world', 25 | textarea: 'Hello world\nin 2 lines', 26 | value: 30, 27 | checked: false, 28 | editable: true, 29 | selected: 'small', 30 | color: '' 31 | } 32 | 33 | function textChange (event) { 34 | console.log('textChange, new value: %s', event.target.value) 35 | if (c.state.editable) { 36 | c.setState({text: event.target.value}) 37 | } 38 | } 39 | function textareaChange (event) { 40 | console.log('textareaChange, new value: %s', event.target.value) 41 | if (c.state.editable) { 42 | c.setState({textarea: event.target.value}) 43 | } 44 | } 45 | function valueChange (event) { 46 | console.log('valueChange, new value: %s', event.target.value) 47 | if (c.state.editable) { 48 | c.setState({value: +event.target.value}) 49 | } 50 | } 51 | function checkedChange (event) { 52 | console.log('checkedChange, new value: %s', event.target.checked) 53 | if (c.state.editable) { 54 | c.setState({checked: event.target.checked}) 55 | } 56 | } 57 | function selectedChange (event) { 58 | var selected = event.target.selected || event.target.value 59 | console.log('selectedChange, new value: %s', selected) 60 | if (c.state.editable) { 61 | c.setState({selected: selected}) 62 | } 63 | } 64 | 65 | function editableChange (event) { 66 | c.setState({editable: event.target.checked}) 67 | } 68 | 69 | function colorChange (event) { 70 | c.setState({color: event.target.color}) 71 | } 72 | 73 | c.render = () => ( 74 |
75 |

react-polymer demo

76 | 77 | 78 | 79 | 80 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 94 | 95 | 96 | 97 |
81 | NativePaperIron
Text 90 | 91 | 92 | 93 |
Textarea