diff --git a/package-lock.json b/package-lock.json index 8581eef79..d3af9f27e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -688,9 +688,9 @@ } }, "node_modules/@lit-labs/task": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@lit-labs/task/-/task-1.1.2.tgz", - "integrity": "sha512-wR6FpzaAwRMcMx/kfH0qmmOVv78gEzz4sXGYt2QBW4EkL6sAd0rC3VgwxnIAa4sWIk4z78k+gJxt6g8uPnaHKQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@lit-labs/task/-/task-3.0.2.tgz", + "integrity": "sha512-X6d+KWZR3q1ZrXs/auM5PbZcW3B5RlpU4gqk/upstwTZM6JN19P6o9Qgo+qjovIDsUZsYnlGQqtdPBwPrKzLUA==", "dependencies": { "@lit/reactive-element": "^1.1.0" } @@ -9143,7 +9143,7 @@ "dependencies": { "@lit-labs/motion": "^1.0.1", "@lit-labs/react": "^1.0.8", - "@lit-labs/task": "^1.0.0", + "@lit-labs/task": "^3.0.2", "@lit/localize": "^0.10.0", "@material/mwc-button": "^0.27.0", "@material/mwc-checkbox": "^0.27.0", @@ -9887,9 +9887,9 @@ "integrity": "sha512-92uQ5ARf7UXYrzaFcAX3T2rTvaS9Z1//ukV+DqjACM4c8s0ZBQd7ayJU5Dh2AFLD/Ayuyz4uMmxQec8q3U4Ong==" }, "@lit-labs/task": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@lit-labs/task/-/task-1.1.2.tgz", - "integrity": "sha512-wR6FpzaAwRMcMx/kfH0qmmOVv78gEzz4sXGYt2QBW4EkL6sAd0rC3VgwxnIAa4sWIk4z78k+gJxt6g8uPnaHKQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@lit-labs/task/-/task-3.0.2.tgz", + "integrity": "sha512-X6d+KWZR3q1ZrXs/auM5PbZcW3B5RlpU4gqk/upstwTZM6JN19P6o9Qgo+qjovIDsUZsYnlGQqtdPBwPrKzLUA==", "requires": { "@lit/reactive-element": "^1.1.0" } @@ -14365,7 +14365,7 @@ "@lit-labs/react": "^1.0.8", "@lit-labs/ssr": "^3.1.2", "@lit-labs/ssr-client": "^1.1.1", - "@lit-labs/task": "^1.0.0", + "@lit-labs/task": "^3.0.2", "@lit/localize": "^0.10.0", "@material/mwc-button": "^0.27.0", "@material/mwc-checkbox": "^0.27.0", diff --git a/packages/lit-dev-content/package.json b/packages/lit-dev-content/package.json index 61ac11fad..0e3f7c177 100644 --- a/packages/lit-dev-content/package.json +++ b/packages/lit-dev-content/package.json @@ -196,7 +196,7 @@ "dependencies": { "@lit-labs/motion": "^1.0.1", "@lit-labs/react": "^1.0.8", - "@lit-labs/task": "^1.0.0", + "@lit-labs/task": "^3.0.2", "@lit/localize": "^0.10.0", "@material/mwc-button": "^0.27.0", "@material/mwc-checkbox": "^0.27.0", diff --git a/packages/lit-dev-content/samples/examples/async-task/index.html b/packages/lit-dev-content/samples/examples/async-task/index.html index c23eb4db4..8099c92be 100644 --- a/packages/lit-dev-content/samples/examples/async-task/index.html +++ b/packages/lit-dev-content/samples/examples/async-task/index.html @@ -1,7 +1,9 @@ - - - - + + + + - + diff --git a/packages/lit-dev-content/samples/examples/async-task/index.js b/packages/lit-dev-content/samples/examples/async-task/index.js deleted file mode 100644 index 1c645e83a..000000000 --- a/packages/lit-dev-content/samples/examples/async-task/index.js +++ /dev/null @@ -1,27 +0,0 @@ -import { LitElement, css, html } from 'lit'; -import './npm-info.js'; - -export class DemoElement extends LitElement { - static properties = { - package: String, - }; - - constructor() { - super(); - this.package = 'lit-element'; - } - - render() { - return html` - - - `; - } - - _onChange(e) { - this.package = e.target.value; - } -} -customElements.define('demo-element', DemoElement); diff --git a/packages/lit-dev-content/samples/examples/async-task/npm-info.js b/packages/lit-dev-content/samples/examples/async-task/npm-info.js deleted file mode 100644 index 3dc38991a..000000000 --- a/packages/lit-dev-content/samples/examples/async-task/npm-info.js +++ /dev/null @@ -1,87 +0,0 @@ -import { LitElement, css, html } from 'lit-element'; -import { Task } from './task.js'; - -export class NpmInfoElement extends LitElement { - - static styles = css` - :host { - display: block; - min-width: 480px; - border-radius: 5px; - border: solid 1px #aaa; - padding: 20px; - } - header { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - } - #logo { - height: 38px; - width: auto; - } - `; - - static properties = { - package: String, - }; - - /** - * This is the task that fetches from npm. - * - * It's given: - * - `this`: A reference to the host so it can trigger updates - * - An async compute function - * - A dependencies provider function - */ - _fetchNpmInfoTask = new Task(this, async (pkg) => { - if (pkg === undefined || pkg === '') { - // InitialStateError indicates that we haven't started a Task - // It's neither pending, complete, or in error - throw new InitialStateError(); - } - const response = await fetch(getPackageUrl(pkg)); - if (response.status === 200) { - return response.json(); - } else { - throw response.text(); - } - }, () => [this.package]); - - render() { - return html` -
-

