Skip to content

Commit

Permalink
Prepare 2.3.0 release (#933)
Browse files Browse the repository at this point in the history
* Prepare 2.3.0 release

* Format

* Fix formatting
  • Loading branch information
justinfagnani authored Mar 18, 2020
1 parent 5a421e1 commit 0eda741
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 113 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
<!-- ### Removed -->
<!-- ### Fixed -->

## [2.3.0-pre.1] - 2020-03-17
## [2.3.0] - 2020-03-18

### Changed
* Added a static `getPropertyDescriptor` method to allow easier customization of property accessors. This method should return a a `PropertyDescriptor` to install on the property. If no descriptor is returned, no property accessor is created. ([#911](https://github.com/Polymer/lit-element/issues/911))
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lit-element",
"version": "2.3.0-pre.1",
"version": "2.3.0",
"description": "A simple base class for creating fast, lightweight web components",
"license": "BSD-3-Clause",
"homepage": "https://lit-element.polymer-project.org/",
Expand Down
3 changes: 2 additions & 1 deletion src/lib/decorators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,8 @@ export function queryAsync(selector: string) {
*
* @param selector A DOMString containing one or more selectors to match.
*
* See: https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
* See:
* https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
*
* @example
*
Expand Down
13 changes: 7 additions & 6 deletions src/lib/updating-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ export interface ComplexAttributeConverter<Type = unknown, TypeHint = unknown> {
}

type AttributeConverter<Type = unknown, TypeHint = unknown> =
ComplexAttributeConverter<Type>|((value: string|null, type?: TypeHint) => Type);
ComplexAttributeConverter<Type>|
((value: string|null, type?: TypeHint) => Type);

/**
* Defines options for a property accessor.
Expand Down Expand Up @@ -112,7 +113,6 @@ export interface PropertyDeclaration<Type = unknown, TypeHint = unknown> {
* the property changes.
*/
readonly noAccessor?: boolean;

}

/**
Expand Down Expand Up @@ -333,7 +333,8 @@ export abstract class UpdatingElement extends HTMLElement {
*
* class MyElement extends LitElement {
* static getPropertyDescriptor(name, key, options) {
* const defaultDescriptor = super.getPropertyDescriptor(name, key, options);
* const defaultDescriptor =
* super.getPropertyDescriptor(name, key, options);
* const setter = defaultDescriptor.set;
* return {
* get: defaultDescriptor.get,
Expand All @@ -349,8 +350,8 @@ export abstract class UpdatingElement extends HTMLElement {
*
* @nocollapse
*/
protected static getPropertyDescriptor(name: PropertyKey,
key: string|symbol, _options: PropertyDeclaration) {
protected static getPropertyDescriptor(
name: PropertyKey, key: string|symbol, _options: PropertyDeclaration) {
return {
// tslint:disable-next-line:no-any no symbol in index
get(): any {
Expand Down Expand Up @@ -381,7 +382,7 @@ export abstract class UpdatingElement extends HTMLElement {
*/
protected static getPropertyOptions(name: PropertyKey) {
return this._classProperties && this._classProperties.get(name) ||
defaultPropertyDeclaration;
defaultPropertyDeclaration;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/lit-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ declare global {
// This line will be used in regexes to search for LitElement usage.
// TODO(justinfagnani): inject version number at build time
(window['litElementVersions'] || (window['litElementVersions'] = []))
.push('2.3.0-pre.1');
.push('2.3.0');

export interface CSSResultArray extends Array<CSSResult|CSSResultArray> {}

Expand Down
10 changes: 4 additions & 6 deletions src/test/lib/decorators_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,22 +461,20 @@ suite('decorators', () => {
});

suite('@queryAsync', () => {

@customElement(generateElementName() as keyof HTMLElementTagNameMap)
class C extends LitElement {
@queryAsync('#blah') blah!: Promise<HTMLDivElement>;

@queryAsync('span') nope!: Promise<HTMLSpanElement|null>;

@property()
foo = false;
@property() foo = false;

render() {
return html`
<div>Not this one</div>
${this.foo ?
html`<div id="blah" foo>This one</div>` :
html`<div id="blah">This one</div>` }
${
this.foo ? html`<div id="blah" foo>This one</div>` :
html`<div id="blah">This one</div>`}
`;
}
}
Expand Down
207 changes: 110 additions & 97 deletions src/test/lib/updating-element_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
* http://polymer.github.io/PATENTS.txt
*/

import {property, customElement} from '../../lib/decorators.js';
import {ComplexAttributeConverter, PropertyDeclarations, PropertyValues, UpdatingElement, PropertyDeclaration, defaultConverter} from '../../lib/updating-element.js';
import {customElement, property} from '../../lib/decorators.js';
import {ComplexAttributeConverter, defaultConverter, PropertyDeclaration, PropertyDeclarations, PropertyValues, UpdatingElement} from '../../lib/updating-element.js';
import {generateElementName} from '../test-helpers.js';

// tslint:disable:no-any ok in tests
Expand Down Expand Up @@ -1429,36 +1429,39 @@ suite('UpdatingElement', () => {
assert.equal(el.updatedText, '6');
});

test('setting properties in update after calling `super.update` *does* trigger update', async () => {
class E extends UpdatingElement {
static get properties() {
return {foo: {}};
}
promiseFulfilled = false;
foo = 0;
updateCount = 0;
updatedText = '';
test(
'setting properties in update after calling `super.update` *does* trigger update',
async () => {
class E extends UpdatingElement {
static get properties() {
return {foo: {}};
}
promiseFulfilled = false;
foo = 0;
updateCount = 0;
updatedText = '';

update(props: PropertyValues) {
this.updateCount++;
super.update(props);
if (this.foo < 1) {
this.foo++;
}
}
update(props: PropertyValues) {
this.updateCount++;
super.update(props);
if (this.foo < 1) {
this.foo++;
}
}

updated() {
this.updatedText = `${this.foo}`;
}
}
customElements.define(generateElementName(), E);
const el = new E();
container.appendChild(el);
while (!(await el.updateComplete)) {}
assert.equal(el.foo, 1);
assert.equal(el.updateCount, 2);
assert.equal(el.updatedText, '1');
});
updated() {
this.updatedText = `${this.foo}`;
}
}
customElements.define(generateElementName(), E);
const el = new E();
container.appendChild(el);
while (!(await el.updateComplete)) {
}
assert.equal(el.foo, 1);
assert.equal(el.updateCount, 2);
assert.equal(el.updatedText, '1');
});

test(
'setting properties in update reflects to attribute and is included in `changedProperties`',
Expand Down Expand Up @@ -1802,68 +1805,62 @@ suite('UpdatingElement', () => {
assert.equal(sub.getAttribute('foo'), '5');
});

test('can provide a default property declaration', async () => {

const SpecialNumber = {};

const myPropertyDeclaration = {
type: SpecialNumber,
reflect: true,
converter: {
toAttribute: function(value: unknown, type?: unknown): unknown {
switch (type) {
case String:
return value === undefined ? null : value;
default:
return defaultConverter.toAttribute!(value, type);
}
},
fromAttribute: function(value: string|null, type?: unknown) {
switch (type) {
case SpecialNumber:
return Number(value) + 10;
default:
return defaultConverter.fromAttribute!(value, type);
}
}
test('can provide a default property declaration', async () => {
const SpecialNumber = {};

const myPropertyDeclaration = {
type: SpecialNumber,
reflect: true,
converter: {
toAttribute: function(value: unknown, type?: unknown): unknown {
switch (type) {
case String:
return value === undefined ? null : value;
default:
return defaultConverter.toAttribute!(value, type);
}
};

@customElement(generateElementName())
class E extends UpdatingElement {

static createProperty(
name: PropertyKey,
options: PropertyDeclaration) {
// Always mix into defaults to preserve custom converter.
options = Object.assign(Object.create(myPropertyDeclaration), options);
super.createProperty(name, options);
},
fromAttribute: function(value: string|null, type?: unknown) {
switch (type) {
case SpecialNumber:
return Number(value) + 10;
default:
return defaultConverter.fromAttribute!(value, type);
}
}
}
};

@property()
foo = 5;
@customElement(generateElementName())
class E extends UpdatingElement {
static createProperty(name: PropertyKey, options: PropertyDeclaration) {
// Always mix into defaults to preserve custom converter.
options = Object.assign(Object.create(myPropertyDeclaration), options);
super.createProperty(name, options);
}

@property({type: String})
bar?: string = 'bar';
}
@property() foo = 5;

const el = new E();
container.appendChild(el);
el.setAttribute('foo', '10');
el.setAttribute('bar', 'attrBar');
await el.updateComplete;
assert.equal(el.foo, 20);
assert.equal(el.bar, 'attrBar');
el.foo = 5;
el.bar = undefined;
await el.updateComplete;
assert.equal(el.getAttribute('foo'), '5');
assert.isFalse(el.hasAttribute('bar'));
});
@property({type: String}) bar?: string = 'bar';
}

test('can customize property options and accessor creation', async () => {
const el = new E();
container.appendChild(el);
el.setAttribute('foo', '10');
el.setAttribute('bar', 'attrBar');
await el.updateComplete;
assert.equal(el.foo, 20);
assert.equal(el.bar, 'attrBar');
el.foo = 5;
el.bar = undefined;
await el.updateComplete;
assert.equal(el.getAttribute('foo'), '5');
assert.isFalse(el.hasAttribute('bar'));
});

interface MyPropertyDeclaration<TypeHint = unknown> extends PropertyDeclaration {
test('can customize property options and accessor creation', async () => {
interface MyPropertyDeclaration<TypeHint = unknown> extends
PropertyDeclaration {
validator?: (value: any) => TypeHint;
observer?: (oldValue: TypeHint) => void;
}
Expand All @@ -1876,18 +1873,21 @@ suite('UpdatingElement', () => {

@customElement(generateElementName())
class E extends UpdatingElement {

static getPropertyDescriptor(name: PropertyKey, key: string|symbol, options: MyPropertyDeclaration) {
const defaultDescriptor = super.getPropertyDescriptor(name, key, options);
static getPropertyDescriptor(
name: PropertyKey, key: string|symbol,
options: MyPropertyDeclaration) {
const defaultDescriptor =
super.getPropertyDescriptor(name, key, options);
return {
get: defaultDescriptor.get,
set(this: E, value: unknown) {
const oldValue =
(this as unknown as {[key: string]: unknown})[name as string];
(this as unknown as {[key: string]: unknown})[name as string];
if (options.validator) {
value = options.validator(value);
}
(this as unknown as {[key: string]: unknown})[key as string] = value;
(this as unknown as {[key: string]: unknown})[key as string] =
value;
(this as unknown as UpdatingElement).requestUpdate(name, oldValue);
},

Expand All @@ -1900,7 +1900,7 @@ suite('UpdatingElement', () => {
super.updated(changedProperties);
changedProperties.forEach((value: unknown, key: PropertyKey) => {
const options = (this.constructor as typeof UpdatingElement)
.getPropertyOptions(key) as MyPropertyDeclaration;
.getPropertyOptions(key) as MyPropertyDeclaration;
const observer = options.observer;
if (typeof observer === 'function') {
observer.call(this, value);
Expand All @@ -1909,11 +1909,13 @@ suite('UpdatingElement', () => {
}

// provide custom deorator expecting extended type
@myProperty({type: Number, validator: (value: number) => Math.min(10, Math.max(value, 0))})
@myProperty({
type: Number,
validator: (value: number) => Math.min(10, Math.max(value, 0))
})
foo = 5;

@property({})
bar = 'bar';
@property({}) bar = 'bar';

// tslint:disable-next-line:no-any
_observedZot?: any;
Expand All @@ -1922,7 +1924,11 @@ suite('UpdatingElement', () => {
_observedZot2?: any;

// use regular decorator and cast to type
@property({observer: function(this: E, oldValue: string) { this._observedZot = {value: this.zot, oldValue}; } } as PropertyDeclaration)
@property({
observer: function(this: E, oldValue: string) {
this._observedZot = {value: this.zot, oldValue};
}
} as PropertyDeclaration)
zot = '';

zot2 = '';
Expand All @@ -1933,9 +1939,16 @@ suite('UpdatingElement', () => {
static get properties(): MyPropertyDeclarations {
return {
// object cast as type
zot2: {observer: function(this: E, oldValue: string) { this._observedZot2 = {value: this.zot2, oldValue}; } } as PropertyDeclaration,
zot2: {
observer: function(this: E, oldValue: string) {
this._observedZot2 = {value: this.zot2, oldValue};
}
} as PropertyDeclaration,
// object satisfying defined custom type.
foo2: {type: Number, validator: (value: number) => Math.min(10, Math.max(value, 0))}
foo2: {
type: Number,
validator: (value: number) => Math.min(10, Math.max(value, 0))
}
};
}
}
Expand Down

0 comments on commit 0eda741

Please sign in to comment.