Merge "Migrate plugin endpoint components to lit" into stable-3.6
diff --git a/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator.ts b/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator.ts
index 8a01ef7..64548ac 100644
--- a/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator.ts
@@ -1,39 +1,24 @@
/**
* @license
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
*/
-import {PolymerElement} from '@polymer/polymer/polymer-element';
-import {htmlTemplate} from './gr-endpoint-decorator_html';
+import {html, LitElement} from 'lit';
+import {customElement, property} from 'lit/decorators';
import {
getPluginEndpoints,
ModuleInfo,
} from '../../shared/gr-js-api-interface/gr-plugin-endpoints';
import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader';
-import {customElement, property} from '@polymer/decorators';
import {PluginApi} from '../../../api/plugin';
import {HookApi, PluginElement} from '../../../api/hook';
import {getAppContext} from '../../../services/app-context';
+import {assertIsDefined} from '../../../utils/common-util';
const INIT_PROPERTIES_TIMEOUT_MS = 10000;
@customElement('gr-endpoint-decorator')
-export class GrEndpointDecorator extends PolymerElement {
- static get template() {
- return htmlTemplate;
- }
-
+export class GrEndpointDecorator extends LitElement {
/**
* If set, then this endpoint only invokes callbacks registered by the target
* plugin. For example this is used for the `check-result-expanded` endpoint.
@@ -43,39 +28,51 @@
@property({type: String})
targetPlugin?: string;
+ /** Required. */
@property({type: String})
- name!: string;
+ name?: string;
- @property({type: Object})
- _domHooks = new Map<PluginElement, HookApi<PluginElement>>();
+ private readonly domHooks = new Map<PluginElement, HookApi<PluginElement>>();
- @property({type: Object})
- _initializedPlugins = new Map<string, boolean>();
-
- /**
- * This is the callback that the plugin endpoint manager should be calling
- * when a new element is registered for this endpoint. It points to
- * _initModule().
- */
- _endpointCallBack: (info: ModuleInfo) => void = () => {};
+ private readonly initializedPlugins = new Map<string, boolean>();
private readonly reporting = getAppContext().reportingService;
+ override render() {
+ return html`<slot></slot>`;
+ }
+
+ override connectedCallback() {
+ super.connectedCallback();
+ assertIsDefined(this.name);
+ getPluginEndpoints().onNewEndpoint(this.name, this.initModule);
+ getPluginLoader()
+ .awaitPluginsLoaded()
+ .then(() => {
+ assertIsDefined(this.name);
+ const modules = getPluginEndpoints().getDetails(this.name);
+ for (const module of modules) {
+ this.initModule(module);
+ }
+ });
+ }
+
override disconnectedCallback() {
- for (const [el, domHook] of this._domHooks) {
+ for (const [el, domHook] of this.domHooks) {
domHook.handleInstanceDetached(el);
}
- getPluginEndpoints().onDetachedEndpoint(this.name, this._endpointCallBack);
+ assertIsDefined(this.name);
+ getPluginEndpoints().onDetachedEndpoint(this.name, this.initModule);
super.disconnectedCallback();
}
- _initDecoration(
+ private initDecoration(
name: string,
plugin: PluginApi,
slot?: string
): Promise<HTMLElement> {
const el = document.createElement(name) as PluginElement;
- return this._initProperties(
+ return this.initProperties(
el,
plugin,
// The direct children are slotted into <slot>, so this is identical to
@@ -88,13 +85,16 @@
if (slot && slotEl?.parentNode) {
slotEl.parentNode.insertBefore(el, slotEl.nextSibling);
} else {
- this._appendChild(el);
+ this.appendChild(el);
}
return el;
});
}
- _initReplacement(name: string, plugin: PluginApi): Promise<HTMLElement> {
+ private initReplacement(
+ name: string,
+ plugin: PluginApi
+ ): Promise<HTMLElement> {
// The direct children are slotted into <slot>, so they are identical to
// this.shadowRoot.querySelector('slot').assignedElements().
const directChildren = [...this.childNodes];
@@ -104,16 +104,16 @@
.filter(node => node.nodeName !== 'SLOT')
.forEach(node => node.remove());
const el = document.createElement(name);
- return this._initProperties(el, plugin).then((el: HTMLElement) =>
- this._appendChild(el)
+ return this.initProperties(el, plugin).then((el: HTMLElement) =>
+ this.appendChild(el)
);
}
- _getEndpointParams() {
+ private getEndpointParams() {
return Array.from(this.querySelectorAll('gr-endpoint-param'));
}
- _initProperties(
+ private initProperties(
el: PluginElement,
plugin: PluginApi,
content?: Element | null
@@ -128,7 +128,7 @@
if (content) {
el.content = content as HTMLElement;
}
- const expectProperties = this._getEndpointParams().map(paramEl => {
+ const expectProperties = this.getEndpointParams().map(paramEl => {
const helper = plugin.attributeHelper(paramEl);
// TODO: this should be replaced by accessing the property directly
const paramName = paramEl.getAttribute('name');
@@ -170,53 +170,40 @@
});
}
- _appendChild(el: HTMLElement): HTMLElement {
- if (!this.root) throw Error('plugin endpoint decorator missing root');
- return this.root.appendChild(el);
- }
-
- _initModule({moduleName, plugin, type, domHook, slot}: ModuleInfo) {
+ private readonly initModule = ({
+ moduleName,
+ plugin,
+ type,
+ domHook,
+ slot,
+ }: ModuleInfo) => {
const name = plugin.getPluginName() + '.' + moduleName;
if (this.targetPlugin) {
if (this.targetPlugin !== plugin.getPluginName()) return;
}
- if (this._initializedPlugins.get(name)) {
+ if (this.initializedPlugins.get(name)) {
return;
}
let initPromise;
switch (type) {
case 'decorate':
- initPromise = this._initDecoration(moduleName, plugin, slot);
+ initPromise = this.initDecoration(moduleName, plugin, slot);
break;
case 'replace':
- initPromise = this._initReplacement(moduleName, plugin);
+ initPromise = this.initReplacement(moduleName, plugin);
break;
}
if (!initPromise) {
throw Error(`unknown endpoint type ${type} used by plugin ${name}`);
}
- this._initializedPlugins.set(name, true);
+ this.initializedPlugins.set(name, true);
initPromise.then(el => {
if (domHook) {
domHook.handleInstanceAttached(el);
- this._domHooks.set(el, domHook);
+ this.domHooks.set(el, domHook);
}
});
- }
-
- override ready() {
- super.ready();
- if (!this.name) return;
- this._endpointCallBack = (info: ModuleInfo) => this._initModule(info);
- getPluginEndpoints().onNewEndpoint(this.name, this._endpointCallBack);
- getPluginLoader()
- .awaitPluginsLoaded()
- .then(() =>
- getPluginEndpoints()
- .getDetails(this.name)
- .forEach(this._initModule, this)
- );
- }
+ };
}
declare global {
diff --git a/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator_html.ts b/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator_html.ts
deleted file mode 100644
index 94196df..0000000
--- a/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator_html.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * @license
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {html} from '@polymer/polymer/lib/utils/html-tag';
-
-export const htmlTemplate = html` <slot></slot> `;
diff --git a/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator_test.ts b/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator_test.ts
index f5096ea..d7acc61 100644
--- a/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator_test.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator_test.ts
@@ -1,60 +1,75 @@
/**
* @license
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Copyright 2020 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
*/
-
import '../../../test/common-test-setup-karma';
import './gr-endpoint-decorator';
import '../gr-endpoint-param/gr-endpoint-param';
import '../gr-endpoint-slot/gr-endpoint-slot';
-import {html} from '@polymer/polymer/lib/utils/html-tag';
-import {resetPlugins} from '../../../test/test-utils';
+import {fixture, html} from '@open-wc/testing-helpers';
+import {
+ mockPromise,
+ queryAndAssert,
+ resetPlugins,
+} from '../../../test/test-utils';
import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader';
import {GrEndpointDecorator} from './gr-endpoint-decorator';
import {PluginApi} from '../../../api/plugin';
import {GrEndpointParam} from '../gr-endpoint-param/gr-endpoint-param';
-const basicFixture = fixtureFromTemplate(
- html`<div>
- <gr-endpoint-decorator name="first">
- <gr-endpoint-param name="someparam" value="barbar"></gr-endpoint-param>
- <p>
- <span>test slot</span>
- <gr-endpoint-slot name="test"></gr-endpoint-slot>
- </p>
- </gr-endpoint-decorator>
- <gr-endpoint-decorator name="second">
- <gr-endpoint-param name="someparam" value="foofoo"></gr-endpoint-param>
- </gr-endpoint-decorator>
- <gr-endpoint-decorator name="banana">
- <gr-endpoint-param name="someParam" value="yes"></gr-endpoint-param>
- </gr-endpoint-decorator>
- </div>`
-);
-
suite('gr-endpoint-decorator', () => {
- let container: GrEndpointDecorator;
+ let container: HTMLElement;
let plugin: PluginApi;
let decorationHook: any;
let decorationHookWithSlot: any;
let replacementHook: any;
+ let first: GrEndpointDecorator;
+ let second: GrEndpointDecorator;
+ let banana: GrEndpointDecorator;
setup(async () => {
resetPlugins();
- container = basicFixture.instantiate() as GrEndpointDecorator;
+ container = await fixture(
+ html`<div>
+ <gr-endpoint-decorator name="first">
+ <gr-endpoint-param
+ name="first-param"
+ .value=${'barbar'}
+ ></gr-endpoint-param>
+ <p>
+ <span>test slot</span>
+ <gr-endpoint-slot name="test"></gr-endpoint-slot>
+ </p>
+ </gr-endpoint-decorator>
+ <gr-endpoint-decorator name="second">
+ <gr-endpoint-param
+ name="second-param"
+ .value=${'foofoo'}
+ ></gr-endpoint-param>
+ </gr-endpoint-decorator>
+ <gr-endpoint-decorator name="banana">
+ <gr-endpoint-param
+ name="banana-param"
+ .value=${'yes'}
+ ></gr-endpoint-param>
+ </gr-endpoint-decorator>
+ </div>`
+ );
+ first = queryAndAssert<GrEndpointDecorator>(
+ container,
+ 'gr-endpoint-decorator[name="first"]'
+ );
+ second = queryAndAssert<GrEndpointDecorator>(
+ container,
+ 'gr-endpoint-decorator[name="second"]'
+ );
+ banana = queryAndAssert<GrEndpointDecorator>(
+ container,
+ 'gr-endpoint-decorator[name="banana"]'
+ );
+
window.Gerrit.install(
p => {
plugin = p;
@@ -64,18 +79,33 @@
);
// Decoration
decorationHook = plugin.registerCustomComponent('first', 'some-module');
+ const decorationHookPromise = mockPromise();
+ decorationHook.onAttached(() => decorationHookPromise.resolve());
+
+ // Decoration with slot
decorationHookWithSlot = plugin.registerCustomComponent(
'first',
'some-module-2',
{slot: 'test'}
);
+ const decorationHookSlotPromise = mockPromise();
+ decorationHookWithSlot.onAttached(() =>
+ decorationHookSlotPromise.resolve()
+ );
+
// Replacement
replacementHook = plugin.registerCustomComponent('second', 'other-module', {
replace: true,
});
+ const replacementHookPromise = mockPromise();
+ replacementHook.onAttached(() => replacementHookPromise.resolve());
+
// Mimic all plugins loaded.
getPluginLoader().loadPlugins([]);
- await flush();
+
+ await decorationHookPromise;
+ await decorationHookSlotPromise;
+ await replacementHookPromise;
});
teardown(() => {
@@ -89,17 +119,15 @@
assert.equal(endpoints.length, 3);
});
- test('decoration', () => {
- const element = container.querySelector(
- 'gr-endpoint-decorator[name="first"]'
- ) as GrEndpointDecorator;
- const modules = Array.from(element.root!.children).filter(
+ test('first decoration', () => {
+ const element = first;
+ const modules = Array.from(element.children).filter(
element => element.nodeName === 'SOME-MODULE'
);
assert.equal(modules.length, 1);
const [module] = modules;
assert.isOk(module);
- assert.equal((module as any)['someparam'], 'barbar');
+ assert.equal((module as any)['first-param'], 'barbar');
return decorationHook
.getLastAttached()
.then((element: any) => {
@@ -112,14 +140,12 @@
});
test('decoration with slot', () => {
- const element = container.querySelector(
- 'gr-endpoint-decorator[name="first"]'
- ) as GrEndpointDecorator;
+ const element = first;
const modules = [...element.querySelectorAll('some-module-2')];
assert.equal(modules.length, 1);
const [module] = modules;
assert.isOk(module);
- assert.equal((module as any)['someparam'], 'barbar');
+ assert.equal((module as any)['first-param'], 'barbar');
return decorationHookWithSlot
.getLastAttached()
.then((element: any) => {
@@ -132,14 +158,12 @@
});
test('replacement', () => {
- const element = container.querySelector(
- 'gr-endpoint-decorator[name="second"]'
- ) as GrEndpointDecorator;
- const module = Array.from(element.root!.children).find(
+ const element = second;
+ const module = Array.from(element.children).find(
element => element.nodeName === 'OTHER-MODULE'
);
assert.isOk(module);
- assert.equal((module as any)['someparam'], 'foofoo');
+ assert.equal((module as any)['second-param'], 'foofoo');
return replacementHook
.getLastAttached()
.then((element: any) => {
@@ -152,73 +176,92 @@
});
test('late registration', async () => {
- plugin.registerCustomComponent('banana', 'noob-noob');
- await flush();
- const element = container.querySelector(
- 'gr-endpoint-decorator[name="banana"]'
- ) as GrEndpointDecorator;
- const module = Array.from(element.root!.children).find(
+ const bananaHook = plugin.registerCustomComponent('banana', 'noob-noob');
+ const bananaHookPromise = mockPromise();
+ bananaHook.onAttached(() => bananaHookPromise.resolve());
+ await bananaHookPromise;
+
+ const element = banana;
+ const module = Array.from(element.children).find(
element => element.nodeName === 'NOOB-NOOB'
);
assert.isOk(module);
});
test('two modules', async () => {
- plugin.registerCustomComponent('banana', 'mod-one');
- plugin.registerCustomComponent('banana', 'mod-two');
- await flush();
- const element = container.querySelector(
- 'gr-endpoint-decorator[name="banana"]'
- ) as GrEndpointDecorator;
- const module1 = Array.from(element.root!.children).find(
+ const bananaHook1 = plugin.registerCustomComponent('banana', 'mod-one');
+ const bananaHookPromise1 = mockPromise();
+ bananaHook1.onAttached(() => bananaHookPromise1.resolve());
+ await bananaHookPromise1;
+
+ const bananaHook = plugin.registerCustomComponent('banana', 'mod-two');
+ const bananaHookPromise2 = mockPromise();
+ bananaHook.onAttached(() => bananaHookPromise2.resolve());
+ await bananaHookPromise2;
+
+ const element = banana;
+ const module1 = Array.from(element.children).find(
element => element.nodeName === 'MOD-ONE'
);
assert.isOk(module1);
- const module2 = Array.from(element.root!.children).find(
+ const module2 = Array.from(element.children).find(
element => element.nodeName === 'MOD-TWO'
);
assert.isOk(module2);
});
test('late param setup', async () => {
- const element = container.querySelector(
- 'gr-endpoint-decorator[name="banana"]'
- ) as GrEndpointDecorator;
- const param = element.querySelector('gr-endpoint-param') as GrEndpointParam;
+ let element = banana;
+ const param = queryAndAssert<GrEndpointParam>(element, 'gr-endpoint-param');
param['value'] = undefined;
- plugin.registerCustomComponent('banana', 'noob-noob');
- await flush();
- let module = Array.from(element.root!.children).find(
+ await param.updateComplete;
+
+ const bananaHook = plugin.registerCustomComponent('banana', 'noob-noob');
+ const bananaHookPromise = mockPromise();
+ bananaHook.onAttached(() => bananaHookPromise.resolve());
+
+ element = queryAndAssert<GrEndpointDecorator>(
+ container,
+ 'gr-endpoint-decorator[name="banana"]'
+ );
+ let module = Array.from(element.children).find(
element => element.nodeName === 'NOOB-NOOB'
);
// Module waits for param to be defined.
assert.isNotOk(module);
const value = {abc: 'def'};
param.value = value;
+ await param.updateComplete;
+ await bananaHookPromise;
- await flush();
- module = Array.from(element.root!.children).find(
+ module = Array.from(element.children).find(
element => element.nodeName === 'NOOB-NOOB'
);
assert.isOk(module);
- assert.strictEqual((module as any)['someParam'], value);
+ assert.strictEqual((module as any)['banana-param'], value);
});
test('param is bound', async () => {
- const element = container.querySelector(
- 'gr-endpoint-decorator[name="banana"]'
- ) as GrEndpointDecorator;
- const param = element.querySelector('gr-endpoint-param') as GrEndpointParam;
+ const element = banana;
+ const param = queryAndAssert<GrEndpointParam>(element, 'gr-endpoint-param');
const value1 = {abc: 'def'};
const value2 = {def: 'abc'};
param.value = value1;
- plugin.registerCustomComponent('banana', 'noob-noob');
- await flush();
- const module = Array.from(element.root!.children).find(
+ await param.updateComplete;
+
+ const bananaHook = plugin.registerCustomComponent('banana', 'noob-noob');
+ const bananaHookPromise = mockPromise();
+ bananaHook.onAttached(() => bananaHookPromise.resolve());
+ await bananaHookPromise;
+
+ const module = Array.from(element.children).find(
element => element.nodeName === 'NOOB-NOOB'
);
- assert.strictEqual((module as any)['someParam'], value1);
+ assert.isOk(module);
+ assert.strictEqual((module as any)['banana-param'], value1);
+
param.value = value2;
- assert.strictEqual((module as any)['someParam'], value2);
+ await param.updateComplete;
+ assert.strictEqual((module as any)['banana-param'], value2);
});
});
diff --git a/polygerrit-ui/app/elements/plugins/gr-endpoint-param/gr-endpoint-param.ts b/polygerrit-ui/app/elements/plugins/gr-endpoint-param/gr-endpoint-param.ts
index ee89c86..5a00c37 100644
--- a/polygerrit-ui/app/elements/plugins/gr-endpoint-param/gr-endpoint-param.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-endpoint-param/gr-endpoint-param.ts
@@ -1,21 +1,10 @@
/**
* @license
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
*/
-import {PolymerElement} from '@polymer/polymer/polymer-element';
-import {customElement, property} from '@polymer/decorators';
+import {LitElement, PropertyValues} from 'lit';
+import {customElement, property} from 'lit/decorators';
declare global {
interface HTMLElementTagNameMap {
@@ -24,26 +13,18 @@
}
@customElement('gr-endpoint-param')
-export class GrEndpointParam extends PolymerElement {
- @property({type: String, reflectToAttribute: true})
+export class GrEndpointParam extends LitElement {
+ @property({type: String, reflect: true})
name = '';
- @property({
- type: Object,
- notify: true,
- observer: '_valueChanged',
- })
+ @property({type: Object})
value?: unknown;
- _valueChanged(value: unknown) {
- /* In polymer 2 the following change was made:
- "Property change notifications (property-changed events) aren't fired when
- the value changes as a result of a binding from the host"
- (see https://polymer-library.polymer-project.org/2.0/docs/about_20).
- To workaround this problem, we fire the event from the observer.
- In some cases this fire the event twice, but our code is
- ready for it.
- */
- this.dispatchEvent(new CustomEvent('value-changed', {detail: {value}}));
+ override willUpdate(changedProperties: PropertyValues) {
+ if (changedProperties.has('value')) {
+ this.dispatchEvent(
+ new CustomEvent('value-changed', {detail: {value: this.value}})
+ );
+ }
}
}
diff --git a/polygerrit-ui/app/elements/plugins/gr-endpoint-slot/gr-endpoint-slot.ts b/polygerrit-ui/app/elements/plugins/gr-endpoint-slot/gr-endpoint-slot.ts
index f15b046..d6d1866 100644
--- a/polygerrit-ui/app/elements/plugins/gr-endpoint-slot/gr-endpoint-slot.ts
+++ b/polygerrit-ui/app/elements/plugins/gr-endpoint-slot/gr-endpoint-slot.ts
@@ -1,21 +1,10 @@
/**
* @license
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Copyright 2020 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
*/
-import {PolymerElement} from '@polymer/polymer/polymer-element';
-import {customElement, property} from '@polymer/decorators';
+import {LitElement} from 'lit';
+import {customElement, property} from 'lit/decorators';
declare global {
interface HTMLElementTagNameMap {
@@ -28,7 +17,7 @@
* the registered element should appear inside of the endpoint.
*/
@customElement('gr-endpoint-slot')
-export class GrEndpointSlot extends PolymerElement {
+export class GrEndpointSlot extends LitElement {
@property({type: String})
name!: string;
}
@@ -40,6 +29,6 @@
* This should help catch errors when you assign an element without
* name to GrEndpointSlot type.
*/
-export interface GrEndpointSlot extends PolymerElement {
+export interface GrEndpointSlot extends LitElement {
name: string;
}