${this.package}

- ${npmLogo} -
-
- ${this._fetchNpmInfoTask.render({ - complete: (pkg) => html` -

${pkg.description}

-

dist-tags:

- - `, - error: (e) => `Error ${e.message}`, - pending: () => 'Loading...', - initial: () => 'Enter a Package Name', - })} -
- `; - } -} -customElements.define('npm-info', NpmInfoElement); - -const getPackageUrl = (name) => `https://cors-anywhere.herokuapp.com/registry.npmjs.org/${name}`; - -const npmLogo = html` - -`; diff --git a/packages/lit-dev-content/samples/examples/async-task/npm-info.ts b/packages/lit-dev-content/samples/examples/async-task/npm-info.ts new file mode 100644 index 000000000..b4a71353f --- /dev/null +++ b/packages/lit-dev-content/samples/examples/async-task/npm-info.ts @@ -0,0 +1,77 @@ +import {LitElement, css, html} from 'lit'; +import {customElement, state} from 'lit/decorators.js'; +import {Task} from '@lit-labs/task'; +import {fetchPackageInfo} from './npm.js'; + +@customElement('npm-info') +export class NpmInfo extends LitElement { + @state() + private _package = 'lit'; + + private _fetchNpmInfoTask = new Task(this, { + task: async ([pkgName], {signal}) => { + if (pkgName === undefined || pkgName === '') { + throw new Error('Empty package name'); + } + return await fetchPackageInfo(pkgName, signal); + }, + args: () => [this._package], + }); + + render() { + return html` + +
+

${this._package}

+ +
+
+ ${this._fetchNpmInfoTask.render({ + pending: () => 'Loading...', + complete: (pkg) => html` +

${pkg.description}

+

dist-tags:

+ + `, + error: (e) => `Error: ${(e as Error).message}`, + })} +
+ `; + } + + private _onChange(e: Event) { + this._package = (e.target as HTMLInputElement).value; + } + + static styles = css` + :host { + display: block; + min-width: 300px; + border-radius: 5px; + border: solid 1px #aaa; + padding: 20px; + } + header { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + } + #logo { + height: 38px; + width: auto; + } + `; +} + diff --git a/packages/lit-dev-content/samples/examples/async-task/npm.ts b/packages/lit-dev-content/samples/examples/async-task/npm.ts new file mode 100644 index 000000000..e0eedbb81 --- /dev/null +++ b/packages/lit-dev-content/samples/examples/async-task/npm.ts @@ -0,0 +1,20 @@ +export interface NpmPackage { + description: string; + ['dist-tags']: {[tag: string]: string}; +} + +export const fetchPackageInfo = async ( + pkgName: string, + signal: AbortSignal +): Promise => { + // Artifical delay for demo purposes + await new Promise((r) => setTimeout(r, 1000)); + const response = await fetch(`https://registry.npmjs.org/${pkgName}`, { + signal, + }); + if (response.status === 200) { + return response.json(); + } else { + throw response.text(); + } +}; diff --git a/packages/lit-dev-content/samples/examples/async-task/project.json b/packages/lit-dev-content/samples/examples/async-task/project.json index cacc82429..176084d49 100644 --- a/packages/lit-dev-content/samples/examples/async-task/project.json +++ b/packages/lit-dev-content/samples/examples/async-task/project.json @@ -1,13 +1,11 @@ { "extends": "/samples/base.json", - "hide": true, "title": "Async Task / NPM Info element", "description": "Shows an example of an async Task controller. This one fetches npm package info and renders based on the state of the fetch.", - "section": "Specific Solutions", + "section": "Managing Data", "files": { - "index.js": {}, - "npm-info.js": {}, - "task.js": {}, + "npm-info.ts": {}, + "npm.ts": {}, "index.html": {} } } diff --git a/packages/lit-dev-content/samples/v2-docs/controllers/names/names-controller.ts b/packages/lit-dev-content/samples/v2-docs/controllers/names/names-controller.ts index 59061c868..b849ce705 100644 --- a/packages/lit-dev-content/samples/v2-docs/controllers/names/names-controller.ts +++ b/packages/lit-dev-content/samples/v2-docs/controllers/names/names-controller.ts @@ -6,7 +6,7 @@ export class NamesController { host: ReactiveControllerHost; value?: string[]; readonly kinds = Names.kinds; - private task!: Task; + private task!: Task<[Names.Kind], Names.Result>; private _kind: Names.Kind = ''; constructor(host: ReactiveControllerHost) { diff --git a/packages/lit-dev-content/samples/v3-docs/controllers/names/names-controller.ts b/packages/lit-dev-content/samples/v3-docs/controllers/names/names-controller.ts index 59061c868..b849ce705 100644 --- a/packages/lit-dev-content/samples/v3-docs/controllers/names/names-controller.ts +++ b/packages/lit-dev-content/samples/v3-docs/controllers/names/names-controller.ts @@ -6,7 +6,7 @@ export class NamesController { host: ReactiveControllerHost; value?: string[]; readonly kinds = Names.kinds; - private task!: Task; + private task!: Task<[Names.Kind], Names.Result>; private _kind: Names.Kind = ''; constructor(host: ReactiveControllerHost) { diff --git a/packages/lit-dev-content/site/_data/playground_examples.js b/packages/lit-dev-content/site/_data/playground_examples.js index 18a087333..bafdc724d 100644 --- a/packages/lit-dev-content/site/_data/playground_examples.js +++ b/packages/lit-dev-content/site/_data/playground_examples.js @@ -12,6 +12,7 @@ const topSectionOrder = [ 'Reactive properties', 'Template concepts', 'Directives', + 'Managing Data', '@lit-labs/react', '@lit-labs/motion' ];