diff --git a/.gitignore b/.gitignore
index 23e14c10..3495b13a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
/node_modules
/bower_components
-/test
-/poly-lit-element.js
-/poly-lit-element.d.ts
-/poly-lit-element.js.map
+/test/lit*
+/lit-element.js
+/lit-element.d.ts
+/lit-element.js.map
diff --git a/README.md b/README.md
index bc1072f9..b6bd6351 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,57 @@
-# polymer-lit
+# lit-element
-## This is just an example, and not event working yet. Please hold.
+## Base class for creating custom elements using Polymer and lit-html.
+
+```javascript
+import {LitElement, html} from 'node_modules/@polymer/lit-element/lit-element.js'
+
+class MyElement extends LitElement {
+
+ // Public property API that triggers re-render (synched with attributes)
+ static get properties() {
+ return {
+ foo: String,
+ whales: Number
+ }
+ }
+
+ constructor() {
+ super();
+ this.foo = 'foo';
+ }
+
+ ready() {
+ this.addEventListener('click', async (e) => {
+ this.whales++;
+ await this.nextRendered;
+ this.dispatchEvent(new CustomEvent('whales', {detail: {whales: this.whales}}))
+ });
+ super.ready();
+ }
+
+ // Render method should return a `TemplateResult` using the provided lit-html `html` tag function
+ render({foo, whales}) {
+ return html`
+
+
Foo: ${foo}
+ whales: ${'🐳'.repeat(whales)}
+
+ `;
+ }
+
+}
+customElements.define('my-element', MyElement);
+```
+
+```html
+ hi
+```
+
+## Known Issues
+* This element does not yet work with the ShadyCSS polyfill. Support is coming soon!
+* API is subject to minor changes.
+* See [lit-html](https://github.com/Polymer/lit-html) for more info.
diff --git a/demo/lit-element.html b/demo/lit-element.html
new file mode 100644
index 00000000..f191ebf5
--- /dev/null
+++ b/demo/lit-element.html
@@ -0,0 +1,75 @@
+
+
+
+ lit-element demo
+
+
+
+ Hi
+
diff --git a/package-lock.json b/package-lock.json
index e7643921..9885048b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,5 +1,5 @@
{
- "name": "poly-lit-element",
+ "name": "@polymer/polymer-lit-element",
"version": "0.1.0",
"lockfileVersion": 1,
"requires": true,
@@ -3681,9 +3681,9 @@
}
},
"lit-html": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-0.6.0.tgz",
- "integrity": "sha512-H8CmAxZ9kdhiEyrcKNBlFF4pREp5/BKzIPE3EggKISEMT10Ez6WxwR3mzGPUfwgjTX9UQHAzLMtpn4tNkqS5sg=="
+ "version": "0.8.0-pre.1",
+ "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-0.8.0-pre.1.tgz",
+ "integrity": "sha512-olcLRCKRlmLE0I78+bJ5GAT9ALD7A9Q6ToouRnGTtTCVJ6UoYQ0sIMieDqiF4DrmOJf1Qm4yq5eACrzIGNPYvg=="
},
"load-json-file": {
"version": "1.1.0",
@@ -5991,12 +5991,6 @@
"integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=",
"dev": true
},
- "string_decoder": {
- "version": "0.10.31",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
- "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
- "dev": true
- },
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
@@ -6008,6 +6002,12 @@
"strip-ansi": "3.0.1"
}
},
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+ "dev": true
+ },
"stringstream": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
@@ -6419,9 +6419,9 @@
"dev": true
},
"typescript": {
- "version": "2.5.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.5.2.tgz",
- "integrity": "sha1-A4qV99m7tCCxvzW6MdTFwd0//jQ=",
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.2.tgz",
+ "integrity": "sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q=",
"dev": true
},
"typical": {
@@ -6721,6 +6721,74 @@
"minimalistic-assert": "1.0.0"
}
},
+ "wct-browser-legacy": {
+ "version": "0.0.1-pre.10",
+ "resolved": "https://registry.npmjs.org/wct-browser-legacy/-/wct-browser-legacy-0.0.1-pre.10.tgz",
+ "integrity": "sha512-TREECc5jI43f/zkMGSLhFB4Fmn7QHV/cAPE+z+S6XU8RurQ6W4JRw72cVOfyc7oTAWF6fIzQMEQPV0HwcIYqCQ==",
+ "dev": true,
+ "requires": {
+ "@polymer/polymer": "3.0.0-pre.1",
+ "@polymer/sinonjs": "1.17.1",
+ "@polymer/test-fixture": "3.0.0-pre.1",
+ "@webcomponents/webcomponentsjs": "1.0.10",
+ "accessibility-developer-tools": "2.12.0",
+ "async": "1.5.2",
+ "chai": "3.5.0",
+ "lodash": "3.10.1",
+ "mocha": "3.5.0",
+ "sinon": "1.17.7",
+ "sinon-chai": "2.13.0",
+ "stacky": "1.3.1"
+ },
+ "dependencies": {
+ "@polymer/test-fixture": {
+ "version": "3.0.0-pre.1",
+ "resolved": "https://registry.npmjs.org/@polymer/test-fixture/-/test-fixture-3.0.0-pre.1.tgz",
+ "integrity": "sha512-HfttRbDMz3DZezvfaFFBdZejlnnM9hT7CyPp81lTeaDWY9kCHEohuIIAEX/BNkrDp0S9+z16t60gdkPgR8JVKg==",
+ "dev": true
+ },
+ "chai": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz",
+ "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=",
+ "dev": true,
+ "requires": {
+ "assertion-error": "1.0.2",
+ "deep-eql": "0.1.3",
+ "type-detect": "1.0.0"
+ }
+ },
+ "deep-eql": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz",
+ "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=",
+ "dev": true,
+ "requires": {
+ "type-detect": "0.1.1"
+ },
+ "dependencies": {
+ "type-detect": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz",
+ "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=",
+ "dev": true
+ }
+ }
+ },
+ "lodash": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
+ "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
+ "dev": true
+ },
+ "type-detect": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz",
+ "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=",
+ "dev": true
+ }
+ }
+ },
"wct-local": {
"version": "2.0.15",
"resolved": "https://registry.npmjs.org/wct-local/-/wct-local-2.0.15.tgz",
diff --git a/package.json b/package.json
index 336e8b6b..bfa843db 100644
--- a/package.json
+++ b/package.json
@@ -1,11 +1,11 @@
{
- "name": "poly-lit-element",
+ "name": "@polymer/lit-element",
"version": "0.1.0",
- "description": "Polymer + Lit",
+ "description": "Polymer based lit-html custom element",
"license": "BSD-3-Clause",
- "repository": "PolymerLabs/poly-lit-element",
- "main": "poly-lit-element.js",
- "module": "poly-lit-element.js",
+ "repository": "PolymerLabs/lit-element",
+ "main": "lit-element.js",
+ "module": "lit-element.js",
"directories": {
"test": "test"
},
@@ -15,7 +15,7 @@
"pretest": "npm run posttest; ln -s node_modules bower_components",
"test": "npm run build && wct -l chrome && npm run lint",
"posttest": "rm -f bower_components",
- "checksize": "uglifyjs poly-lit-element.js -mc --toplevel | gzip -9 | wc -c",
+ "checksize": "uglifyjs lit-element.js -mc --toplevel | gzip -9 | wc -c",
"format": "find src test | grep '\\.js$\\|\\.ts$' | xargs clang-format --style=file -i",
"lint": "tslint --project ./"
},
@@ -27,13 +27,17 @@
"mocha": "^3.4.2",
"tslint": "^5.7.0",
"typedoc": "^0.8.0",
- "typescript": "^2.5.2",
+ "typescript": "^2.6.2",
"uglify-es": "^3.0.27",
+ "wct-browser-legacy": "0.0.1-pre.10",
"web-component-tester": "^6.0.1"
},
- "typings": "poly-lit-element.d.ts",
+ "typings": "lit-element.d.ts",
"dependencies": {
- "@polymer/polymer": "^3.0.0-pre.1",
- "lit-html": "^0.6.0"
- }
+ "@polymer/polymer": "^3.0.0-pre.4",
+ "lit-html": "^0.8.0"
+ },
+"publishConfig": {
+"access": "public"
+}
}
diff --git a/src/@polymer/lit-element.ts b/src/@polymer/lit-element.ts
new file mode 100644
index 00000000..30436d3a
--- /dev/null
+++ b/src/@polymer/lit-element.ts
@@ -0,0 +1,64 @@
+/**
+ * @license
+ * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
+ * This code may only be used under the BSD style license found at
+ * http://polymer.github.io/LICENSE.txt
+ * The complete set of authors may be found at
+ * http://polymer.github.io/AUTHORS.txt
+ * The complete set of contributors may be found at
+ * http://polymer.github.io/CONTRIBUTORS.txt
+ * Code distributed by Google as part of the polymer project is also
+ * subject to an additional IP rights grant found at
+ * http://polymer.github.io/PATENTS.txt
+ */
+import { PropertiesMixin } from '../../@polymer/polymer/lib/mixins/properties-mixin.js';
+import { TemplateResult } from '../../lit-html/lit-html.js';
+import { render } from '../../lit-html/lib/lit-extended.js';
+
+export { html } from '../../lit-html/lit-html.js';
+export class LitElement extends PropertiesMixin(HTMLElement) {
+
+ _nextRendered: Promise|null = null;
+ _nextRenderedResolver: Function|null = null;
+
+ ready() {
+ this.attachShadow({mode: 'open'});
+ super.ready();
+ }
+
+ _flushProperties() {
+ super._flushProperties();
+ // TODO(sorvell): propertiesChanged should have `_getData`
+ const result = this.render(this.__data);
+ if (result) {
+ render(result, this.shadowRoot!);
+ }
+ if (this._nextRenderedResolver) {
+ this._nextRenderedResolver();
+ this._nextRenderedResolver = null;
+ this._nextRendered = null;
+ }
+ }
+
+ /**
+ * Return a template result to render using lit-html.
+ */
+ render(_props: object): TemplateResult {
+ throw new Error('render() not implemented');
+ }
+
+ invalidate() {
+ this._invalidateProperties();
+ }
+
+ get nextRendered() {
+ if (!this._nextRendered) {
+ // TODO(sorvell): handle rejected render.
+ this._nextRendered = new Promise((resolve) => {
+ this._nextRenderedResolver = resolve;
+ });
+ }
+ return this._nextRendered;
+ }
+
+}
diff --git a/src/@polymer/test/lit-element_test.ts b/src/@polymer/test/lit-element_test.ts
new file mode 100644
index 00000000..699af67f
--- /dev/null
+++ b/src/@polymer/test/lit-element_test.ts
@@ -0,0 +1,163 @@
+/**
+ * @license
+ * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
+ * This code may only be used under the BSD style license found at
+ * http://polymer.github.io/LICENSE.txt
+ * The complete set of authors may be found at
+ * http://polymer.github.io/AUTHORS.txt
+ * The complete set of contributors may be found at
+ * http://polymer.github.io/CONTRIBUTORS.txt
+ * Code distributed by Google as part of the polymer project is also
+ * subject to an additional IP rights grant found at
+ * http://polymer.github.io/PATENTS.txt
+ */
+
+import { LitElement, html } from '../lit-element.js';
+
+///
+///
+
+const assert = chai.assert;
+
+suite('LitElement', () => {
+
+ test('renders initial content', () => {
+ const rendered = `hello world`;
+ customElements.define('x-1', class extends LitElement {
+ render() {
+ return html`${rendered}`
+ }
+ });
+ const el = document.createElement('x-1');
+ document.body.appendChild(el);
+ assert.ok(el.shadowRoot);
+ assert.equal((el.shadowRoot as ShadowRoot).innerHTML, rendered);
+ document.body.removeChild(el);
+ });
+
+ test('renders when created via constructor', () => {
+ const rendered = `hello world`;
+ const C = class extends LitElement {
+ render() {
+ return html`${rendered}`
+ }
+ };
+ customElements.define('x-2', C);
+ const el = new C();
+ document.body.appendChild(el);
+ assert.ok(el.shadowRoot);
+ assert.equal((el.shadowRoot as ShadowRoot).innerHTML, rendered);
+ document.body.removeChild(el);
+ });
+
+ test('renders changes when properties change', (done) => {
+ customElements.define('x-3', class extends LitElement {
+ static get properties() {
+ return {
+ foo: String
+ }
+ }
+
+ foo = 'one';
+
+ render(props: any) {
+ return html`${props.foo}`
+ }
+ });
+ const el = document.createElement('x-3');
+ document.body.appendChild(el);
+ assert.ok(el.shadowRoot);
+ assert.equal((el.shadowRoot as ShadowRoot).innerHTML, 'one');
+ el.foo = 'changed';
+ requestAnimationFrame(() => {
+ assert.equal((el.shadowRoot as ShadowRoot).innerHTML, 'changed');
+ document.body.removeChild(el);
+ done();
+ });
+ });
+
+ test('renders changes when attributes change', (done) => {
+ customElements.define('x-4', class extends LitElement {
+ static get properties() {
+ return {
+ foo: String
+ }
+ }
+
+ foo = 'one';
+
+ render(props: any) {
+ return html`${props.foo}`
+ }
+ });
+ const el = document.createElement('x-4');
+ document.body.appendChild(el);
+ assert.ok(el.shadowRoot);
+ assert.equal((el.shadowRoot as ShadowRoot).innerHTML, 'one');
+ el.setAttribute('foo', 'changed');
+ requestAnimationFrame(() => {
+ assert.equal((el.shadowRoot as ShadowRoot).innerHTML, 'changed');
+ document.body.removeChild(el);
+ done();
+ });
+ });
+
+ test('renders changes made at `ready` time', () => {
+ customElements.define('x-5', class extends LitElement {
+ static get properties() {
+ return {
+ foo: String
+ }
+ }
+
+ foo = 'one';
+
+ ready() {
+ this.foo = 'changed';
+ super.ready();
+ }
+
+ render(props: any) {
+ return html`${props.foo}`
+ }
+ });
+ const el = document.createElement('x-5');
+ document.body.appendChild(el);
+ assert.ok(el.shadowRoot);
+ assert.equal((el.shadowRoot as ShadowRoot).innerHTML, 'changed');
+ document.body.removeChild(el);
+ });
+
+ test('nextRendered waits until next rendering', (done) => {
+ customElements.define('x-6', class extends LitElement {
+ static get properties() {
+ return {
+ foo: Number
+ }
+ }
+
+ foo = 0;
+
+ render(props: any) {
+ return html`${props.foo}`
+ }
+ });
+ const el = document.createElement('x-6');
+ document.body.appendChild(el);
+ el.foo++;
+ el.nextRendered.then(() => {
+ assert.equal((el.shadowRoot as ShadowRoot).innerHTML, '1');
+ el.foo++;
+ el.nextRendered.then(() => {
+ assert.equal((el.shadowRoot as ShadowRoot).innerHTML, '2');
+ el.foo++;
+ el.nextRendered.then(() => {
+ assert.equal((el.shadowRoot as ShadowRoot).innerHTML, '3');
+ document.body.removeChild(el);
+ done();
+ });
+ });
+ });
+ });
+
+});
diff --git a/src/poly-lit-element.ts b/src/poly-lit-element.ts
deleted file mode 100644
index cd2df476..00000000
--- a/src/poly-lit-element.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * @license
- * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
- * This code may only be used under the BSD style license found at
- * http://polymer.github.io/LICENSE.txt
- * The complete set of authors may be found at
- * http://polymer.github.io/AUTHORS.txt
- * The complete set of contributors may be found at
- * http://polymer.github.io/CONTRIBUTORS.txt
- * Code distributed by Google as part of the polymer project is also
- * subject to an additional IP rights grant found at
- * http://polymer.github.io/PATENTS.txt
- */
-
-import { dedupingMixin } from '../@polymer/polymer/lib/utils/mixin.js';
-import { TemplateResult } from '../lit-html/lit-html.js';
-import { render } from '../lit-html/lib/lit-extended.js';
-
-export { html } from '../lit-html/lit-html.js';
-
-export type Constructor = { new(...args: any[]): T };
-
-declare interface PropertyAccessors {
- ready(): void;
- __dataPending: object;
- __dataOld: object;
- _invalidateProperties(): void;
- _propertiesChanged(props: any, changed: any, old: any): void;
-}
-
-export const PolymerLit = dedupingMixin(>(base: S) => {
-
- return class PolymerLit extends base {
-
- _templateResult: TemplateResult;
-
- ready() {
- this.attachShadow({mode: 'open'});
- super.ready();
- // TODO(sorvell): we need to trigger rendering even if no changes occurred!
- // can set a dummy property, but that's maybe not good so we "invalidate"
- // but need to ready private state to do so.
- //this._setProperty('_readied', true);
- this.__dataPending = this.__dataPending || {};
- this.__dataOld = this.__dataOld || {};
- this._invalidateProperties();
- }
-
- _propertiesChanged(props: any, changed: any, old: any) {
- super._propertiesChanged(props, changed, old);
- this._templateResult = this.render();
- if (this._templateResult) {
- render(this._templateResult, this.shadowRoot!);
- }
- }
-
- /**
- * Return a template result to render using lit-html.
- */
- render(): TemplateResult {
- throw new Error('render() not implemented');
- }
- }
-
-});
diff --git a/src/test/poly-lit-element_test.ts b/src/test/poly-lit-element_test.ts
deleted file mode 100644
index 3fbb3847..00000000
--- a/src/test/poly-lit-element_test.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * @license
- * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
- * This code may only be used under the BSD style license found at
- * http://polymer.github.io/LICENSE.txt
- * The complete set of authors may be found at
- * http://polymer.github.io/AUTHORS.txt
- * The complete set of contributors may be found at
- * http://polymer.github.io/CONTRIBUTORS.txt
- * Code distributed by Google as part of the polymer project is also
- * subject to an additional IP rights grant found at
- * http://polymer.github.io/PATENTS.txt
- */
-
-import { html, PolymerLit } from '../poly-lit-element.js';
-import { PropertyAccessors } from '../../@polymer/polymer/lib/mixins/property-accessors.js';
-
-///
-///
-
-const assert = chai.assert;
-
-suite('PolymerList', () => {
-
- test('constructrs', () => {
-
- const C = class extends PolymerLit(PropertyAccessors(HTMLElement)) {
- foo: string = 'foo';
-
- render() {
- return html`
- ${this.foo}
- `;
- }
- };
-
- const c = new C();
- const container = document.createElement('div');
- document.body.appendChild(container);
- container.appendChild(c as any as HTMLElement);
- assert.equal(c.shadowRoot!.innerHTML, 'foo
');
- });
-
-});
diff --git a/test/index.html b/test/index.html
new file mode 100644
index 00000000..2e8daca7
--- /dev/null
+++ b/test/index.html
@@ -0,0 +1,17 @@
+
+
+
+ lit-element tests
+
+
+
+
+
diff --git a/tsconfig.json b/tsconfig.json
index 0e72c957..6d4b2a9e 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -5,15 +5,16 @@
"lib": ["es2017", "dom"],
"declaration": true,
"sourceMap": true,
- "outDir": "./",
+ "inlineSources": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
- "allowJs": true,
+ "outDir": "./",
+ "rootDir": "./src/@polymer",
"rootDirs": [
- ".",
+ "./",
"./node_modules",
"./node_modules/@types"
]
@@ -21,5 +22,7 @@
"include": [
"./src/**/*.ts"
],
- "exclude": []
+ "exclude": [
+ ""
+ ]
}