├── polymer3 ├── .gitignore ├── src │ ├── index.js │ ├── my-todo-styles.js │ ├── todo-input-styles.js │ ├── todo-item.js │ ├── todo-input.js │ └── my-todo.js ├── polymer.json ├── rollup.config.js ├── README.md ├── index.html └── package.json ├── atomico ├── .gitignore ├── public │ ├── logo.png │ ├── preview.png │ └── index.html ├── README.md ├── src │ ├── style.css │ ├── todo-input │ │ ├── style.css │ │ └── index.js │ └── todo-item │ │ ├── index.js │ │ └── style.css ├── package.json └── rollup.config.js ├── dist └── .gitignore ├── stencil-0.16 ├── src │ ├── global │ │ ├── app.ts │ │ └── app.css │ ├── assets │ │ └── icon │ │ │ ├── icon.png │ │ │ └── favicon.ico │ ├── manifest.json │ ├── components │ │ ├── my-todo │ │ │ ├── my-todo.css │ │ │ └── my-todo.tsx │ │ ├── todo-input │ │ │ ├── todo-input.css │ │ │ └── todo-input.tsx │ │ └── todo-item │ │ │ ├── todo-item.tsx │ │ │ └── todo-item.css │ ├── index.html │ └── components.d.ts ├── .editorconfig ├── .gitignore ├── stencil.config.ts ├── tsconfig.json ├── package.json ├── LICENSE └── readme.md ├── slim-js ├── src │ ├── index.js │ ├── todo-app.css │ ├── directives │ │ └── bind-boolean.js │ ├── components │ │ ├── todo-input.css │ │ ├── todo-input.js │ │ ├── todo-item.js │ │ └── todo-item.css │ └── todo-app.js ├── jsconfig.json ├── .babelrc ├── webpack.config.js ├── index.html └── package.json ├── polymer2 ├── .gitignore ├── manifest.json ├── polymer.json ├── package.json ├── bower.json ├── README.md ├── index.html ├── test │ └── my-todo │ │ └── my-todo_test.html └── src │ └── todo-input │ └── todo-input.html ├── non-web-components-refs ├── angular │ ├── src │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── styles.css │ │ ├── favicon.ico │ │ ├── tsconfig.app.json │ │ ├── tsconfig.spec.json │ │ ├── tslint.json │ │ ├── main.ts │ │ ├── browserslist │ │ ├── app │ │ │ ├── app.module.ts │ │ │ ├── todo-input │ │ │ │ └── todo-input.component.ts │ │ │ └── app.component.ts │ │ ├── test.ts │ │ ├── karma.conf.js │ │ └── index.html │ ├── .editorconfig │ ├── tsconfig.json │ ├── .gitignore │ ├── README.md │ └── package.json ├── vue │ ├── vue.config.js │ ├── babel.config.js │ ├── public │ │ ├── favicon.ico │ │ └── index.html │ ├── src │ │ ├── assets │ │ │ └── logo.png │ │ ├── main.js │ │ ├── App.vue │ │ └── components │ │ │ ├── todo-input.vue │ │ │ └── my-todo.vue │ ├── .gitignore │ ├── README.md │ └── package.json └── react │ ├── public │ ├── favicon.ico │ ├── manifest.json │ └── index.html │ ├── src │ ├── index.js │ ├── index.css │ └── components │ │ ├── my-todo │ │ ├── my-todo.css │ │ └── my-todo.js │ │ ├── todo-input │ │ ├── todo-input.css │ │ └── todo-input.js │ │ └── todo-item │ │ ├── todo-item.js │ │ └── todo-item.css │ ├── .gitignore │ └── package.json ├── skatejs-lit-html ├── .gitignore ├── .babelrc ├── webpack.config.js ├── src │ ├── index.js │ ├── input.js │ ├── util.js │ └── app.js ├── package.json └── index.html ├── skatejs-preact ├── .gitignore ├── .babelrc ├── webpack.config.js ├── src │ ├── index.js │ ├── util.js │ ├── input.js │ └── app.js ├── package.json └── index.html ├── svelte ├── src │ ├── main.js │ └── components │ │ ├── TodoInput.html │ │ └── MyTodo.html ├── .gitignore ├── package.json ├── public │ └── index.html ├── rollup.config.js └── README.md ├── solid ├── .gitignore ├── src │ ├── MyTodo.css │ ├── TodoInput.css │ ├── TodoItem.jsx │ ├── TodoInput.jsx │ ├── MyTodo.jsx │ └── TodoItem.css ├── rollup.config.js ├── public │ └── index.html └── package.json ├── .firebaserc ├── vue ├── vue.config.js ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── assets │ │ └── logo.png │ ├── main.js │ └── components │ │ ├── todo-input.vue │ │ └── my-todo.vue ├── .gitignore ├── package.json └── index.html ├── stencil-0.11 ├── src │ ├── assets │ │ └── icon │ │ │ ├── icon.png │ │ │ └── favicon.ico │ ├── manifest.json │ ├── components │ │ ├── my-todo │ │ │ ├── my-todo.css │ │ │ └── my-todo.tsx │ │ ├── todo-input │ │ │ ├── todo-input.css │ │ │ └── todo-input.tsx │ │ └── todo-item │ │ │ ├── todo-item.tsx │ │ │ └── todo-item.css │ ├── global │ │ └── app.css │ └── index.html ├── stencil.config.ts ├── .editorconfig ├── .gitignore ├── tsconfig.json ├── LICENSE ├── .github │ └── ISSUE_TEMPLATE.md ├── package.json └── readme.md ├── native-shadow-dom ├── webpack.config.js ├── src │ ├── index.js │ └── todo-input.js ├── package.json └── index.html ├── functional-element ├── public │ ├── functional-element.d.ts │ └── index.html ├── tsconfig.json ├── rollup.config.js ├── package.json ├── src │ ├── todo-input.js │ └── my-todo.js └── index.html ├── lit-element-0.6 ├── src │ ├── index.js │ └── todo-input.js ├── package.json └── index.html ├── lit-element-2.1 ├── src │ ├── index.js │ ├── todo-input.js │ └── my-todo.js ├── package.json └── index.html ├── tests ├── commands │ ├── addItem.js │ ├── checkItem.js │ ├── uncheckItem.js │ └── removeItem.js └── suite │ └── wc.js ├── firebase.json ├── angular-elements ├── src │ ├── main.ts │ ├── todo.module.ts │ ├── index.html │ ├── todo-input.ts │ └── my-todo.ts ├── tsconfig.json ├── README.md ├── .gitignore ├── package.json ├── webpack.config.js └── LICENSE ├── benchmark ├── package.json └── filesize.js ├── templates ├── group.ejs └── row.ejs ├── generateIndex.js ├── LICENSE ├── .gitignore ├── native └── js │ ├── todo-input.js │ ├── my-todo.js │ └── todo-item.js ├── README.md └── nightwatch.json /polymer3/.gitignore: -------------------------------------------------------------------------------- 1 | build/ -------------------------------------------------------------------------------- /atomico/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /dist/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /stencil-0.16/src/global/app.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /slim-js/src/index.js: -------------------------------------------------------------------------------- 1 | import './todo-app'; -------------------------------------------------------------------------------- /polymer2/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | bower_components/ -------------------------------------------------------------------------------- /non-web-components-refs/angular/src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /skatejs-lit-html/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | -------------------------------------------------------------------------------- /skatejs-preact/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | -------------------------------------------------------------------------------- /svelte/src/main.js: -------------------------------------------------------------------------------- 1 | import './components/MyTodo.html'; 2 | -------------------------------------------------------------------------------- /solid/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | public/bundle.* -------------------------------------------------------------------------------- /skatejs-lit-html/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["stage-0"] 3 | } 4 | -------------------------------------------------------------------------------- /skatejs-preact/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react", "stage-0"] 3 | } 4 | -------------------------------------------------------------------------------- /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "wc-todo" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /vue/vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | lintOnSave: true, 3 | baseUrl: '/vue/' 4 | } -------------------------------------------------------------------------------- /slim-js/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "experimentalDecorators": true 4 | } 5 | } -------------------------------------------------------------------------------- /svelte/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | public/bundle.* 4 | package-lock.json 5 | yarn.lock -------------------------------------------------------------------------------- /polymer3/src/index.js: -------------------------------------------------------------------------------- 1 | import './todo-input.js'; 2 | import './todo-item.js'; 3 | import './my-todo.js'; 4 | -------------------------------------------------------------------------------- /vue/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shprink/web-components-todo/HEAD/vue/public/favicon.ico -------------------------------------------------------------------------------- /atomico/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shprink/web-components-todo/HEAD/atomico/public/logo.png -------------------------------------------------------------------------------- /non-web-components-refs/vue/vue.config.js: -------------------------------------------------------------------------------- 1 | // vue.config.js 2 | module.exports = { 3 | baseUrl: '/vue/', 4 | } -------------------------------------------------------------------------------- /polymer3/polymer.json: -------------------------------------------------------------------------------- 1 | { 2 | "builds": [ 3 | { 4 | "preset": "es6-bundled" 5 | } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /vue/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shprink/web-components-todo/HEAD/vue/src/assets/logo.png -------------------------------------------------------------------------------- /atomico/public/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shprink/web-components-todo/HEAD/atomico/public/preview.png -------------------------------------------------------------------------------- /non-web-components-refs/vue/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /non-web-components-refs/angular/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /non-web-components-refs/angular/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /polymer2/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "todo", 3 | "short_name": "todo", 4 | "start_url": "/", 5 | "display": "standalone" 6 | } 7 | -------------------------------------------------------------------------------- /stencil-0.11/src/assets/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shprink/web-components-todo/HEAD/stencil-0.11/src/assets/icon/icon.png -------------------------------------------------------------------------------- /stencil-0.16/src/assets/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shprink/web-components-todo/HEAD/stencil-0.16/src/assets/icon/icon.png -------------------------------------------------------------------------------- /stencil-0.11/src/assets/icon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shprink/web-components-todo/HEAD/stencil-0.11/src/assets/icon/favicon.ico -------------------------------------------------------------------------------- /stencil-0.16/src/assets/icon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shprink/web-components-todo/HEAD/stencil-0.16/src/assets/icon/favicon.ico -------------------------------------------------------------------------------- /non-web-components-refs/angular/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shprink/web-components-todo/HEAD/non-web-components-refs/angular/src/favicon.ico -------------------------------------------------------------------------------- /non-web-components-refs/vue/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shprink/web-components-todo/HEAD/non-web-components-refs/vue/public/favicon.ico -------------------------------------------------------------------------------- /non-web-components-refs/vue/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shprink/web-components-todo/HEAD/non-web-components-refs/vue/src/assets/logo.png -------------------------------------------------------------------------------- /non-web-components-refs/react/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shprink/web-components-todo/HEAD/non-web-components-refs/react/public/favicon.ico -------------------------------------------------------------------------------- /native-shadow-dom/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | module: { 3 | rules: [ 4 | { 5 | use: "babel-loader" 6 | } 7 | ] 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /skatejs-lit-html/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | module: { 3 | rules: [ 4 | { 5 | use: "babel-loader" 6 | } 7 | ] 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /skatejs-preact/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | module: { 3 | rules: [ 4 | { 5 | use: "babel-loader" 6 | } 7 | ] 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /polymer2/polymer.json: -------------------------------------------------------------------------------- 1 | { 2 | "lint": { 3 | "rules": [ 4 | "polymer-2" 5 | ] 6 | }, 7 | "builds": [ 8 | { 9 | "preset": "es6-bundled" 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /non-web-components-refs/vue/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './components/my-todo' 3 | 4 | Vue.config.productionTip = false 5 | 6 | new Vue({ 7 | render: h => h(App) 8 | }).$mount('#app') 9 | -------------------------------------------------------------------------------- /polymer3/rollup.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | input: 'src/index.js', 3 | output: { 4 | file: 'build/es6-bundled/src_tmp/index.js', 5 | format: 'es', 6 | sourcemap: false 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /functional-element/public/functional-element.d.ts: -------------------------------------------------------------------------------- 1 | import { UserFunction } from './index.d'; 2 | export { html } from 'lit-html'; 3 | export declare function customElement(tagName: string, userFunction: UserFunction): void; 4 | -------------------------------------------------------------------------------- /skatejs-preact/src/index.js: -------------------------------------------------------------------------------- 1 | import App from "./app"; 2 | import Input from "./input"; 3 | import Item from "./item"; 4 | 5 | customElements.define("todo-app", App); 6 | customElements.define("todo-input", Input); 7 | customElements.define("todo-item", Item); 8 | -------------------------------------------------------------------------------- /skatejs-lit-html/src/index.js: -------------------------------------------------------------------------------- 1 | import App from "./app"; 2 | import Input from "./input"; 3 | import Item from "./item"; 4 | 5 | customElements.define("todo-app", App); 6 | customElements.define("todo-input", Input); 7 | customElements.define("todo-item", Item); 8 | -------------------------------------------------------------------------------- /non-web-components-refs/angular/src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "types": [] 6 | }, 7 | "exclude": [ 8 | "test.ts", 9 | "**/*.spec.ts" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /slim-js/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [[ 3 | "@babel/preset-env", 4 | { 5 | "targets": { 6 | "esmodules": true 7 | }, 8 | "useBuiltIns": "usage" 9 | } 10 | ]], 11 | "plugins": [ 12 | ["@babel/plugin-proposal-decorators", { "legacy": true }] 13 | ] 14 | } -------------------------------------------------------------------------------- /polymer2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polymer", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "build": "polymer build" 11 | }, 12 | "author": "", 13 | "license": "MIT" 14 | } 15 | -------------------------------------------------------------------------------- /lit-element-0.6/src/index.js: -------------------------------------------------------------------------------- 1 | import MyTodo from "./my-todo"; 2 | import TodoInput from "./todo-input"; 3 | import TodoItem from "./todo-item"; 4 | 5 | window.customElements.define('my-todo', MyTodo); 6 | window.customElements.define('todo-input', TodoInput); 7 | window.customElements.define('todo-item', TodoItem); -------------------------------------------------------------------------------- /lit-element-2.1/src/index.js: -------------------------------------------------------------------------------- 1 | import MyTodo from "./my-todo"; 2 | import TodoInput from "./todo-input"; 3 | import TodoItem from "./todo-item"; 4 | 5 | window.customElements.define('my-todo', MyTodo); 6 | window.customElements.define('todo-input', TodoInput); 7 | window.customElements.define('todo-item', TodoItem); -------------------------------------------------------------------------------- /native-shadow-dom/src/index.js: -------------------------------------------------------------------------------- 1 | import MyTodo from "./my-todo"; 2 | import TodoInput from "./todo-input"; 3 | import TodoItem from "./todo-item"; 4 | 5 | window.customElements.define('my-todo', MyTodo); 6 | window.customElements.define('todo-input', TodoInput); 7 | window.customElements.define('todo-item', TodoItem); -------------------------------------------------------------------------------- /tests/commands/addItem.js: -------------------------------------------------------------------------------- 1 | exports.command = function (text, wait) { 2 | return this.setValue('#new-todo', text) 3 | .sendKeys('#new-todo', this.Keys.ENTER) 4 | .waitForElementVisible(`todo-item[text="${text}"]`, wait) 5 | .assert.cssClassNotPresent(`todo-item[text="${text}"]`, 'completed'); 6 | }; 7 | -------------------------------------------------------------------------------- /vue/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | /distWC 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | 15 | # Editor directories and files 16 | .idea 17 | .vscode 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | -------------------------------------------------------------------------------- /stencil-0.11/stencil.config.ts: -------------------------------------------------------------------------------- 1 | import { Config } from '@stencil/core'; 2 | 3 | // https://stenciljs.com/docs/config 4 | 5 | export const config: Config = { 6 | globalStyle: 'src/global/app.css', 7 | outputTargets: [ 8 | { 9 | type: 'www', 10 | baseUrl: process.env.DEMO_BASE_URL 11 | } 12 | ] 13 | }; 14 | -------------------------------------------------------------------------------- /tests/commands/checkItem.js: -------------------------------------------------------------------------------- 1 | exports.command = function (text, wait) { 2 | return this 3 | .assert.cssClassNotPresent(`todo-item[text="${text}"] > li`, 'completed') 4 | .click(`todo-item[text="${text}"] input[type="checkbox"]`) 5 | .assert.cssClassPresent(`todo-item[text="${text}"] > li`, 'completed') 6 | }; 7 | -------------------------------------------------------------------------------- /tests/commands/uncheckItem.js: -------------------------------------------------------------------------------- 1 | exports.command = function (text, wait) { 2 | return this 3 | .assert.cssClassPresent(`todo-item[text="${text}"] > li`, 'completed') 4 | .click(`todo-item[text="${text}"] input[type="checkbox"]`) 5 | .assert.cssClassNotPresent(`todo-item[text="${text}"] > li`, 'completed') 6 | }; 7 | -------------------------------------------------------------------------------- /stencil-0.11/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | insert_final_newline = false 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /stencil-0.16/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | insert_final_newline = false 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /functional-element/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "declarationDir": "./dist", 5 | "module": "es6", 6 | "noImplicitAny": true, 7 | "outDir": "./dist", 8 | "target": "es6" 9 | }, 10 | "include": [ 11 | "src/**/*" 12 | ], 13 | "exclude": ["node_modules"] 14 | } 15 | -------------------------------------------------------------------------------- /non-web-components-refs/angular/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /non-web-components-refs/vue/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw* 22 | -------------------------------------------------------------------------------- /stencil-0.11/src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Stencil Starter", 3 | "short_name": "Stencil", 4 | "start_url": "/", 5 | "display": "standalone", 6 | "icons": [{ 7 | "src": "assets/icon/icon.png", 8 | "sizes": "512x512", 9 | "type": "image/png" 10 | }], 11 | "background_color": "#16161d", 12 | "theme_color": "#16161d" 13 | } -------------------------------------------------------------------------------- /stencil-0.16/src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Stencil Starter", 3 | "short_name": "Stencil", 4 | "start_url": "/", 5 | "display": "standalone", 6 | "icons": [{ 7 | "src": "assets/icon/icon.png", 8 | "sizes": "512x512", 9 | "type": "image/png" 10 | }], 11 | "background_color": "#16161d", 12 | "theme_color": "#16161d" 13 | } -------------------------------------------------------------------------------- /non-web-components-refs/react/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import './index.css'; 5 | import MyTodo from './components/my-todo/my-todo'; 6 | import registerServiceWorker from './registerServiceWorker'; 7 | 8 | ReactDOM.render(, document.getElementById('root')); 9 | registerServiceWorker(); 10 | -------------------------------------------------------------------------------- /non-web-components-refs/vue/README.md: -------------------------------------------------------------------------------- 1 | # vue 2 | 3 | ## Project setup 4 | ``` 5 | yarn install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | yarn run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | yarn run build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | yarn run lint 21 | ``` 22 | -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "dist", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "**", 12 | "destination": "/index.html" 13 | } 14 | ] 15 | } 16 | } -------------------------------------------------------------------------------- /tests/commands/removeItem.js: -------------------------------------------------------------------------------- 1 | exports.command = function (text, wait) { 2 | return this 3 | .assert.elementPresent(`todo-item[text="${text}"] button`) 4 | .click(`todo-item[text="${text}"] button`, () => console.log('eee')) 5 | .waitForElementNotPresent(`todo-item[text="${text}"]`, wait) 6 | .assert.elementNotPresent(`todo-item[text="${text}"]`) 7 | }; 8 | -------------------------------------------------------------------------------- /non-web-components-refs/angular/src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "test.ts", 12 | "polyfills.ts" 13 | ], 14 | "include": [ 15 | "**/*.spec.ts", 16 | "**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /stencil-0.11/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | !www/favicon.ico 3 | www/ 4 | 5 | *~ 6 | *.sw[mnpcod] 7 | *.log 8 | *.lock 9 | *.tmp 10 | *.tmp.* 11 | log.txt 12 | *.sublime-project 13 | *.sublime-workspace 14 | 15 | .stencil/ 16 | .idea/ 17 | .vscode/ 18 | .sass-cache/ 19 | .versions/ 20 | node_modules/ 21 | $RECYCLE.BIN/ 22 | 23 | .DS_Store 24 | Thumbs.db 25 | UserInterfaceState.xcuserstate 26 | .env 27 | -------------------------------------------------------------------------------- /stencil-0.16/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | !www/favicon.ico 3 | www/ 4 | 5 | *~ 6 | *.sw[mnpcod] 7 | *.log 8 | *.lock 9 | *.tmp 10 | *.tmp.* 11 | log.txt 12 | *.sublime-project 13 | *.sublime-workspace 14 | 15 | .stencil/ 16 | .idea/ 17 | .vscode/ 18 | .sass-cache/ 19 | .versions/ 20 | node_modules/ 21 | $RECYCLE.BIN/ 22 | 23 | .DS_Store 24 | Thumbs.db 25 | UserInterfaceState.xcuserstate 26 | .env 27 | -------------------------------------------------------------------------------- /non-web-components-refs/react/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | -------------------------------------------------------------------------------- /non-web-components-refs/react/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /non-web-components-refs/react/src/index.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | 6 | #back { 7 | margin: 50px 0; 8 | display: block; 9 | } 10 | 11 | body { 12 | font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; 13 | line-height: 1.4em; 14 | background: #f5f5f5; 15 | color: #4d4d4d; 16 | min-width: 230px; 17 | max-width: 550px; 18 | margin: 0 auto; 19 | font-weight: 300; 20 | } -------------------------------------------------------------------------------- /non-web-components-refs/angular/src/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tslint.json", 3 | "rules": { 4 | "directive-selector": [ 5 | true, 6 | "attribute", 7 | "app", 8 | "camelCase" 9 | ], 10 | "component-selector": [ 11 | true, 12 | "element", 13 | "app", 14 | "kebab-case" 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /angular-elements/src/main.ts: -------------------------------------------------------------------------------- 1 | import 'zone.js/dist/zone'; 2 | 3 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 4 | 5 | import { registerAsCustomElements } from '@angular/elements'; 6 | 7 | import { TodoModule } from './todo.module'; 8 | import { MyTodo } from './my-todo'; 9 | 10 | registerAsCustomElements([ 11 | MyTodo, 12 | ], () => 13 | platformBrowserDynamic().bootstrapModule(TodoModule) 14 | ); 15 | -------------------------------------------------------------------------------- /polymer2/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "todo", 3 | "main": "index.html", 4 | "dependencies": { 5 | "polymer": "Polymer/polymer#^2.0.0", 6 | "iron-input": "PolymerElements/iron-input#^2.0.1", 7 | "iron-form": "PolymerElements/iron-form#^2.1.3" 8 | }, 9 | "devDependencies": { 10 | "web-component-tester": "Polymer/web-component-tester#^6.0.0", 11 | "webcomponentsjs": "webcomponents/webcomponentsjs#^1.0.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /angular-elements/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "outDir": "./dist/out-tsc", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "module": "es2015", 8 | "moduleResolution": "node", 9 | "emitDecoratorMetadata": true, 10 | "experimentalDecorators": true, 11 | "target": "es2015", 12 | "typeRoots": ["node_modules/@types"], 13 | "lib": ["es2017", "dom"] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /non-web-components-refs/angular/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.error(err)); 13 | 14 | -------------------------------------------------------------------------------- /non-web-components-refs/angular/src/browserslist: -------------------------------------------------------------------------------- 1 | # This file is currently used by autoprefixer to adjust CSS to support the below specified browsers 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | # 5 | # For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed 6 | 7 | > 0.5% 8 | last 2 versions 9 | Firefox ESR 10 | not dead 11 | not IE 9-11 -------------------------------------------------------------------------------- /non-web-components-refs/react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reactv", 3 | "version": "0.1.0", 4 | "private": true, 5 | "homepage": "https://wc-todo.firebaseapp.com/react/", 6 | "dependencies": { 7 | "react": "^16.5.1", 8 | "react-dom": "^16.5.1", 9 | "react-scripts": "1.1.5" 10 | }, 11 | "scripts": { 12 | "start": "react-scripts start", 13 | "build": "react-scripts build", 14 | "test": "react-scripts test --env=jsdom", 15 | "eject": "react-scripts eject" 16 | } 17 | } -------------------------------------------------------------------------------- /stencil-0.16/stencil.config.ts: -------------------------------------------------------------------------------- 1 | import { Config } from '@stencil/core'; 2 | 3 | // https://stenciljs.com/docs/config 4 | 5 | export const config: Config = { 6 | globalStyle: 'src/global/app.css', 7 | globalScript: 'src/global/app.ts', 8 | prerenderIndex: null, 9 | outputTargets: [ 10 | { 11 | type: 'www', 12 | baseUrl: process.env.DEMO_BASE_URL, 13 | // uncomment the following line to disable service workers in production 14 | serviceWorker: null 15 | } 16 | ] 17 | }; -------------------------------------------------------------------------------- /native-shadow-dom/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-shadow-dom", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "webpack --mode production", 8 | "start": "webpack --mode development --watch" 9 | }, 10 | "author": "", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "babel-loader": "^7.1.2", 14 | "babel-preset-stage-0": "^6.24.1", 15 | "webpack": "^4.0.0-beta.2", 16 | "webpack-cli": "^2.0.6" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /solid/src/MyTodo.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | h1 { 6 | font-size: 60px; 7 | font-weight: 100; 8 | text-align: center; 9 | color: rgba(175, 47, 47, 0.15); 10 | } 11 | 12 | section { 13 | background: #fff; 14 | margin: 30px 0 40px 0; 15 | position: relative; 16 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1); 17 | } 18 | 19 | #list-container { 20 | margin: 0; 21 | padding: 0; 22 | list-style: none; 23 | border-top: 1px solid #e6e6e6; 24 | } -------------------------------------------------------------------------------- /slim-js/src/todo-app.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | h1 { 6 | font-size: 100px; 7 | font-weight: 100; 8 | text-align: center; 9 | color: rgba(175, 47, 47, 0.15); 10 | } 11 | 12 | section { 13 | background: #fff; 14 | margin: 30px 0 40px 0; 15 | position: relative; 16 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1); 17 | } 18 | 19 | #list-container { 20 | margin: 0; 21 | padding: 0; 22 | list-style: none; 23 | border-top: 1px solid #e6e6e6; 24 | } -------------------------------------------------------------------------------- /vue/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import wrap from '@vue/web-component-wrapper'; 3 | 4 | Vue.config.productionTip = false 5 | 6 | import MyTodo from './components/my-todo.vue'; 7 | import TodoInput from './components/todo-input.vue'; 8 | import TodoItem from './components/todo-item.vue'; 9 | 10 | window.customElements.define('vue-my-todo', wrap(Vue, MyTodo)); 11 | window.customElements.define('vue-todo-input', wrap(Vue, TodoInput)); 12 | window.customElements.define('vue-todo-item', wrap(Vue, TodoItem)); -------------------------------------------------------------------------------- /slim-js/src/directives/bind-boolean.js: -------------------------------------------------------------------------------- 1 | import { Slim } from "slim-js" 2 | 3 | const test = attr => /^(bind.boolean):(\S+)/.exec(attr.nodeName) 4 | const execute = (source, target, attribute, match) => { 5 | const tAttr = match[2] 6 | const path = attribute.value 7 | Slim.bind(source, target, path, () => { 8 | if (Slim.lookup(source, path)) { 9 | target.setAttribute(tAttr, '') 10 | } else { 11 | target.removeAttribute(tAttr) 12 | } 13 | }) 14 | } 15 | 16 | Slim.customDirective(test, execute) -------------------------------------------------------------------------------- /atomico/README.md: -------------------------------------------------------------------------------- 1 | # atomico-todo 2 | 3 | This is a small example of a component generated with [**Atomico**](https://github.com/uppercod/atomico) and packaged thanks to [**Rollup**](https://rollupjs.org/guide/en) 4 | 5 | As learning of the use of Atomico i invite you to see explore the directory **/src**. 6 | 7 | |File|Min|Gzip| 8 | |----|---|----| 9 | |Atomico| 3.76kB| 1.63kB| 10 | |atom-todo| 4.15kB| 1.43kB| 11 | |Total| 7,91kB| 3.06kB| 12 | 13 | [![Imagen](public/preview.png)](https://uppercod.github.io/atomico-todo) 14 | 15 | 16 | -------------------------------------------------------------------------------- /lit-element-2.1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lit-element", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "webpack --mode production", 9 | "start": "webpack --mode development --watch" 10 | }, 11 | "author": "", 12 | "license": "MIT", 13 | "dependencies": { 14 | "lit-element": "2.1.0" 15 | }, 16 | "devDependencies": { 17 | "webpack": "^4.17.2", 18 | "webpack-cli": "^3.1.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /non-web-components-refs/angular/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "module": "es2015", 9 | "moduleResolution": "node", 10 | "emitDecoratorMetadata": true, 11 | "experimentalDecorators": true, 12 | "target": "es5", 13 | "typeRoots": [ 14 | "node_modules/@types" 15 | ], 16 | "lib": [ 17 | "es2017", 18 | "dom" 19 | ] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /stencil-0.11/src/components/my-todo/my-todo.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | h1 { 6 | font-size: 100px; 7 | font-weight: 100; 8 | text-align: center; 9 | color: rgba(175, 47, 47, 0.15); 10 | } 11 | 12 | section { 13 | background: #fff; 14 | margin: 30px 0 40px 0; 15 | position: relative; 16 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1); 17 | } 18 | 19 | #list-container { 20 | margin: 0; 21 | padding: 0; 22 | list-style: none; 23 | border-top: 1px solid #e6e6e6; 24 | } 25 | -------------------------------------------------------------------------------- /stencil-0.16/src/components/my-todo/my-todo.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | h1 { 6 | font-size: 100px; 7 | font-weight: 100; 8 | text-align: center; 9 | color: rgba(175, 47, 47, 0.15); 10 | } 11 | 12 | section { 13 | background: #fff; 14 | margin: 30px 0 40px 0; 15 | position: relative; 16 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1); 17 | } 18 | 19 | #list-container { 20 | margin: 0; 21 | padding: 0; 22 | list-style: none; 23 | border-top: 1px solid #e6e6e6; 24 | } 25 | -------------------------------------------------------------------------------- /non-web-components-refs/react/src/components/my-todo/my-todo.css: -------------------------------------------------------------------------------- 1 | .MyTodo h1 { 2 | font-size: 70px; 3 | line-height: 70px; 4 | font-weight: 100; 5 | text-align: center; 6 | color: rgba(175, 47, 47, 0.15); 7 | } 8 | 9 | .MyTodo section { 10 | background: #fff; 11 | margin: 30px 0 40px 0; 12 | position: relative; 13 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1); 14 | } 15 | 16 | .MyTodo #list-container { 17 | margin: 0; 18 | padding: 0; 19 | list-style: none; 20 | border-top: 1px solid #e6e6e6; 21 | } -------------------------------------------------------------------------------- /atomico/src/style.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | h1 { 6 | font-size: 70px; 7 | line-height: 70px; 8 | font-weight: 100; 9 | text-align: center; 10 | color: rgba(175, 47, 47, 0.15); 11 | } 12 | 13 | section { 14 | background: #fff; 15 | margin: 30px 0 40px 0; 16 | position: relative; 17 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1); 18 | } 19 | 20 | #list-container { 21 | margin: 0; 22 | padding: 0; 23 | list-style: none; 24 | border-top: 1px solid #e6e6e6; 25 | } -------------------------------------------------------------------------------- /lit-element-0.6/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lit-element", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "webpack --mode production", 9 | "start": "webpack --mode development --watch" 10 | }, 11 | "author": "", 12 | "license": "MIT", 13 | "dependencies": { 14 | "@polymer/lit-element": "^0.6.0-dev.6" 15 | }, 16 | "devDependencies": { 17 | "webpack": "^4.17.2", 18 | "webpack-cli": "^3.1.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /benchmark/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "benchmark", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "build:filesize": "node ./filesize.js", 8 | "build:lighthouse": "node ./lighthouse.js http://localhost:3000" 9 | }, 10 | "author": "", 11 | "license": "MIT", 12 | "dependencies": { 13 | "ascii-horizontal-barchart": "^1.3.3", 14 | "chrome-launcher": "^0.10.5", 15 | "lighthouse": "^4.2.0" 16 | }, 17 | "devDependencies": { 18 | "ejs": "^2.6.1", 19 | "express": "^4.16.4" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /angular-elements/README.md: -------------------------------------------------------------------------------- 1 | # Angular Elements demo 2 | 3 | This project is a first try of using the experimental `@angular/elements`. 4 | 5 | It uses Ahead of Time Compilation provided by `@ngtools/webpack`. 6 | 7 | The bundle will run only in browsers supporting WebComponents. 8 | 9 | ## Install 10 | 11 | ``` 12 | npm install 13 | ``` 14 | 15 | ## Build 16 | 17 | Run `npm run build` to build the project. The build artifacts will be stored in the `dist/` directory. 18 | 19 | ## Run 20 | 21 | Run `npm run serve` to serve the index.html page with the builded element. 22 | -------------------------------------------------------------------------------- /skatejs-lit-html/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "build": "webpack --mode production", 5 | "start": "webpack --mode development --watch" 6 | }, 7 | "dependencies": { 8 | "@skatejs/renderer-lit-html": "^0.2.0", 9 | "lit-html": "^0.9.0", 10 | "skatejs": "^5.1.1" 11 | }, 12 | "devDependencies": { 13 | "babel-loader": "^7.1.2", 14 | "babel-preset-stage-0": "^6.24.1", 15 | "prettier": "^1.10.2", 16 | "prettier-eslint": "^8.8.1", 17 | "webpack": "^4.0.0-beta.2", 18 | "webpack-cli": "^2.0.6" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /angular-elements/src/todo.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { FormsModule, ReactiveFormsModule } from '@angular/forms'; 3 | 4 | import { BrowserModule } from '@angular/platform-browser'; 5 | import { MyTodo } from './my-todo'; 6 | import { TodoInput } from './todo-input'; 7 | import { TodoItem } from './todo-item'; 8 | 9 | @NgModule({ 10 | imports: [BrowserModule, FormsModule, ReactiveFormsModule], 11 | declarations: [MyTodo, TodoInput, TodoItem], 12 | entryComponents: [MyTodo], 13 | }) 14 | export class TodoModule { 15 | ngDoBootstrap() { } 16 | } 17 | -------------------------------------------------------------------------------- /stencil-0.11/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "allowUnreachableCode": false, 5 | "declaration": false, 6 | "experimentalDecorators": true, 7 | "lib": [ 8 | "dom", 9 | "es2015" 10 | ], 11 | "moduleResolution": "node", 12 | "module": "es2015", 13 | "target": "es2015", 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "jsx": "react", 17 | "jsxFactory": "h" 18 | }, 19 | "include": [ 20 | "src" 21 | ], 22 | "exclude": [ 23 | "node_modules" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /stencil-0.16/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "allowUnreachableCode": false, 5 | "declaration": false, 6 | "experimentalDecorators": true, 7 | "lib": [ 8 | "dom", 9 | "es2015" 10 | ], 11 | "moduleResolution": "node", 12 | "module": "esnext", 13 | "target": "es2017", 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "jsx": "react", 17 | "jsxFactory": "h" 18 | }, 19 | "include": [ 20 | "src" 21 | ], 22 | "exclude": [ 23 | "node_modules" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /svelte/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-app", 3 | "version": "1.0.0", 4 | "devDependencies": { 5 | "rollup": "^0.65.2", 6 | "rollup-plugin-buble": "^0.19.2", 7 | "rollup-plugin-commonjs": "^9.1.6", 8 | "rollup-plugin-node-resolve": "^3.3.0", 9 | "rollup-plugin-svelte": "^4.0.0", 10 | "rollup-plugin-terser": "^2.0.2", 11 | "serve": "^10.0.1", 12 | "svelte": "^2.13.4" 13 | }, 14 | "scripts": { 15 | "prebuild": "npm prune && npm install", 16 | "build": "rollup -c", 17 | "dev": "serve public & rollup -c -w", 18 | "start": "serve public" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /skatejs-preact/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "build": "webpack --mode production", 5 | "start": "webpack --mode development --watch" 6 | }, 7 | "dependencies": { 8 | "@skatejs/renderer-preact": "^0.2.5", 9 | "preact": "^8.2.7", 10 | "skatejs": "^5.1.1" 11 | }, 12 | "devDependencies": { 13 | "babel-loader": "^7.1.2", 14 | "babel-preset-react": "^6.24.1", 15 | "babel-preset-stage-0": "^6.24.1", 16 | "prettier": "^1.10.2", 17 | "prettier-eslint": "^8.8.1", 18 | "webpack": "^4.0.0-beta.2", 19 | "webpack-cli": "^2.0.6" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /non-web-components-refs/vue/src/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 18 | 19 | 29 | -------------------------------------------------------------------------------- /functional-element/rollup.config.js: -------------------------------------------------------------------------------- 1 | import commonjs from 'rollup-plugin-commonjs'; 2 | import resolve from "rollup-plugin-node-resolve"; 3 | import { terser } from 'rollup-plugin-terser'; 4 | import typescript from 'rollup-plugin-typescript2' 5 | 6 | const production = !process.env.ROLLUP_WATCH; 7 | 8 | export default { 9 | input: 'src/my-todo.js', 10 | output: { 11 | sourcemap: true, 12 | format: 'iife', 13 | file: 'public/bundle.js', 14 | name: 'app' 15 | }, 16 | plugins: [ 17 | resolve(), 18 | typescript({ 19 | typescript: require('typescript'), 20 | }), 21 | commonjs(), 22 | terser() 23 | ] 24 | }; -------------------------------------------------------------------------------- /templates/group.ejs: -------------------------------------------------------------------------------- 1 | <%- include('row', {project: row}); %> 2 | <% row.group.forEach(function(project){ %> 3 | 4 | 5 | |-- <%= project.name %> 6 | 7 | 8 |
9 |
12 | <%= project.size.toFixed(1) %>
13 |
14 | 15 | 16 | <% }); %> -------------------------------------------------------------------------------- /solid/src/TodoInput.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | form { 6 | position: relative; 7 | font-size: 24px; 8 | border-bottom: 1px solid #ededed; 9 | } 10 | 11 | input { 12 | padding: 16px 16px 16px 60px; 13 | border: none; 14 | background: rgba(0, 0, 0, 0.003); 15 | position: relative; 16 | margin: 0; 17 | width: 100%; 18 | font-size: 24px; 19 | font-family: inherit; 20 | font-weight: inherit; 21 | line-height: 1.4em; 22 | border: 0; 23 | outline: none; 24 | color: inherit; 25 | padding: 6px; 26 | border: 1px solid #CCC; 27 | box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); 28 | box-sizing: border-box; 29 | } -------------------------------------------------------------------------------- /non-web-components-refs/react/src/components/todo-input/todo-input.css: -------------------------------------------------------------------------------- 1 | form { 2 | position: relative; 3 | font-size: 24px; 4 | border-bottom: 1px solid #ededed; 5 | } 6 | 7 | input { 8 | padding: 16px 16px 16px 60px; 9 | border: none; 10 | background: rgba(0, 0, 0, 0.003); 11 | position: relative; 12 | margin: 0; 13 | width: 100%; 14 | font-size: 24px; 15 | font-family: inherit; 16 | font-weight: inherit; 17 | line-height: 1.4em; 18 | border: 0; 19 | outline: none; 20 | color: inherit; 21 | padding: 6px; 22 | border: 1px solid #CCC; 23 | box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); 24 | box-sizing: border-box; 25 | } 26 | -------------------------------------------------------------------------------- /slim-js/webpack.config.js: -------------------------------------------------------------------------------- 1 | const HtmlWebpackPlugin = require('html-webpack-plugin') 2 | 3 | const mode = process.env.NODE_ENV || 'development' 4 | 5 | module.exports = { 6 | entry: './src/index.js', 7 | target: 'web', 8 | mode, 9 | module: { 10 | rules: [ 11 | { 12 | test: /\.js$/, 13 | loader: 'babel-loader' 14 | }, 15 | { 16 | test: /\.css$/, 17 | loader: 'raw-loader' 18 | } 19 | ] 20 | }, 21 | devtool: 'sourcemap', 22 | devServer: { 23 | port: 1337, 24 | compress: true 25 | }, 26 | plugins: [ 27 | new HtmlWebpackPlugin({ 28 | template: './index.html' 29 | }) 30 | ] 31 | } -------------------------------------------------------------------------------- /solid/src/TodoItem.jsx: -------------------------------------------------------------------------------- 1 | import { Component } from 'solid-components' 2 | import { r } from 'solid-js/dom' 3 | 4 | import style from './TodoItem.css' 5 | 6 | const TodoItem = (props, element) => 7 | <> 8 | 9 |
  • 10 | element.trigger('check', { detail: !props.checked })} 13 | /> 14 | 17 | 18 |
  • 19 | 20 | 21 | Component('todo-item', { checked: false }, TodoItem); 22 | -------------------------------------------------------------------------------- /stencil-0.11/src/components/todo-input/todo-input.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | form { 6 | position: relative; 7 | font-size: 24px; 8 | border-bottom: 1px solid #ededed; 9 | } 10 | 11 | input { 12 | padding: 16px 16px 16px 60px; 13 | border: none; 14 | background: rgba(0, 0, 0, 0.003); 15 | position: relative; 16 | margin: 0; 17 | width: 100%; 18 | font-size: 24px; 19 | font-family: inherit; 20 | font-weight: inherit; 21 | line-height: 1.4em; 22 | border: 0; 23 | outline: none; 24 | color: inherit; 25 | padding: 6px; 26 | border: 1px solid #CCC; 27 | box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); 28 | box-sizing: border-box; 29 | } 30 | -------------------------------------------------------------------------------- /stencil-0.16/src/components/todo-input/todo-input.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | form { 6 | position: relative; 7 | font-size: 24px; 8 | border-bottom: 1px solid #ededed; 9 | } 10 | 11 | input { 12 | padding: 16px 16px 16px 60px; 13 | border: none; 14 | background: rgba(0, 0, 0, 0.003); 15 | position: relative; 16 | margin: 0; 17 | width: 100%; 18 | font-size: 24px; 19 | font-family: inherit; 20 | font-weight: inherit; 21 | line-height: 1.4em; 22 | border: 0; 23 | outline: none; 24 | color: inherit; 25 | padding: 6px; 26 | border: 1px solid #CCC; 27 | box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); 28 | box-sizing: border-box; 29 | } 30 | -------------------------------------------------------------------------------- /slim-js/src/components/todo-input.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | form { 6 | position: relative; 7 | font-size: 24px; 8 | border-bottom: 1px solid #ededed; 9 | } 10 | 11 | input { 12 | padding: 16px 16px 16px 60px; 13 | border: none; 14 | background: rgba(0, 0, 0, 0.003); 15 | position: relative; 16 | margin: 0; 17 | margin-bottom: 2px; 18 | width: 100%; 19 | font-size: 24px; 20 | font-family: inherit; 21 | font-weight: inherit; 22 | line-height: 1.4em; 23 | border: 0; 24 | outline: none; 25 | color: inherit; 26 | padding: 6px; 27 | border: 1px solid #CCC; 28 | box-shadow: 0 0px 1px 0px rgba(0, 0, 0, 0.5); 29 | box-sizing: border-box; 30 | } 31 | -------------------------------------------------------------------------------- /stencil-0.16/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stencil", 3 | "private": true, 4 | "version": "0.0.1", 5 | "description": "Stencil App Starter", 6 | "scripts": { 7 | "build": "DEMO_BASE_URL=/stencil-0.16 stencil build", 8 | "build:prerendered": "DEMO_BASE_URL=/stencil-prerendered stencil build --prerender", 9 | "start": "stencil build --dev --watch --serve", 10 | "test": "stencil test --spec --e2e", 11 | "test.watch": "stencil test --spec --e2e --watchAll" 12 | }, 13 | "dependencies": { 14 | "@stencil/core": "~0.16.2", 15 | "@stencil/router": "~0.3.1" 16 | }, 17 | "license": "MIT", 18 | "devDependencies": { 19 | "workbox-build": "3.4.1" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /atomico/src/todo-input/style.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | form { 6 | position: relative; 7 | font-size: 24px; 8 | border-bottom: 1px solid #ededed; 9 | } 10 | 11 | input { 12 | padding: 16px 16px 16px 60px; 13 | border: none; 14 | background: rgba(0, 0, 0, 0.003); 15 | position: relative; 16 | margin: 0; 17 | width: 100%; 18 | font-size: 24px; 19 | font-family: inherit; 20 | font-weight: inherit; 21 | line-height: 1.4em; 22 | border: 0; 23 | outline: none; 24 | color: inherit; 25 | padding: 6px; 26 | border: 1px solid #CCC; 27 | box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); 28 | box-sizing: border-box; 29 | } -------------------------------------------------------------------------------- /non-web-components-refs/angular/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { NgModule } from '@angular/core'; 3 | import { FormsModule } from '@angular/forms'; 4 | 5 | import { AppComponent } from './app.component'; 6 | import { TodoInputComponent } from './todo-input/todo-input.component'; 7 | import { TodoItemComponent } from './todo-item/todo-item.component'; 8 | 9 | @NgModule({ 10 | declarations: [ 11 | AppComponent, 12 | TodoInputComponent, 13 | TodoItemComponent 14 | ], 15 | imports: [ 16 | BrowserModule, 17 | FormsModule, 18 | ], 19 | providers: [], 20 | bootstrap: [AppComponent] 21 | }) 22 | export class AppModule { } 23 | -------------------------------------------------------------------------------- /slim-js/src/components/todo-input.js: -------------------------------------------------------------------------------- 1 | import { tag, template, useShadow } from "slim-js/Decorators"; 2 | import { Slim } from "slim-js"; 3 | 4 | @tag('todo-input') 5 | @template(/*html*/` 6 | 7 |
    8 | 9 |
    10 | `) 11 | @useShadow(true) 12 | export default class extends Slim { 13 | onSubmit (e) { 14 | const { input } = this 15 | input.value = input.value.trim() 16 | const { value: text } = input 17 | e.preventDefault() 18 | if (text) { 19 | this.callAttribute('on-new-item', text) 20 | input.value = null 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /angular-elements/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /tmp 5 | /out-tsc 6 | 7 | # dependencies 8 | /node_modules 9 | 10 | # IDEs and editors 11 | /.idea 12 | .project 13 | .classpath 14 | .c9/ 15 | *.launch 16 | .settings/ 17 | *.sublime-workspace 18 | 19 | # IDE - VSCode 20 | .vscode/* 21 | !.vscode/settings.json 22 | !.vscode/tasks.json 23 | !.vscode/launch.json 24 | !.vscode/extensions.json 25 | 26 | # misc 27 | /.sass-cache 28 | /connect.lock 29 | /coverage 30 | /libpeerconnection.log 31 | npm-debug.log 32 | testem.log 33 | /typings 34 | 35 | # e2e 36 | /e2e/*.js 37 | /e2e/*.map 38 | 39 | # System Files 40 | .DS_Store 41 | Thumbs.db 42 | -------------------------------------------------------------------------------- /non-web-components-refs/angular/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | /node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | 37 | # System Files 38 | .DS_Store 39 | Thumbs.db 40 | -------------------------------------------------------------------------------- /solid/rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel'; 2 | import resolve from 'rollup-plugin-node-resolve'; 3 | import commonjs from 'rollup-plugin-commonjs'; 4 | import postcss from 'rollup-plugin-postcss' 5 | import { terser } from 'rollup-plugin-terser'; 6 | 7 | const production = !process.env.ROLLUP_WATCH; 8 | 9 | export default { 10 | input: 'src/MyTodo.jsx', 11 | output: { 12 | // sourcemap: true, 13 | format: 'iife', 14 | file: 'public/bundle.js', 15 | name: 'app' 16 | }, 17 | plugins: [ 18 | babel({ 19 | exclude: 'node_modules/**', 20 | plugins: ["jsx-dom-expressions"] 21 | }), 22 | resolve({ extensions: ['.js', '.jsx'] }), 23 | postcss({ inject: false }), 24 | production && terser() 25 | ] 26 | }; -------------------------------------------------------------------------------- /stencil-0.11/src/global/app.css: -------------------------------------------------------------------------------- 1 | /* 2 | Global App CSS 3 | ---------------------- 4 | Use this file for styles that should be applied to all components. 5 | For example, "font-family" within the "body" selector is a CSS property 6 | most apps will want applied to all components. 7 | 8 | Any global CSS variables should also be applied here. 9 | */ 10 | 11 | html, body { 12 | margin: 0; 13 | padding: 0; 14 | } 15 | 16 | #back { 17 | margin: 50px 0; 18 | display: block; 19 | } 20 | 21 | body { 22 | font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; 23 | line-height: 1.4em; 24 | background: #f5f5f5; 25 | color: #4d4d4d; 26 | min-width: 230px; 27 | max-width: 550px; 28 | margin: 0 auto; 29 | font-weight: 300; 30 | } -------------------------------------------------------------------------------- /stencil-0.16/src/global/app.css: -------------------------------------------------------------------------------- 1 | /* 2 | Global App CSS 3 | ---------------------- 4 | Use this file for styles that should be applied to all components. 5 | For example, "font-family" within the "body" selector is a CSS property 6 | most apps will want applied to all components. 7 | 8 | Any global CSS variables should also be applied here. 9 | */ 10 | 11 | html, body { 12 | margin: 0; 13 | padding: 0; 14 | } 15 | 16 | #back { 17 | margin: 50px 0; 18 | display: block; 19 | } 20 | 21 | body { 22 | font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; 23 | line-height: 1.4em; 24 | background: #f5f5f5; 25 | color: #4d4d4d; 26 | min-width: 230px; 27 | max-width: 550px; 28 | margin: 0 auto; 29 | font-weight: 300; 30 | } -------------------------------------------------------------------------------- /non-web-components-refs/angular/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone-testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: any; 11 | 12 | // First, initialize the Angular testing environment. 13 | getTestBed().initTestEnvironment( 14 | BrowserDynamicTestingModule, 15 | platformBrowserDynamicTesting() 16 | ); 17 | // Then we find all the tests. 18 | const context = require.context('./', true, /\.spec\.ts$/); 19 | // And load the modules. 20 | context.keys().map(context); 21 | -------------------------------------------------------------------------------- /non-web-components-refs/angular/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /solid/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Solid Todo 9 | 32 | 33 | 34 | 35 | 36 | 37 | ⬅ Back to other implementations 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /svelte/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Svelte app 9 | 32 | 33 | 34 | 35 | 36 | 37 | ⬅ Back to other implementations 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /solid/src/TodoInput.jsx: -------------------------------------------------------------------------------- 1 | import { Component } from 'solid-components'; 2 | import { useState } from 'solid-js'; 3 | import { r } from 'solid-js/dom'; 4 | 5 | import style from './TodoInput.css'; 6 | 7 | const TodoInput = (props, element) => { 8 | const [state, setState] = useState({ value: '' }), 9 | handleSubmit = e => { 10 | e.preventDefault(); 11 | if (!state.value) return; 12 | element.trigger('submit', { detail: state.value }); 13 | setState({ value: '' }); 14 | }; 15 | return <> 16 | 17 |
    18 | setState({ value })} 23 | /> 24 |
    25 | 26 | } 27 | 28 | Component('todo-input', TodoInput); -------------------------------------------------------------------------------- /templates/row.ejs: -------------------------------------------------------------------------------- 1 | class="table-light" <% } %>> 2 | 3 | <%= project.name %> 4 | <% if (project.new) { %> 5 | NEW! 6 | <% } %> 7 | 8 | Demo 9 | 10 | <% if (project.docs) { %> 11 | Docs 12 | <% } %> 13 | 14 | 15 |
    16 |
    <%= project.size.toFixed(1) %>
    18 |
    19 | 20 | -------------------------------------------------------------------------------- /slim-js/src/components/todo-item.js: -------------------------------------------------------------------------------- 1 | import { tag, template, useShadow } from "slim-js/Decorators"; 2 | import { Slim } from "slim-js"; 3 | 4 | @tag('todo-item') 5 | @template(/*html*/` 6 | 9 |
  • 10 | 13 | 14 | 15 |
  • 16 | `) 17 | @useShadow(true) 18 | export default class TodoItem extends Slim { 19 | 20 | onChecked () { 21 | this.checked = this.data.checked = this.checkbox.checked 22 | this.commit() 23 | } 24 | 25 | getClass (checked) { 26 | return checked ? 'completed' : '' 27 | } 28 | 29 | onRemove (e) { 30 | this.callAttribute('on-remove', this.data) 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /slim-js/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Todo Demo with slim-js 7 | 30 | 31 | 32 | ⬅ Back to other implementations 33 | 34 | 35 | -------------------------------------------------------------------------------- /slim-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slim-todo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "dev": "webpack-dev-server --watch --progress --colors --config webpack.config.js", 9 | "build": "NODE_ENV=production webpack" 10 | }, 11 | "author": "Avichay Eyal ", 12 | "license": "MIT", 13 | "dependencies": { 14 | "slim-js": "^3.3.4" 15 | }, 16 | "devDependencies": { 17 | "@babel/cli": "^7.0.0", 18 | "@babel/core": "^7.0.1", 19 | "@babel/plugin-proposal-decorators": "^7.0.0", 20 | "@babel/preset-env": "^7.0.0", 21 | "babel-loader": "^8.0.2", 22 | "html-webpack-plugin": "^3.2.0", 23 | "raw-loader": "^0.5.1", 24 | "webpack": "^4.18.0", 25 | "webpack-cli": "^3.1.0", 26 | "webpack-dev-server": "^3.1.8" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /stencil-0.11/src/components/todo-item/todo-item.tsx: -------------------------------------------------------------------------------- 1 | 2 | import { Component, Prop, Event, EventEmitter } from '@stencil/core'; 3 | 4 | @Component({ 5 | tag: 'todo-item', 6 | styleUrl: 'todo-item.css', 7 | // shadow: true, 8 | }) 9 | export class TodoItem { 10 | @Prop() checked: boolean; 11 | @Prop() text: string; 12 | @Prop() index: number; 13 | @Event() onTodoItemChecked: EventEmitter; 14 | @Event() onTodoItemRemove: EventEmitter; 15 | 16 | handleOnRemove = () => this.onTodoItemRemove.emit(this.index); 17 | handleOnChecked = () => this.onTodoItemChecked.emit(this.index); 18 | 19 | render() { 20 | return ( 21 |
  • 22 | 23 | 24 | 25 |
  • 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /stencil-0.16/src/components/todo-item/todo-item.tsx: -------------------------------------------------------------------------------- 1 | 2 | import { Component, Prop, Event, EventEmitter } from '@stencil/core'; 3 | 4 | @Component({ 5 | tag: 'todo-item', 6 | styleUrl: 'todo-item.css', 7 | // shadow: true, 8 | }) 9 | export class TodoItem { 10 | @Prop() checked: boolean; 11 | @Prop() text: string; 12 | @Prop() index: number; 13 | @Event() onTodoItemChecked: EventEmitter; 14 | @Event() onTodoItemRemove: EventEmitter; 15 | 16 | handleOnRemove = () => this.onTodoItemRemove.emit(this.index); 17 | handleOnChecked = () => this.onTodoItemChecked.emit(this.index); 18 | 19 | render() { 20 | return ( 21 |
  • 22 | 23 | 24 | 25 |
  • 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /skatejs-lit-html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SkateJS & LitHTML 6 | 7 | 30 | 31 | 32 | 33 | ⬅ Back to other implementations 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /skatejs-preact/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SkateJS & Preact 6 | 7 | 30 | 31 | 32 | 33 | ⬅ Back to other implementations 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /stencil-0.11/src/components/todo-input/todo-input.tsx: -------------------------------------------------------------------------------- 1 | import { Component, State, Event, EventEmitter } from '@stencil/core'; 2 | 3 | @Component({ 4 | tag: 'todo-input', 5 | styleUrl: 'todo-input.css', 6 | // shadow: true, 7 | }) 8 | export class TodoInput { 9 | @Event() onTodoInputSubmit: EventEmitter; 10 | @State() value: string; 11 | 12 | handleOnSubmit = (e) => { 13 | e.preventDefault(); 14 | if (!this.value) return; 15 | this.onTodoInputSubmit.emit(this.value); 16 | this.value = ''; 17 | } 18 | 19 | handleInputChange = (event) => this.value = event.target.value; 20 | 21 | render() { 22 | return ( 23 |
    24 | 30 |
    31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /stencil-0.16/src/components/todo-input/todo-input.tsx: -------------------------------------------------------------------------------- 1 | import { Component, State, Event, EventEmitter } from '@stencil/core'; 2 | 3 | @Component({ 4 | tag: 'todo-input', 5 | styleUrl: 'todo-input.css', 6 | // shadow: true, 7 | }) 8 | export class TodoInput { 9 | @Event() onTodoInputSubmit: EventEmitter; 10 | @State() value: string; 11 | 12 | handleOnSubmit = (e) => { 13 | e.preventDefault(); 14 | if (!this.value) return; 15 | this.onTodoInputSubmit.emit(this.value); 16 | this.value = ''; 17 | } 18 | 19 | handleInputChange = (event) => this.value = event.target.value; 20 | 21 | render() { 22 | return ( 23 |
    24 | 30 |
    31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /native-shadow-dom/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Native Web Component Todo 6 | 7 | 30 | 31 | 32 | 33 | ⬅ Back to other implementations 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /polymer2/README.md: -------------------------------------------------------------------------------- 1 | # \ 2 | 3 | 4 | 5 | ## Install the Polymer-CLI 6 | 7 | First, make sure you have the [Polymer CLI](https://www.npmjs.com/package/polymer-cli) installed. Then run `polymer serve` to serve your application locally. 8 | 9 | ## Viewing Your Application 10 | 11 | ``` 12 | $ polymer serve 13 | ``` 14 | 15 | ## Building Your Application 16 | 17 | ``` 18 | $ polymer build 19 | ``` 20 | 21 | This will create builds of your application in the `build/` directory, optimized to be served in production. You can then serve the built versions by giving `polymer serve` a folder to serve from: 22 | 23 | ``` 24 | $ polymer serve build/default 25 | ``` 26 | 27 | ## Running Tests 28 | 29 | ``` 30 | $ polymer test 31 | ``` 32 | 33 | Your application is already set up to be tested via [web-component-tester](https://github.com/Polymer/web-component-tester). Run `polymer test` to run your application's test suite locally. 34 | -------------------------------------------------------------------------------- /polymer3/README.md: -------------------------------------------------------------------------------- 1 | # \ 2 | 3 | 4 | 5 | ## Install the Polymer-CLI 6 | 7 | First, make sure you have the [Polymer CLI](https://www.npmjs.com/package/polymer-cli) installed. Then run `polymer serve` to serve your application locally. 8 | 9 | ## Viewing Your Application 10 | 11 | ``` 12 | $ polymer serve 13 | ``` 14 | 15 | ## Building Your Application 16 | 17 | ``` 18 | $ polymer build 19 | ``` 20 | 21 | This will create builds of your application in the `build/` directory, optimized to be served in production. You can then serve the built versions by giving `polymer serve` a folder to serve from: 22 | 23 | ``` 24 | $ polymer serve build/default 25 | ``` 26 | 27 | ## Running Tests 28 | 29 | ``` 30 | $ polymer test 31 | ``` 32 | 33 | Your application is already set up to be tested via [web-component-tester](https://github.com/Polymer/web-component-tester). Run `polymer test` to run your application's test suite locally. 34 | -------------------------------------------------------------------------------- /functional-element/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "functional-element-todo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "my-todo.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "rollup -c", 9 | "dev": "serve public & rollup -c -w", 10 | "start": "serve public" 11 | }, 12 | "author": "Jordan Last ", 13 | "license": "MIT", 14 | "devDependencies": { 15 | "jsverify-es-module": "0.0.2", 16 | "rollup": "^0.65.2", 17 | "rollup-plugin-buble": "^0.19.2", 18 | "rollup-plugin-commonjs": "^9.1.6", 19 | "rollup-plugin-node-resolve": "^3.3.0", 20 | "rollup-plugin-svelte": "^4.0.0", 21 | "rollup-plugin-terser": "^2.0.2", 22 | "rollup-plugin-typescript2": "^0.20.1", 23 | "serve": "^10.1.2", 24 | "typescript": "^3.3.4000" 25 | }, 26 | "dependencies": { 27 | "functional-element": "0.0.9" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /solid/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solid-todo", 3 | "version": "0.0.1", 4 | "source": "src/index.js", 5 | "author": "Ryan Carniato", 6 | "license": "MIT", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/ryansolid/solid" 10 | }, 11 | "scripts": { 12 | "prebuild": "npm prune && npm install", 13 | "build": "rollup -c", 14 | "dev": "serve public & rollup -c -w", 15 | "start": "serve public" 16 | }, 17 | "dependencies": { 18 | "babel-plugin-jsx-dom-expressions": "0.3.6", 19 | "solid-components": "0.0.6", 20 | "solid-js": "0.3.4" 21 | }, 22 | "devDependencies": { 23 | "@babel/core": "7.2.2", 24 | "rollup": "^1.0.0", 25 | "rollup-plugin-babel": "4.2.0", 26 | "rollup-plugin-commonjs": "^9.2.0", 27 | "rollup-plugin-node-resolve": "^4.0.0", 28 | "rollup-plugin-postcss": "^1.6.3", 29 | "rollup-plugin-terser": "4.0.1", 30 | "serve": "^10.0.1" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /atomico/src/todo-input/index.js: -------------------------------------------------------------------------------- 1 | import { h, Element } from "atomico"; 2 | import style from "./style.css"; 3 | 4 | export default class extends Element { 5 | constructor() { 6 | super(); 7 | this.attachShadow({ mode: "open" }); 8 | } 9 | static get props() { 10 | return ["placeholder"]; 11 | } 12 | render() { 13 | return ( 14 |
    { 16 | event.preventDefault(); 17 | this.dispatch("create", { 18 | text: event.target.task.value 19 | }); 20 | event.target.reset(); 21 | }} 22 | > 23 | 24 | 29 |
    30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /polymer3/src/my-todo-styles.js: -------------------------------------------------------------------------------- 1 | import { 2 | Element as PolymerElement 3 | } 4 | from '../node_modules/@polymer/polymer/polymer-element.js'; 5 | 6 | const myTodoStyleElement = document.createElement('dom-module'); 7 | myTodoStyleElement.innerHTML = 8 | `` 36 | myTodoStyleElement.register('my-todo-style-element'); -------------------------------------------------------------------------------- /atomico/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Atomico todo 8 | 31 | 32 | 33 | ⬅ Back to other implementations 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /stencil-0.16/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Stencil Starter App 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ⬅ Back to other implementations 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /non-web-components-refs/react/src/components/todo-item/todo-item.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import './todo-item.css'; 4 | 5 | class MyTodo extends Component { 6 | static propTypes = { 7 | checked: PropTypes.bool.isRequired, 8 | text: PropTypes.string.isRequired, 9 | index: PropTypes.number.isRequired, 10 | onTodoItemRemove: PropTypes.func.isRequired, 11 | onTodoItemChecked: PropTypes.func.isRequired, 12 | }; 13 | 14 | handleOnRemove = () => this.props.onTodoItemRemove(this.props.index); 15 | handleOnChecked = () => this.props.onTodoItemChecked(this.props.index); 16 | 17 | render() { 18 | const { checked, text } = this.props; 19 | return ( 20 |
  • 21 | 22 | 23 | 24 |
  • 25 | ); 26 | } 27 | } 28 | 29 | export default MyTodo; 30 | 31 | -------------------------------------------------------------------------------- /stencil-0.11/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Stencil Starter App 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ⬅ Back to other implementations 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /non-web-components-refs/vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "npm run serve", 7 | "serve": "vue-cli-service serve", 8 | "build": "vue-cli-service build", 9 | "lint": "vue-cli-service lint" 10 | }, 11 | "dependencies": { 12 | "vue": "^2.5.17" 13 | }, 14 | "devDependencies": { 15 | "@vue/cli-plugin-babel": "^3.0.3", 16 | "@vue/cli-plugin-eslint": "^3.0.3", 17 | "@vue/cli-service": "^3.0.3", 18 | "vue-template-compiler": "^2.5.17" 19 | }, 20 | "eslintConfig": { 21 | "root": true, 22 | "env": { 23 | "node": true 24 | }, 25 | "extends": [ 26 | "plugin:vue/essential", 27 | "eslint:recommended" 28 | ], 29 | "rules": {}, 30 | "parserOptions": { 31 | "parser": "babel-eslint" 32 | } 33 | }, 34 | "postcss": { 35 | "plugins": { 36 | "autoprefixer": {} 37 | } 38 | }, 39 | "browserslist": [ 40 | "> 1%", 41 | "last 2 versions", 42 | "not ie <= 8" 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /non-web-components-refs/react/src/components/todo-input/todo-input.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import './todo-input.css'; 4 | 5 | class MyTodo extends Component { 6 | state = { value: '' }; 7 | 8 | static propTypes = { 9 | onTodoInputSubmit: PropTypes.func.isRequired, 10 | }; 11 | 12 | handleOnSubmit = (e) => { 13 | e.preventDefault(); 14 | if (!this.state.value) return; 15 | this.props.onTodoInputSubmit(this.state.value); 16 | this.setState({ value: '' }); 17 | } 18 | 19 | handleInputChange = (event) => this.setState({ value: event.target.value }); 20 | 21 | render() { 22 | const { checked, text } = this.props; 23 | return ( 24 |
    25 | 31 |
    32 | ); 33 | } 34 | } 35 | 36 | export default MyTodo; 37 | 38 | 39 | -------------------------------------------------------------------------------- /atomico/src/todo-item/index.js: -------------------------------------------------------------------------------- 1 | import { h, Element } from "atomico"; 2 | import style from "./style.css"; 3 | export default class extends Element { 4 | constructor() { 5 | super(); 6 | this.attachShadow({ mode: "open" }); 7 | } 8 | static get props() { 9 | return ["text", "checked"]; 10 | } 11 | render() { 12 | return ( 13 |
  • 14 | 15 | { 18 | this.dispatch("toggle"); 19 | }} 20 | checked={this.props.checked} 21 | /> 22 | 23 | 30 |
  • 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-web-component-wrapper", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "vue-cli-service serve --open", 7 | "build": "npm run build:wc && cp index.html dist/ && rm dist/demo.html", 8 | "build:wc": "vue-cli-service build --target wc --name vue 'src/components/*.vue'", 9 | "lint": "vue-cli-service lint" 10 | }, 11 | "dependencies": { 12 | "vue": "^2.5.13" 13 | }, 14 | "devDependencies": { 15 | "@vue/cli-plugin-babel": "^3.0.0-alpha.11", 16 | "@vue/cli-plugin-eslint": "^3.0.0-alpha.11", 17 | "@vue/cli-service": "^3.0.0-alpha.11", 18 | "vue-template-compiler": "^2.5.13" 19 | }, 20 | "babel": { 21 | "presets": [ 22 | "@vue/app" 23 | ] 24 | }, 25 | "eslintConfig": { 26 | "root": true, 27 | "extends": [ 28 | "plugin:vue/essential", 29 | "eslint:recommended" 30 | ] 31 | }, 32 | "postcss": { 33 | "plugins": { 34 | "autoprefixer": {} 35 | } 36 | }, 37 | "browserslist": [ 38 | "> 1%", 39 | "last 2 versions", 40 | "not ie <= 8" 41 | ] 42 | } -------------------------------------------------------------------------------- /angular-elements/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-elements-demo", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "build": "webpack", 7 | "start": "npm run build && http-server ./dist" 8 | }, 9 | "private": true, 10 | "dependencies": { 11 | "@angular/common": "^5.2.2", 12 | "@angular/compiler": "^5.2.2", 13 | "@angular/core": "^5.2.2", 14 | "@angular/elements": "github:angular/elements-builds#labs/elements", 15 | "@angular/forms": "^5.2.2", 16 | "@angular/platform-browser": "^5.2.2", 17 | "@angular/platform-browser-dynamic": "^5.2.2", 18 | "core-js": "^2.5.3", 19 | "mutation-observer": "^1.0.3", 20 | "rxjs": "^5.5.6", 21 | "zone.js": "^0.8.20" 22 | }, 23 | "devDependencies": { 24 | "@angular/cli": "^1.6.6", 25 | "@angular/compiler-cli": "^5.2.2", 26 | "@ngtools/webpack": "^1.9.6", 27 | "compression-webpack-plugin": "^1.1.3", 28 | "custom-elements": "^1.0.2", 29 | "html-webpack-plugin": "^2.30.1", 30 | "http-server": "^0.11.1", 31 | "typescript": "~2.6.2", 32 | "webpack": "^3.10.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /non-web-components-refs/vue/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Todos Vue 10 | 33 | 34 | 35 | 36 | 39 | ⬅ Back to other implementations 40 |
    41 | 42 | 43 | -------------------------------------------------------------------------------- /vue/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | vue-web-component-wrapper 10 | 11 | 12 | 13 | 14 | 15 | ⬅ Back to other implementations 16 | 17 | 18 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /generateIndex.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const ejs = require('ejs'); 3 | const benchmark = require('./benchmark/filesize.js'); 4 | const { legacy, latest } = require('./benchmark/meta'); 5 | 6 | const latestWithBytes = benchmark.filesizeGzipped(latest); 7 | const metasWithKb = latestWithBytes.map((project) => ({ 8 | ...project, 9 | size: project.size / 1000, 10 | group: project.group ? benchmark.filesizeGzipped(legacy[project.group]).map((project) => ({ 11 | ...project, 12 | size: project.size / 1000, 13 | })) : null, 14 | })); 15 | 16 | console.log('metasWithKb', metasWithKb) 17 | const maxSize = Math.max(...metasWithKb.map(project => project.size)); 18 | const WCprojects = metasWithKb.filter(project => project.wc); 19 | const NonWCprojects = metasWithKb.filter(project => !project.wc); 20 | 21 | ejs.renderFile('./templates/index.ejs', { 22 | WCprojects, 23 | NonWCprojects, 24 | maxSize, 25 | }, {}, function (err, str) { 26 | fs.writeFile('dist/index.html', str, (err) => { 27 | if (err) throw err; 28 | console.log('The file has been saved!'); 29 | }); 30 | }); -------------------------------------------------------------------------------- /non-web-components-refs/angular/src/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, '../coverage'), 20 | reports: ['html', 'lcovonly'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false 30 | }); 31 | }; -------------------------------------------------------------------------------- /angular-elements/webpack.config.js: -------------------------------------------------------------------------------- 1 | /* global module */ 2 | const AotPlugin = require('@ngtools/webpack').AngularCompilerPlugin; 3 | const CompressionPlugin = require("compression-webpack-plugin"); 4 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | const path = require('path'); 6 | 7 | module.exports = { 8 | entry: './src/main.ts', 9 | resolve: { 10 | mainFields: ['es2015', 'browser', 'module', 'main'] 11 | }, 12 | module: { 13 | rules: [{ test: /\.ts$/, loaders: ['@ngtools/webpack'] }] 14 | }, 15 | plugins: [ 16 | new AotPlugin({ 17 | tsConfigPath: './tsconfig.json', 18 | entryModule: path.resolve(__dirname, './src/todo.module#TodoModule') 19 | }), 20 | new HtmlWebpackPlugin({ 21 | inject: true, 22 | template: 'src/index.html' 23 | }), 24 | // new CompressionPlugin({ 25 | // asset: "[path].gz[query]", 26 | // algorithm: "gzip", 27 | // test: /\.js$|\.css$/, 28 | // threshold: 10240, 29 | // minRatio: 0.8 30 | // }) 31 | ], 32 | output: { 33 | path: __dirname + '/dist', 34 | filename: 'main.bundle.js' 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /tests/suite/wc.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const url = `file:///${path.join(__dirname, '../..')}/native/index.html`; 3 | 4 | const pause = 200; 5 | const wait = 5000; 6 | 7 | module.exports = { 8 | '@tags': ['wc'], 9 | 'Todo sequence': browser => 10 | browser.url(url) 11 | .waitForElementVisible('#new-todo', wait) 12 | .waitForElementVisible('todo-item[text="my initial todo"]', wait) 13 | .addItem('first added todo', wait) 14 | .pause(pause) 15 | .addItem('second added todo', wait) 16 | .pause(pause) 17 | .checkItem('first added todo', wait) 18 | .pause(pause) 19 | .uncheckItem('first added todo', wait) 20 | .pause(pause) 21 | .removeItem('first added todo', wait) 22 | .pause(pause) 23 | .removeItem('second added todo', wait) 24 | .pause(pause) 25 | .removeItem('Learn about Web Components', wait) 26 | .pause(pause) 27 | .removeItem('my initial todo', wait) 28 | .pause(pause) 29 | .end(), 30 | }; 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Julien Renaux 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /atomico/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "atom-todo", 3 | "version": "0.0.1", 4 | "description": "This is a small skeleton to create distributable components based on Atomico", 5 | "iife": "public/atom-todo.iife.js", 6 | "source": "src/index.js", 7 | "author": "Matias Trujillo Olivares", 8 | "license": "ISC", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/UpperCod/atomico-starter-component.git" 12 | }, 13 | "scripts": { 14 | "prebuild": "npm prune && npm install", 15 | "watch": "rollup -c -w", 16 | "build": "rollup -c" 17 | }, 18 | "dependencies": { 19 | "atomico": "^0.0.9" 20 | }, 21 | "globals": { 22 | "atomico": "atomico" 23 | }, 24 | "devDependencies": { 25 | "cssnano": "^4.1.0", 26 | "rollup": "^0.65.2", 27 | "rollup-plugin-buble": "^0.19.2", 28 | "rollup-plugin-commonjs": "^9.1.6", 29 | "rollup-plugin-copy": "^0.2.3", 30 | "rollup-plugin-filesize": "^4.0.1", 31 | "rollup-plugin-node-resolve": "^3.4.0", 32 | "rollup-plugin-postcss": "^1.6.2", 33 | "rollup-plugin-terser": "1.0.1", 34 | "rollup-prepare": "^0.0.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /stencil-0.16/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /stencil-0.11/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Ionic 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /svelte/rollup.config.js: -------------------------------------------------------------------------------- 1 | import svelte from 'rollup-plugin-svelte'; 2 | import resolve from 'rollup-plugin-node-resolve'; 3 | import commonjs from 'rollup-plugin-commonjs'; 4 | import { terser } from 'rollup-plugin-terser'; 5 | 6 | const production = !process.env.ROLLUP_WATCH; 7 | 8 | export default { 9 | input: 'src/main.js', 10 | output: { 11 | sourcemap: true, 12 | format: 'iife', 13 | file: 'public/bundle.js', 14 | name: 'app' 15 | }, 16 | plugins: [ 17 | svelte({ 18 | // enable run-time checks when not in production 19 | dev: !production, 20 | 21 | customElement: true, 22 | 23 | // this results in smaller CSS files 24 | cascade: false 25 | }), 26 | 27 | // If you have external dependencies installed from 28 | // npm, you'll most likely need these plugins. In 29 | // some cases you'll need additional configuration — 30 | // consult the documentation for details: 31 | // https://github.com/rollup/rollup-plugin-commonjs 32 | resolve(), 33 | commonjs(), 34 | 35 | // If we're building for production (npm run build 36 | // instead of npm run dev), minify bundle 37 | production && terser() 38 | ] 39 | }; -------------------------------------------------------------------------------- /angular-elements/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Angular Elements Todo 7 | 8 | 9 | 10 | 11 | 12 | ⬅ Back to other implementations 13 | 14 | 15 | 16 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /non-web-components-refs/angular/README.md: -------------------------------------------------------------------------------- 1 | # Angular 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 6.2.2. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 28 | -------------------------------------------------------------------------------- /angular-elements/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Vincent Ogloblinsky 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /polymer2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | todo 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | ⬅ Back to other implementations 22 | 23 | 24 | 47 | 48 | -------------------------------------------------------------------------------- /polymer3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | polymer-3 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ⬅ Back to other implementations 21 | 22 | 23 | 46 | 47 | -------------------------------------------------------------------------------- /vue/src/components/todo-input.vue: -------------------------------------------------------------------------------- 1 | 6 | 20 | -------------------------------------------------------------------------------- /slim-js/src/todo-app.js: -------------------------------------------------------------------------------- 1 | import { Slim } from 'slim-js' 2 | import { tag, template, useShadow } from 'slim-js/Decorators'; 3 | import './directives/bind-boolean.js' 4 | import TodoItem from './components/todo-item'; 5 | import todoInput from './components/todo-input.js'; 6 | 7 | @tag('todo-app') 8 | @template(/*html*/` 9 | 10 |
    11 |

    Todos slim-js

    12 |
    13 | 14 |
      15 | 18 |
    19 |
    20 |
    21 | `) 22 | @useShadow(true) 23 | export default class TodoApp extends Slim { 24 | 25 | constructor () { 26 | super() 27 | this.list = [ 28 | { text: 'my initial todo', checked: false }, 29 | { text: 'Learn about Web Components', checked: true } 30 | ] 31 | } 32 | 33 | onNewItem (text) { 34 | this.list = [...this.list, { 35 | text, 36 | checked: false 37 | }] 38 | } 39 | 40 | onRemoveItem (item) { 41 | this.list = this.list.filter(existingItem => existingItem !== item) 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /non-web-components-refs/vue/src/components/todo-input.vue: -------------------------------------------------------------------------------- 1 | 6 | 20 | -------------------------------------------------------------------------------- /vue/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | vue-web-component-wrapper 10 | 11 | 12 | 13 | 14 | 15 | ⬅ Back to other implementations 16 | 17 | 18 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /stencil-0.11/.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Resources:** 2 | Before submitting an issue, please consult our [docs](https://stenciljs.com/). 3 | 4 | **Stencil version:** (run `npm list @stencil/core` from a terminal/cmd prompt and paste output below): 5 | 6 | ``` 7 | insert the output from npm list @stencil/core here 8 | ``` 9 | 10 | **I'm submitting a ...** (check one with "x") 11 | [ ] bug report 12 | [ ] feature request 13 | [ ] support request => Please do not submit support requests here, use one of these channels: https://forum.ionicframework.com/ or https://stencil-worldwide.slack.com 14 | 15 | **Current behavior:** 16 | 17 | 18 | **Expected behavior:** 19 | 20 | 21 | **Steps to reproduce:** 22 | 24 | 25 | **Related code:** 26 | 27 | ``` 28 | insert any relevant code here 29 | ``` 30 | 31 | **Other information:** 32 | 33 | -------------------------------------------------------------------------------- /polymer3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polymer3", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "flat": true, 7 | "scripts": { 8 | "build": "npm run build-polymer && npm run build-es6 && npm run minify-es6", 9 | "build-polymer": "polymer build", 10 | "postbuild-polymer": "rm -rf build/es6-bundled/node_modules && rm -rf build/es6-bundled/src/*", 11 | "build-es6": "rollup -c rollup.config.js", 12 | "minify-es6": "mkdir -p build/es6-bundled/src/ && uglifyjs build/es6-bundled/src_tmp/index.js -o build/es6-bundled/src/index.js -c -m", 13 | "postminify-es6": "rm -rf build/es6-bundled/src_tmp" 14 | }, 15 | "dependencies": { 16 | "@polymer/iron-form": "^3.0.0-pre.8", 17 | "@polymer/iron-input": "^3.0.0-pre.8", 18 | "@polymer/polymer": "^3.0.0-pre.9", 19 | "@webcomponents/webcomponentsjs": "^1.1.0" 20 | }, 21 | "resolutions": { 22 | "@webcomponents/webcomponentsjs": "1.1.0", 23 | "@polymer/polymer": "3.0.0-pre.9" 24 | }, 25 | "devDependencies": { 26 | "rollup": "^0.56.2", 27 | "rollup-plugin-node-resolve": "^3.0.3", 28 | "uglify-es": "^3.3.9" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | .rpt2_cache 8 | 9 | # Runtime data 10 | pids 11 | *.pid 12 | *.seed 13 | *.pid.lock 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 | # nyc test coverage 22 | .nyc_output 23 | 24 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 25 | .grunt 26 | 27 | # Bower dependency directory (https://bower.io/) 28 | bower_components 29 | 30 | # node-waf configuration 31 | .lock-wscript 32 | 33 | # Compiled binary addons (http://nodejs.org/api/addons.html) 34 | build/Release 35 | 36 | # Dependency directories 37 | node_modules/ 38 | jspm_packages/ 39 | 40 | # Typescript v1 declaration files 41 | typings/ 42 | 43 | # Optional npm cache directory 44 | .npm 45 | 46 | # Optional eslint cache 47 | .eslintcache 48 | 49 | # Optional REPL history 50 | .node_repl_history 51 | 52 | # Output of 'npm pack' 53 | *.tgz 54 | 55 | # Yarn Integrity file 56 | .yarn-integrity 57 | 58 | # dotenv environment variables file 59 | .env 60 | 61 | .e2e-results 62 | 63 | # functional-element dist 64 | /functional-element/dist -------------------------------------------------------------------------------- /native/js/todo-input.js: -------------------------------------------------------------------------------- 1 | const templateTodoInput = document.createElement('template'); 2 | templateTodoInput.innerHTML = ` 3 |
    4 | 5 |
    6 | `; 7 | 8 | class TodoInput extends HTMLElement { 9 | constructor() { 10 | super(); 11 | // Do not use shadow DOM to avoid problems when testing with selenium 12 | // this._root = this.attachShadow({ 'mode': 'open' }); 13 | } 14 | 15 | connectedCallback() { 16 | console.log('TodoInput ADDED TO THE DOM'); 17 | this.appendChild(templateTodoInput.content.cloneNode(true)); 18 | this.$form = this.querySelector('form'); 19 | this.$input = this.querySelector('input'); 20 | this.$form.addEventListener("submit", (e) => { 21 | e.preventDefault(); 22 | if (!this.$input.value) return; 23 | this.dispatchEvent(new CustomEvent('onSubmit', { detail: this.$input.value })); 24 | this.$input.value = ''; 25 | }); 26 | } 27 | 28 | disconnectedCallback() { 29 | console.log('TodoInput REMOVED TO THE DOM'); 30 | } 31 | } 32 | 33 | window.customElements.define('todo-input', TodoInput); 34 | -------------------------------------------------------------------------------- /polymer3/src/todo-input-styles.js: -------------------------------------------------------------------------------- 1 | import { 2 | Element as PolymerElement 3 | } 4 | from '../node_modules/@polymer/polymer/polymer-element.js'; 5 | 6 | const todoInputStyleElement = document.createElement('dom-module'); 7 | todoInputStyleElement.innerHTML = 8 | `` 45 | todoInputStyleElement.register('todo-input-style-element'); -------------------------------------------------------------------------------- /solid/src/MyTodo.jsx: -------------------------------------------------------------------------------- 1 | import { Component } from 'solid-components'; 2 | import { useState } from 'solid-js'; 3 | import { r } from 'solid-js/dom'; 4 | 5 | import style from './MyTodo.css'; 6 | import './TodoInput'; 7 | import './TodoItem'; 8 | 9 | let uid = 1; 10 | const MyTodo = () => { 11 | const [state, setState] = useState({ list: [ 12 | { id: uid++, text: "my initial todo", checked: false }, 13 | { id: uid++, text: "Learn about Web Components", checked: true } 14 | ] }); 15 | return <> 16 | 17 |

    Solid Todo

    18 |
    19 | 20 | setState('list', l => [...l, { id: uid++, text, checked: false }]) 21 | }/> 22 |
      setState('list', state.list.findIndex(t => t.id === id), { checked })} 24 | onRemove={(e, id) => setState('list', l => l.filter(t => t.id !== id))} 25 | > 26 | <$ each={ state.list }>{ item => 27 | 32 | } 33 |
    34 |
    35 | 36 | } 37 | 38 | Component('my-todo', MyTodo); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # web-components-todo 2 | 3 | Comparison on how to update DOM, pass attributes/properties and dispatch/listen to events with Web Components 4 | 5 | ![todo](https://user-images.githubusercontent.com/1388706/36195203-098d39ea-116d-11e8-8573-5c19cab826e0.gif) 6 | 7 | ## Demos 8 | 9 | * [Native Web Component](https://wc-todo.firebaseapp.com/native) 10 | * [Lit-Element](https://wc-todo.firebaseapp.com/lit-element-2.1/) 11 | * [Stencil](https://wc-todo.firebaseapp.com/stencil-0.16/) 12 | * [Slim.js](https://wc-todo.firebaseapp.com/slimjs) 13 | * [SkateJS + Lit-Html](https://wc-todo.firebaseapp.com/skatejs-lit-html) 14 | * [SkateJS + Preact](https://wc-todo.firebaseapp.com/skatejs-preact) 15 | * [Svelte](https://wc-todo.firebaseapp.com/svelte/) 16 | * [Solid](https://wc-todo.firebaseapp.com/solid/) 17 | * [Functional-element](https://wc-todo.firebaseapp.com/functional-element/) 18 | * [Angular Elements](https://wc-todo.firebaseapp.com/angular-elements) 19 | * [Vue Web Component Wrapper](https://wc-todo.firebaseapp.com/vue) 20 | * [Polymer 2](https://wc-todo.firebaseapp.com/polymer2) 21 | * [Polymer 3](https://wc-todo.firebaseapp.com/polymer3) 22 | 23 | ## syntax differences 24 | 25 | ![stencil_vs_wc](https://user-images.githubusercontent.com/1084459/45477634-a6480200-b74a-11e8-8b57-c96026896c89.png) 26 | -------------------------------------------------------------------------------- /stencil-0.11/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@stencil/starter", 3 | "private": true, 4 | "version": "0.0.1", 5 | "description": "Stencil App Starter", 6 | "scripts": { 7 | "build": "DEMO_BASE_URL=/stencil-0.11 stencil build", 8 | "build:prerendered": "DEMO_BASE_URL=/stencil-prerendered stencil build --prerender", 9 | "start": "stencil build --dev --watch --serve", 10 | "test": "jest", 11 | "test.watch": "jest --watch" 12 | }, 13 | "dependencies": { 14 | "@stencil/core": "^0.11.0", 15 | "@stencil/router": "^0.2.5" 16 | }, 17 | "devDependencies": { 18 | "@types/jest": "^23.3.1", 19 | "jest": "^23.4.2" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "git+https://github.com/ionic-team/stencil-app-starter.git" 24 | }, 25 | "author": "Ionic Team", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/ionic-team/stencil" 29 | }, 30 | "homepage": "https://github.com/ionic-team/stencil", 31 | "jest": { 32 | "transform": { 33 | "^.+\\.(ts|tsx)$": "/node_modules/@stencil/core/testing/jest.preprocessor.js" 34 | }, 35 | "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(tsx?|jsx?)$", 36 | "moduleFileExtensions": [ 37 | "ts", 38 | "tsx", 39 | "js", 40 | "json", 41 | "jsx" 42 | ] 43 | } 44 | } -------------------------------------------------------------------------------- /polymer3/src/todo-item.js: -------------------------------------------------------------------------------- 1 | import { 2 | Element as PolymerElement 3 | } 4 | from '../node_modules/@polymer/polymer/polymer-element.js'; 5 | 6 | import './todo-item-styles.js'; 7 | 8 | export class TodoItem extends PolymerElement { 9 | static get is() { 10 | return 'todo-item'; 11 | } 12 | static get template() { 13 | return ` 14 | 15 |
  • 16 | 17 | 18 | 19 |
  • 20 | ` 21 | } 22 | static get properties() { 23 | return { 24 | checked: { type: Boolean }, 25 | index: { type: Number }, 26 | text: { type: String } 27 | } 28 | } 29 | handleOnRemove(e) { 30 | this.dispatchEvent(new CustomEvent('remove', { detail: this.index })); 31 | } 32 | handleOnToggle(e){ 33 | this.dispatchEvent(new CustomEvent('toggle', { detail: this.index })); 34 | } 35 | isCompleted(completed) { 36 | return completed ? 'completed' : ''; 37 | } 38 | } 39 | 40 | customElements.define(TodoItem.is, TodoItem); 41 | -------------------------------------------------------------------------------- /svelte/src/components/TodoInput.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
    4 | 5 | 36 | 37 | -------------------------------------------------------------------------------- /non-web-components-refs/angular/src/app/todo-input/todo-input.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-todo-input', 5 | styles: [` 6 | form { 7 | position: relative; 8 | font-size: 24px; 9 | border-bottom: 1px solid #ededed; 10 | } 11 | 12 | input[type=text] { 13 | padding: 16px 16px 16px 60px; 14 | border: none; 15 | background: rgba(0, 0, 0, 0.003); 16 | position: relative; 17 | margin: 0; 18 | width: 100%; 19 | font-size: 24px; 20 | font-family: inherit; 21 | font-weight: inherit; 22 | line-height: 1.4em; 23 | border: 0; 24 | outline: none; 25 | color: inherit; 26 | padding: 6px; 27 | border: 1px solid #CCC; 28 | box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); 29 | box-sizing: border-box; 30 | } 31 | `], 32 | template: ` 33 |
    34 | 35 |
    36 | `, 37 | changeDetection: ChangeDetectionStrategy.OnPush, 38 | }) 39 | export class TodoInputComponent { 40 | text: string; 41 | @Output() newTodo: EventEmitter = new EventEmitter(); 42 | 43 | onSubmit(e) { 44 | this.newTodo.emit(this.text); 45 | this.text = ''; 46 | } 47 | 48 | } 49 | 50 | -------------------------------------------------------------------------------- /polymer3/src/todo-input.js: -------------------------------------------------------------------------------- 1 | import { 2 | Element as PolymerElement 3 | } 4 | from '../node_modules/@polymer/polymer/polymer-element.js'; 5 | 6 | import '../node_modules/@polymer/iron-form/iron-form.js'; 7 | import '../node_modules/@polymer/iron-input/iron-input.js'; 8 | 9 | import './todo-input-styles.js'; 10 | 11 | export class TodoInput extends PolymerElement { 12 | 13 | static get is() { 14 | return 'todo-input'; 15 | } 16 | 17 | static get template() { 18 | return ` 19 | 20 | 21 |
    22 | 23 | 24 | 25 |
    26 |
    27 | ` 28 | } 29 | 30 | static get properties() { 31 | return { 32 | text: { 33 | type: String, 34 | value: '' 35 | } 36 | } 37 | } 38 | 39 | ready() { 40 | super.ready(); 41 | this.$form = this.shadowRoot.querySelector('iron-form'); 42 | this.$form.addEventListener('iron-form-submit', (e) => { 43 | if (!this.text) return; 44 | this.dispatchEvent(new CustomEvent('onSubmit', { detail: this.text })); 45 | this.text = ''; 46 | }); 47 | } 48 | } 49 | 50 | customElements.define(TodoInput.is, TodoInput); -------------------------------------------------------------------------------- /nightwatch.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_folders": [ 3 | "tests/suite" 4 | ], 5 | "output_folder": ".e2e-results", 6 | "custom_commands_path": "./tests/commands", 7 | "custom_assertions_path": "", 8 | "page_objects_path": "", 9 | "globals_path": "", 10 | "live_output": true, 11 | "selenium": { 12 | "start_process": true, 13 | "server_path": "./node_modules/selenium-server-standalone-jar/jar/selenium-server-standalone-3.8.1.jar", 14 | "log_path": "", 15 | "port": 4444, 16 | "cli_args": { 17 | "webdriver.chrome.driver": "", 18 | "webdriver.gecko.driver": "", 19 | "webdriver.edge.driver": "" 20 | } 21 | }, 22 | "test_settings": { 23 | "default": { 24 | "selenium_port": 4444, 25 | "selenium_host": "localhost", 26 | "silent": true, 27 | "screenshots": { 28 | "enabled": false, 29 | "path": "" 30 | }, 31 | "desiredCapabilities": { 32 | "browserName": "chrome", 33 | "javascriptEnabled": true, 34 | "acceptSslCerts": true, 35 | "marionette": true, 36 | "chromeOptions": { 37 | "args": [ 38 | "disable-web-security", 39 | "ignore-certificate-errors", 40 | "no-sandbox" 41 | ] 42 | } 43 | } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /lit-element-0.6/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Native Web Component Todo 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 40 | 41 | 42 | 43 | 44 | ⬅ Back to other implementations 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /lit-element-2.1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Native Web Component Todo 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 40 | 41 | 42 | 43 | 44 | ⬅ Back to other implementations 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /non-web-components-refs/angular/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Angular Todo list 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 40 | 41 | 42 | 43 | 44 | ⬅ Back to other implementations 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /non-web-components-refs/angular/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build --prod --configuration=production", 8 | "test": "ng test", 9 | "lint": "ng lint", 10 | "e2e": "ng e2e" 11 | }, 12 | "private": true, 13 | "dependencies": { 14 | "@angular/animations": "^6.1.0", 15 | "@angular/common": "^6.1.0", 16 | "@angular/compiler": "^6.1.0", 17 | "@angular/core": "^6.1.0", 18 | "@angular/forms": "^6.1.0", 19 | "@angular/http": "^6.1.0", 20 | "@angular/platform-browser": "^6.1.0", 21 | "@angular/platform-browser-dynamic": "^6.1.0", 22 | "@angular/router": "^6.1.0", 23 | "core-js": "^2.5.4", 24 | "rxjs": "~6.2.0", 25 | "zone.js": "~0.8.26" 26 | }, 27 | "devDependencies": { 28 | "@angular-devkit/build-angular": "~0.8.0", 29 | "@angular/cli": "~6.2.2", 30 | "@angular/compiler-cli": "^6.1.0", 31 | "@angular/language-service": "^6.1.0", 32 | "@types/jasmine": "~2.8.8", 33 | "@types/jasminewd2": "~2.0.3", 34 | "@types/node": "~8.9.4", 35 | "codelyzer": "~4.3.0", 36 | "jasmine-core": "~2.99.1", 37 | "jasmine-spec-reporter": "~4.2.1", 38 | "karma": "~3.0.0", 39 | "karma-chrome-launcher": "~2.2.0", 40 | "karma-coverage-istanbul-reporter": "~2.0.1", 41 | "karma-jasmine": "~1.1.2", 42 | "karma-jasmine-html-reporter": "^0.2.2", 43 | "protractor": "~5.4.0", 44 | "ts-node": "~7.0.0", 45 | "tslint": "~5.11.0", 46 | "typescript": "~2.9.2" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /svelte/README.md: -------------------------------------------------------------------------------- 1 | # svelte app 2 | 3 | This is a project template for [Svelte](https://svelte.technology) apps. It lives at https://github.com/sveltejs/template-custom-element. 4 | 5 | To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit): 6 | 7 | ```bash 8 | npm install -g degit # you only need to do this once 9 | 10 | degit sveltejs/template-custom-element svelte-app 11 | cd svelte-app 12 | ``` 13 | 14 | *Note that you will need to have [Node.js](https://nodejs.org) installed.* 15 | 16 | 17 | ## Get started 18 | 19 | Install the dependencies... 20 | 21 | ```bash 22 | cd svelte-app 23 | npm install 24 | ``` 25 | 26 | ...then start [Rollup](https://rollupjs.org): 27 | 28 | ```bash 29 | npm run dev 30 | ``` 31 | 32 | Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes. 33 | 34 | 35 | ## Deploying to the web 36 | 37 | ### With [now](https://zeit.co/now) 38 | 39 | Install `now` if you haven't already: 40 | 41 | ```bash 42 | npm install -g now 43 | ``` 44 | 45 | Then, from within your project folder: 46 | 47 | ```bash 48 | now 49 | ``` 50 | 51 | As an alternative, use the [Now desktop client](https://zeit.co/download) and simply drag the unzipped project folder to the taskbar icon. 52 | 53 | ### With [surge](https://surge.sh/) 54 | 55 | Install `surge` if you haven't already: 56 | 57 | ```bash 58 | npm install -g surge 59 | ``` 60 | 61 | Then, from within your project folder: 62 | 63 | ```bash 64 | npm run build 65 | surge public 66 | ``` 67 | -------------------------------------------------------------------------------- /functional-element/src/todo-input.js: -------------------------------------------------------------------------------- 1 | import { customElement, html } from 'functional-element'; 2 | 3 | customElement('todo-input', ({ element }) => { 4 | return html` 5 | 32 | 33 |
    onSubmit(e, element)}> 34 | 35 |
    36 | `; 37 | }); 38 | 39 | function onSubmit(e, element) { 40 | const $input = element.querySelector('input'); 41 | e.stopPropagation(); 42 | e.preventDefault(); 43 | if (!$input.value) return; 44 | element.dispatchEvent(new CustomEvent('submit', { detail: $input.value })); 45 | $input.value = ''; 46 | } -------------------------------------------------------------------------------- /stencil-0.16/readme.md: -------------------------------------------------------------------------------- 1 | # Stencil App Starter 2 | 3 | Stencil is a compiler for building fast web apps using Web Components. 4 | 5 | Stencil combines the best concepts of the most popular frontend frameworks into a compile-time rather than run-time tool. Stencil takes TypeScript, JSX, a tiny virtual DOM layer, efficient one-way data binding, an asynchronous rendering pipeline (similar to React Fiber), and lazy-loading out of the box, and generates 100% standards-based Web Components that run in any browser supporting the Custom Elements v1 spec. 6 | 7 | Stencil components are just Web Components, so they work in any major framework or with no framework at all. In many cases, Stencil can be used as a drop in replacement for traditional frontend frameworks given the capabilities now available in the browser, though using it as such is certainly not required. 8 | 9 | Stencil also enables a number of key capabilities on top of Web Components, in particular Server Side Rendering (SSR) without the need to run a headless browser, pre-rendering, and objects-as-properties (instead of just strings). 10 | 11 | ## Getting Started 12 | 13 | To start a new project using Stencil, clone this repo to a new directory: 14 | 15 | ```bash 16 | npm init stencil app 17 | ``` 18 | 19 | and run: 20 | 21 | ```bash 22 | npm start 23 | ``` 24 | 25 | To build the app for production, run: 26 | 27 | ```bash 28 | npm run build 29 | ``` 30 | 31 | To run the unit tests once, run: 32 | 33 | ``` 34 | npm test 35 | ``` 36 | 37 | To run the unit tests and watch for file changes during development, run: 38 | 39 | ``` 40 | npm run test.watch 41 | ``` 42 | -------------------------------------------------------------------------------- /stencil-0.11/src/components/my-todo/my-todo.tsx: -------------------------------------------------------------------------------- 1 | import { Component, State, Listen } from '@stencil/core'; 2 | 3 | interface TodoItem { 4 | text: string; 5 | checked: boolean; 6 | } 7 | 8 | @Component({ 9 | tag: 'my-todo', 10 | styleUrl: 'my-todo.css', 11 | // shadow: true, 12 | }) 13 | export class MyTodo { 14 | @State() list: TodoItem[] = [ 15 | { text: 'my initial todo', checked: false }, 16 | { text: 'Learn about Web Components', checked: true } 17 | ]; 18 | 19 | @Listen('onTodoInputSubmit') 20 | todoInputSubmiHandler(e: CustomEvent) { 21 | this.list = [...this.list, { text: e.detail, checked: false, }]; 22 | } 23 | 24 | @Listen('onTodoItemChecked') 25 | todoItemCheckedHandler(e: CustomEvent) { 26 | const list = [...this.list]; 27 | const item = list[e.detail]; 28 | list[e.detail] = Object.assign({}, item, { checked: !item.checked }); 29 | this.list = list; 30 | } 31 | 32 | @Listen('onTodoItemRemove') 33 | todoItemRemoveHandler(e: CustomEvent) { 34 | this.list = [...this.list.slice(0, e.detail), ...this.list.slice(e.detail + 1)]; 35 | } 36 | 37 | render() { 38 | return ( 39 |
    40 |

    Todos Stencil

    41 |
    42 | 43 |
      44 | {this.list.map((item, index) => ( 45 | 50 | ))} 51 |
    52 |
    53 |
    54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /stencil-0.16/src/components/my-todo/my-todo.tsx: -------------------------------------------------------------------------------- 1 | import { Component, State, Listen } from '@stencil/core'; 2 | 3 | interface TodoItem { 4 | text: string; 5 | checked: boolean; 6 | } 7 | 8 | @Component({ 9 | tag: 'my-todo', 10 | styleUrl: 'my-todo.css', 11 | // shadow: true, 12 | }) 13 | export class MyTodo { 14 | @State() list: TodoItem[] = [ 15 | { text: 'my initial todo', checked: false }, 16 | { text: 'Learn about Web Components', checked: true } 17 | ]; 18 | 19 | @Listen('onTodoInputSubmit') 20 | todoInputSubmiHandler(e: CustomEvent) { 21 | this.list = [...this.list, { text: e.detail, checked: false, }]; 22 | } 23 | 24 | @Listen('onTodoItemChecked') 25 | todoItemCheckedHandler(e: CustomEvent) { 26 | const list = [...this.list]; 27 | const item = list[e.detail]; 28 | list[e.detail] = Object.assign({}, item, { checked: !item.checked }); 29 | this.list = list; 30 | } 31 | 32 | @Listen('onTodoItemRemove') 33 | todoItemRemoveHandler(e: CustomEvent) { 34 | this.list = [...this.list.slice(0, e.detail), ...this.list.slice(e.detail + 1)]; 35 | } 36 | 37 | render() { 38 | return ( 39 |
    40 |

    Todos Stencil

    41 |
    42 | 43 |
      44 | {this.list.map((item, index) => ( 45 | 50 | ))} 51 |
    52 |
    53 |
    54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /polymer3/src/my-todo.js: -------------------------------------------------------------------------------- 1 | import { 2 | Element as PolymerElement 3 | } 4 | from '../node_modules/@polymer/polymer/polymer-element.js'; 5 | 6 | import './my-todo-styles.js'; 7 | 8 | export class MyTodo extends PolymerElement { 9 | 10 | static get is() { return 'my-todo'; } 11 | 12 | static get template() { 13 | return ` 14 | 15 |

    Todos Polymer 3

    16 |
    17 | 18 |
      19 | 22 |
    23 |
    24 | ` 25 | } 26 | 27 | static get properties() { 28 | return { 29 | list: { 30 | type: Array, 31 | value: () => [ 32 | { text: 'my initial todo', checked: false }, 33 | { text: 'Learn about Web Components', checked: true } 34 | ] 35 | } 36 | } 37 | } 38 | 39 | ready() { 40 | super.ready(); 41 | this.$input = this.shadowRoot.querySelector('todo-input'); 42 | this.$input.addEventListener('onSubmit', this.addItem.bind(this)); 43 | } 44 | 45 | addItem(e) { 46 | this.push('list', { text: e.detail, checked: false }); 47 | } 48 | 49 | removeItem(e) { 50 | this.splice('list', e.detail, 1); 51 | } 52 | 53 | toggleItem(e) { 54 | this.set('list.'+e.detail, { ...this.list[e.detail], checked: !this.list[e.detail].checked }); 55 | } 56 | } 57 | 58 | customElements.define(MyTodo.is, MyTodo); 59 | -------------------------------------------------------------------------------- /functional-element/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Functional Element 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 40 | 41 | 42 | 43 | ⬅ Back to other implementations 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /functional-element/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Functional Element 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 40 | 41 | 42 | 43 | ⬅ Back to other implementations 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /stencil-0.11/readme.md: -------------------------------------------------------------------------------- 1 | # Stencil App Starter 2 | 3 | Stencil is a compiler for building fast web apps using Web Components. 4 | 5 | Stencil combines the best concepts of the most popular frontend frameworks into a compile-time rather than run-time tool. Stencil takes TypeScript, JSX, a tiny virtual DOM layer, efficient one-way data binding, an asynchronous rendering pipeline (similar to React Fiber), and lazy-loading out of the box, and generates 100% standards-based Web Components that run in any browser supporting the Custom Elements v1 spec. 6 | 7 | Stencil components are just Web Components, so they work in any major framework or with no framework at all. In many cases, Stencil can be used as a drop in replacement for traditional frontend frameworks given the capabilities now available in the browser, though using it as such is certainly not required. 8 | 9 | Stencil also enables a number of key capabilities on top of Web Components, in particular Server Side Rendering (SSR) without the need to run a headless browser, pre-rendering, and objects-as-properties (instead of just strings). 10 | 11 | ## Getting Started 12 | 13 | To start a new project using Stencil, clone this repo to a new directory: 14 | 15 | ```bash 16 | git clone https://github.com/ionic-team/stencil-starter.git my-app 17 | cd my-app 18 | git remote rm origin 19 | ``` 20 | 21 | and run: 22 | 23 | ```bash 24 | npm install 25 | npm start 26 | ``` 27 | 28 | To build the app for production, run: 29 | 30 | ```bash 31 | npm run build 32 | ``` 33 | 34 | To run the unit tests once, run: 35 | 36 | ``` 37 | npm test 38 | ``` 39 | 40 | To run the unit tests and watch for file changes during development, run: 41 | 42 | ``` 43 | npm run test.watch 44 | ``` 45 | -------------------------------------------------------------------------------- /lit-element-2.1/src/todo-input.js: -------------------------------------------------------------------------------- 1 | import { LitElement, html } from 'lit-element'; 2 | 3 | export default class TodoInput extends LitElement { 4 | constructor() { 5 | super(); 6 | this.onSubmit = this.onSubmit.bind(this); 7 | } 8 | 9 | onSubmit(e) { 10 | const $input = this.shadowRoot.querySelector('input'); 11 | e.preventDefault(); 12 | if (!$input.value) return; 13 | this.dispatchEvent(new CustomEvent('submit', { detail: $input.value })); 14 | $input.value = ''; 15 | } 16 | 17 | render(props) { 18 | return html` 19 | 46 |
    47 | 48 |
    49 | `; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lit-element-0.6/src/todo-input.js: -------------------------------------------------------------------------------- 1 | import { LitElement, html } from '@polymer/lit-element'; 2 | 3 | export default class TodoInput extends LitElement { 4 | constructor() { 5 | super(); 6 | this.onSubmit = this.onSubmit.bind(this); 7 | } 8 | 9 | onSubmit(e) { 10 | const $input = this.shadowRoot.querySelector('input'); 11 | e.preventDefault(); 12 | if (!$input.value) return; 13 | this.dispatchEvent(new CustomEvent('submit', { detail: $input.value })); 14 | $input.value = ''; 15 | } 16 | 17 | render(props) { 18 | return html` 19 | 46 |
    47 | 48 |
    49 | `; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /vue/src/components/my-todo.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 40 | 41 | 66 | -------------------------------------------------------------------------------- /svelte/src/components/MyTodo.html: -------------------------------------------------------------------------------- 1 |

    Todos Svelte

    2 |
    3 | 4 |
      5 | {#each list as item, index (item.id)} 6 | 11 | {/each} 12 |
    13 |
    14 | 15 | 41 | 42 | -------------------------------------------------------------------------------- /skatejs-lit-html/src/input.js: -------------------------------------------------------------------------------- 1 | import { props } from "skatejs/dist/esnext"; 2 | import { html } from "lit-html/lib/lit-extended"; 3 | import { Component } from "./util"; 4 | 5 | export default class extends Component { 6 | static events = ["submit"]; 7 | state = { 8 | value: "" 9 | }; 10 | 11 | handleInput = e => { 12 | this.state = { value: e.target.value }; 13 | }; 14 | handleSubmit = e => { 15 | e.preventDefault(); 16 | if (!this.state.value) return; 17 | this.onSubmit({ value: this.state.value }); 18 | this.state = { value: "" }; 19 | }; 20 | 21 | render({ handleInput, handleSubmit }) { 22 | return html` 23 | 54 |
    55 | 61 |
    62 | `; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /non-web-components-refs/react/src/components/my-todo/my-todo.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import './my-todo.css'; 4 | import TodoInput from '../todo-input/todo-input'; 5 | import TodoItem from '../todo-item/todo-item'; 6 | 7 | class MyTodo extends Component { 8 | state = { 9 | list: [ 10 | { text: 'my initial todo', checked: false }, 11 | { text: 'Learn about Web Components', checked: true } 12 | ], 13 | } 14 | 15 | handleOnTodoInputSubmit = (text) => { 16 | this.setState({ list: [...this.state.list, { text, checked: false, }] }); 17 | } 18 | 19 | handleOnTodoItemChecked = (index) => { 20 | const { list } = this.state; 21 | const newList = [...list]; 22 | const item = newList[index]; 23 | newList[index] = Object.assign({}, item, { checked: !item.checked }); 24 | this.setState({ list: newList }); 25 | } 26 | 27 | handleOnTodoItemRemove = (index) => { 28 | const { list } = this.state; 29 | this.setState({ list: [...list.slice(0, index), ...list.slice(index + 1)] }); 30 | } 31 | 32 | render() { 33 | return ( 34 |
    35 |

    Todos React

    36 |
    37 | 38 |
      39 | {this.state.list.map((item, index) => ( 40 | 48 | ))} 49 |
    50 |
    51 |
    52 | ); 53 | } 54 | } 55 | 56 | export default MyTodo; 57 | -------------------------------------------------------------------------------- /skatejs-preact/src/util.js: -------------------------------------------------------------------------------- 1 | import { emit, withComponent } from "skatejs/dist/esnext"; 2 | import withRenderer from "@skatejs/renderer-preact/dist/esnext"; 3 | 4 | // Mixin for auto-defining functions that emit events. 5 | const withEvents = (Base = HTMLElement) => 6 | class extends Base { 7 | // Since observedAttributes are called only once, we can use that as a hook 8 | // to do any one-time setup we need upon definition. 9 | static get observedAttributes() { 10 | (this.events || []).forEach(e => { 11 | const name = `on${e[0].toUpperCase() + e.substring(1)}`; 12 | 13 | // Allows the following for the consumer: 14 | // 15 | // - elem.onEvent = fn 16 | // - elem.addEventListener('event', fn) 17 | // 18 | // Allows the following for the author: 19 | // 20 | // - this.onEvent(detail) 21 | Object.defineProperty(this.prototype, name, { 22 | get() { 23 | if (!this.__events[e]) { 24 | this[name] = () => {}; 25 | } 26 | return this.__events[e]; 27 | }, 28 | set(fn) { 29 | this.__events[e] = detail => { 30 | fn(detail); 31 | emit(this, e, { detail }); 32 | }; 33 | if (this.triggerUpdate) { 34 | this.triggerUpdate(); 35 | } 36 | } 37 | }); 38 | }); 39 | return super.observedAttributes; 40 | } 41 | __events = {}; 42 | }; 43 | 44 | // We must mixin in this order because withComponent() doesn't yet call super 45 | // on observedAttributes. This means that observedAttributes from the 46 | // withEvents() mixin wouldn't get called. This will be fixed in the next 47 | // version of Skate. 48 | export const Component = withEvents(withComponent(withRenderer())); 49 | -------------------------------------------------------------------------------- /skatejs-lit-html/src/util.js: -------------------------------------------------------------------------------- 1 | import { emit, withComponent } from "skatejs/dist/esnext"; 2 | import withRenderer from "@skatejs/renderer-lit-html/dist/esnext"; 3 | 4 | // Mixin for auto-defining functions that emit events. 5 | const withEvents = (Base = HTMLElement) => 6 | class extends Base { 7 | // Since observedAttributes are called only once, we can use that as a hook 8 | // to do any one-time setup we need upon definition. 9 | static get observedAttributes() { 10 | (this.events || []).forEach(e => { 11 | const name = `on${e[0].toUpperCase() + e.substring(1)}`; 12 | 13 | // Allows the following for the consumer: 14 | // 15 | // - elem.onEvent = fn 16 | // - elem.addEventListener('event', fn) 17 | // 18 | // Allows the following for the author: 19 | // 20 | // - this.onEvent(detail) 21 | Object.defineProperty(this.prototype, name, { 22 | get() { 23 | if (!this.__events[e]) { 24 | this[name] = () => {}; 25 | } 26 | return this.__events[e]; 27 | }, 28 | set(fn) { 29 | this.__events[e] = detail => { 30 | fn(detail); 31 | emit(this, e, { detail }); 32 | }; 33 | if (this.triggerUpdate) { 34 | this.triggerUpdate(); 35 | } 36 | } 37 | }); 38 | }); 39 | return super.observedAttributes; 40 | } 41 | __events = {}; 42 | }; 43 | 44 | // We must mixin in this order because withComponent() doesn't yet call super 45 | // on observedAttributes. This means that observedAttributes from the 46 | // withEvents() mixin wouldn't get called. This will be fixed in the next 47 | // version of Skate. 48 | export const Component = withEvents(withComponent(withRenderer())); 49 | -------------------------------------------------------------------------------- /non-web-components-refs/react/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 22 | React App 23 | 24 | 25 | 28 | ⬅ Back to other implementations 29 |
    30 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /non-web-components-refs/vue/src/components/my-todo.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 45 | 46 | 72 | -------------------------------------------------------------------------------- /polymer2/test/my-todo/my-todo_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | my-todo test 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /non-web-components-refs/angular/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ChangeDetectionStrategy } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | changeDetection: ChangeDetectionStrategy.OnPush, 6 | template: ` 7 |

    Todos Angular

    8 |
    9 | 10 | 17 |
      18 |
      19 | `, 20 | styles: [` 21 | h1 { 22 | font-size: 70px; 23 | line-height: 70px; 24 | font-weight: 100; 25 | text-align: center; 26 | color: rgba(175, 47, 47, 0.15); 27 | } 28 | 29 | section { 30 | background: #fff; 31 | margin: 30px 0 40px 0; 32 | position: relative; 33 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1); 34 | } 35 | 36 | #list-container { 37 | margin: 0; 38 | padding: 0; 39 | list-style: none; 40 | border-top: 1px solid #e6e6e6; 41 | } 42 | ` ] 43 | }) 44 | export class AppComponent { 45 | list = [ 46 | { text: 'my initial todo', checked: false }, 47 | { text: 'Learn about Web Components', checked: true }, 48 | ] 49 | 50 | addItem(text) { 51 | this.list = [...this.list, { text, checked: false, }]; 52 | } 53 | 54 | removeItem(index) { 55 | this.list = [...this.list.slice(0, index), ...this.list.slice(index + 1)]; 56 | } 57 | 58 | toggleItem(index) { 59 | const list = [...this.list]; 60 | const item = list[index]; 61 | list[index] = Object.assign({}, item, { checked: !item.checked }); 62 | this.list = list; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /atomico/rollup.config.js: -------------------------------------------------------------------------------- 1 | import buble from "rollup-plugin-buble"; 2 | import resolve from "rollup-plugin-node-resolve"; 3 | import { terser } from "rollup-plugin-terser"; 4 | import commonjs from "rollup-plugin-commonjs"; 5 | import filesize from "rollup-plugin-filesize"; 6 | import pkg from "./package.json"; 7 | import colors from "colors"; 8 | import prepare from "rollup-prepare"; 9 | import postcss from "rollup-plugin-postcss"; 10 | import copy from 'rollup-plugin-copy'; 11 | import cssnano from "cssnano"; 12 | 13 | export default { 14 | ...prepare({ 15 | pkg 16 | }), 17 | plugins: plugins(false) 18 | }; 19 | 20 | /** 21 | * Returns the generic plugins to be used for packaging 22 | * @param {boolean} classes - lets you disable the transformation of classes 23 | * @return {Array} 24 | */ 25 | function plugins(classes = true) { 26 | return [ 27 | commonjs({ 28 | include: "node_modules/**" 29 | }), 30 | resolve(), 31 | postcss({ 32 | plugins: [cssnano] 33 | }), 34 | buble({ 35 | jsx: "h", 36 | transforms: { 37 | classes 38 | }, 39 | objectAssign: "Object.assign" 40 | }), 41 | terser(), 42 | copy({ 43 | "node_modules/atomico/dist/atomico.umd.js": "public/atomico.umd.js", 44 | verbose: true 45 | }), 46 | filesize({ 47 | /** 48 | * allows to generate the printing of the output size of each file 49 | */ 50 | render(options, size, gzip, brotliSize, minifiedSize, bundle) { 51 | let title = colors.cyan.bold, 52 | value = colors.yellow; 53 | return `${title(bundle.file)} Min: ${value( 54 | size 55 | )} Gzip: ${value(gzip)}`; 56 | } 57 | }) 58 | ]; 59 | } 60 | -------------------------------------------------------------------------------- /skatejs-preact/src/input.js: -------------------------------------------------------------------------------- 1 | // @jsx h 2 | 3 | import { props } from "skatejs/dist/esnext"; 4 | import { h } from "preact"; 5 | import { Component } from "./util"; 6 | 7 | export default class extends Component { 8 | static events = ["submit"]; 9 | state = { 10 | value: "" 11 | }; 12 | 13 | handleInput = e => { 14 | this.state = { value: e.target.value }; 15 | }; 16 | handleSubmit = e => { 17 | e.preventDefault(); 18 | if (!this.state.value) return; 19 | this.onSubmit({ value: this.state.value }); 20 | this.state = { value: "" }; 21 | }; 22 | 23 | render({ handleInput, handleSubmit }) { 24 | return ( 25 |
      26 | 57 |
      58 | 64 |
      65 |
      66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /benchmark/filesize.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const zlib = require('zlib'); 3 | const chart = require('ascii-horizontal-barchart') 4 | 5 | const filesize = () => projects.reduce((previous, project) => { 6 | previous[project.name] = project.paths.reduce((previous, current) => { 7 | const exists = fs.existsSync(`dist/${current}`); 8 | if (!exists) return undefined; 9 | return previous + fs.statSync(`/dist/${current}`).size 10 | }, 0); 11 | return previous; 12 | }, {}) 13 | 14 | 15 | // console.log(stats) 16 | // console.log(chart(filesize(), true, 30)) 17 | 18 | 19 | // Gzipped 20 | // const filesizeGzipped = (list) => list.reduce((previous, project) => { 21 | // previous[project.name] = project.paths.reduce((previous, current) => { 22 | // const exists = fs.existsSync(`dist/${current}`); 23 | // if (!exists) return undefined; 24 | // const fileContents = fs.readFileSync(`dist/${current}`) 25 | // const zippedContent = zlib.gzipSync(fileContents.toString()); 26 | // fs.writeFileSync(`dist/${current}.gzip`, zippedContent) 27 | // return previous + fs.statSync(`dist/${current}.gzip`).size 28 | // }, 0); 29 | // return previous; 30 | // }, {}); 31 | 32 | const filesizeGzipped = (list) => list.map(project => ({ 33 | ...project, 34 | size: project.paths.reduce((previous, current) => { 35 | const exists = fs.existsSync(`dist/${current}`); 36 | if (!exists) return undefined; 37 | const fileContents = fs.readFileSync(`dist/${current}`) 38 | const zippedContent = zlib.gzipSync(fileContents.toString()); 39 | fs.writeFileSync(`dist/${current}.gzip`, zippedContent) 40 | return previous + fs.statSync(`dist/${current}.gzip`).size 41 | }, 0), 42 | })).sort((a, b) => a.size - b.size); 43 | 44 | 45 | // console.log(filesizeGzipped()) 46 | // console.log(chart(filesizeGzipped(), true, 30)) 47 | 48 | module.exports = { 49 | filesize, 50 | filesizeGzipped 51 | } -------------------------------------------------------------------------------- /native-shadow-dom/src/todo-input.js: -------------------------------------------------------------------------------- 1 | const templateTodoInput = document.createElement('template'); 2 | templateTodoInput.innerHTML = ` 3 | 30 |
      31 | 32 |
      33 | `; 34 | 35 | export default class TodoInput extends HTMLElement { 36 | constructor() { 37 | super(); 38 | this._root = this.attachShadow({ 'mode': 'open' }); 39 | } 40 | 41 | connectedCallback() { 42 | console.log('TodoInput ADDED TO THE DOM'); 43 | this._root.appendChild(templateTodoInput.content.cloneNode(true)); 44 | this.$form = this._root.querySelector('form'); 45 | this.$input = this._root.querySelector('input'); 46 | this.$form.addEventListener("submit", (e) => { 47 | e.preventDefault(); 48 | if (!this.$input.value) return; 49 | this.dispatchEvent(new CustomEvent('onSubmit', { detail: this.$input.value })); 50 | this.$input.value = ''; 51 | }); 52 | } 53 | 54 | disconnectedCallback() { 55 | console.log('TodoInput REMOVED TO THE DOM'); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /angular-elements/src/todo-input.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Component, 3 | EventEmitter, 4 | Input, 5 | Output, 6 | ViewEncapsulation 7 | } from '@angular/core'; 8 | import { FormBuilder, FormGroup, Validators } from '@angular/forms'; 9 | 10 | @Component({ 11 | selector: 'todo-input', 12 | template: ` 13 |
      14 | 19 |
      20 | `, 21 | styles: [` 22 | :host { 23 | display: block; 24 | } 25 | form { 26 | position: relative; 27 | font-size: 24px; 28 | border-bottom: 1px solid #ededed; 29 | } 30 | input { 31 | padding: 16px 16px 16px 60px; 32 | border: none; 33 | background: rgba(0, 0, 0, 0.003); 34 | position: relative; 35 | margin: 0; 36 | width: 100%; 37 | font-size: 24px; 38 | font-family: inherit; 39 | font-weight: inherit; 40 | line-height: 1.4em; 41 | border: 0; 42 | outline: none; 43 | color: inherit; 44 | padding: 6px; 45 | border: 1px solid #CCC; 46 | box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); 47 | box-sizing: border-box; 48 | } 49 | `], 50 | encapsulation: ViewEncapsulation.Native 51 | }) 52 | export class TodoInput { 53 | @Output() onTodoInputSubmit = new EventEmitter(); 54 | inputForm: FormGroup; 55 | 56 | constructor( 57 | private formBuilder: FormBuilder, 58 | ) { 59 | this.inputForm = this.formBuilder.group({ 60 | 'text': ['', Validators.required], 61 | }); 62 | } 63 | 64 | handleOnSubmit(e) { 65 | if (!this.inputForm.value.text) return; 66 | this.onTodoInputSubmit.emit(this.inputForm.value.text); 67 | this.inputForm.reset(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /skatejs-lit-html/src/app.js: -------------------------------------------------------------------------------- 1 | import { props } from "skatejs/dist/esnext"; 2 | import { html } from "lit-html/lib/lit-extended"; 3 | import { Component } from "./util"; 4 | 5 | export default class extends Component { 6 | state = { 7 | list: [ 8 | { text: "my initial todo", checked: false }, 9 | { text: "Learn about Web Components", checked: true } 10 | ] 11 | }; 12 | 13 | handleCheck = e => { 14 | this.state.list[e.detail.index].checked = e.detail.value; 15 | this.state = this.state; 16 | }; 17 | handleRemove = e => { 18 | this.state = { 19 | list: this.state.list.filter((item, index) => index !== e.detail.index) 20 | }; 21 | }; 22 | handleSubmit = e => { 23 | this.state = { 24 | list: [...this.state.list, { text: e.detail.value, checked: false }] 25 | }; 26 | }; 27 | 28 | render({ handleCheck, handleRemove, handleSubmit }) { 29 | return html` 30 | 56 |

      SkateJS & lit-html

      57 |
      58 | 59 |
        60 | ${this.state.list.map( 61 | ({ checked, text }, index) => html` 62 | ${text} 68 | ` 69 | )} 70 |
      71 |
      72 | `; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /angular-elements/src/my-todo.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Component, 3 | ViewEncapsulation, 4 | } from '@angular/core'; 5 | 6 | interface TodoItem { 7 | text: string; 8 | checked: boolean; 9 | } 10 | 11 | @Component({ 12 | selector: 'my-todo', 13 | template: ` 14 |

      Todos Angular Elements

      15 |
      16 | 17 | 25 |
      26 | `, 27 | styles: [` 28 | h1 { 29 | font-size: 55px; 30 | font-weight: 100; 31 | text-align: center; 32 | color: rgba(175, 47, 47, 0.15); 33 | } 34 | 35 | section { 36 | background: #fff; 37 | margin: 30px 0 40px 0; 38 | position: relative; 39 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1); 40 | } 41 | 42 | #list-container { 43 | margin: 0; 44 | padding: 0; 45 | list-style: none; 46 | border-top: 1px solid #e6e6e6; 47 | } 48 | `], 49 | encapsulation: ViewEncapsulation.Native 50 | }) 51 | export class MyTodo { 52 | list: TodoItem[] = [ 53 | { text: 'my initial todo', checked: false }, 54 | { text: 'Learn about Web Components', checked: true } 55 | ]; 56 | 57 | todoInputSubmiHandler(e) { 58 | this.list = [...this.list, { text: e, checked: false, }]; 59 | } 60 | 61 | todoItemCheckedHandler(e, i) { 62 | const list = [...this.list]; 63 | const item = list[i]; 64 | list[i] = Object.assign({}, item, { checked: !item.checked }); 65 | this.list = list; 66 | } 67 | 68 | todoItemRemoveHandler(e, i) { 69 | this.list = [...this.list.slice(0, i), ...this.list.slice(i + 1)]; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /native/js/my-todo.js: -------------------------------------------------------------------------------- 1 | const templateTodo = document.createElement('template'); 2 | templateTodo.innerHTML = ` 3 |
      4 | 5 |
        6 |
        7 | `; 8 | 9 | class MyTodo extends HTMLElement { 10 | constructor() { 11 | super(); 12 | // Do not use shadow DOM to avoid problems when testing with selenium 13 | // this._root = this.attachShadow({ 'mode': 'open' }); 14 | // initial state 15 | this._list = [ 16 | { text: 'my initial todo', checked: false }, 17 | { text: 'Learn about Web Components', checked: true } 18 | ]; 19 | } 20 | 21 | connectedCallback() { 22 | this.appendChild(templateTodo.content.cloneNode(true)); 23 | this.$input = this.querySelector('todo-input'); 24 | this.$listContainer = this.querySelector('#list-container'); 25 | this.$input.addEventListener('onSubmit', this.addItem.bind(this)); 26 | this._render(); 27 | } 28 | 29 | addItem(e) { 30 | this._list.push({ text: e.detail, checked: false, }); 31 | this._render(); 32 | } 33 | 34 | removeItem(e) { 35 | this._list.splice(e.detail, 1); 36 | this._render(); 37 | } 38 | 39 | toggleItem(e) { 40 | const item = this._list[e.detail]; 41 | this._list[e.detail] = Object.assign({}, item, { 42 | checked: !item.checked 43 | }); 44 | this._render(); 45 | } 46 | 47 | disconnectedCallback() { } 48 | 49 | _render() { 50 | if (!this.$listContainer) return; 51 | // empty the list 52 | this.$listContainer.innerHTML = ''; 53 | this._list.forEach((item, index) => { 54 | let $item = document.createElement('todo-item'); 55 | $item.setAttribute('text', item.text); 56 | $item.checked = item.checked; 57 | $item.index = index; 58 | $item.addEventListener('onRemove', this.removeItem.bind(this)); 59 | $item.addEventListener('onToggle', this.toggleItem.bind(this)); 60 | this.$listContainer.appendChild($item); 61 | }); 62 | } 63 | } 64 | 65 | window.customElements.define('my-todo', MyTodo); 66 | -------------------------------------------------------------------------------- /skatejs-preact/src/app.js: -------------------------------------------------------------------------------- 1 | // @jsx h 2 | 3 | import { props } from "skatejs/dist/esnext"; 4 | import { h } from "preact"; 5 | import { Component } from "./util"; 6 | 7 | export default class extends Component { 8 | state = { 9 | list: [ 10 | { text: "my initial todo", checked: false }, 11 | { text: "Learn about Web Components", checked: true } 12 | ] 13 | }; 14 | 15 | handleCheck = e => { 16 | this.state.list[e.detail.index].checked = e.detail.value; 17 | this.state = this.state; 18 | }; 19 | handleRemove = e => { 20 | this.state = { 21 | list: this.state.list.filter((item, index) => index !== e.detail.index) 22 | }; 23 | }; 24 | handleSubmit = e => { 25 | this.state = { 26 | list: [...this.state.list, { text: e.detail.value, checked: false }] 27 | }; 28 | }; 29 | 30 | render({ handleCheck, handleRemove, handleSubmit }) { 31 | return ( 32 |
        33 | 59 |

        SkateJS & Preact

        60 |
        61 | 62 |
          63 | {this.state.list.map(({ checked, text }, index) => ( 64 | 70 | {text} 71 | 72 | ))} 73 |
        74 |
        75 |
        76 | ); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /polymer2/src/todo-input/todo-input.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 50 | 51 | 79 | -------------------------------------------------------------------------------- /solid/src/TodoItem.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | li { 6 | font-size: 24px; 7 | display: block; 8 | position: relative; 9 | border-bottom: 1px solid #ededed; 10 | } 11 | 12 | li input { 13 | text-align: center; 14 | width: 40px; 15 | /* auto, since non-WebKit browsers doesn't support input styling */ 16 | height: auto; 17 | position: absolute; 18 | top: 9px; 19 | bottom: 0; 20 | margin: auto 0; 21 | border: none; 22 | /* Mobile Safari */ 23 | -webkit-appearance: none; 24 | appearance: none; 25 | } 26 | 27 | li input:after { 28 | content: url('data:image/svg+xml;utf8,'); 29 | } 30 | 31 | li input:checked:after { 32 | content: url('data:image/svg+xml;utf8,'); 33 | } 34 | 35 | li label { 36 | white-space: pre; 37 | word-break: break-word; 38 | padding: 15px 60px 15px 15px; 39 | margin-left: 45px; 40 | display: block; 41 | line-height: 1.2; 42 | transition: color 0.4s; 43 | } 44 | 45 | li.completed label { 46 | color: #d9d9d9; 47 | text-decoration: line-through; 48 | } 49 | 50 | li button, 51 | li input[type="checkbox"] { 52 | outline: none; 53 | } 54 | 55 | li button { 56 | margin: 0; 57 | padding: 0; 58 | border: 0; 59 | background: none; 60 | font-size: 100%; 61 | vertical-align: baseline; 62 | font-family: inherit; 63 | font-weight: inherit; 64 | color: inherit; 65 | -webkit-appearance: none; 66 | appearance: none; 67 | -webkit-font-smoothing: antialiased; 68 | -moz-font-smoothing: antialiased; 69 | font-smoothing: antialiased; 70 | } 71 | 72 | li button { 73 | position: absolute; 74 | top: 0; 75 | right: 10px; 76 | bottom: 0; 77 | width: 40px; 78 | height: 40px; 79 | margin: auto 0; 80 | font-size: 30px; 81 | color: #cc9a9a; 82 | margin-bottom: 11px; 83 | transition: color 0.2s ease-out; 84 | } 85 | 86 | li button:hover { 87 | color: #af5b5e; 88 | } -------------------------------------------------------------------------------- /non-web-components-refs/react/src/components/todo-item/todo-item.css: -------------------------------------------------------------------------------- 1 | li { 2 | font-size: 24px; 3 | display: block; 4 | position: relative; 5 | border-bottom: 1px solid #ededed; 6 | } 7 | 8 | li input { 9 | text-align: center; 10 | width: 40px; 11 | /* auto, since non-WebKit browsers doesn't support input styling */ 12 | height: auto; 13 | position: absolute; 14 | top: 9px; 15 | bottom: 0; 16 | margin: auto 0; 17 | border: none; 18 | /* Mobile Safari */ 19 | -webkit-appearance: none; 20 | appearance: none; 21 | padding: 0; 22 | box-shadow: none; 23 | } 24 | 25 | li input:after { 26 | content: url('data:image/svg+xml;utf8,'); 27 | } 28 | 29 | li input:checked:after { 30 | content: url('data:image/svg+xml;utf8,'); 31 | } 32 | 33 | li label { 34 | white-space: pre; 35 | word-break: break-word; 36 | padding: 15px 60px 15px 15px; 37 | margin-left: 45px; 38 | display: block; 39 | line-height: 1.2; 40 | transition: color 0.4s; 41 | } 42 | 43 | li.completed label { 44 | color: #d9d9d9; 45 | text-decoration: line-through; 46 | } 47 | 48 | li button, li input[type="checkbox"] { 49 | outline: none; 50 | } 51 | 52 | li button { 53 | margin: 0; 54 | padding: 0; 55 | border: 0; 56 | background: none; 57 | font-size: 100%; 58 | vertical-align: baseline; 59 | font-family: inherit; 60 | font-weight: inherit; 61 | color: inherit; 62 | -webkit-appearance: none; 63 | appearance: none; 64 | -webkit-font-smoothing: antialiased; 65 | -moz-font-smoothing: antialiased; 66 | font-smoothing: antialiased; 67 | } 68 | 69 | li button { 70 | position: absolute; 71 | top: 0; 72 | right: 10px; 73 | bottom: 0; 74 | width: 40px; 75 | height: 40px; 76 | margin: auto 0; 77 | font-size: 30px; 78 | color: #cc9a9a; 79 | margin-bottom: 11px; 80 | transition: color 0.2s ease-out; 81 | } 82 | 83 | li button:hover { 84 | color: #af5b5e; 85 | } -------------------------------------------------------------------------------- /native/js/todo-item.js: -------------------------------------------------------------------------------- 1 | const templateTodoItem = document.createElement('template'); 2 | templateTodoItem.innerHTML = ` 3 |
      • 4 | 5 | 6 | 7 |
      • 8 | `; 9 | 10 | class TodoItem extends HTMLElement { 11 | constructor() { 12 | super(); 13 | // Do not use shadow DOM to avoid problems when testing with selenium 14 | // this._root = this.attachShadow({ 'mode': 'open' }); 15 | this._checked = false; 16 | this._text = ''; 17 | } 18 | 19 | connectedCallback() { 20 | this.appendChild(templateTodoItem.content.cloneNode(true)); 21 | this.$item = this.querySelector('.item'); 22 | this.$removeButton = this.querySelector('.destroy'); 23 | this.$text = this.querySelector('label'); 24 | this.$checkbox = this.querySelector('input'); 25 | this.$removeButton.addEventListener('click', (e) => { 26 | e.preventDefault(); 27 | this.dispatchEvent(new CustomEvent('onRemove', { detail: this.index })); 28 | }); 29 | this.$checkbox.addEventListener('click', (e) => { 30 | e.preventDefault(); 31 | this.dispatchEvent(new CustomEvent('onToggle', { detail: this.index })); 32 | }); 33 | this._render(); 34 | } 35 | 36 | disconnectedCallback() { } 37 | 38 | static get observedAttributes() { 39 | return ['text']; 40 | } 41 | attributeChangedCallback(name, oldValue, newValue) { 42 | this._text = newValue; 43 | } 44 | 45 | set index(value) { 46 | this._index = value; 47 | } 48 | 49 | get index() { 50 | return this._index; 51 | } 52 | 53 | set checked(value) { 54 | this._checked = Boolean(value); 55 | } 56 | 57 | get checked() { 58 | return this.hasAttribute('checked'); 59 | } 60 | 61 | _render() { 62 | if (!this.$item) return; 63 | this.$text.textContent = this._text; 64 | if (this._checked) { 65 | this.$item.classList.add('completed'); 66 | this.$checkbox.setAttribute('checked', ''); 67 | } else { 68 | this.$item.classList.remove('completed'); 69 | this.$checkbox.removeAttribute('checked'); 70 | } 71 | 72 | } 73 | } 74 | 75 | window.customElements.define('todo-item', TodoItem); 76 | -------------------------------------------------------------------------------- /slim-js/src/components/todo-item.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | li { 6 | font-size: 24px; 7 | display: block; 8 | position: relative; 9 | border-bottom: 1px solid #ededed; 10 | } 11 | 12 | li input { 13 | text-align: center; 14 | width: 40px; 15 | /* auto, since non-WebKit browsers doesn't support input styling */ 16 | height: auto; 17 | position: absolute; 18 | top: 9px; 19 | bottom: 0; 20 | margin: auto 0; 21 | border: none; 22 | /* Mobile Safari */ 23 | -webkit-appearance: none; 24 | appearance: none; 25 | padding: 0; 26 | box-shadow: none; 27 | } 28 | 29 | li input:after { 30 | content: url('data:image/svg+xml;utf8,'); 31 | } 32 | 33 | li input:checked:after { 34 | content: url('data:image/svg+xml;utf8,'); 35 | } 36 | 37 | li label { 38 | white-space: pre; 39 | word-break: break-word; 40 | padding: 15px 60px 15px 15px; 41 | margin-left: 45px; 42 | display: block; 43 | line-height: 1.2; 44 | transition: color 0.4s; 45 | } 46 | 47 | li.completed label { 48 | color: #d9d9d9; 49 | text-decoration: line-through; 50 | } 51 | 52 | li button, 53 | li input[type="checkbox"] { 54 | outline: none; 55 | } 56 | 57 | li button { 58 | margin: 0; 59 | padding: 0; 60 | border: 0; 61 | background: none; 62 | font-size: 100%; 63 | vertical-align: baseline; 64 | font-family: inherit; 65 | font-weight: inherit; 66 | color: inherit; 67 | -webkit-appearance: none; 68 | appearance: none; 69 | -webkit-font-smoothing: antialiased; 70 | -moz-font-smoothing: antialiased; 71 | font-smoothing: antialiased; 72 | } 73 | 74 | li button { 75 | position: absolute; 76 | top: 0; 77 | right: 10px; 78 | bottom: 0; 79 | width: 40px; 80 | height: 40px; 81 | margin: auto 0; 82 | font-size: 30px; 83 | color: #cc9a9a; 84 | margin-bottom: 11px; 85 | transition: color 0.2s ease-out; 86 | } 87 | 88 | li button:hover { 89 | color: #af5b5e; 90 | } -------------------------------------------------------------------------------- /stencil-0.11/src/components/todo-item/todo-item.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | li { 6 | font-size: 24px; 7 | display: block; 8 | position: relative; 9 | border-bottom: 1px solid #ededed; 10 | } 11 | 12 | li input { 13 | text-align: center; 14 | width: 40px; 15 | /* auto, since non-WebKit browsers doesn't support input styling */ 16 | height: auto; 17 | position: absolute; 18 | top: 9px; 19 | bottom: 0; 20 | margin: auto 0; 21 | border: none; 22 | /* Mobile Safari */ 23 | -webkit-appearance: none; 24 | appearance: none; 25 | padding: 0; 26 | box-shadow: none; 27 | } 28 | 29 | li input:after { 30 | content: url('data:image/svg+xml;utf8,'); 31 | } 32 | 33 | li input:checked:after { 34 | content: url('data:image/svg+xml;utf8,'); 35 | } 36 | 37 | li label { 38 | white-space: pre; 39 | word-break: break-word; 40 | padding: 15px 60px 15px 15px; 41 | margin-left: 45px; 42 | display: block; 43 | line-height: 1.2; 44 | transition: color 0.4s; 45 | } 46 | 47 | li.completed label { 48 | color: #d9d9d9; 49 | text-decoration: line-through; 50 | } 51 | 52 | li button, 53 | li input[type="checkbox"] { 54 | outline: none; 55 | } 56 | 57 | li button { 58 | margin: 0; 59 | padding: 0; 60 | border: 0; 61 | background: none; 62 | font-size: 100%; 63 | vertical-align: baseline; 64 | font-family: inherit; 65 | font-weight: inherit; 66 | color: inherit; 67 | -webkit-appearance: none; 68 | appearance: none; 69 | -webkit-font-smoothing: antialiased; 70 | -moz-font-smoothing: antialiased; 71 | font-smoothing: antialiased; 72 | } 73 | 74 | li button { 75 | position: absolute; 76 | top: 0; 77 | right: 10px; 78 | bottom: 0; 79 | width: 40px; 80 | height: 40px; 81 | margin: auto 0; 82 | font-size: 30px; 83 | color: #cc9a9a; 84 | margin-bottom: 11px; 85 | transition: color 0.2s ease-out; 86 | } 87 | 88 | li button:hover { 89 | color: #af5b5e; 90 | } 91 | -------------------------------------------------------------------------------- /stencil-0.16/src/components/todo-item/todo-item.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | li { 6 | font-size: 24px; 7 | display: block; 8 | position: relative; 9 | border-bottom: 1px solid #ededed; 10 | } 11 | 12 | li input { 13 | text-align: center; 14 | width: 40px; 15 | /* auto, since non-WebKit browsers doesn't support input styling */ 16 | height: auto; 17 | position: absolute; 18 | top: 9px; 19 | bottom: 0; 20 | margin: auto 0; 21 | border: none; 22 | /* Mobile Safari */ 23 | -webkit-appearance: none; 24 | appearance: none; 25 | padding: 0; 26 | box-shadow: none; 27 | } 28 | 29 | li input:after { 30 | content: url('data:image/svg+xml;utf8,'); 31 | } 32 | 33 | li input:checked:after { 34 | content: url('data:image/svg+xml;utf8,'); 35 | } 36 | 37 | li label { 38 | white-space: pre; 39 | word-break: break-word; 40 | padding: 15px 60px 15px 15px; 41 | margin-left: 45px; 42 | display: block; 43 | line-height: 1.2; 44 | transition: color 0.4s; 45 | } 46 | 47 | li.completed label { 48 | color: #d9d9d9; 49 | text-decoration: line-through; 50 | } 51 | 52 | li button, 53 | li input[type="checkbox"] { 54 | outline: none; 55 | } 56 | 57 | li button { 58 | margin: 0; 59 | padding: 0; 60 | border: 0; 61 | background: none; 62 | font-size: 100%; 63 | vertical-align: baseline; 64 | font-family: inherit; 65 | font-weight: inherit; 66 | color: inherit; 67 | -webkit-appearance: none; 68 | appearance: none; 69 | -webkit-font-smoothing: antialiased; 70 | -moz-font-smoothing: antialiased; 71 | font-smoothing: antialiased; 72 | } 73 | 74 | li button { 75 | position: absolute; 76 | top: 0; 77 | right: 10px; 78 | bottom: 0; 79 | width: 40px; 80 | height: 40px; 81 | margin: auto 0; 82 | font-size: 30px; 83 | color: #cc9a9a; 84 | margin-bottom: 11px; 85 | transition: color 0.2s ease-out; 86 | } 87 | 88 | li button:hover { 89 | color: #af5b5e; 90 | } 91 | -------------------------------------------------------------------------------- /functional-element/src/my-todo.js: -------------------------------------------------------------------------------- 1 | import { customElement, html } from 'functional-element'; 2 | import './todo-input.js'; 3 | import './todo-item.js'; 4 | 5 | customElement('my-todo', ({ constructing, props, update }) => { 6 | if (constructing) { 7 | return { 8 | list: [ 9 | { text: 'my initial todo', checked: false }, 10 | { text: 'Learn about Web Components', checked: true }, 11 | ] 12 | }; 13 | } 14 | 15 | return html` 16 | 39 | 40 |

        Todos Functional Element

        41 | 42 |
        43 | update(addItem(props.list, e.detail))}> 44 | ${props.list.map((item, index) => html` 45 | update(removeItem(props.list, e.detail))} 50 | @toggle=${(e) => update(toggleItem(props.list, e.detail))} 51 | >`)} 52 |
          53 |
          54 | `; 55 | }); 56 | 57 | function addItem(list, text) { 58 | return { 59 | list: [...list, { text, checked: false, }] 60 | }; 61 | } 62 | 63 | function removeItem(list, index) { 64 | return { 65 | list: [...list.slice(0, index), ...list.slice(index + 1)] 66 | }; 67 | } 68 | 69 | function toggleItem(list, index) { 70 | const originalList = [...list]; 71 | const item = originalList[index]; 72 | originalList[index] = Object.assign({}, item, { checked: !item.checked }); 73 | 74 | return { 75 | list: originalList 76 | }; 77 | } -------------------------------------------------------------------------------- /atomico/src/todo-item/style.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | li { 6 | font-size: 24px; 7 | display: block; 8 | position: relative; 9 | border-bottom: 1px solid #ededed; 10 | } 11 | 12 | li input { 13 | text-align: center; 14 | width: 40px; 15 | /* auto, since non-WebKit browsers doesn't support input styling */ 16 | height: auto; 17 | position: absolute; 18 | top: 9px; 19 | bottom: 0; 20 | margin: auto 0; 21 | border: none; 22 | /* Mobile Safari */ 23 | -webkit-appearance: none; 24 | appearance: none; 25 | padding: 0; 26 | box-shadow: none; 27 | } 28 | 29 | li input:after { 30 | content: url('data:image/svg+xml;utf8,'); 31 | } 32 | 33 | li input:checked:after { 34 | content: url('data:image/svg+xml;utf8,'); 35 | } 36 | 37 | li label { 38 | white-space: pre; 39 | word-break: break-word; 40 | padding: 15px 60px 15px 15px; 41 | margin-left: 45px; 42 | display: block; 43 | line-height: 1.2; 44 | transition: color 0.4s; 45 | } 46 | 47 | li.completed label { 48 | color: #d9d9d9; 49 | text-decoration: line-through; 50 | } 51 | 52 | li button, li input[type="checkbox"] { 53 | outline: none; 54 | } 55 | 56 | li button { 57 | margin: 0; 58 | padding: 0; 59 | border: 0; 60 | background: none; 61 | font-size: 100%; 62 | vertical-align: baseline; 63 | font-family: inherit; 64 | font-weight: inherit; 65 | color: inherit; 66 | -webkit-appearance: none; 67 | appearance: none; 68 | -webkit-font-smoothing: antialiased; 69 | -moz-font-smoothing: antialiased; 70 | font-smoothing: antialiased; 71 | } 72 | 73 | li button { 74 | position: absolute; 75 | top: 0; 76 | right: 10px; 77 | bottom: 0; 78 | width: 40px; 79 | height: 40px; 80 | margin: auto 0; 81 | font-size: 30px; 82 | color: #cc9a9a; 83 | margin-bottom: 11px; 84 | transition: color 0.2s ease-out; 85 | } 86 | 87 | li button:hover { 88 | color: #af5b5e; 89 | } -------------------------------------------------------------------------------- /stencil-0.16/src/components.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /** 3 | * This is an autogenerated file created by the Stencil compiler. 4 | * It contains typing information for all components that exist in this project. 5 | */ 6 | 7 | 8 | import '@stencil/core'; 9 | 10 | 11 | 12 | 13 | export namespace Components { 14 | 15 | interface MyTodo {} 16 | interface MyTodoAttributes extends StencilHTMLAttributes {} 17 | 18 | interface TodoInput {} 19 | interface TodoInputAttributes extends StencilHTMLAttributes { 20 | 'onOnTodoInputSubmit'?: (event: CustomEvent) => void; 21 | } 22 | 23 | interface TodoItem { 24 | 'checked': boolean; 25 | 'index': number; 26 | 'text': string; 27 | } 28 | interface TodoItemAttributes extends StencilHTMLAttributes { 29 | 'checked'?: boolean; 30 | 'index'?: number; 31 | 'onOnTodoItemChecked'?: (event: CustomEvent) => void; 32 | 'onOnTodoItemRemove'?: (event: CustomEvent) => void; 33 | 'text'?: string; 34 | } 35 | } 36 | 37 | declare global { 38 | interface StencilElementInterfaces { 39 | 'MyTodo': Components.MyTodo; 40 | 'TodoInput': Components.TodoInput; 41 | 'TodoItem': Components.TodoItem; 42 | } 43 | 44 | interface StencilIntrinsicElements { 45 | 'my-todo': Components.MyTodoAttributes; 46 | 'todo-input': Components.TodoInputAttributes; 47 | 'todo-item': Components.TodoItemAttributes; 48 | } 49 | 50 | 51 | interface HTMLMyTodoElement extends Components.MyTodo, HTMLStencilElement {} 52 | var HTMLMyTodoElement: { 53 | prototype: HTMLMyTodoElement; 54 | new (): HTMLMyTodoElement; 55 | }; 56 | 57 | interface HTMLTodoInputElement extends Components.TodoInput, HTMLStencilElement {} 58 | var HTMLTodoInputElement: { 59 | prototype: HTMLTodoInputElement; 60 | new (): HTMLTodoInputElement; 61 | }; 62 | 63 | interface HTMLTodoItemElement extends Components.TodoItem, HTMLStencilElement {} 64 | var HTMLTodoItemElement: { 65 | prototype: HTMLTodoItemElement; 66 | new (): HTMLTodoItemElement; 67 | }; 68 | 69 | interface HTMLElementTagNameMap { 70 | 'my-todo': HTMLMyTodoElement 71 | 'todo-input': HTMLTodoInputElement 72 | 'todo-item': HTMLTodoItemElement 73 | } 74 | 75 | interface ElementTagNameMap { 76 | 'my-todo': HTMLMyTodoElement; 77 | 'todo-input': HTMLTodoInputElement; 78 | 'todo-item': HTMLTodoItemElement; 79 | } 80 | 81 | 82 | export namespace JSX { 83 | export interface Element {} 84 | export interface IntrinsicElements extends StencilIntrinsicElements { 85 | [tagName: string]: any; 86 | } 87 | } 88 | export interface HTMLAttributes extends StencilHTMLAttributes {} 89 | 90 | } 91 | -------------------------------------------------------------------------------- /lit-element-2.1/src/my-todo.js: -------------------------------------------------------------------------------- 1 | import { LitElement, html } from 'lit-element'; 2 | 3 | export default class MyTodo extends LitElement { 4 | constructor() { 5 | super(); 6 | this.list = [ 7 | { text: 'my initial todo', checked: false }, 8 | { text: 'Learn about Web Components', checked: true }, 9 | ]; 10 | this.addItem = this.addItem.bind(this); 11 | this.removeItem = this.removeItem.bind(this); 12 | this.toggleItem = this.toggleItem.bind(this); 13 | } 14 | 15 | addItem(e, text) { 16 | this.list = [...this.list, { text, checked: false, }]; 17 | this.requestUpdate('list'); 18 | } 19 | 20 | removeItem(e, index) { 21 | this.list = [...this.list.slice(0, index), ...this.list.slice(index + 1)]; 22 | this.requestUpdate('list'); 23 | } 24 | 25 | toggleItem(e, index) { 26 | const list = [...this.list]; 27 | const item = list[index]; 28 | list[index] = Object.assign({}, item, { checked: !item.checked }); 29 | this.list = list; 30 | this.requestUpdate('list'); 31 | } 32 | 33 | render() { 34 | return html` 35 | 58 |

          Todos Lit Element

          59 |
          60 | 61 | ${this.list.map((item, index) => html` 62 | `)} 69 |
            70 |
            `; 71 | } 72 | } 73 | --------------------------------------------------------------------------------