diff --git a/.changeset/fluffy-garlics-smash.md b/.changeset/fluffy-garlics-smash.md new file mode 100644 index 0000000000..22bd71f104 --- /dev/null +++ b/.changeset/fluffy-garlics-smash.md @@ -0,0 +1,5 @@ +--- +'@lit/context': patch +--- + +Fix context types to be compatible with WCCG context protocol types. diff --git a/packages/context/src/lib/context-request-event.ts b/packages/context/src/lib/context-request-event.ts index 1dfc67938c..cea31e458b 100644 --- a/packages/context/src/lib/context-request-event.ts +++ b/packages/context/src/lib/context-request-event.ts @@ -53,7 +53,7 @@ export class ContextRequestEvent> { readonly context: C; readonly callback: ContextCallback>; - readonly subscribe: boolean; + readonly subscribe?: boolean; /** * diff --git a/packages/context/src/test/protocol-types-test.ts b/packages/context/src/test/protocol-types-test.ts new file mode 100644 index 0000000000..21eb72a0ae --- /dev/null +++ b/packages/context/src/test/protocol-types-test.ts @@ -0,0 +1,26 @@ +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ + +import {ContextRequestEvent, Context} from './protocol-types.js'; +import {ContextRequestEvent as LitContextRequestEvent} from '../lib/context-request-event.js'; +import {Context as LitContext} from '../index.js'; + +/* + * These function definitions check whether the Lit and protocol types are + * compatible. + */ + +export const protocolFunction = ( + e: ContextRequestEvent> +) => { + litFunction(e); +}; + +export const litFunction = ( + e: LitContextRequestEvent> +) => { + protocolFunction(e); +}; diff --git a/packages/context/src/test/protocol-types.ts b/packages/context/src/test/protocol-types.ts new file mode 100644 index 0000000000..06c9c6da35 --- /dev/null +++ b/packages/context/src/test/protocol-types.ts @@ -0,0 +1,68 @@ +// Copied from https://github.com/webcomponents-cg/community-protocols/blob/main/proposals/context.md#definitions +// at 43f8158a75446af25164ff35d1a6b4f9e96e9d36 + +/** + * A context key. + * + * A context key can be any type of object, including strings and symbols. The + * Context type brands the key type with the `__context__` property that + * carries the type of the value the context references. + */ +export type Context = KeyType & {__context__: ValueType}; + +/** + * An unknown context type + */ +export type UnknownContext = Context; + +/** + * A helper type which can extract a Context value type from a Context type + */ +export type ContextType = + // eslint-disable-next-line @typescript-eslint/no-unused-vars + T extends Context ? V : never; + +/** + * A function which creates a Context value object + */ +export const createContext = (key: unknown) => + key as Context; + +/** + * A callback which is provided by a context requester and is called with the value satisfying the request. + * This callback can be called multiple times by context providers as the requested value is changed. + */ +export type ContextCallback = ( + value: ValueType, + unsubscribe?: () => void +) => void; + +/** + * An event fired by a context requester to signal it desires a named context. + * + * A provider should inspect the `context` property of the event to determine if it has a value that can + * satisfy the request, calling the `callback` with the requested value if so. + * + * If the requested context event contains a truthy `subscribe` value, then a provider can call the callback + * multiple times if the value is changed, if this is the case the provider should pass an `unsubscribe` + * function to the callback which requesters can invoke to indicate they no longer wish to receive these updates. + */ +export class ContextRequestEvent extends Event { + public constructor( + public readonly context: T, + public readonly callback: ContextCallback>, + public readonly subscribe?: boolean + ) { + super('context-request', {bubbles: true, composed: true}); + } +} + +declare global { + interface HTMLElementEventMap { + /** + * A 'context-request' event can be emitted by any element which desires + * a context value to be injected by an external provider. + */ + 'context-request': ContextRequestEvent>; + } +}