diff --git a/.github/skills/typescript/SKILL.md b/.github/skills/typescript/SKILL.md index a72686fecf8..e57e9e796d4 100644 --- a/.github/skills/typescript/SKILL.md +++ b/.github/skills/typescript/SKILL.md @@ -47,11 +47,12 @@ await MyElement.define({ Use `compose()` when registration should be deferred — downstream libraries like Fluent Web Components use this pattern with a design-system registry. `compose()` returns a -`Promise` that always resolves immediately: +`FASTElementDefinition` synchronously, or a `Promise` when the +definition's `template` is a resolver: ```ts // my-element.definition.ts -export const definition = await MyElement.compose({ +export const definition = MyElement.compose({ name: "my-element", template, styles, @@ -61,6 +62,17 @@ export const definition = await MyElement.compose({ definition.define(); ``` +```ts +// my-element.definition-async.ts +export const declarativeDefinition = MyElement.compose({ + name: "my-element", + template: declarativeTemplate(), +}); + +// define.ts (side-effect import) +void declarativeDefinition.then(definition => definition.define()); +``` + ## Templates Templates use the `html` tagged template literal typed to the element class: diff --git a/change/@microsoft-fast-element-269e7b6d-2eaf-45a5-9643-391c9d9fde68.json b/change/@microsoft-fast-element-269e7b6d-2eaf-45a5-9643-391c9d9fde68.json new file mode 100644 index 00000000000..9a27ea511f9 --- /dev/null +++ b/change/@microsoft-fast-element-269e7b6d-2eaf-45a5-9643-391c9d9fde68.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Return compose() synchronously unless a template resolver is provided; only resolver-bearing definitions yield a Promise.", + "packageName": "@microsoft/fast-element", + "email": "863023+radium-v@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/examples/csr/todo-mobx-app/src/main.ts b/examples/csr/todo-mobx-app/src/main.ts index 211838ec6e5..f43a49aea38 100644 --- a/examples/csr/todo-mobx-app/src/main.ts +++ b/examples/csr/todo-mobx-app/src/main.ts @@ -8,4 +8,4 @@ import "./todo-form.js"; // lifetime of the page. connectStoreToStorage(todoStore, "fast-todo-mobx-app"); -void app.then(definition => definition.define()); +app.define(); diff --git a/packages/fast-element/DESIGN.md b/packages/fast-element/DESIGN.md index 6e576558dbc..8494fe555d4 100644 --- a/packages/fast-element/DESIGN.md +++ b/packages/fast-element/DESIGN.md @@ -176,7 +176,7 @@ logging, telemetry, or a devtools panel. - `onAttributeChangedCallback()` is the standard handler that processes attribute changes. During the prerendered bind, it is temporarily swapped to a no-op (see above) to avoid redundant processing of server-rendered attribute values. - Exposes `addBehavior` / `removeBehavior` for dynamic `HostBehavior` management (used by `ElementStyles`). -`FASTElementDefinition` wraps all the metadata for a custom element class: its tag name, template, styles, and observed attribute list. It is created by `FASTElement.compose()` (which returns `Promise`, always resolving immediately) and registered globally via `fastElementRegistry`. Consumers that need focused access to definition lookup can import `fastElementRegistry` from `@microsoft/fast-element/registry.js`. `PartialFASTElementDefinition.template` may be either a concrete `ElementViewTemplate>` or a `FASTElementTemplateResolver` function that receives the composed definition and returns the concrete template (sync or async). `FASTElementDefinition.template` always stores the concrete `ElementViewTemplate>` after composition or resolver settlement. The subclass static `define()` method returns `Promise` — resolving immediately for complete definitions or definitions without an initial template, and resolving async template resolver functions only after extensions have had a chance to update the definition. `FASTElementDefinition.register()` returns `Promise` — resolving when a definition with the given name has been registered. +`FASTElementDefinition` wraps all the metadata for a custom element class: its tag name, template, styles, and observed attribute list. It is created by `FASTElement.compose()` (which returns the definition synchronously, or a `Promise` when the definition's `template` is a resolver function) and registered globally via `fastElementRegistry`. Consumers that need focused access to definition lookup can import `fastElementRegistry` from `@microsoft/fast-element/registry.js`. `PartialFASTElementDefinition.template` may be either a concrete `ElementViewTemplate>` or a `FASTElementTemplateResolver` function that receives the composed definition and returns the concrete template (sync or async). `FASTElementDefinition.template` always stores the concrete `ElementViewTemplate>` after composition or resolver settlement. The subclass static `define()` method returns `Promise` — resolving immediately for complete definitions or definitions without an initial template, and resolving async template resolver functions only after extensions have had a chance to update the definition. `FASTElementDefinition.register()` returns `Promise` — resolving when a definition with the given name has been registered. #### Extensions diff --git a/packages/fast-element/MIGRATION.md b/packages/fast-element/MIGRATION.md index 77f3e8567c8..cbe5478333f 100644 --- a/packages/fast-element/MIGRATION.md +++ b/packages/fast-element/MIGRATION.md @@ -314,7 +314,7 @@ This is a **breaking change** for SSR output format. Any system that produces or | Removed | Replacement | |---|---| | `FASTElement.defineAsync()` | Subclass `define()` calls (now return `Promise`) | -| `FASTElementDefinition.composeAsync()` | `FASTElementDefinition.compose()` (now returns `Promise`) | +| `FASTElementDefinition.composeAsync()` | `FASTElementDefinition.compose()` (returns `Promise` when given a template resolver) | | `FASTElementDefinition.registerAsync()` | `FASTElementDefinition.register()` (same `Promise` return type) | ### Changed behavior @@ -323,8 +323,8 @@ This is a **breaking change** for SSR output format. Any system that produces or template is provided at definition time, the Promise resolves immediately. When `template: declarativeTemplate()` is used, the Promise resolves after the matching `` supplies the concrete template. -- **`FASTElement.compose()`** now returns `Promise`. The Promise always resolves immediately. -- **`FASTElementDefinition.compose()`** now returns `Promise`. The Promise always resolves immediately. +- **`FASTElement.compose()`** returns a `FASTElementDefinition` synchronously. It returns a `Promise` when the definition's `template` is a resolver function. +- **`FASTElementDefinition.compose()`** returns a `FASTElementDefinition` synchronously. It returns a `Promise` when the definition's `template` is a resolver function. - **`@customElement` decorator** calls `define()` internally but does not return the Promise (fire-and-forget). For complete definitions with a template, the element is registered via a microtask. ### Migration steps @@ -349,10 +349,16 @@ This is a **breaking change** for SSR output format. Any system that produces or ```typescript // Before - const def = await FASTElementDefinition.composeAsync(MyElement, name); + const def = await FASTElementDefinition.composeAsync(MyElement, { + name, + template: declarativeTemplate(), + }); // After - const def = await FASTElementDefinition.compose(MyElement, name); + const def = await FASTElementDefinition.compose(MyElement, { + name, + template: declarativeTemplate(), + }); ``` 3. Replace `registerAsync()` calls with `register()`: @@ -365,14 +371,15 @@ This is a **breaking change** for SSR output format. Any system that produces or const el = await FASTElementDefinition.register(name); ``` -4. Add `await` to `compose()` calls that chain `.define()`: +4. `compose()` calls that chain `.define()` stay synchronous unless `options` + passes a template resolver: ```typescript - // Before + // Concrete template or none — compose() is synchronous, no await needed FASTElementDefinition.compose(MyElement, options).define(); - // After - (await FASTElementDefinition.compose(MyElement, options)).define(); + // Resolver-backed template — compose() returns a Promise + (await FASTElementDefinition.compose(MyElement, resolverOptions)).define(); ``` ## Dynamic stylesheet behaviors (v3) diff --git a/packages/fast-element/SIZES.md b/packages/fast-element/SIZES.md index 0f9bfaac85a..353f07a7f4a 100644 --- a/packages/fast-element/SIZES.md +++ b/packages/fast-element/SIZES.md @@ -4,8 +4,8 @@ Bundle sizes for `@microsoft/fast-element` exports. | Export | Minified | Gzip | Brotli | |--------|----------|------|--------| -| CDN Rollup Bundle | 79.42 KB | 23.81 KB | 21.04 KB | -| FASTElement (@microsoft/fast-element/fast-element.js) | 23.84 KB | 7.39 KB | 6.65 KB | +| CDN Rollup Bundle | 79.50 KB | 23.82 KB | 21.04 KB | +| FASTElement (@microsoft/fast-element/fast-element.js) | 23.89 KB | 7.40 KB | 6.67 KB | | Updates (@microsoft/fast-element/updates.js) | 473 B | 335 B | 288 B | | Observable (@microsoft/fast-element/observable.js) | 6.77 KB | 2.52 KB | 2.24 KB | | observable (@microsoft/fast-element/observable.js) | 6.80 KB | 2.54 KB | 2.25 KB | @@ -18,8 +18,8 @@ Bundle sizes for `@microsoft/fast-element` exports. | html (@microsoft/fast-element/html.js) | 27.75 KB | 8.96 KB | 8.03 KB | | repeat (@microsoft/fast-element/repeat.js) | 31.82 KB | 10.01 KB | 9.03 KB | | css (@microsoft/fast-element/css.js) | 2.43 KB | 1.00 KB | 911 B | -| enableHydration (@microsoft/fast-element/hydration.js) | 45.56 KB | 13.82 KB | 12.42 KB | +| enableHydration (@microsoft/fast-element/hydration.js) | 45.59 KB | 13.83 KB | 12.43 KB | | declarativeTemplate (@microsoft/fast-element/declarative.js) | 62.88 KB | 19.72 KB | 17.59 KB | | ArrayObserver (@microsoft/fast-element/array-observer.js) | 12.57 KB | 4.47 KB | 4.03 KB | -| observerMap (@microsoft/fast-element/observer-map.js) | 20.61 KB | 7.33 KB | 6.59 KB | -| attributeMap (@microsoft/fast-element/attribute-map.js) | 15.84 KB | 5.60 KB | 5.05 KB | +| observerMap (@microsoft/fast-element/observer-map.js) | 20.64 KB | 7.34 KB | 6.61 KB | +| attributeMap (@microsoft/fast-element/attribute-map.js) | 15.88 KB | 5.61 KB | 5.06 KB | diff --git a/packages/fast-element/docs/api-report.api.md b/packages/fast-element/docs/api-report.api.md index 56b1f904454..5edefeaa9fe 100644 --- a/packages/fast-element/docs/api-report.api.md +++ b/packages/fast-element/docs/api-report.api.md @@ -538,8 +538,14 @@ export const FASTElement: FASTElementConstructor; // @public export interface FASTElementConstructor { new (): FASTElement; - compose = Constructable>(this: TType, nameOrDef: string | PartialFASTElementDefinition): Promise>; - compose = Constructable>(type: TType, nameOrDef?: string | PartialFASTElementDefinition): Promise>; + compose = Constructable>(this: TType, nameOrDef: PartialFASTElementDefinition & { + template: FASTElementTemplateResolver; + }): Promise>; + compose = Constructable>(this: TType, nameOrDef: string | PartialFASTElementDefinition): FASTElementDefinition; + compose = Constructable>(type: TType, nameOrDef: PartialFASTElementDefinition & { + template: FASTElementTemplateResolver; + }): Promise>; + compose = Constructable>(type: TType, nameOrDef?: string | PartialFASTElementDefinition): FASTElementDefinition; define = Constructable>(this: TType, nameOrDef: string | PartialFASTElementDefinition, extensions?: FASTElementExtension[]): Promise; define = Constructable>(type: TType, nameOrDef?: string | PartialFASTElementDefinition, extensions?: FASTElementExtension[]): Promise; from(BaseType: TBase): { @@ -551,7 +557,10 @@ export interface FASTElementConstructor { export class FASTElementDefinition = Constructable> { readonly attributeLookup: Record; readonly attributes: ReadonlyArray; - static compose = Constructable>(type: TType, nameOrDef?: string | PartialFASTElementDefinition): Promise>; + static compose = Constructable>(type: TType, nameOrDef: PartialFASTElementDefinition & { + template: FASTElementTemplateResolver; + }): Promise>; + static compose = Constructable>(type: TType, nameOrDef?: string | PartialFASTElementDefinition): FASTElementDefinition; define(registry?: CustomElementRegistry, extensions?: FASTElementExtension[]): this; readonly elementOptions: ElementDefinitionOptions; static readonly getByType: (key: Function) => FASTElementDefinition> | undefined; diff --git a/packages/fast-element/docs/declarative/api-report.api.md b/packages/fast-element/docs/declarative/api-report.api.md index d0a45d285c7..055301d5503 100644 --- a/packages/fast-element/docs/declarative/api-report.api.md +++ b/packages/fast-element/docs/declarative/api-report.api.md @@ -201,7 +201,10 @@ export interface EventCachedPath extends CachedPathCommon { export class FASTElementDefinition = Constructable> { readonly attributeLookup: Record; readonly attributes: ReadonlyArray; - static compose = Constructable>(type: TType, nameOrDef?: string | PartialFASTElementDefinition): Promise>; + static compose = Constructable>(type: TType, nameOrDef: PartialFASTElementDefinition & { + template: FASTElementTemplateResolver; + }): Promise>; + static compose = Constructable>(type: TType, nameOrDef?: string | PartialFASTElementDefinition): FASTElementDefinition; define(registry?: CustomElementRegistry, extensions?: FASTElementExtension[]): this; readonly elementOptions: ElementDefinitionOptions; static readonly getByType: (key: Function) => FASTElementDefinition> | undefined; diff --git a/packages/fast-element/src/components/fast-definitions.pw.spec.ts b/packages/fast-element/src/components/fast-definitions.pw.spec.ts index f861094f201..ef50c22790a 100644 --- a/packages/fast-element/src/components/fast-definitions.pw.spec.ts +++ b/packages/fast-element/src/components/fast-definitions.pw.spec.ts @@ -341,6 +341,131 @@ test.describe("FASTElementDefinition", () => { expect(def1Extends).toBe(true); expect(def2Extends).toBe(true); }); + + test("returns the definition synchronously when no template resolver is provided", async ({ + page, + }) => { + await page.goto("/"); + + const result = await page.evaluate(async () => { + const { FASTElementDefinition, uniqueElementName } = + // @ts-expect-error: Client module. + await import("/main.js"); + + class MyElement extends HTMLElement {} + + const composed = FASTElementDefinition.compose( + MyElement, + uniqueElementName(), + ); + + return { + isPromise: typeof composed?.then === "function", + isDefinition: composed instanceof FASTElementDefinition, + }; + }); + + expect(result.isPromise).toBe(false); + expect(result.isDefinition).toBe(true); + }); + + test("returns the definition synchronously when given a concrete template", async ({ + page, + }) => { + await page.goto("/"); + + const result = await page.evaluate(async () => { + const { FASTElement, FASTElementDefinition, html, uniqueElementName } = + // @ts-expect-error: Client module. + await import("/main.js"); + + class TestElement extends FASTElement {} + + const composed = FASTElementDefinition.compose(TestElement, { + name: uniqueElementName(), + template: html`concrete`, + }); + + return { + isPromise: typeof composed?.then === "function", + isDefinition: composed instanceof FASTElementDefinition, + hasTemplate: composed.template !== undefined, + }; + }); + + expect(result.isPromise).toBe(false); + expect(result.isDefinition).toBe(true); + expect(result.hasTemplate).toBe(true); + }); + + test("returns a Promise when a template resolver is provided", async ({ + page, + }) => { + await page.goto("/"); + + const result = await page.evaluate(async () => { + const { FASTElement, FASTElementDefinition, html, uniqueElementName } = + // @ts-expect-error: Client module. + await import("/main.js"); + + class TestElement extends FASTElement {} + + const template = html`resolved`; + const composed = FASTElementDefinition.compose(TestElement, { + name: uniqueElementName(), + template: () => template, + }); + + const isPromise = typeof composed?.then === "function"; + const definition = await composed; + + return { + isPromise, + isDefinition: definition instanceof FASTElementDefinition, + // compose does not run the resolver; the template is resolved + // later, during define(). + templateUnresolvedAfterCompose: definition.template === undefined, + }; + }); + + expect(result.isPromise).toBe(true); + expect(result.isDefinition).toBe(true); + expect(result.templateUnresolvedAfterCompose).toBe(true); + }); + + test("composes synchronously for compose(type) even when the type carries a resolver definition", async ({ + page, + }) => { + await page.goto("/"); + + const result = await page.evaluate(async () => { + const { FASTElement, FASTElementDefinition, html, uniqueElementName } = + // @ts-expect-error: Client module. + await import("/main.js"); + + const template = html`resolved`; + + class ResolverElement extends FASTElement { + static definition = { + name: uniqueElementName(), + template: () => template, + }; + } + + // No explicit `nameOrDef`, so the resolver is inherited from + // `ResolverElement.definition`. This must stay synchronous to + // keep the `compose(type)` overload sound. + const composed = FASTElementDefinition.compose(ResolverElement); + + return { + isPromise: typeof composed?.then === "function", + isDefinition: composed instanceof FASTElementDefinition, + }; + }); + + expect(result.isPromise).toBe(false); + expect(result.isDefinition).toBe(true); + }); }); test.describe("register async", () => { diff --git a/packages/fast-element/src/components/fast-definitions.ts b/packages/fast-element/src/components/fast-definitions.ts index 95bd9865c98..281b8074690 100644 --- a/packages/fast-element/src/components/fast-definitions.ts +++ b/packages/fast-element/src/components/fast-definitions.ts @@ -646,22 +646,58 @@ export class FASTElementDefinition< /** * Creates an instance of FASTElementDefinition. + * + * @param type - The type this definition is being created for. + * @param nameOrDef - A config object whose `template` is a resolver. + * @returns A promise that resolves to the composed FASTElementDefinition. + */ + public static compose< + TType extends Constructable = Constructable, + >( + type: TType, + nameOrDef: PartialFASTElementDefinition & { + template: FASTElementTemplateResolver; + }, + ): Promise>; + + /** + * Creates an instance of FASTElementDefinition. + * * @param type - The type this definition is being created for. * @param nameOrDef - The name of the element to define or a config object * that describes the element to define. + * @returns A composed FASTElementDefinition instance. */ public static compose< TType extends Constructable = Constructable, >( type: TType, nameOrDef?: string | PartialFASTElementDefinition, - ): Promise> { + ): FASTElementDefinition; + public static compose< + TType extends Constructable = Constructable, + >( + type: TType, + nameOrDef?: string | PartialFASTElementDefinition, + ): FASTElementDefinition | Promise> { const definition = fastElementBaseTypes.has(type) || fastElementRegistry.getByType(type) ? new FASTElementDefinition(class extends type {}, nameOrDef) : new FASTElementDefinition(type, nameOrDef); - return Promise.resolve(definition); + // Return a Promise when the caller passes a definition carrying a + // template resolver. Inspecting the constructed definition instead + // would make `compose(type)` asynchronous whenever the resolver is + // inherited from `type.definition`, breaking the synchronous overload. + if ( + nameOrDef != null && + !isString(nameOrDef) && + isFASTElementTemplateResolver(nameOrDef.template) + ) { + return Promise.resolve(definition); + } + + return definition; } /** diff --git a/packages/fast-element/src/components/fast-element.pw.spec.ts b/packages/fast-element/src/components/fast-element.pw.spec.ts index 5c0fc2c4a48..28b6e05a4e1 100644 --- a/packages/fast-element/src/components/fast-element.pw.spec.ts +++ b/packages/fast-element/src/components/fast-element.pw.spec.ts @@ -369,4 +369,61 @@ test.describe("FASTElement", () => { expect(result.shadowText).toContain("deferred"); }); }); + + test.describe("compose", () => { + test("composes synchronously when no template resolver is provided", async ({ + page, + }) => { + await page.goto("/"); + + const result = await page.evaluate(async () => { + const { FASTElement, FASTElementDefinition, uniqueElementName } = + // @ts-expect-error: Client module. + await import("/main.js"); + + class SyncElement extends FASTElement {} + + const composed = SyncElement.compose(uniqueElementName()); + + return { + isPromise: typeof composed?.then === "function", + isDefinition: composed instanceof FASTElementDefinition, + }; + }); + + expect(result.isPromise).toBe(false); + expect(result.isDefinition).toBe(true); + }); + + test("composes asynchronously when a template resolver is provided", async ({ + page, + }) => { + await page.goto("/"); + + const result = await page.evaluate(async () => { + const { FASTElement, FASTElementDefinition, html, uniqueElementName } = + // @ts-expect-error: Client module. + await import("/main.js"); + + class AsyncElement extends FASTElement {} + + const template = html`resolved`; + const composed = AsyncElement.compose({ + name: uniqueElementName(), + template: () => template, + }); + + const isPromise = typeof composed?.then === "function"; + const definition = await composed; + + return { + isPromise, + isDefinition: definition instanceof FASTElementDefinition, + }; + }); + + expect(result.isPromise).toBe(true); + expect(result.isDefinition).toBe(true); + }); + }); }); diff --git a/packages/fast-element/src/components/fast-element.ts b/packages/fast-element/src/components/fast-element.ts index 15172df4366..e5b126a5ceb 100644 --- a/packages/fast-element/src/components/fast-element.ts +++ b/packages/fast-element/src/components/fast-element.ts @@ -4,6 +4,7 @@ import { applyFASTElementExtensions, FASTElementDefinition, type FASTElementExtension, + type FASTElementTemplateResolver, type PartialFASTElementDefinition, resolveFASTElementTemplate, } from "./fast-definitions.js"; @@ -108,18 +109,56 @@ function createFASTElement( return type as any; } +/** + * Composes element metadata into a FASTElementDefinition instance. + * + * @param nameOrDef - A definition object with a template resolver. + * @returns A promise that resolves to the composed FASTElementDefinition. + */ +function compose = Constructable>( + this: TType, + nameOrDef: PartialFASTElementDefinition & { + template: FASTElementTemplateResolver; + }, +): Promise>; +/** + * Composes element metadata into a FASTElementDefinition instance. + * + * @param nameOrDef - The element's tag name, or a definition object describing the element. + * @returns A FASTElementDefinition instance. + */ function compose = Constructable>( this: TType, nameOrDef: string | PartialFASTElementDefinition, +): FASTElementDefinition; +/** + * Composes element metadata into a FASTElementDefinition instance. + * + * @param type - The custom element type to compose. + * @param nameOrDef - A definition object with a template resolver. + * @returns A promise that resolves to the composed FASTElementDefinition. + */ +function compose = Constructable>( + type: TType, + nameOrDef: PartialFASTElementDefinition & { + template: FASTElementTemplateResolver; + }, ): Promise>; +/** + * Composes element metadata into a FASTElementDefinition instance. + * + * @param type - The custom element type to compose. + * @param nameOrDef - The element's tag name, or a definition object describing the element. + * @returns A FASTElementDefinition instance. + */ function compose = Constructable>( type: TType, nameOrDef?: string | PartialFASTElementDefinition, -): Promise>; +): FASTElementDefinition; function compose = Constructable>( type: TType | string | PartialFASTElementDefinition, nameOrDef?: string | PartialFASTElementDefinition, -): Promise> { +): FASTElementDefinition | Promise> { if (isFunction(type)) { return FASTElementDefinition.compose(type, nameOrDef); } @@ -151,14 +190,14 @@ function define = Constructable | undefined, ) : FASTElementDefinition.compose(this, type); - return composePromise.then(def => { + return Promise.resolve(composed).then(def => { applyFASTElementExtensions(def, def.registry, extensions); const template = resolveFASTElementTemplate(def); @@ -210,22 +249,52 @@ export interface FASTElementConstructor { /** * Composes FASTElement metadata without registering the element. - * @param nameOrDef - The name of the element to compose or a definition object. + * + * @param nameOrDef - A definition object with a template resolver. + * @returns A promise that resolves to the composed FASTElementDefinition. + */ + compose = Constructable>( + this: TType, + nameOrDef: PartialFASTElementDefinition & { + template: FASTElementTemplateResolver; + }, + ): Promise>; + + /** + * Composes element metadata into a FASTElementDefinition instance. + * + * @param nameOrDef - The element's tag name, or a definition object describing the element. + * @returns A FASTElementDefinition instance. */ compose = Constructable>( this: TType, nameOrDef: string | PartialFASTElementDefinition, + ): FASTElementDefinition; + + /** + * Composes FASTElement metadata into a FASTElementDefinition instance. + * @param type - The custom element type to compose. + * @param nameOrDef - A definition object with a template resolver. + * @returns A promise that resolves to the composed FASTElementDefinition. + */ + compose = Constructable>( + type: TType, + nameOrDef: PartialFASTElementDefinition & { + template: FASTElementTemplateResolver; + }, ): Promise>; /** - * Composes FASTElement metadata without registering the element. + * Composes FASTElement metadata into a FASTElementDefinition instance. + * * @param type - The custom element type to compose. - * @param nameOrDef - The name of the element to compose or a definition object. + * @param nameOrDef - The element's tag name, or a definition object describing the element. + * @returns A FASTElementDefinition instance. */ compose = Constructable>( type: TType, nameOrDef?: string | PartialFASTElementDefinition, - ): Promise>; + ): FASTElementDefinition; /** * Creates a new FASTElement base class inherited from the provided base type. diff --git a/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.compose.md b/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.compose.md index a248e7f29cc..c52d8b130b3 100644 --- a/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.compose.md +++ b/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.compose.md @@ -20,7 +20,9 @@ Composes FASTElement metadata without registering the element. **Signature:** ```typescript -compose = Constructable>(this: TType, nameOrDef: string | PartialFASTElementDefinition): Promise>; +compose = Constructable>(this: TType, nameOrDef: PartialFASTElementDefinition & { + template: FASTElementTemplateResolver; + }): Promise>; ``` ## Parameters @@ -62,12 +64,12 @@ nameOrDef -string \| [PartialFASTElementDefinition](../fast-element.partialfastelementdefinition/)<TType> +[PartialFASTElementDefinition](../fast-element.partialfastelementdefinition/)<TType> & { template: [FASTElementTemplateResolver](../fast-element.fastelementtemplateresolver/)<TType>; } -The name of the element to compose or a definition object. +A definition object with a template resolver. @@ -76,3 +78,5 @@ The name of the element to compose or a definition object. **Returns:** Promise<[FASTElementDefinition](../fast-element.fastelementdefinition/)<TType>> + +A promise that resolves to the composed FASTElementDefinition. diff --git a/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.compose_1.md b/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.compose_1.md index 79d9b40313a..5df18842046 100644 --- a/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.compose_1.md +++ b/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.compose_1.md @@ -15,12 +15,12 @@ navigationOptions: ## FASTElementConstructor.compose() method -Composes FASTElement metadata without registering the element. +Composes element metadata into a FASTElementDefinition instance. **Signature:** ```typescript -compose = Constructable>(type: TType, nameOrDef?: string | PartialFASTElementDefinition): Promise>; +compose = Constructable>(this: TType, nameOrDef: string | PartialFASTElementDefinition): FASTElementDefinition; ``` ## Parameters @@ -43,7 +43,7 @@ Description -type +this @@ -53,8 +53,6 @@ TType -The custom element type to compose. - @@ -69,7 +67,7 @@ string \| [PartialFASTElementDefinition](../fast-element.partialfastelementdefin -_(Optional)_ The name of the element to compose or a definition object. +The element's tag name, or a definition object describing the element. @@ -77,4 +75,6 @@ _(Optional)_ The name of the element to compose or a definition object. **Returns:** -Promise<[FASTElementDefinition](../fast-element.fastelementdefinition/)<TType>> +[FASTElementDefinition](../fast-element.fastelementdefinition/)<TType> + +A FASTElementDefinition instance. diff --git a/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.compose_2.md b/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.compose_2.md new file mode 100644 index 00000000000..51060a6c15b --- /dev/null +++ b/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.compose_2.md @@ -0,0 +1,84 @@ +--- +id: "fast-element.fastelementconstructor.compose_2" +title: "FASTElementConstructor.compose() method" +layout: 3x-api +eleventyNavigation: + key: "api3xfast-element.fastelementconstructor.compose_2" + parent: "api3xfast-element" + title: "FASTElementConstructor.compose() method" +navigationOptions: + activeKey: "api3xfast-element.fastelementconstructor.compose_2" +--- + + +[@microsoft/fast-element](../fast-element/index.html) > [FASTElementConstructor](../fast-element.fastelementconstructor/index.html) > [compose](../fast-element.fastelementconstructor.compose_2/index.html) + +## FASTElementConstructor.compose() method + +Composes FASTElement metadata into a FASTElementDefinition instance. + +**Signature:** + +```typescript +compose = Constructable>(type: TType, nameOrDef: PartialFASTElementDefinition & { + template: FASTElementTemplateResolver; + }): Promise>; +``` + +## Parameters + + + + +
+ +Parameter + + + + +Type + + + + +Description + + +
+ +type + + + + +TType + + + + +The custom element type to compose. + + +
+ +nameOrDef + + + + +[PartialFASTElementDefinition](../fast-element.partialfastelementdefinition/)<TType> & { template: [FASTElementTemplateResolver](../fast-element.fastelementtemplateresolver/)<TType>; } + + + + +A definition object with a template resolver. + + +
+ +**Returns:** + +Promise<[FASTElementDefinition](../fast-element.fastelementdefinition/)<TType>> + +A promise that resolves to the composed FASTElementDefinition. diff --git a/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.compose_3.md b/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.compose_3.md new file mode 100644 index 00000000000..15b0e2e1c5c --- /dev/null +++ b/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.compose_3.md @@ -0,0 +1,82 @@ +--- +id: "fast-element.fastelementconstructor.compose_3" +title: "FASTElementConstructor.compose() method" +layout: 3x-api +eleventyNavigation: + key: "api3xfast-element.fastelementconstructor.compose_3" + parent: "api3xfast-element" + title: "FASTElementConstructor.compose() method" +navigationOptions: + activeKey: "api3xfast-element.fastelementconstructor.compose_3" +--- + + +[@microsoft/fast-element](../fast-element/index.html) > [FASTElementConstructor](../fast-element.fastelementconstructor/index.html) > [compose](../fast-element.fastelementconstructor.compose_3/index.html) + +## FASTElementConstructor.compose() method + +Composes FASTElement metadata into a FASTElementDefinition instance. + +**Signature:** + +```typescript +compose = Constructable>(type: TType, nameOrDef?: string | PartialFASTElementDefinition): FASTElementDefinition; +``` + +## Parameters + + + + +
+ +Parameter + + + + +Type + + + + +Description + + +
+ +type + + + + +TType + + + + +The custom element type to compose. + + +
+ +nameOrDef + + + + +string \| [PartialFASTElementDefinition](../fast-element.partialfastelementdefinition/)<TType> + + + + +_(Optional)_ The element's tag name, or a definition object describing the element. + + +
+ +**Returns:** + +[FASTElementDefinition](../fast-element.fastelementdefinition/)<TType> + +A FASTElementDefinition instance. diff --git a/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.md b/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.md index 81bb1cad145..dc72646ff8d 100644 --- a/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.md +++ b/sites/website/src/docs/3.x/api/fast-element.fastelementconstructor.md @@ -60,12 +60,34 @@ Composes FASTElement metadata without registering the element. -[compose(type, nameOrDef)](../fast-element.fastelementconstructor.compose_1/) +[compose(this, nameOrDef)](../fast-element.fastelementconstructor.compose_1/) -Composes FASTElement metadata without registering the element. +Composes element metadata into a FASTElementDefinition instance. + + + + + +[compose(type, nameOrDef)](../fast-element.fastelementconstructor.compose_2/) + + + + +Composes FASTElement metadata into a FASTElementDefinition instance. + + + + + +[compose(type, nameOrDef)](../fast-element.fastelementconstructor.compose_3/) + + + + +Composes FASTElement metadata into a FASTElementDefinition instance. diff --git a/sites/website/src/docs/3.x/api/fast-element.fastelementdefinition.compose.md b/sites/website/src/docs/3.x/api/fast-element.fastelementdefinition.compose.md index e23677948c5..6c8f5028458 100644 --- a/sites/website/src/docs/3.x/api/fast-element.fastelementdefinition.compose.md +++ b/sites/website/src/docs/3.x/api/fast-element.fastelementdefinition.compose.md @@ -20,7 +20,9 @@ Creates an instance of FASTElementDefinition. **Signature:** ```typescript -static compose = Constructable>(type: TType, nameOrDef?: string | PartialFASTElementDefinition): Promise>; +static compose = Constructable>(type: TType, nameOrDef: PartialFASTElementDefinition & { + template: FASTElementTemplateResolver; + }): Promise>; ``` ## Parameters @@ -64,12 +66,12 @@ nameOrDef -string \| [PartialFASTElementDefinition](../fast-element.partialfastelementdefinition/)<TType> +[PartialFASTElementDefinition](../fast-element.partialfastelementdefinition/)<TType> & { template: [FASTElementTemplateResolver](../fast-element.fastelementtemplateresolver/)<TType>; } -_(Optional)_ The name of the element to define or a config object that describes the element to define. +A config object whose `template` is a resolver. @@ -78,3 +80,5 @@ _(Optional)_ The name of the element to define or a config object that describes **Returns:** Promise<[FASTElementDefinition](../fast-element.fastelementdefinition/)<TType>> + +A promise that resolves to the composed FASTElementDefinition. diff --git a/sites/website/src/docs/3.x/api/fast-element.fastelementdefinition.compose_1.md b/sites/website/src/docs/3.x/api/fast-element.fastelementdefinition.compose_1.md new file mode 100644 index 00000000000..a02c0cad9ca --- /dev/null +++ b/sites/website/src/docs/3.x/api/fast-element.fastelementdefinition.compose_1.md @@ -0,0 +1,82 @@ +--- +id: "fast-element.fastelementdefinition.compose_1" +title: "FASTElementDefinition.compose() method" +layout: 3x-api +eleventyNavigation: + key: "api3xfast-element.fastelementdefinition.compose_1" + parent: "api3xfast-element" + title: "FASTElementDefinition.compose() method" +navigationOptions: + activeKey: "api3xfast-element.fastelementdefinition.compose_1" +--- + + +[@microsoft/fast-element](../fast-element/index.html) > [FASTElementDefinition](../fast-element.fastelementdefinition/index.html) > [compose](../fast-element.fastelementdefinition.compose_1/index.html) + +## FASTElementDefinition.compose() method + +Creates an instance of FASTElementDefinition. + +**Signature:** + +```typescript +static compose = Constructable>(type: TType, nameOrDef?: string | PartialFASTElementDefinition): FASTElementDefinition; +``` + +## Parameters + + + + +
+ +Parameter + + + + +Type + + + + +Description + + +
+ +type + + + + +TType + + + + +The type this definition is being created for. + + +
+ +nameOrDef + + + + +string \| [PartialFASTElementDefinition](../fast-element.partialfastelementdefinition/)<TType> + + + + +_(Optional)_ The name of the element to define or a config object that describes the element to define. + + +
+ +**Returns:** + +[FASTElementDefinition](../fast-element.fastelementdefinition/)<TType> + +A composed FASTElementDefinition instance. diff --git a/sites/website/src/docs/3.x/api/fast-element.fastelementdefinition.md b/sites/website/src/docs/3.x/api/fast-element.fastelementdefinition.md index e7af9bc9823..5db54f57414 100644 --- a/sites/website/src/docs/3.x/api/fast-element.fastelementdefinition.md +++ b/sites/website/src/docs/3.x/api/fast-element.fastelementdefinition.md @@ -436,6 +436,22 @@ Description Creates an instance of FASTElementDefinition. + + + +[compose(type, nameOrDef)](../fast-element.fastelementdefinition.compose_1/) + + + + +`static` + + + + +Creates an instance of FASTElementDefinition. + + diff --git a/sites/website/src/docs/3.x/api/fast-element/declarative/fast-element.fastelementdefinition.compose.md b/sites/website/src/docs/3.x/api/fast-element/declarative/fast-element.fastelementdefinition.compose.md index d4a47e38ed3..f69723b4f60 100644 --- a/sites/website/src/docs/3.x/api/fast-element/declarative/fast-element.fastelementdefinition.compose.md +++ b/sites/website/src/docs/3.x/api/fast-element/declarative/fast-element.fastelementdefinition.compose.md @@ -20,7 +20,9 @@ Creates an instance of FASTElementDefinition. **Signature:** ```typescript -static compose = Constructable>(type: TType, nameOrDef?: string | PartialFASTElementDefinition): Promise>; +static compose = Constructable>(type: TType, nameOrDef: PartialFASTElementDefinition & { + template: FASTElementTemplateResolver; + }): Promise>; ``` ## Parameters @@ -64,12 +66,12 @@ nameOrDef -string \| [PartialFASTElementDefinition](../fast-element.partialfastelementdefinition/)<TType> +[PartialFASTElementDefinition](../fast-element.partialfastelementdefinition/)<TType> & { template: [FASTElementTemplateResolver](../fast-element.fastelementtemplateresolver/)<TType>; } -_(Optional)_ The name of the element to define or a config object that describes the element to define. +A config object whose `template` is a resolver. @@ -78,3 +80,5 @@ _(Optional)_ The name of the element to define or a config object that describes **Returns:** Promise<[FASTElementDefinition](../fast-element.fastelementdefinition/)<TType>> + +A promise that resolves to the composed FASTElementDefinition. diff --git a/sites/website/src/docs/3.x/api/fast-element/declarative/fast-element.fastelementdefinition.compose_1.md b/sites/website/src/docs/3.x/api/fast-element/declarative/fast-element.fastelementdefinition.compose_1.md new file mode 100644 index 00000000000..c5fd8b7fcba --- /dev/null +++ b/sites/website/src/docs/3.x/api/fast-element/declarative/fast-element.fastelementdefinition.compose_1.md @@ -0,0 +1,82 @@ +--- +id: "fast-element.fastelementdefinition.compose_1" +title: "FASTElementDefinition.compose() method" +layout: 3x-api +eleventyNavigation: + key: "declarative.jsapi3xfast-element.fastelementdefinition.compose_1" + parent: "@microsoft/fast-element/declarative.js3x" + title: "FASTElementDefinition.compose() method" +navigationOptions: + activeKey: "declarative.jsapi3xfast-element.fastelementdefinition.compose_1" +--- + + +[@microsoft/fast-element/declarative.js](../fast-element/index.html) > [FASTElementDefinition](../fast-element.fastelementdefinition/index.html) > [compose](../fast-element.fastelementdefinition.compose_1/index.html) + +## FASTElementDefinition.compose() method + +Creates an instance of FASTElementDefinition. + +**Signature:** + +```typescript +static compose = Constructable>(type: TType, nameOrDef?: string | PartialFASTElementDefinition): FASTElementDefinition; +``` + +## Parameters + + + + +
+ +Parameter + + + + +Type + + + + +Description + + +
+ +type + + + + +TType + + + + +The type this definition is being created for. + + +
+ +nameOrDef + + + + +string \| [PartialFASTElementDefinition](../fast-element.partialfastelementdefinition/)<TType> + + + + +_(Optional)_ The name of the element to define or a config object that describes the element to define. + + +
+ +**Returns:** + +[FASTElementDefinition](../fast-element.fastelementdefinition/)<TType> + +A composed FASTElementDefinition instance. diff --git a/sites/website/src/docs/3.x/api/fast-element/declarative/fast-element.fastelementdefinition.md b/sites/website/src/docs/3.x/api/fast-element/declarative/fast-element.fastelementdefinition.md index 8ec8d243f0c..543c430d25a 100644 --- a/sites/website/src/docs/3.x/api/fast-element/declarative/fast-element.fastelementdefinition.md +++ b/sites/website/src/docs/3.x/api/fast-element/declarative/fast-element.fastelementdefinition.md @@ -436,6 +436,22 @@ Description Creates an instance of FASTElementDefinition. + + + +[compose(type, nameOrDef)](../fast-element.fastelementdefinition.compose_1/) + + + + +`static` + + + + +Creates an instance of FASTElementDefinition. + + diff --git a/sites/website/src/docs/3.x/resources/export-sizes.md b/sites/website/src/docs/3.x/resources/export-sizes.md index 4c96e62ae9d..82026732153 100644 --- a/sites/website/src/docs/3.x/resources/export-sizes.md +++ b/sites/website/src/docs/3.x/resources/export-sizes.md @@ -19,8 +19,8 @@ Bundle sizes for `@microsoft/fast-element` exports. | Export | Minified | Gzip | Brotli | |--------|----------|------|--------| -| CDN Rollup Bundle | 79.42 KB | 23.81 KB | 21.04 KB | -| FASTElement (@microsoft/fast-element/fast-element.js) | 23.84 KB | 7.39 KB | 6.65 KB | +| CDN Rollup Bundle | 79.50 KB | 23.82 KB | 21.04 KB | +| FASTElement (@microsoft/fast-element/fast-element.js) | 23.89 KB | 7.40 KB | 6.67 KB | | Updates (@microsoft/fast-element/updates.js) | 473 B | 335 B | 288 B | | Observable (@microsoft/fast-element/observable.js) | 6.77 KB | 2.52 KB | 2.24 KB | | observable (@microsoft/fast-element/observable.js) | 6.80 KB | 2.54 KB | 2.25 KB | @@ -33,8 +33,8 @@ Bundle sizes for `@microsoft/fast-element` exports. | html (@microsoft/fast-element/html.js) | 27.75 KB | 8.96 KB | 8.03 KB | | repeat (@microsoft/fast-element/repeat.js) | 31.82 KB | 10.01 KB | 9.03 KB | | css (@microsoft/fast-element/css.js) | 2.43 KB | 1.00 KB | 911 B | -| enableHydration (@microsoft/fast-element/hydration.js) | 45.56 KB | 13.82 KB | 12.42 KB | +| enableHydration (@microsoft/fast-element/hydration.js) | 45.59 KB | 13.83 KB | 12.43 KB | | declarativeTemplate (@microsoft/fast-element/declarative.js) | 62.88 KB | 19.72 KB | 17.59 KB | | ArrayObserver (@microsoft/fast-element/array-observer.js) | 12.57 KB | 4.47 KB | 4.03 KB | -| observerMap (@microsoft/fast-element/observer-map.js) | 20.61 KB | 7.33 KB | 6.59 KB | -| attributeMap (@microsoft/fast-element/attribute-map.js) | 15.84 KB | 5.60 KB | 5.05 KB | +| observerMap (@microsoft/fast-element/observer-map.js) | 20.64 KB | 7.34 KB | 6.61 KB | +| attributeMap (@microsoft/fast-element/attribute-map.js) | 15.88 KB | 5.61 KB | 5.06 KB |