# Technical Documentation: microsoft/fast

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/microsoft/fast)

### Overview (`README.md`)

# FAST

[](https://opensource.org/licenses/MIT)
[](https://www.typescriptlang.org/)
[](https://github.com/prettier/prettier)

[](https://github.com/microsoft/fast/actions/workflows/ci-validate-pr.yml)
[](https://github.com/microsoft/fast/actions/workflows/ci-validate-platforms.yml)

[](https://discord.gg/FcSNfg4)
[](https://twitter.com/intent/follow?screen_name=fast_ui)

:star: We appreciate your star, it helps!

## Introduction

FAST is dedicated to providing support for native Web Components and modern Web Standards, and it's designed to help you efficiently tackle some of the most common challenges in website and application design and development.

**TL;DR**

* Create reusable UI components with `@microsoft/fast-element`, all based on W3C Web Component standards.
* Integrate FAST Web Components with any library, framework, or build system. You can adopt incrementally without re-writing your existing systems.

For an in-depth explanation of FAST [see our docs introduction](https://fast.design/docs/3.x/introduction/).

## Packages

### `@microsoft/fast-element`

[](https://opensource.org/licenses/MIT)
[](https://badge.fury.io/js/%40microsoft%2Ffast-element)

The `@microsoft/fast-element` library is a lightweight means to easily build performant, memory-efficient, standards-compliant Web Components. FAST Elements work in every major browser and can be used in combination with any front-end framework or even without a framework. To get up and running with `@microsoft/fast-element` see [the Getting Started guide](https://fast.design/docs/3.x/getting-started/quick-start/).

### `@fluentui/web-components`

[](https://opensource.org/licenses/MIT)
[](https://badge.fury.io/js/%40fluentui%2Fweb-components)

`@fluentui/web-components` is a library of Web Components based on the Fluent design language, built with `@microsoft/fast-element`.

The source for `@fluentui/web-components` is hosted in [the Fluent UI monorepo](https://github.com/microsoft/fluentui/tree/master/packages/web-components).

## Getting Started

We hope you're excited by the possibilities that FAST presents. But, you may be wondering where to start. Here are a few statements that describe various members of our community. We recommend that you pick the statement you most identify with and follow the links where they lead. You can always come back and explore another topic at any time.

* "I just want ready-made components!"
  * [Check out the FluentUI Web Components.](https://learn.microsoft.com/en-us/fluent-ui/web-components/)
* "I want to build my own components."
  * [Jump to the fast-element docs.](https://fast.design/docs/3.x/getting-started/quick-start/)
* "I need to integrate FAST with another framework or build system."
  * [Jump to the integration docs.](https://fast.design/docs/3.x/integrations/)
* "I want to look at a quick reference."
  * [Jump to the Cheat Sheet](https://fast.design/docs/1.x/resources/cheat-sheet) *(only available in 1.x)*

## Roadmap

Major features for the FAST project can be found in the [roadmap](https://github.com/orgs/microsoft/projects/240/views/1).

## Joining the Community

Looking to get answers to questions or engage with us in realtime? Our community is most active [on Discord](https://discord.gg/FcSNfg4). Submit requests and issues on [GitHub](https://github.com/Microsoft/fast/issues/new/choose), or join us by contributing on [some good first issues via GitHub](https://github.com/Microsoft/fast/labels/community:good-first-issue).

Get started here with the [Contributor Guide](https://www.fast.design/docs/community/contributor-guide).

We look forward to building an amazing open source community with you!

## Contact

* Join the community and chat with us in real-time on [Discord](https://discord.gg/FcSNfg4).
* Submit requests and issues on [GitHub](https://github.com/Microsoft/fast/issues/new/choose).
* Contribute by helping out on some of our recommended first issues on [GitHub](https://github.com/Microsoft/fast/labels/community:good-first-issue).

---

### Overview (`examples/README.md`)

# FAST example apps

The `examples/` workspace hosts small, focused applications that show how to
build real UI with FAST using production-shaped tooling, app structure, and
styling. It is aimed at contributors, library consumers, and anyone evaluating
FAST patterns in a complete app context.

## Apps

| Folder | Package | Purpose |
| --- | --- | --- |
| `design-system` | `@microsoft/fast-examples-design-system` | Shared CSS design tokens (no JS) consumed by every example app. |
| `csr/todo-app` | `@microsoft/fast-todo-app-example` | A To-Do app demonstrating `@microsoft/fast-element` patterns end to end, styled with the shared design-system tokens (light theme, no runtime toggle). |
| `csr/todo-mobx-app` | `@microsoft/fast-todo-mobx-app-example` | A To-Do app showing how to integrate MobX state with `@microsoft/fast-element` using a single `autorun` per component (no custom bridge code), styled with the shared design-system tokens. |
| `ssr/chat-app` | `@microsoft/fast-chat-app-example` | A declarative FAST chat demo that pre-renders with `@microsoft/fast-build` and streams canned assistant replies into the transcript, styled with the shared design-system tokens (dark theme, no runtime toggle). |
| `ssr/webui-todo-app` | `@microsoft/fast-webui-todo-app-example` | A To-Do app pre-rendered by `@microsoft/webui` and hydrated by `@microsoft/fast-element/declarative.js`, styled with the shared design-system tokens (light theme, no runtime toggle). |

Example apps are grouped by rendering strategy. Client-side-rendered (CSR)
apps live under [`examples/csr/`](./csr/) and server-side-rendered (SSR) apps
live under [`examples/ssr/`](./ssr/).

## Shared design system

Every example app must consume `@microsoft/fast-examples-design-system`. The
package is **CSS-only** — it ships a single stylesheet (`tokens.css`) and no
JavaScript or TypeScript. Apps wire theme switching themselves using the
`data-theme` attribute on `<html>`.

The package exposes a single import:

| Import | What it does |
| --- | --- |
| `@microsoft/fast-examples-design-system/tokens.css` | Declares every token on `:root`. Color and elevation values use `light-dark()`; theme is controlled by `prefers-color-scheme` (default) or `<html data-theme="light"\|"dark">` (forced). |

Style components with semantic tokens such as
`--fast-background-layer-primary-solid`,
`--fast-foreground-ctrl-neutral-primary-rest`,
`--fast-background-ctrl-brand-rest`, `--fast-text-global-body3-font-size`,
`--fast-padding-content-medium`, and `--fast-corner-large`. Never hard-code
colors, font sizes, padding, gaps, corners, stroke widths, shadows,
durations, or curves.

See:

- [`examples/design-system/README.md`](./design-system/README.md) — quickstart,
  available imports, token catalog.
- [`examples/design-system/DESIGN.md`](./design-system/DESIGN.md) — naming
  grammar, role catalog, theme model, and rules for adding tokens (the
  canonical authoring guide for both humans and coding agents).
- [`examples/DESIGN.md`](./DESIGN.md) — workspace-level guidance for building
  new example apps on top of the design system.

## Creating a new example app

1. Scaffold a new folder under the appropriate rendering-strategy subfolder
   (CSR apps go under `examples/csr/<your-app>/`; SSR apps go under
   `examples/ssr/<your-app>/`).
2. Use [`examples/csr/todo-app/`](./csr/todo-app/) as a reference for CSR
   apps, or [`examples/ssr/chat-app/`](./ssr/chat-app/) /
   [`examples/ssr/webui-todo-app/`](./ssr/webui-todo-app/) as a reference
   for SSR apps (`package.json`, `tsconfig.json`, build config, entry HTML).
3. Add `"@microsoft/fast-examples-design-system": "^1.0.0"` to the new
   app's `dependencies` and run `npm install` from the repo root.
4. Import `@microsoft/fast-examples-design-system/tokens.css` exactly once at
   the app entry point (typically `src/main.ts` or `src/index.ts`). For an
   intentionally single-theme app, hard-code `<html data-theme="light">` (or
   `"dark"`) in the entry HTML and never touch it from JavaScript.
5. Reference tokens via `var(--fast-...)` in component `css` template
   literals or `.css` files — do not hard-code design values.
6. If the app needs a theme toggle, set or remove the `data-theme` attribute
   on `<html>` from your app code:
   ```ts
   document.documentElement.setAttribute("data-theme", "dark");
   document.documentElement.removeAttribute("data-theme"); // restore system
   ```
   Do **not** import any JavaScript from the design-system package — it
   intentionally exposes none.
7. Add the new app to the table at the top of this file.

## Running an example

From the repository root:

```shell
npm install
npm start -w @microsoft/fast-<your-app>-example
```

For the existing example apps:

```shell
npm start -w @microsoft/fast-todo-app-example
npm start -w @microsoft/fast-todo-mobx-app-example
npm start -w @microsoft/fast-chat-app-example
npm start -w @microsoft/fast-webui-todo-app-example
```

## Useful links

- [Examples design guide](./DESIGN.md)
- [Examples design-system package](./design-system/README.md)
- [FAST repository README](../README.md)
- [FAST documentation](https://fast.design/docs/3.x/introduction/)

---

### Overview (`packages/README.md`)

# FAST Packages

Our web component packages.

## `@microsoft/fast-element`

[](https://opensource.org/licenses/MIT)
[](https://badge.fury.io/js/%40microsoft%2Ffast-element)

The `@microsoft/fast-element` library is a lightweight means to easily build performant, memory-efficient, standards-compliant Web Components. FAST Elements work in every major browser and can be used in combination with any front-end framework or even without a framework. To get up and running with `@microsoft/fast-element` see [the Getting Started guide](https://fast.design/docs/getting-started/quick-start).

## `@microsoft/fast-router`

[](https://opensource.org/licenses/MIT)
[](https://badge.fury.io/js/%40microsoft%2Ffast-router)

The `@microsoft/fast-router` package contains a history-based navigation and routing solution designed around Web Components. By using `fast-router`, you can create multi-page and full application experiences. The router works with any Web Components, but has special support for Web Components built on FAST.

---

### Overview (`.github/workflows/README.md`)

# Testing

To test workflows, use the GitHub CLI and trigger the workflow from a branch.

For more information see the [GitHub CLI documentation](https://cli.github.com/manual/gh_workflow_run).

## Draft Pull Requests

All CI workflows that run against pull requests are configured to skip draft PRs:

- **GitHub Actions** (`ci-validate-pr.yml`, `ci-validate-platforms.yml`, `ci-validate-rust.yml`): The `pull_request` trigger includes `ready_for_review` in its event types, and each job has a condition that skips execution when the PR is a draft. When a draft PR is marked as ready for review, the workflows will automatically trigger.
- **Azure Pipelines** (`azure-pipelines-bench.yml`, `azure-pipelines-ci.yml`): The `pr` trigger uses `drafts: false` to prevent pipeline runs on draft PRs.

## Continuous Deployment

Nightly publishing is coordinated across GitHub Actions and Azure Pipelines so that npm credentials never leave the Azure environment. GitHub Releases are the source of truth, and `deployed/<tag>` git marker tags track which releases have already been published.

- **`cd-github-releases.yml`** (GitHub Actions) runs nightly via cron (`0 8 * * *` UTC, ~12am PST) and on `workflow_dispatch`. It does **not** bump versions or push source changes to `main` — version bumps land on `main` through ordinary human-authored pull requests (for example, by running `npm run bump` locally and opening a PR). The cron is scheduled ~1 hour before the Azure CD pipeline (09:00 UTC) so any GitHub releases this job creates are picked up by that same night's publish run. The workflow has two jobs:
  1. **`detect`** — checks out `main` with `fetch-depth: 0` and runs [`build/scripts/create-github-releases.mjs --check-only`](../../build/scripts/create-github-releases.mjs). The script walks the workspaces tree (no `npm ci` required), computes `${name}_v${version}` for every non-private workspace, and emits `hasMissingReleases=true` if any of those git tags do not yet exist.
  2. **`release`** runs only when missing releases exist. Installs Node, the Rust toolchain (for `cargo package`), and the npm workspace dependencies, builds the repo, then runs the script in default mode. For every missing release the script: packs the npm tarball into `publish_artifacts_npm/`, packs any paired Rust crates into `publish_artifacts_crates/`, and creates the GitHub release with all assets attached via `gh release create --target <sha>`. `@microsoft/fast-build` is a bundled release: it uses one npm package, one tag, and one GitHub release containing both `microsoft-fast-build` and `microsoft-fast-convert` crate assets. The `gh` CLI creates the git tag atomically with the release, so "tag exists" and "release exists" are always the same fact — a failed release is safely retried on the next workflow run, with no orphan tag stranded behind. The script errors if a paired crate's version does not match the npm package's version — but this is purely a safety net: the [`postbump` hook in `beachball.config.js`](../../beachball.config.js) rewrites each crate's `Cargo.toml` (and the matching entry in `Cargo.lock`) automatically whenever `npm run bump` bumps the paired npm package, so they stay in sync from the same commit.
- **`azure-pipelines-cd.yml`** (Azure Pipelines) runs every night at **1am PST (`0 9 * * *` UTC)** with `always: true` so it still runs on no-op nights (it is checking external GitHub state, not repo commits). It is split into two stages so the heavy publish work is skipped on no-op nights:
  1. **`Check`** — runs [`build/scripts/download-github-releases.mjs --check-only`](../../build/scripts/download-github-releases.mjs). The script walks the current publishable workspaces, keeps only workspaces whose current `${name}_v${version}` release tag exists, filters out tags that already have a `deployed/<tag>` counterpart, and emits Azure Pipelines output variables for the overall deployment decision, npm dist-tag, and each package-specific release tag. No network calls to GitHub, npm, or crates.io are needed.
  2. **`Package`** — depends on `Check` and runs only when `needsDeployment == 'true'`. Its `PrepareReleaseInputs` job downloads undeployed release assets through the `fast` GitHub service connection, sorts them into `publish_artifacts_npm/` (`.tgz`) and `publish_artifacts_crates/` (`.crate`), configures the detected npm dist-tag, and publishes those files as a governed pipeline artifact. The checkout-free `Deploy` release job consumes that artifact through `templateContext.inputs`, then `FAST.Release.PipelineTemplate.yml@fastPipelines` performs the actual `npm publish` / `cargo publish`. After publishing succeeds, the ordinary `MarkDeployed` job checks out the repository and pushes a `deployed/<tag>` marker for each release. The next nightly run sees those markers and skips the corresponding releases.

Both scripts are thin Node.js wrappers around existing CLI tools and repository metadata — no extra npm dependencies and no custom GitHub API client. Idempotency is enforced entirely through git tags (`${name}_v${version}` on the GitHub side, `deployed/${name}_v${version}` on the Azure side), so neither side needs to talk to npm.org or crates.io to decide whether work is required.

### Adding a publishable package

`cd-github-releases.yml` discovers publishable workspaces automatically from the root `package.json` `workspaces` list, but `azure-pipelines-cd.yml` must be updated because Azure Pipelines cannot create `DownloadGitHubRelease@0` tasks dynamically from the runtime detection output.

The `npm run checkchange` command runs `build/scripts/check-publish-pipeline.mjs` to verify that every non-private workspace has matching Azure CD variables and a conditional `DownloadGitHubRelease@0` task. This guardrail runs in PR validation and fails when a new publishable package is added without updating the publish pipeline.

When adding a new non-private workspace that should publish through CD:

1. Ensure the workspace is included in the root `package.json` `workspaces` list and has a `name` and `version`.
2. If the package has paired crate assets, place each crate at `crates/<crate-name>/Cargo.toml`. By default, `<crate-name>` is the npm package name with the leading `@` removed and `/` replaced by `-`. `@microsoft/fast-build` is the special bundled release and pairs with both `crates/microsoft-fast-build/Cargo.toml` and `crates/microsoft-fast-convert/Cargo.toml`.
3. Add package-specific output variables to the `Package` stage in `azure-pipelines-cd.yml`. The output prefix is generated from the npm package name by converting `@microsoft/<name>` to camel case. For example, `@microsoft/fast-foo` emits `fastFooNeedsDeployment` and `fastFooReleaseTag`.
4. Add a conditional `DownloadGitHubRelease@0` task to `PrepareReleaseInputs` using the `fast` GitHub service connection, `defaultVersionType: 'specificTag'`, and the package's `$(<prefix>ReleaseTag)` variable. Release jobs cannot check out source or directly acquire undeclared dependencies, so all downloaded assets must remain part of the governed `fast-release-inputs` pipeline artifact.
5. Confirm the artifact sorting step still covers the package assets. Packages should attach `.tgz` assets, and paired crates should also attach `.crate` assets.

Example Azure additions for `@microsoft/fast-foo`:

```yml
variables:
  fastFooNeedsDeployment: $[ stageDependencies.Check.CheckVersion.outputs['deploymentCheck.fastFooNeedsDeployment'] ]
  fastFooReleaseTag: $[ stageDependencies.Check.CheckVersion.outputs['deploymentCheck.fastFooReleaseTag'] ]

steps:
- task: DownloadGitHubRelease@0
  displayName: "Download @microsoft/fast-foo release assets"
  condition: and(succeeded(), eq(variables['fastFooNeedsDeployment'], 'true'))
  inputs:
    connection: fast
    userRepository: microsoft/fast
    defaultVersionType: 'specificTag'
    version: '$(fastFooReleaseTag)'
    downloadPath: '$(System.ArtifactsDirectory)'
```

---

### Overview (`crates/microsoft-fast-build/README.md`)

# microsoft-fast-build

A server-side renderer for [FAST](https://www.fast.design/) declarative HTML templates, written in pure Rust with no native runtime dependencies.

It takes FAST declarative HTML template syntax and a JSON state object, resolves bindings, evaluates conditionals, iterates repeats, and renders custom elements — producing static HTML ready to be served.

## Installation

Add the crate to your `Cargo.toml`:

```toml
[dependencies]
microsoft-fast-build = "0.1"
```

Or use `cargo add`:

```sh
cargo add microsoft-fast-build
```

## Usage

### Render with a JSON string

```rust
use microsoft_fast_build::render_template;

let html = render_template(
    "<h1>{{title}}</h1>",
    r#"{"title": "Hello, World!"}"#,
)?;
// html == "<h1>Hello, World!</h1>"
```

### Render with a parsed `JsonValue`

```rust
use microsoft_fast_build::{render, JsonValue};
use std::collections::HashMap;

let mut map = HashMap::new();
map.insert("name".to_string(), JsonValue::String("Alice".to_string()));
let state = JsonValue::Object(map);

let html = render("<p>{{name}}</p>", &state)?;
// html == "<p>Alice</p>"
```

Both functions return `Result<String, RenderError>`. See [Error Handling](#error-handling).

### Render simulated stream chunks

Streaming APIs return precomputed HTML chunks in memory. Joining the chunks
matches the equivalent non-streamed render, while chunk boundaries are chosen
around content bindings and custom elements. Stream rendering uses the same
top-level preprocessing as normal rendering, including automatic escaping of
FAST-like syntax inside `<code>` elements.

```rust
use microsoft_fast_build::{render_template, render_template_stream};

let chunks = render_template_stream(
    "<p>{{message}}</p>",
    r#"{"message": "Hello"}"#,
    None,
)?;

let html = render_template(
    "<p>{{message}}</p>",
    r#"{"message": "Hello"}"#,
    None,
)?;

assert_eq!(chunks, vec!["<p>", "Hello", "</p>"]);
assert_eq!(chunks.join(""), html);
```

Custom element streaming uses the `*_stream_with_locator` and
`render_entry_*_stream_with_locator` APIs. For entry HTML, a custom element's
opening tag chunk includes the complete Declarative Shadow DOM template; light
DOM content follows in later chunks. Template host attributes declared on the
inner `<template>` element are merged onto the streamed host opening tag with
the same author-wins and client-only-attribute filtering rules as normal
rendering.

---

## Plugin integration APIs

`render_shadow_root_with_locator(element_name, state, locator, config)` renders
only the complete Declarative Shadow DOM `<template>` fragment. Its JSON-state
counterpart is `render_shadow_root_template_with_locator(element_name,
state: Option<&str>, locator, config)`. Pass resolved **component state**;
these APIs do not synthesize a host, overlay host attributes, emit template-host
attributes, or render caller-owned light DOM. Nested components, code-sample
escaping, and fresh v3/v2 hydration scopes use the whole-host rendering path.
Unknown template names and invalid JSON state return explicit errors.

```rust
use microsoft_fast_build::{
    parse_f_templates, render_shadow_root_template_with_locator, Locator,
};

let definitions = parse_f_templates(
    r#"<f-template name="my-card"><template>{{title}}</template></f-template>"#,
);
let locator = Locator::from_metadata(definitions)?;
let fragment = render_shadow_root_template_with_locator(
    "my-card", Some(r#"{"title":"Hello"}"#), &locator, None,
)?;
```

`parse_f_templates` is also a public native API. It returns `Vec<FTemplate>`
with `format_version`, `bindings`, name/content, and host/shadow-root attributes.
`BindingMetadata` records direct names, expressions, syntax kinds, lexical
paths, and nested `BindingScope { variable, iterable }` frames. Application
types and required/optional declarations remain unknown (`None`); repeat
collections alone have a known array requirement. Metadata describes syntax,
not a state schema or a full validation certificate. Code samples are excluded.
`Locator::from_metadata` validates names, duplicates, and the format version.
Legacy content/tuple constructors remain supported.

Each `BindingMetadata` also has a `span: SourceSpan` containing `start` and `end`
`SourcePosition` records. Positions refer to the complete original input to
`parse_f_templates`, including document prefixes and whitespace removed from the
returned content. `offset` is zero-based UTF-16, **not a Rust byte index**; `line`
and `column` are one-based, with columns measured in UTF-16 code units. Tabs count
as one column and non-BMP characters as two. CRLF is one line break and two offset
units; lone CR and LF each start a new line.

Spans are half-open and cover trimmed expressions without braces. Repeat spans
cover the iterable, matching the existing expression metadata; lexical scopes are
unchanged. Attribute entities retain their authored spelling. Code-sample
preprocessing does not shift later spans. Bindings and FAST directive markup
inside HTML comments remain unsupported.

The WASM exports are `parse_f_templates(html)` (JSON metadata array) and
`render_shadow_root(elementName, templatesJson, state?, attributeNameStrategy?,
markers_v2?)`. Generated declarations include `FTemplateMetadata`,
`TemplateBinding`, `TemplateBindingScope`, `TemplateSourceSpan`, and
`TemplateSourcePosition`. Each generated record has
`formatVersion: 1`; render exports reject unsupported or malformed explicit
versions, while still accepting unversioned maps and string-valued definitions.

### Nullable and boolean attributes

Missing or explicit `null` bindings omit the entire attribute, including when
embedded in a literal value such as `href="/prefix/{{value}}"`. An explicit
empty string remains `href=""`. Boolean JSON values bound to known HTML boolean
attributes use presence/absence; ordinary attributes such as `aria-hidden`
still serialize booleans as `"true"`/`"false"`. `?name="{{expr}}"` remains the
recommended truthy/falsy form for matching browser-side FAST behavior.
Omitted bindings still reserve hydration slots. An author binding that resolves
to absence overrides template-host defaults rather than reintroducing them.
See the [migration guide](../../packages/fast-build/docs/migration/plugin-integrations.md)
for intentional changes from earlier output.

## Template Syntax

Bindings and FAST directive markup inside HTML comments are unsupported.
Commenting out bound markup does not reliably disable its bindings and can cause
rendering errors or client hydration mismatches. Remove unused bound markup
instead, and keep explanatory comments free of binding syntax and FAST directive
tags.

### Content Bindings

| Syntax | Description |
|--------|-------------|
| `{{expr}}` | HTML-escaped value from state |
| `{{{expr}}}` | Raw (unescaped) HTML value from state |

```html
<h1>{{title}}</h1>
<div>{{{richContent}}}</div>
```

### Single-Brace Passthrough

Single-brace expressions (`{expr}`) are FAST client-side-only bindings (event handlers, attribute directives). They are **never** interpreted by the server renderer.

In non-hydration rendering they pass through verbatim. When rendering **Declarative Shadow DOM** (inside a custom element's shadow template), client-side attribute directives — `f-ref`, `f-slotted`, `f-children` — are **stripped** from the HTML output, just like `@event` and `:property` bindings. The `data-fe` binding count still includes them so the FAST runtime can allocate the correct number of binding slots.

```html

<slot f-slotted="{slottedNodes}"></slot>
<video f-ref="{video}"></video>
<ul f-children="{listItems}"></ul>


<slot data-fe="1"></slot>
<video data-fe="1"></video>
<ul data-fe="1"></ul>
```

### Boolean Attribute Bindings — `?attr`

The `?attr="{{expr}}"` syntax is a FAST convention for conditionally rendering a boolean HTML attribute. The renderer evaluates `expr` against the element's state:

- **truthy** → the bare attribute name is emitted (e.g. `disabled`)
- **falsy** → the attribute is omitted entirely

```html

<input type="checkbox" ?disabled="{{!isEnabled}}">
<input ?disabled="{{activeGroup == currentGroup}}" type="button">


<input type="checkbox" disabled data-fe="1">


<input type="button" data-fe="1">
```

The `data-fe` marker is still emitted so the FAST client runtime knows to reconnect the binding during hydration.

### Dataset Attribute Bindings — `dataset.propertyName`

FAST elements follow the [MDN `HTMLElement.dataset`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset) convention: camelCase property names (e.g. `dateOfBirth`) correspond to kebab-case `data-*` HTML attributes (e.g. `data-date-of-birth`).

#### Passing `data-*` attributes to custom elements

When a custom element receives `data-*` attributes, the renderer groups them under a nested `"dataset"` key in the child state so that `{{dataset.X}}` bindings in the shadow template resolve naturally:

```html

<test-el data-date-of-birth="{{dob}}"></test-el>


<div data-date-of-birth="{{dataset.dateOfBirth}}"></div>
```

With parent state `{"dob": "1990-01-01"}`, the shadow template receives child state `{"dataset": {"dateOfBirth": "1990-01-01"}}` and renders:

```html
<div data-date-of-birth="1990-01-01" data-fe="1"></div>
```

The `data-*` → `dataset.*` mapping uses the same camelCase conversion as the browser: `data-date-of-birth` → `dataset.dateOfBirth`.

#### Using `{{dataset.X}}` bindings

`{{dataset.X}}` is ordinary dot-notation: it reads `state["dataset"]["X"]`. The `dataset` key must be present in state, either from a `data-*` attribute on the enclosing custom element or from a state object you supply directly:

```html

<span>{{dataset.name}}</span>


<f-when value="{{dataset.active}}">Active</f-when>
```

### ARIA Attribute Bindings — `ariaPropertyName`

ARIA attributes follow the [Element ARIA reflection](https://developer.mozilla.org/en-US/docs/Web/API/Element#instance_properties_included_from_aria) convention: camelCase property names (e.g. `ariaDisabled`) correspond to `aria-*` HTML attributes (e.g. `aria-disabled`).

#### Passing `aria-*` attributes to custom elements

When a custom element receives `aria-*` attributes, the renderer converts them to their camelCase property name and stores them as top-level state keys using a static lookup table:

```html

<test-el aria-label="Close dialog" aria-disabled="true"></test-el>


<button aria-label="{{ariaLabel}}" aria-disabled="{{ariaDisabled}}">×</button>
```

The shadow template receives child state `{"ariaLabel": "Close dialog", "ariaDisabled": "true"}`.

A lookup table is used instead of algorithmic conversion because ARIA attribute names do not place dashes at word boundaries — for example, `aria-valuenow` (not `aria-value-now`) maps to `ariaValueNow`.

### HTML Attribute-to-Property Mappings

Some HTML attributes have DOM property names that differ from their attribute names (e.g. `tabindex` → `tabIndex`, `readonly` → `readOnly`). When a custom element receives these attributes, the renderer converts them to their camelCase property name:

```html

<test-el tabindex="0" readonly="true"></test-el>


<input tabindex="{{tabIndex}}" readonly="{{readOnly}}">
```

The shadow template receives child state `{"tabIndex": "0", "readOnly": "true"}`.

Only attributes where the property name differs are in the lookup table. Attributes like `disabled`, `title`, and `hidden` whose attribute and property names are identical pass through as-is.

### Conditional Rendering — `<f-when>`

```html
<f-when value="{{isAdmin}}">Admin panel</f-when>
<f-when value="{{!isGuest}}">Member content</f-when>
<f-when value="{{status == 'active'}}">Active</f-when>
<f-when value="{{count > 0}}">Has items</f-when>
<f-when value="{{a || b}}">Either</f-when>
<f-when value="{{a && b}}">Both</f-when>
```

Supported operators: `==`, `!=`, `>=`, `>`, `<=`, `<`, `||`, `&&`, `!`

Operators can be chained — `&&` binds tighter than `||`, matching standard precedence:

```html
<f-when value="{{isAdmin && !isGuest && status == 'active'}}">Admin</f-when>
<f-when value="{{a || b || c}}">Any of the above</f-when>
<f-when value="{{isPublished || isAdmin && canPreview}}">Visible</f-when>
```

Right-hand operands can be string literals (`'foo'`), boolean literals (`true`/`false`), number literals (`42`), or other state references.

When `value` is a bare reference (e.g. `{{items}}`), the value is coerced to a boolean using JavaScript semantics. Because the input state is JSON, users cannot provide `undefined` directly; however, missing state properties or unresolved paths behave like JavaScript `undefined` and are treated as falsy.

| Type | Falsy | Truthy |
|---|---|---|
| `null` | always | — |
| `boolean` | `false` | `true` |
| `number` | `0`, `NaN` | any other |
| `string` | `""` | any non-empty |
| `array` | — | always (even `[]`) |
| `object` | — | always (even `{}`) |

### Array Iteration — `<f-repeat>`

```html
<ul>
  <f-repeat value="{{item in items}}">
    <li>{{item.name}} — {{title}}</li>
  </f-repeat>
</ul>
```

Inside `<f-repeat>`, `{{item}}` resolves to the current loop variable and `{{$index}}` resolves to the 0-based iteration index. Other bindings fall back to the root state (e.g. `{{title}}` above).
If the list binding or dot path is missing, `<f-repeat>` treats it as an empty array and renders zero iterations. Present non-array values still return `RenderError::NotAnArray`.

```html
<f-repeat value="{{row in rows}}">
  <tr data-index="{{$index}}">
    <td>{{row.name}}</td>
  </tr>
</f-repeat>
```

### Nesting

`<f-when>` and `<f-repeat>` can be nested arbitrarily:

```html
<f-when value="{{show}}">
  <f-repeat value="{{row in rows}}">
    <f-repeat value="{{cell in row.cells}}">
      <span>{{cell}}</span>
    </f-repeat>
  </f-repeat>
</f-when>
```

### Property Access, Array Indexing, and `.length`

Dot-notation, numeric indices, and the special `.length` property on arrays are all supported:

```html
{{user.address.city}}
{{list.0.name}}
{{items.length}}
```

`{{items.length}}` resolves to the number of elements in the array. It can be used in both content bindings and `<f-when>` expressions:

```html
<f-when value="{{items.length > 0}}">
  <p>{{items.length}} items found</p>
</f-when>
```

---

## Custom Elements

When given a `Locator`, the renderer detects custom elements (any tag whose name contains a hyphen, excluding `f-when`/`f-repeat`) and renders their corresponding HTML template files.

### Setting up a Locator

```rust
use microsoft_fast_build::Locator;

// From glob patterns — scans the filesystem
let locator = Locator::from_patterns(&[
    "./components/**/*.html",
    "./templates/*.html",
])?;

// Or build manually (useful in tests)
let mut locator = Locator::from_templates(std::collections::HashMap::new());
locator.add_template("my-button", "<button>{{label}}</button>");
```

Glob patterns support `*` (any characters within one path segment), `**` (any number of segments), and `?` (any single character).

> **Note:** `Locator::from_patterns` walks the filesystem recursively up to 50 directory levels deep and skips symlinks. Symlinked directories are never followed, guarding against cycles in the directory tree.

### HTML File Format

Template HTML files must wrap their content in an `<f-template>` element with a `name` attribute identifying the custom element, and an inner `<template>` element containing the template markup:

```html
<f-template name="my-button">
    <template>
        <button>{{label}}</button>
    </template>
</f-template>
```

A single file may contain multiple templates:

```html
<f-template name="my-header">
    <template>
        <header><h1>{{title}}</h1></header>
    </template>
</f-template>
<f-template name="my-footer">
    <template>
        <footer>{{copyright}}</footer>
    </template>
</f-template>
```

If an `<f-template>` element is missing a `name` attribute, a warning is emitted to stderr and the template is ignored. The parser follows browser tag boundaries for the `<f-template>` and inner `<template>` wrappers, including ASCII whitespace before `>` in opening and closing tags.

Any `shadowroot*` attributes on `<f-template>` are copied to the rendered Declarative Shadow DOM `<template>`. The renderer normalizes `shadowrootmode` and legacy `shadowroot` for compatibility: when neither has a non-empty value, it emits `shadowrootmode="open" shadowroot="open"`; when exactly one has a non-empty value, that value is mirrored to the other; when both have explicit non-empty values, both are preserved as authored, even if they conflict.

### Composing CSS into an `<f-template>` — `compose_f_template_styles`

`compose_f_template_styles` inserts a `<style>` element as the first child of an `<f-template>` definition's inner `<template>`, entirely in memory:

```rust
use microsoft_fast_build::compose_f_template_styles;

let template_html = r#"
    <f-template name="my-button">
        <template>
            <button>{{label}}</button>
        </template>
    </f-template>
"#;

let composed = compose_f_template_styles(
    template_html,
    ":host { display: inline-block; }",
)?;
// composed now has <style>:host { display: inline-block; }</style> as the
// first child of the inner <template>, with every other byte preserved.
```

This has no filesystem requirement — `template_html` and `css` can come from any source (a build pipeline, a bundler plugin, generated CSS). The result is ordinary `<f-template>` source: write it to a file for `Locator::from_patterns` to discover, or pass it to `locator::parse_f_templates` directly.

Validation:

- `template_html` must contain exactly one `<f-template>` element, and that element must contain exactly one inner `<template>` element, or the call returns an error (`MissingFTemplate`, `MultipleFTemplates`, `MissingInnerTemplate`, `MultipleInnerTemplates`).
- `css` must not contain a case-insensitive `</style` raw-text terminator sequence (e.g. `</style>`, `</STYLE >`, `</style/`) — this would prematurely close the inserted `<style>` element. Content like `content: "</stylesheet>"` is not affected, since `style` must be followed by whitespace, `/`, `>`, or end of string to count as a terminator.

The WASM build exposes the same function as `compose_f_template_styles(templateHtml, css)`, throwing a JS error on any validation failure.

### Rendering with a Locator

```rust
use microsoft_fast_build::{render_with_locator, render_template_with_locator, Locator};

let locator = Locator::from_patterns(&["./components/**/*.html"])?;

let html = render_template_with_locator(
    r#"<my-button label="Submit"></my-button>"#,
    r#"{"disabled": false}"#,
    &locator,
)?;
```

### Rendering entry HTML (root custom elements)

When rendering the top-level **entry HTML** of a page, use `render_entry_with_locator` or `render_entry_template_with_locator`. Custom elements found at this level are treated as **root elements** — their opening-tag `{{binding}}` attributes are resolved (primitives kept, non-primitives stripped) rather than forwarded verbatim.

All custom elements (root and nested) receive the full root state merged with their HTML attribute-derived state. Attribute-derived values take precedence over root state for overlapping keys. This gives every element access to the complete state tree without requiring explicit attribute bindings.

```rust
use microsoft_fast_build::{render_entry_with_locator, render_entry_template_with_locator, Locator};

let locator = Locator::from_patterns(&["./components/**/*.html"])?;

// Root custom elements (my-header, my-app) receive the full root state merged with
// any per-element attributes. Their templates can reference any key in the state JSON directly.
let html = render_entry_template_with_locator(
    r#"{{heading}}<my-header></my-header><my-app planet="earth"></my-app>"#,
    r#"{"heading": "Hello", "user": "Alice", "items": [{"name": "Item 1"}]}"#,
    &locator,
)?;
// my-header's template can use {{user}}, {{heading}}, etc. directly.
// my-app's template can use {{items}}, {{planet}}, etc. directly.
```

### State Propagation

All custom elements — whether at the entry level or deeply nested — receive the current root state as a base for their child state. Per-element HTML attributes are overlaid on top, with attribute-derived values taking precedence over any matching root state keys.

This means unbound state keys automatically propagate through the entire element tree. A child element can reference any state key from its ancestors without requiring explicit attribute bindings on every intermediate element:

```html



<f-template name="my-el">
    <template>
        {{text}}
        <my-child-el></my-child-el>
    </template>
</f-template>


<f-template name="my-child-el">
    <template>
        {{text}}
    </template>
</f-template>
```

Both `my-el` and `my-child-el` render "Hello world" — the state propagates through the element tree without any explicit bindings.

#### Attribute handling on root elements

Root custom elements (rendered via `render_entry_*`) have their opening-tag `{{binding}}` attributes resolved in the rendered HTML output:

- **Primitive bindings** (`string`, `number`, `boolean`) — resolved and rendered with the resolved value. e.g. `text="{{message}}"` → `text="Hello world"`.
- **Non-primitive bindings** (`array`, `object`, `null`) — stripped from the HTML output (the state is still available in the element's template via state propagation).
- **Static attributes** (no binding syntax) — passed through unchanged.

| Context | Child state source | `{{binding}}` attrs in rendered HTML |
|---|---|---|
| Root element in entry HTML (via `render_entry_*`) | Root state merged with element's own attrs | Resolved — primitives kept, non-primitives stripped |
| Nested element inside a shadow template | Parent state merged with element's own attrs | Rendered (resolved) |
| Element inside `f-repeat` or `f-when` (at any level) | Parent state merged with element's own attrs | Rendered (resolved) |

```html

<my-parent label="{{title}}" list="{{items}}" planet="earth"></my-parent>


<my-child label="{{heading}}" :items="{{items}}"></my-child>
```

### Attribute → State Mapping

Attributes on a custom element become the state passed to its template:

| Attribute form | State entry |
|---|---|
| `disabled` (boolean, no value) | `{"disabled": true}` |
| `label="Click me"` | `{"label": "Click me"}` |
| `count="42"` | `{"count": "42"}` |
| `items="{{items}}"` | `{"items": <value of items from parent state>}` (array, object, or any type) |
| `:items="{{items}}"` | `{"items": <value of items from parent state>}` — same as above but **not rendered as an HTML attribute** |
| `foo="{{bar}}"` | `{"foo": <value of bar from parent state>}` |
| `selected-user-id="42"` | `{"selected-user-id": "42"}` (or `{"selectedUserId": "42"}` with `camelCase` strategy) |
| `isEnabled="{{isEnabled}}"` | `{"isenabled": <resolved value>}` |
| `data-date-of-birth="1990-01-01"` | `{"dataset": {"dateOfBirth": "1990-01-01"}}` |
| `data-date-of-birth="{{dob}}"` | `{"dataset": {"dateOfBirth": <value of dob from parent state>}}` |
| `aria-disabled="true"` | `{"ariaDisabled": "true"}` |
| `aria-label="{{label}}"` | `{"ariaLabel": <value of label from parent state>}` |
| `tabindex="0"` | `{"tabIndex": "0"}` |
| `readonly="true"` | `{"readOnly": "true"}` |
| `contenteditable="true"` | `{"contentEditable": "true"}` |
| `:myProp="{{expr}}"` | `{"myprop": <resolved value>}` — **not rendered as an HTML attribute** |
| `@click="{handler()}"` | *(skipped — client-side only)* |
| `f-ref="{video}"` | *(skipped — client-side only)* |
| `f-slotted="{nodes}"` | *(skipped — client-side only)* |
| `f-children="{items}"` | *(skipped — client-side only)* |

**HTML attribute keys are lowercased** — HTML attribute names are case-insensitive and browsers always store them lowercase. `isEnabled` becomes `isenabled`; hyphens are preserved so `selected-user-id` stays `selected-user-id`. Templates must reference the lowercase form. When the `attribute-name-strategy` configuration is set to `"camelCase"`, dashed attribute names that are not handled by specialized lookup tables (`data-*`, `aria-*`, HTML global attributes) are converted to camelCase instead: `selected-user-id` becomes `selectedUserId`, matching `{{selectedUserId}}` in the template. See the [Configuration](#configuration) section for details.

**Attribute value coercion** — attribute values are resolved in this order:
- No value (boolean attribute) → `true`
- `"{{binding}}"` → resolved from parent state (any type: string, number, boolean, array, or object)
- Value starting with `[` or `{` → parsed as a JSON array or object literal (e.g. `items='["a","b","c"]'`)
- Anything else → `String` (e.g. `count="42"` yields `{"count": "42"}`; use `count="{{count}}"` to get a number)

**Use `:prop="{{binding}}"` to pass arrays and objects from state without polluting HTML attributes** — the `:` prefix causes the attribute to be stripped from the rendered HTML while still forwarding the resolved value (which can be an array or object) into the child element's rendering state. Alternatively, JSON array or object literals can be inlined directly as attribute values (e.g. `items='["a","b","c"]'`), which is useful when the data is static and does not come from parent state.

**`data-*` attributes** are always grouped under a nested `"dataset"` key. `data_attr_to_dataset_key` returns the full dot-notation path (e.g. `"dataset.dateOfBirth"`), which is split on `.` when building the nested state, making `{{dataset.X}}` bindings work naturally in shadow templates.

**`aria-*` attributes** are converted to their camelCase ARIA property name (e.g. `aria-disabled` → `ariaDisabled`, `aria-valuenow` → `ariaValueNow`) using a static lookup table, following the [Element ARIA reflection](https://developer.mozilla.org/en-US/docs/Web/API/Element#instance_properties_included_from_aria) convention. Unrecognised `aria-*` attributes fall through to the default lowercased-key path.

**HTML attributes with mismatched property names** (e.g. `tabindex` → `tabIndex`, `readonly` → `readOnly`, `contenteditable` → `contentEditable`) are converted to their camelCase DOM property name using a static lookup table. Only attributes where the property name differs are included — attributes like `disabled`, `title`, and `hidden` pass through as-is.

**`@event` bindings and `f-ref`/`f-slotted`/`f-children` directives are skipped entirely** — not added to child state and removed from rendered HTML. They are resolved purely by the FAST client runtime. The `data-fe` binding count still includes them so the FAST runtime allocates the correct number of binding slots.

### Output Format

The renderer wraps the rendered template in Declarative Shadow DOM and adds the hydration attributes required by the FAST client runtime:

```html

<my-button label="Submit">light DOM</my-button>


<my-button label="Submit">
  <template shadowrootmode="open" shadowroot="open">
    <button>Submit</button>
  </template>
  light DOM
</my-button>
```

- `shadowrootmode="open"` — the standard declarative shadow DOM mode emitted by default.
- `shadowroot="open"` — legacy declarative shadow DOM attribute for broader browser compatibility.
- `shadowroot*` attributes declared on the source `<f-template>` are forwarded to the output `<template>`; `shadowrootmode` and `shadowroot` default to `open` when neither has a non-empty value, mirror when exactly one has a non-empty value, and are preserved as authored when both have explicit non-empty values.

Custom elements that have no matching template in the locator are passed through verbatim.

---

## Configuration

The `RenderConfig` struct provides configuration options that control rendering behaviour. Pass `Some(&config)` to any render function, or `None` for defaults.

### `attribute-name-strategy`

Controls how HTML attribute names are mapped to state property names when building child state for custom elements.

| Strategy | Behaviour | Example |
|---|---|---|
| `"none"` (default) | Attribute names are lowercased as-is. Dashes preserved. | `foo-bar` → `{{foo-bar}}` |
| `"camelCase"` | Dashed attribute names are converted to camelCase. | `foo-bar` → `{{fooBar}}` |

The `camelCase` strategy only applies to "plain" attributes. It does **not** affect:
- `data-*` attributes (always use `dataset.*` grouping)
- `aria-*` attributes (always use ARIA reflection lookup)
- HTML global attributes with known property names (e.g. `tabindex` → `tabIndex`)
- `:prop` property bindings (always lowercased)

#### Rust API

```rust
use microsoft_fast_build::{RenderConfig, AttributeNameStrategy, render_template_with_locator};

let config = RenderConfig::new()
    .with_attribute_name_strategy(AttributeNameStrategy::CamelCase)
    .with_markers_v2(true);

let result = render_template_with_locator(
    r#"<my-el foo-bar="hello"></my-el>"#,
    r#"{}"#,
    &locator,
    Some(&config),
)?;
// In my-el's template, use {{fooBar}} instead of {{foo-bar}}
```

#### WASM / JavaScript API

```javascript
const html = render_entry_with_templates(
    entry,
    templatesJson,
    stateJson,
    "camelCase", // or "none"
    false,       // optional stream flag
    true         // optional markers_v2 flag
);

const chunksJson = render_entry_with_templates(
    entry,
    templatesJson,
    stateJson,
    "camelCase",
    true,
    true
);
```

Use `render_with_templates` for the original non-entry template-rendering semantics; use `render_entry_with_templates` for top-level entry HTML rendering. Passing `true` as the optional fifth argument switches `render_entry_with_templates` to stream mode and returns a JSON array string of HTML chunks; omitted or `false` returns normal HTML. Passing `true` as the optional sixth `markers_v2` argument emits FAST Element 2.x indexed hydration markers.

Passing `"none"` or `""` as the strategy uses the default behaviour.

---

## Hydration Markers

When a custom element's shadow template is rendered, the renderer emits **hydration markers** so the FAST client runtime can efficiently locate and patch DOM nodes without a full diff.

FAST Element 3.x data-free markers are emitted by default. Set
`RenderConfig::with_markers_v2(true)` in Rust, or pass the `markers_v2` WASM/CLI
option, to emit FAST Element 2.x indexed markers for a client configured with
`enableHydration({ markers: markers_v2 })`.

### Content binding markers

Each `{{expr}}` or `{{{expr}}}` text binding is wrapped in data-free HTML comment markers:

```html
Hello world
```

Markers carry no binding index or expression name. They are matched by string equality and paired using balanced depth counting.

### Attribute binding markers

Elements with `{{expr}}` attribute values, `?attr="{{expr}}"` boolean bindings, or `{expr}` single-brace event/directive bindings receive a `data-fe="N"` marker attribute where `N` is the binding count. Client-only attributes (`@event`, `:property`, `f-ref`, `f-slotted`, `f-children`) are **stripped** from the HTML output but still counted in the marker:

```html

<input type="checkbox" disabled data-fe="1">


<input disabled data-fe="1">


<input data-fe="1">


<button data-fe="1">Label</button>


<slot data-fe="1"></slot>


<video class="my-video" data-fe="2">
```

`data-fe="N"` — `N` is the total number of attribute bindings on the element.

### Scope boundaries

Each custom element shadow, `<f-when>` body, and `<f-repeat>` item template gets its own scope with the binding index reset to 0. Scopes don't carry numeric IDs — markers are data-free and paired by balanced depth counting.

### Directive markers

```html


  [inner content, or empty if condition is false]





  [item 0 — binding index reset to 0 per item]


  [item 1 — binding index reset to 0 per item]


```


## Error Handling

Render functions return `Result<_, RenderError>` (HTML or stream chunks).
`RenderError` exposes `code()`, `location() -> Option<ErrorLocation>`, and
`template_name()`. `ErrorLocation` has one-based `line` and UTF-16 `column`, plus
a UTF-16 `length`. Match `error.kind()` to inspect variants through source-location
wrappers. WASM failures are JavaScript `Error` instances with these details as
properties, not plain strings. See the [source-coordinate contract and migration
notes](../../packages/fast-build/README.md#structured-errors).

| Variant | Code | Triggered by |
|---|---|---|
| `InvalidTemplateMetadata` | `invalid-template-metadata` | Unsupported version, missing name, or duplicate metadata name |
| `UnknownTemplate` | `missing-template` | Shadow-root render requests an unknown definition |
| `UnclosedBinding` | `unclosed-binding` | `{{` with no closing `}}` |
| `UnclosedUnescapedBinding` | `unclosed-unescaped-binding` | `{{{` with no closing `}}}` |
| `EmptyBinding` | `empty-binding` | Blank binding expression |
| `MissingState` | `missing-state` | Required directive state is absent; missing repeat lists still render zero iterations |
| `UnclosedDirective` | `unclosed-directive` | Directive/custom element with no matching close tag |
| `MissingValueAttribute` | `missing-value-attribute` | Directive missing a valid `value="{{…}}"` |
| `InvalidRepeatExpression` | `invalid-repeat-expression` | Repeat value not in `item in list` format |
| `NotAnArray` | `repeat-not-array` | Repeat binding resolves to a non-array |
| `DuplicateTemplate` | `duplicate-template` | Multiple files define the same name |
| `TemplateReadError` | `template-read-error` | A matched template file could not be read |
| `JsonParse` | `invalid-state-json` | Invalid JSON state |
| `MissingFTemplate` | `missing-f-template` | Composition input has no outer wrapper |
| `MultipleFTemplates` | `multiple-f-templates` | Composition input has multiple outer wrappers |
| `MissingInnerTemplate` | `missing-inner-template` | Composition input has no inner template |
| `MultipleInnerTemplates` | `multiple-inner-templates` | Composition input has multiple inner templates |
| `UnsafeStyleContent` | `unsafe-style-content` | Separately supplied CSS contains a `</style` terminator |

`Located` preserves its underlying variant's code/message. WASM template-map JSON
and attribute-record validation also use `invalid-template-metadata`; an invalid
WASM attribute-name strategy uses `invalid-attribute-name-strategy`. These failures
do not acquire HTML coordinates.

Messages retain the existing explanation and include a snippet when available:

```
type error: '{{items}}' must resolve to a JSON array for use in <f-repeat> — template: "…<f-repeat value=\"{{item in items}}\">…"
unclosed binding '{{name': no closing '}}' found to end the expression — template: "Hello {{name"
duplicate template: element '<my-button>' is defined in multiple files: ./a/my-button.html, ./b/my-button.html
```

---

## Numeric Precision

The hand-rolled JSON parser stores all numbers as `f64`. This means integers larger than 2^53 (9,007,199,254,740,992) lose precision, as is the case with standard JavaScript `number` values. For typical use cases (IDs, counts, display values) this is not a concern. If your state contains very large integers, represent them as strings and bind with `{{expr}}` accordingly.

## Renderer performance

Tag and binding discovery uses a forward event scan rather than repeated
remaining-suffix searches for each directive kind. Adjacent custom elements
and plain tags no longer incur those quadratic searches. Rendered HTML,
attribute handling, default markers, and `markers_v2` remain compatible.
Templates still render recursively; this is not a compiled-template or lazy
streaming API. Stream functions continue to return fully materialized chunks.

From a FAST repository checkout, run the native benchmarks and parity tests:

```sh
cargo bench --manifest-path crates/microsoft-fast-build/Cargo.toml --bench render
cargo test --manifest-path crates/microsoft-fast-build/Cargo.toml
```

Criterion separates parsed-state rendering, state parsing plus rendering, and
locator construction. Shared fixtures cover 1k/5k/20k instances and
50/200/1,000 definitions with payload sizes 1/20 in both marker modes.
See [performance baselines](benchmark-baselines/README.md) for the packaged
WASM runner, golden hashes, scaling checks, RSS measurement, and limitations.

The guide also records post-scanner repeat/state-overlay and many-definition
profiles, with bounded workload commands and symbolized native CPU sampling
through Criterion's `--profile-time` mode. Those measurements identify child-state
copying as the next repeat/overlay target; they do not claim that memory or
allocation targets have been met.

For native allocation baselines, use the opt-in development example or the
fresh-process matrix runner from the repository root:

```sh
node crates/microsoft-fast-build/benches/profile-allocations.mjs --output=/tmp/fast-allocations.json
cargo run --manifest-path crates/microsoft-fast-build/Cargo.toml --release --features allocation-profiling --example profile-allocations -- --case=repeat_custom_elements --count=250 --mode=v3 --phase=render
```

The feature does not instrument the library or shipped WASM. Reports count
only allocations on the measuring thread within the selected phase, excluding
prepared inputs and report generation. See the baseline guide for controls,
output retention, reallocation semantics, and test commands.

---

### Overview (`crates/microsoft-fast-convert/README.md`)

# microsoft-fast-convert

`microsoft-fast-convert` converts one FAST declarative HTML template string into another supported syntax. It is written in Rust and exposes both a Rust API and a `wasm-bindgen` API for Node tooling.

## Supported targets

- `webui-prerelease` — unwraps the outer `<f-template>` and emits HTML for WebUI's FAST parser plugin, converting only `<f-repeat>` to `<for>` and `<f-when>` to `<if>`. Other supported FAST attributes (`@click`, `:prop`, `?bool`, `f-ref`, `f-children`, `f-slotted`) pass through unchanged.
- `webui-framework-prerelease` — converts FAST's declarative syntax into the Microsoft WebUI Framework's own declarative runtime syntax (transferring Shadow/Light DOM policy from the outer `<f-template>` onto the inner `<template>`). It converts `<f-repeat>` to `<for>`, `<f-when>` to `<if>`, `f-ref` to a braced `w-ref`, and FAST's `$e` event argument to bare `e`. `f-slotted`/`f-children` are stripped from the output with a warning, since WebUI Framework has no equivalent; every other unsupported construct (unknown `f-*`, `$c` event context, non-braced `f-ref`, conflicting shadow-root modes) remains a hard error. The target's name reflects the WebUI Framework project's own current prerelease status, not the stability of this target's implementation.
- `fast-v3-ts` — emits TypeScript source that imports FAST helpers and exports `template` as an `html` tagged template.

## Rust usage

```rust
use microsoft_fast_convert::{convert_template, convert_stylesheet};

let source = r#"<f-template name="my-element"><template>{{title}}</template></f-template>"#;
let result = convert_template(source, "fast-v3-ts")?;
let ts = result.output;

let css = ":host { display: block; }";
let styles = convert_stylesheet(css, "fast-v3-ts", "styles")?;
```

`convert_template`/`convert_template_with_options` return
`Result<ConvertOutput, ConvertError>`, where `ConvertOutput { output: String,
warnings: Vec<ConvertWarning> }`. `warnings` reports non-fatal issues — such as a
stripped `f-slotted`/`f-children` directive, produced only by
`webui-framework-prerelease` — that didn't stop conversion;
`webui-prerelease` and `fast-v3-ts` output always have an empty `warnings`
vector, since neither strips anything. `convert_stylesheet` is unaffected and
still returns `Result<String, ConvertError>`.

`convert_stylesheet(stylesheet, syntax, export_name)` converts a CSS source string
into a TypeScript module that imports `css` from `@microsoft/fast-element` and
exports `export_name` as a `css` tagged template. It has no filesystem
requirement and, like `convert_template`, is only supported for the
`fast-v3-ts` syntax. `export_name` must be a valid TypeScript/JavaScript
identifier (no dotted paths).

`fast-v3-ts` output can optionally include an explicit `TSource` generic parameter
(`html<TypeSource>` instead of bare `html`) via `convert_template_with_options` and
`ConvertOptions`:

```rust
use microsoft_fast_convert::{convert_template_with_options, ConvertOptions};

let options = ConvertOptions {
    type_source: Some("MyElement".to_string()),
    type_source_import: Some("./my-element.js".to_string()),
    ..ConvertOptions::default()
};
let ts = convert_template_with_options(source, "fast-v3-ts", &options)?.output;
```

`type_source` must be a dotted TypeScript identifier (e.g. `MyElement` or
`Namespace.MyElement`); `type_source_import`, when provided, also emits a matching
`import type { <root_identifier> } from "<type_source_import>";` statement. `type_source`
is only supported for `fast-v3-ts`; `type_source_import` requires `type_source`.

Syntax metadata is available through `syntax_metadata()`. The metadata includes each
supported syntax name, required output extension, and default output suffix so package
tooling can avoid duplicating target definitions.

### Explicit public export types

Set `ConvertOptions { typed: true, ..ConvertOptions::default() }` for
`fast-v3-ts` template conversion. It emits an `ElementViewTemplate<TSource>`
annotation (or `ElementViewTemplate` when no source type is supplied) and a
type-only FAST import. The default remains byte-compatible unannotated output.
Other syntax targets reject `typed: true`.

`convert_stylesheet_with_options(css, syntax, export_name, &options)` similarly
emits `export const styles: ElementStyles = css...` with a type-only import.
Stylesheet options reject `type_source`/`type_source_import`. Existing
`convert_stylesheet` calls keep their original output. Type imports use the
root of dotted source names; FAST type names are aliased when necessary to
avoid collisions with supplied names.

Typed exports support `isolatedDeclarations`; the converter does not infer a
state interface. Supply a concrete source type for strict property validation.
Native struct literals should use `..ConvertOptions::default()` for unset options.

## WASM usage

When built with `wasm-pack --target nodejs`, the crate exports:

```ts
interface ConvertResult {
    readonly output: string;
    readonly warnings: string[];
}

convert_template(template: string, syntax: string): ConvertResult
convert_template_with_options(
    template: string,
    syntax: string,
    typeSource?: string,
    typeSourceImport?: string,
    typed?: boolean,
): ConvertResult
convert_stylesheet(stylesheet: string, syntax: string, export_name: string, typed?: boolean): string
convert_syntax_metadata(): string
```

`convert_syntax_metadata()` returns JSON metadata for supported syntax targets.
Errors are JavaScript `Error` instances, retaining the `ConvertError` message and
adding `code` plus optional `line`, `column`, `length`, and `templateName`.
Generated declarations export the `FastBuildError extends Error` interface.
Coordinates refer to the complete original input, not the extracted inner
template or rewritten output. They use one-based UTF-16 columns/lines and a UTF-16
error-token highlight length; CRLF is one break and lone CR/LF also break lines.
Options/syntax failures have no HTML coordinates.

Native `ConvertError` provides `code()`, `location() -> Option<ErrorLocation>`,
`template_name()`, and `kind()`; use `kind()` when matching source-wrapped
validation errors. Context fields are now boxed `ErrorContext` values. See the
[migration guide](../../packages/fast-build/docs/migration/plugin-integrations.md#structured-errors).

## Error codes

| Code | Failure |
|---|---|
| `unsupported-syntax` | Unknown syntax target |
| `typed-unsupported-for-syntax` | Typed output requested for non-TypeScript syntax |
| `type-source-unsupported-for-stylesheet` | Source-type options supplied for CSS |
| `stylesheet-unsupported-for-syntax` | CSS requested for a target other than `fast-v3-ts` |
| `invalid-export-name` | Invalid stylesheet export identifier |
| `type-source-unsupported-for-syntax` | Source-type options supplied for a non-TypeScript target |
| `invalid-type-source` | Invalid dotted source-type identifier |
| `type-source-import-requires-type-source` | Import module supplied without a source type |
| `missing-f-template` | No outer wrapper |
| `multiple-f-templates` | Multiple outer wrappers |
| `missing-f-template-name` | Outer wrapper lacks a string name |
| `empty-f-template-name` | Outer wrapper name is blank |
| `missing-inner-template` | No inner template |
| `multiple-inner-templates` | Multiple inner templates |
| `unclosed-element` | No matching closing element |
| `unclosed-tag` | Opening tag has no terminating `>` |
| `missing-value-attribute` | Directive lacks its required value |
| `invalid-directive-value` | Directive value lacks double-brace delimiters |
| `invalid-repeat-expression` | Repeat value is not `item in items` |
| `unclosed-binding` | Binding lacks closing delimiters |
| `empty-binding` | Binding expression is blank |
| `unsupported-f-attribute` | Unsupported FAST attribute |
| `unsupported-f-element` | Unsupported FAST element |
| `unsupported-expression` | Expression is outside the converter grammar |
| `unsupported-event-handler` | Event handler cannot be converted |
| `unsupported-event-context` | FAST context token has no WebUI mapping |
| `conflicting-shadow-root-mode` | Outer and inner shadow-root declarations conflict |
| `unsupported-publisher-attribute` | Outer attribute cannot be transferred |
| `invalid-attribute-value` | Attribute lacks its required braced form |

## Validation

The converter validates that the input contains exactly one `<f-template name="…">` with a non-empty name and exactly one inner `<template>`. It validates supported syntax values, `<f-repeat>` and `<f-when>` `value="{{…}}"` expressions, supported `f-*` attributes, and the limited expression grammar used for `fast-v3-ts` output. It also validates that `type_source` is a dotted identifier, that `type_source` is only supplied for `fast-v3-ts`, and that `type_source_import` is only supplied alongside `type_source`.

The `webui-framework-prerelease` target additionally validates that outer `<f-template>` attributes (other than `name`) are `shadowroot`-prefixed (`ConvertError::UnsupportedPublisherAttribute` otherwise), that a `shadowroot`-prefixed outer attribute doesn't conflict with a differently-valued attribute already on the inner `<template>` (`ConvertError::ConflictingShadowRootMode`), that `f-ref` values are single-braced (`ConvertError::InvalidAttributeValue`), and that event arguments don't use FAST's repeat-context tokens such as `$c` (`ConvertError::UnsupportedEventContext`). `f-slotted` and `f-children` are the one exception to this target's otherwise strict validation: rather than erroring, they are stripped from the output and reported via `ConvertOutput::warnings` as a `ConvertWarning::StrippedUnsupportedDirective`.

`convert_stylesheet` validates that `syntax` is `fast-v3-ts` (CSS conversion is not supported for `webui-prerelease`/`webui-framework-prerelease`) and that `export_name` is a valid TypeScript/JavaScript identifier. Stylesheet content is escaped for safe embedding in a TypeScript template literal: backslashes, backticks, literal `${` sequences, and carriage returns are all escaped.

---

### Overview (`examples/design-system/README.md`)

# @microsoft/fast-examples-design-system

A CSS-only design system for FAST example apps. The package ships three
hand-authored stylesheets that define a shared set of CSS custom properties
for color, typography, spacing, shape, elevation, and motion. There is **no
JavaScript or TypeScript implementation** — example apps wire themes
themselves by toggling the `data-theme` attribute on `<html>`.

This README and [`DESIGN.md`](./DESIGN.md) are the canonical guidance for both
humans and coding agents working in the `examples/*` workspace.

Token names are semantic and use-site-oriented, with the `--fast-` prefix
and coverage tuned for FAST example apps.

## What ships

The package ships exactly one stylesheet:

| File | Contents |
| --- | --- |
| `tokens.css` | Every token, declared once on `:root`. Color and elevation values use the CSS `light-dark()` function, so each declaration carries both its light and dark resolution side by side. `color-scheme: light dark` enables system-preference resolution; `<html data-theme="light">` or `<html data-theme="dark">` forces a theme. |

The package is `"private": true` and consumed via the workspace dependency
`"@microsoft/fast-examples-design-system": "workspace:*"`.

`tokens.css` uses the CSS `light-dark()` function, which requires
Chrome / Edge 123+, Firefox 120+, or Safari 17.5+ (all shipped in
2023–2024). These example apps target evergreen browsers; there is no
fallback for older versions.

## Install

Add the workspace dependency in the consuming example app's `package.json`,
then run `npm install` from the repository root.

```json
{
    "dependencies": {
        "@microsoft/fast-examples-design-system": "workspace:*"
    }
}
```

## Use

Import the stylesheet exactly once at the app entry point — typically the same
file that defines or bootstraps the root custom element. The bundler (Vite in
the existing examples) inlines the CSS into the document.

```ts
// src/main.ts
import "@microsoft/fast-examples-design-system/tokens.css";
```

```html

<!doctype html>
<html lang="en">
    
    <body>
        <my-app></my-app>
    </body>
</html>
```

If the app is intentionally single-theme, hard-code the attribute and never
touch it from JavaScript:

```html
<html lang="en" data-theme="light"> 
```

### Referencing tokens from component CSS

Reference tokens through `var(--fast-...)` in FAST `css` template literals or
in any other CSS context. Never hard-code colors, font sizes, spacing, radii,
border widths, shadows, durations, or curves.

```ts
import { css } from "@microsoft/fast-element";

export const styles = css`
    :host {
        display: block;
        padding: var(--fast-padding-content-medium);
        background: var(--fast-background-layer-primary-solid);
        color: var(--fast-foreground-ctrl-neutral-primary-rest);
        border: var(--fast-stroke-width-default) solid
            var(--fast-stroke-divider-subtle);
        border-radius: var(--fast-corner-large);
        box-shadow: var(--fast-shadow-card-rest);
        font-family: var(--fast-text-style-default-regular-font-family);
        font-size: var(--fast-text-global-body3-font-size);
        line-height: var(--fast-text-global-body3-line-height);
        transition: background var(--fast-duration-fast)
            var(--fast-curve-easy-ease);
    }
`;
```

## Theme switching

The active theme is selected by the `data-theme` attribute on `<html>`:

| `data-theme` value | Effective theme |
| --- | --- |
| `"light"` | Forced light |
| `"dark"` | Forced dark |
| _absent_ | Follows `prefers-color-scheme` (dark if the system requests dark, light otherwise) |

Under the hood, `tokens.css` declares `color-scheme: light dark` on `:root`
and uses the CSS `light-dark()` function in every color/elevation token.
The browser picks the matching value based on the inherited
`color-scheme`. Setting `data-theme="light"` or `data-theme="dark"`
overrides `color-scheme` to that single value, which flips every
`light-dark()` resolution. No media query is needed.

To wire a toggle, write the attribute directly from your application code. The
design system itself contains no JavaScript — toggles, persistence, and event
plumbing are intentionally left to the consuming app so the system stays
framework-neutral and dependency-free.

```ts
// Force light
document.documentElement.setAttribute("data-theme", "light");

// Force dark
document.documentElement.setAttribute("data-theme", "dark");

// Restore system preference
document.documentElement.removeAttribute("data-theme");
```

See [`../todo-app/`](../todo-app/) for a working consumer of the design
system. The example deliberately uses a single (light) theme set
statically in markup; it does not implement a runtime toggle.

## Token catalog

The complete list of tokens lives in [`tokens.css`](./tokens.css). Categories
at a glance:

| Category | Examples |
| --- | --- |
| Background: surfaces | `--fast-background-web-page-primary`, `--fast-background-layer-primary-solid`, `--fast-background-layer-secondary` |
| Background: subtle controls | `--fast-background-ctrl-subtle-rest`, `--fast-background-ctrl-subtle-hover`, `--fast-background-ctrl-subtle-pressed`, `--fast-background-ctrl-subtle-disabled` |
| Background: brand controls | `--fast-background-ctrl-brand-rest`, `--fast-background-ctrl-brand-hover`, `--fast-background-ctrl-brand-pressed`, `--fast-background-ctrl-brand-disabled` |
| Foreground | `--fast-foreground-ctrl-neutral-primary-rest`, `--fast-foreground-ctrl-neutral-primary-disabled`, `--fast-foreground-ctrl-neutral-secondary-rest`, `--fast-foreground-ctrl-hint-default`, `--fast-foreground-ctrl-on-brand-rest`, `--fast-foreground-ctrl-brand-rest` |
| Stroke: dividers | `--fast-stroke-divider-default`, `--fast-stroke-divider-subtle`, `--fast-stroke-divider-strong`, `--fast-stroke-divider-brand` |
| Stroke: control outlines | `--fast-stroke-ctrl-on-outline-rest`, `--fast-stroke-ctrl-on-outline-disabled` |
| Stroke widths | `--fast-stroke-width-default`, `--fast-stroke-width-divider-strong` |
| Control focus | `--fast-ctrl-focus-outer-stroke`, `--fast-ctrl-focus-outer-stroke-width` |
| Status: solid | `--fast-status-{danger, success, warning}-background`, `--fast-status-{danger, success, warning}-foreground` |
| Status: tinted | `--fast-status-{danger, success, warning}-tint-background`, `--fast-status-{danger, success, warning}-tint-foreground`, `--fast-status-{danger, success, warning}-tint-stroke` |
| Shadow | `--fast-shadow-card-rest-key`, `--fast-shadow-card-rest-ambient`, `--fast-shadow-card-rest`, `--fast-shadow-flyout-key`, `--fast-shadow-flyout-ambient`, `--fast-shadow-flyout` |
| Text: families | `--fast-text-style-default-regular-font-family`, `--fast-text-style-code-regular-font-family`, `--fast-text-style-data-viz-regular-font-family` |
| Text: weights | `--fast-text-style-default-regular-weight`, `--fast-text-style-default-header-weight`, `--fast-text-style-default-display-weight` |
| Text: global ramp (font size + line height pairs) | `--fast-text-global-caption2-*`, `--fast-text-global-caption1-*`, `--fast-text-global-body3-*`, `--fast-text-global-body2-*`, `--fast-text-global-body1-*`, `--fast-text-global-subtitle2-*`, `--fast-text-global-subtitle1-*`, `--fast-text-global-title2-*`, `--fast-text-global-title1-*`, `--fast-text-global-display2-*`, `--fast-text-global-display1-*` |
| Padding (inset) | `--fast-padding-content-none`, `--fast-padding-content-xx-small`, `-x-small`, `-small`, `-medium`, `-large`, `-x-large`, `-xx-large`, `-xxx-large` |
| Gap (between elements) | `--fast-gap-between-content-none`, `--fast-gap-between-content-xx-small`, `-x-small`, `-small`, `-medium`, `-large`, `-x-large`, `-xx-large` |
| Corner | `--fast-corner-none`, `--fast-corner-small`, `--fast-corner-medium`, `--fast-corner-large`, `--fast-corner-circular` |
| Duration | `--fast-duration-ultra-fast`, `--fast-duration-faster`, `--fast-duration-fast`, `--fast-duration-normal`, `--fast-duration-gentle`, `--fast-duration-slow`, `--fast-duration-slower`, `--fast-duration-ultra-slow` |
| Curve | `--fast-curve-accelerate-max`, `-mid`, `-min`, `--fast-curve-decelerate-max`, `-mid`, `-min`, `--fast-curve-easy-ease-max`, `--fast-curve-easy-ease`, `--fast-curve-linear` |

State vocabulary on interactive tokens: `rest`, `hover`, `pressed`,
`disabled`. Optionally prefixed with `selected-` for selectable controls.

See [`DESIGN.md`](./DESIGN.md) for the full naming grammar, the rationale, and
the rules for adding new tokens.

---

### Overview (`examples/test/README.md`)

# FAST Examples — End-to-End Tests

Playwright end-to-end tests that exercise the three Todo example apps in this monorepo as black-box web applications. The same test suite runs against each app, asserting that the unified UI and functionality behave identically regardless of implementation.

| App | Project name | Dev server |
|---|---|---|
| [`examples/csr/todo-app`](../csr/todo-app) | `csr-todo` | `vite` on port `9000` |
| [`examples/csr/todo-mobx-app`](../csr/todo-mobx-app) | `csr-todo-mobx` | `vite` on port `9001` |
| [`examples/ssr/webui-todo-app`](../ssr/webui-todo-app) | `ssr-webui-todo` | `webui serve` on port `8081` |

Each project is configured in [`playwright.config.ts`](./playwright.config.ts) with its own `webServer` block — Playwright starts and stops them automatically.

## Running

From the monorepo root:

```bash
# install deps and browsers (once)
npm ci
npx playwright install --with-deps chromium

# build the example apps the tests depend on
npm run build -w @microsoft/fast-element
npm run build -w @microsoft/fast-todo-app-example
npm run build -w @microsoft/fast-todo-mobx-app-example
npm run build -w @microsoft/fast-webui-todo-app-example

# run all three suites
npm run test:e2e
```

To run a single app's suite:

```bash
npm run test:e2e -w @microsoft/fast-examples-e2e -- --project=csr-todo
npm run test:e2e -w @microsoft/fast-examples-e2e -- --project=csr-todo-mobx
npm run test:e2e -w @microsoft/fast-examples-e2e -- --project=ssr-webui-todo
```

## Layout

```
examples/test/
├── package.json
├── playwright.config.ts
├── DESIGN.md                    // design notes for contributors
├── support/
│   ├── fixtures.ts              // injects the per-project adapter
│   ├── global-setup.ts
│   ├── global-teardown.ts
│   └── adapters/
│       ├── index.ts             // resolves the adapter for a project
│       ├── types.ts             // TodoAppAdapter interface
│       ├── csr.ts               // shared adapter for both CSR apps
│       └── ssr-webui-todo.ts
└── tests/
    └── todo.pw.spec.ts          // shared suite, runs against every project
```

Adapters wrap the per-app DOM differences (e.g. SSR app uses a nested `<todo-item>` shadow root per row, while CSR apps render inline `<li>` content) behind a uniform interface (`addTodo`, `descriptions`, `toggleByDescription`, `deleteByDescription`, `setFilter`, `getCounts`, …). Test specs use that interface only — no app-specific selectors leak into the suite.

Spec files use the `*.pw.spec.ts` suffix so Playwright picks them up while leaving the `*.spec.ts` suffix free for future Node-based tests.

## CI

The `test:e2e` script is run as a separate step in [`.github/workflows/ci-validate-pr.yml`](../../.github/workflows/ci-validate-pr.yml) after unit tests, gated on the same `npx playwright install --with-deps` invocation that already runs there.

---

### Overview (`packages/fast-build/README.md`)

# FAST Build

[](https://opensource.org/licenses/MIT)
[](https://badge.fury.io/js/%40microsoft%2Ffast-build)

The `fast-build` package renders the declarative HTML template syntax of [`@microsoft/fast-element`](https://www.npmjs.com/package/@microsoft/fast-element), primarily for use in testing environments. It is powered by a WebAssembly core with zero runtime npm dependencies.

> **Note:** For production server-side rendering, we recommend using the [`@microsoft/webui`](https://github.com/microsoft/webui) project instead.

## Installation

### From NPM

To install the latest `@microsoft/fast-build` package using `npm`:

```shell
npm install --save @microsoft/fast-build
```

Within your JavaScript or TypeScript code, you can then import library APIs like this:

```ts
import { render } from '@microsoft/fast-build';
```

## CLI usage

Once installed, the `fast` binary is available. Use the `build` subcommand to render an HTML template with an optional JSON state file, or `convert` to convert a FAST declarative HTML template to another supported syntax:

```shell
fast build [options]
fast convert [options]
```

### Build options

| Option | Default | Description |
|---|---|---|
| `--entry="<path>"` | `index.html` | Entry HTML template to render |
| `--state="<path>"` | `{}` when omitted | JSON file containing the template state. If omitted, no state file is loaded and rendering uses an empty state object. If `--state` is provided, the file must exist. |
| `--output="<path>"` | `output.html` | Where to write the rendered HTML |
| `--templates="<glob>"` | _(none)_ | Glob pattern(s) for custom element template HTML files. Separate multiple patterns with commas. A warning is printed if not provided in non-streaming mode or if no files match a pattern. |
| `--attribute-name-strategy="<strategy>"` | `camelCase` | Strategy for mapping HTML attribute names to state property names on custom elements. `"camelCase"` converts dashes to camelCase (e.g. `foo-bar` → `fooBar`). `"none"` preserves dashes (e.g. `foo-bar` → `foo-bar`). See [Attribute name strategy](#attribute-name-strategy). |
| `--markers_v2[=true/false]` | `false` | Emit FAST Element 2.x indexed hydration markers instead of the default FAST Element 3.x data-free markers. |
| `--config="<path>"` | `fast-build.config.json` | Path to a JSON configuration file. If omitted, `fast-build.config.json` in the current directory is used when present. CLI arguments take precedence over config values. See [Configuration file](#configuration-file). |
| `--stream[=true/false]` | `false` | Write rendered HTML chunks directly to stdout instead of writing `--output`. Valueless `--stream` is treated as `true`. |

### Example

Given an `index.html`:

```html
<html>
  <body>
    <h1>{{title}}</h1>
    <p>{{description}}</p>
  </body>
</html>
```

And a `state.json`:

```json
{
  "title": "Hello FAST",
  "description": "Server-side rendered with WebAssembly."
}
```

Run:

```shell
fast build --entry=index.html --state=state.json --output=output.html
```

Produces `output.html`:

```html
<html>
  <body>
    <h1>Hello FAST</h1>
    <p>Server-side rendered with WebAssembly.</p>
  </body>
</html>
```

### Streaming output

Pass `--stream`, `--stream=true`, or `--stream=false`, or set
`"stream": true` in `fast-build.config.json`, to control stdout streaming. When
streaming is enabled, the CLI writes raw rendered HTML chunks to stdout, does
not write the `--output` file, and does not print the normal `Built: ...`
message.

```shell
fast build --entry=index.html --state=state.json --stream
```

Streaming is simulated by the WebAssembly renderer: chunks are prepared in
memory, returned to JavaScript as a JSON array, parsed by the CLI, and then
written to stdout. `--stream` uses the same entry renderer with its stream flag
enabled and passes an empty templates map when no `--templates` glob is
provided. Chunk boundaries are safe for HTML parsing:

- Attribute bindings stay within complete opening tag chunks.
- Custom element opening chunks include the complete Declarative Shadow DOM
  template.
- Streamed output uses the same renderer preprocessing and custom-element host
  attribute propagation as normal output.
- Empty chunks are omitted.
- Concatenating all chunks matches the normal non-streamed render.

### Performance benchmarks for contributors

The renderer discovers tags and bindings in a forward scan, eliminating repeated
remaining-suffix searches for adjacent custom elements and plain tags. Existing
WASM exports, rendered bytes, default markers, and `markers_v2` remain compatible.
Rendering is still synchronous, and `--stream` still buffers all chunks in WASM.

From a FAST repository checkout, not an installed npm package:

```shell
npm run build -w @microsoft/fast-build
npm run bench:render -w @microsoft/fast-build -- --case=url_sink_siblings --output=/tmp/fast-render.json
npm run bench:render -w @microsoft/fast-build -- --case=url_sink_siblings --check-scaling
```

The runner benchmarks the actual packaged WASM in fresh child processes in both
marker modes, recording timing, CPU, output hashes, throughput, and peak RSS.
Use `--case`, `--counts`, `--samples`, or `--compare=<baseline.json>` to narrow
or compare a run. Output files are never overwritten. Normal tests verify the
same fixtures against pre-optimization hashes without flaky timing thresholds.
See the [benchmark guide](../../crates/microsoft-fast-build/benchmark-baselines/README.md)
for native Criterion benchmarks, fixture sizes, methodology, and limitations.

The guide includes post-scanner repeat/state-heavy and many-definition profiles.
Start expensive repeat cases with `--counts=250,1000 --warmup-count=250`;
state-overlay controls and separate native phases help identify the next
optimization without running an unbounded matrix. Native CPU samples are not
WASM allocation measurements, and no production rendering behavior is changed.

The guide also includes an opt-in native allocation baseline and a fresh-process
matrix command: `node crates/microsoft-fast-build/benches/profile-allocations.mjs
--output=/tmp/fast-allocations.json` from the repository root. Its counters are
development-only Rust tooling, not part of the npm CLI or WASM; native peak
newly-live heap is not process RSS.

### Missing or omitted state

State is optional. When `--state` is omitted and no `state` path is provided by config, `fast build` does not look for `state.json`; rendering uses an empty object (`{}`). An explicit `--state` path, or a `state` path from config, must exist or the command exits with an error.

> **Breaking change:** Earlier versions implicitly loaded `state.json` from the current working directory when `--state` was omitted. To use a state file, pass `--state=state.json` or set `"state": "state.json"` in `fast-build.config.json`.

When a binding value is not present in state:

- Content bindings render nothing, including unresolved dot paths: `<p>{{foo.bar}}</p>` becomes `<p></p>`.
- Attribute bindings omit the entire attribute, including unresolved dot paths: `<div class="{{foo.bar}}"></div>` becomes `<div></div>`.
- `<f-repeat>` treats a missing list binding, including unresolved dot paths, as an empty array and renders zero iterations. If the binding is present but is not an array, rendering still errors.

Explicit `null` also omits an attribute, even in an interpolated attribute
value. Empty strings remain present. Known HTML boolean attributes bound to
JSON booleans use presence/absence; ordinary attributes (including ARIA)
retain textual booleans. Use `?name` for browser-side truthy/falsy bindings.
Author bindings resolving to absence still override template-host defaults.
These intentional output changes are described in the
[plugin migration guide](./docs/migration/plugin-integrations.md).

### APIs for build-time plugins

Import the actual exported WASM subpath; do not slice rendered host HTML:

```js
import {
    parse_f_templates,
    render_shadow_root,
} from "@microsoft/fast-build/wasm/microsoft_fast_build.js";

const definitions = JSON.parse(parse_f_templates(templateHtml));
const templates = Object.fromEntries(
    definitions.filter(definition => definition.name !== null)
        .map(definition => [definition.name, definition]),
);
const shadowRootHtml = render_shadow_root(
    "my-card", JSON.stringify(templates), JSON.stringify(componentState),
);
```

The result is the complete DSD `<template>` fragment, with hydration markers
and nested components, but no host, host defaults, or light DOM. Pass resolved
component state; the API does not derive it from caller-owned host attributes.
It accepts the existing attribute-name strategy and v2 marker options.

Parsed records add `formatVersion: 1` and `bindings` without changing the array
shape. Binding records expose `name` (null for compound expressions),
`expression`, syntax `kind`, lexical `paths`, and outer-to-inner repeat
`scope` frames. `type` is null except for repeat collections (`"array"`);
`optional` is null because required state declarations are not inferable.
`$index` paths refer to the active repeat frame, not a root state key.
Client expressions are described lexically, not fully JavaScript-type-checked.
Code samples are excluded; metadata is not full syntax or state validation.
Generated WASM declarations expose these JSON interfaces.

#### Authored binding source spans

Each binding occurrence includes `span: { start, end }`. Both positions contain
`offset`, `line`, and `column`, relative to the **complete HTML string passed to
`parse_f_templates`**, not the extracted or trimmed template body. Duplicate
expressions have separate spans, including occurrences in host attributes,
interpolated attribute values, and nested directives.

- `offset` is a zero-based UTF-16 code-unit offset, compatible with JavaScript
  string slicing. It is not a UTF-8 byte offset.
- `line` and `column` are one-based. Columns count UTF-16 code units, not visual
  width or Unicode code points; a tab counts as one and a non-BMP character
  counts as two.
- Ranges are half-open: `start` is inclusive and `end` is exclusive. They cover
  the trimmed expression, excluding braces and surrounding whitespace.
- CRLF counts as one line break but two offset units. Lone CR and LF each count
  as one line break. Input line endings are not normalized.
- Repeat bindings locate the iterable expression, not the alias or `in` keyword,
  matching their existing `expression` field. Nested `scope` frames are unchanged.

```js
const [definition] = JSON.parse(parse_f_templates(templateHtml));
for (const binding of definition.bindings) {
    const { start, end } = binding.span;
    const authoredExpression = templateHtml.slice(start.offset, end.offset);
    console.log(`${start.line}:${start.column}`, authoredExpression);
}
```

Positions refer to the original, entity-encoded attribute text. No entity decoding
is introduced. Code samples remain excluded without shifting subsequent spans.
Callers associate the input with its file name and must regenerate metadata after
editing that input. Bindings and directives inside HTML comments remain unsupported.

Render exports reject unsupported/malformed explicit versions before rendering.
Legacy unversioned maps and string definitions remain supported. The CLI keeps
version/binding fields when assembling a map; persisted metadata should do the
same instead of discarding them.

#### Structured errors

Failing render, conversion, composition, and metadata-validation APIs throw actual
JavaScript `Error` objects, retaining the existing human-readable `message`.
Both WASM modules export this TypeScript interface (not a runtime constructor):

```ts
interface FastBuildError extends Error {
    code: string;
    line?: number;
    column?: number;
    length?: number;
    templateName?: string;
}
```

Use `code`, such as `unclosed-binding`, `repeat-not-array`, or `missing-template`,
instead of parsing messages. The complete code lists are documented with the
[renderer errors](../../crates/microsoft-fast-build/README.md#error-handling)
and [converter errors](../../crates/microsoft-fast-convert/README.md#error-codes).

Locations use one-based lines and UTF-16 columns, with a UTF-16 highlight `length`.
Tabs count as one unit, non-BMP characters as two; CRLF is one line break and lone
CR/LF are also line breaks. A highlight covers the offending opening tag or
binding including its delimiters; an unclosed binding highlights its opening
delimiters. Unlike successful binding metadata, these are error-token ranges,
not trimmed expression ranges.

Entry-render and conversion coordinates refer to the original HTML argument,
even after code-sample escaping, inner-template extraction, or publisher-attribute
rewriting. Light DOM remains in its caller's source. Errors in separately supplied
custom-element definitions include `templateName` and use coordinates within that
definition's supplied `content`, not the entry HTML or the full file it was
extracted from. Maintain a name-to-source mapping when presenting these locations.
For a missing inner template, the highlight identifies its containing
`<f-template>`; duplicate-wrapper errors identify the second wrapper.

Coordinates are absent when there is no meaningful HTML position: invalid state
JSON, malformed metadata/options, missing template definitions or outer wrappers,
filesystem errors, and unsafe separately supplied CSS. A known `templateName`
can still be present without coordinates. `parse_f_templates` remains permissive:
it does not gain strict syntax validation or new failures.

For a direct `render(html, stateJson)` call, an integration can report:

```js
try {
    render(html, stateJson);
} catch (error) {
    if (!(error instanceof Error)) throw error;
    const location = error.line === undefined
        ? inputPath
        : `${inputPath}:${error.line}:${error.column}`;
    console.error(`${location} [${error.code}]: ${error.message}`);
}
```

See the [migration guide](./docs/migration/plugin-integrations.md#structured-errors)
when updating consumers that previously caught strings.

### Custom element templates

Pass a glob pattern (or comma-separated list of patterns) to `--templates` to expand custom elements into [Declarative Shadow DOM](https://developer.chrome.com/docs/css-ui/declarative-shadow-dom):

```shell
fast build \
  --templates="./components/**/*.html" \
  --entry=index.html \
  --state=state.json \
  --output=output.html
```

Each matched `.html` file is scanned for `<f-template>` elements. The `name` attribute of each `<f-template>` determines the custom element name. A single file may contain multiple templates.

Template files must use the following format:

```html
<f-template name="my-button">
    <template>
        <button>{{label}}</button>
    </template>
</f-template>
```

If an `<f-template>` element has no `name` attribute, a warning is printed and it is ignored. Exact file paths (no wildcards) are also accepted as patterns, making it possible to register a single template file. The parser follows browser tag boundaries for the `<f-template>` and inner `<template>` wrappers, including ASCII whitespace before `>` in opening and closing tags.

Any `shadowroot*` attributes on `<f-template>` are forwarded to the rendered Declarative Shadow DOM `<template>`. The CLI normalizes `shadowrootmode` and legacy `shadowroot` for compatibility: when neither has a non-empty value, it emits `shadowrootmode="open" shadowroot="open"`; when exactly one has a non-empty value, that value is mirrored to the other; when both have explicit non-empty values, both are preserved as authored, even if they conflict.

### Attribute name strategy

The `--attribute-name-strategy` option controls how HTML attribute names on custom elements are mapped to state property names in their shadow templates.

| Strategy | Behaviour | Template binding |
|---|---|---|
| `camelCase` (default) | Dashed attribute names converted to camelCase | `foo-bar` → `{{fooBar}}` |
| `none` | Attribute names lowercased as-is, dashes preserved | `foo-bar` → `{{foo-bar}}` |

The `camelCase` strategy only affects "plain" custom element attributes. It does **not** change:
- `data-*` attributes (always use `dataset.*` grouping)
- `aria-*` attributes (always use ARIA reflection lookup)
- HTML global attributes with known property names (e.g. `tabindex` → `tabIndex`)

```shell
fast build \
  --templates="./components/**/*.html" \
  --attribute-name-strategy=camelCase \
  --entry=index.html \
  --state=state.json \
  --output=output.html
```

### Configuration file

Instead of passing every option on the command line, you can place a `fast-build.config.json` file alongside your project files:

```json
{
    "entry": "index.html",
    "state": "state.json",
    "output": "output.html",
    "templates": "./components/**/*.html",
    "markers_v2": true
}
```

The CLI automatically loads `fast-build.config.json` from the current directory when it exists. To use a different file, pass `--config`:

```shell
fast build --config=configs/my-build.json
```

**Precedence:** CLI arguments always override config file values. For example, `--output=other.html` will override the `output` value in the config file.

**Path resolution:** File paths in the config file (`entry`, `state`, `output`, `templates`) are resolved relative to the config file's directory, not the current working directory. This ensures the config works correctly regardless of where the CLI is invoked.

All keys are optional. Only the following keys are allowed: `entry`, `state`, `output`, `templates`, `attribute-name-strategy`, `markers_v2`, and `stream`. Unknown keys produce an error. Values must be strings except `markers_v2` and `stream`, which must be JSON booleans (`true` or `false`). If `state` is omitted, rendering uses `{}`; if `state` is present, the referenced file must exist. CLI arguments always override config values, including `--stream=false` overriding `"stream": true`.

## Convert

`fast convert` converts FAST declarative template files using the converter WASM module in `wasm/convert/`. Supported syntax names, output extensions, and default output suffixes are read from the converter WASM metadata so the Rust converter remains the source of truth for syntax targets.

```shell
fast convert --syntax=webui-prerelease --templates=example.html
fast convert --syntax=fast-v3-ts --templates=example.html --output=../*.template.ts
fast convert --syntax=fast-v3-ts --templates="src/**/*.html" --output=generated/*.template.ts
fast convert --syntax=fast-v3-ts --templates=example.html \
    --type-source=MyElement --type-source-import=./my-element.js
```

### Convert options

| Option | Default | Description |
|---|---|---|
| `--syntax="<syntax>"` | _(required)_ | Target syntax: `webui-prerelease`, `webui-framework-prerelease`, or `fast-v3-ts` |
| `--templates="<glob>"` | _(required)_ | Comma-separated glob pattern(s) matching `.html` templates to convert. An exact single file path is also accepted. Loads the converter WASM module once for the whole batch. |
| `--output="<path>"` | Next to source | Output file path. `webui-prerelease` defaults to `*.webui.html`; `webui-framework-prerelease` defaults to `*.webui-framework.html`; `fast-v3-ts` defaults to `*.template.ts`. Any `*` in the output path is replaced with the input basename without extension. Every file matched by `--templates` is written under `--output`'s directory (or next to its source if `--output` is omitted). |
| `--overwrite` | `false` | Allow replacing an existing output file. CLI presence always means `true`. |
| `--typed[=true/false]` | `false` | Only for `fast-v3-ts`. Add an explicit `ElementViewTemplate<TSource>` export annotation and type-only import. Explicit false overrides configured true. |
| `--type-source="<Name>"` | _(none)_ | Only valid with `--syntax=fast-v3-ts`. Emits `export const template = html<Name>\`…\`;` instead of the untyped `html` call. Must be a dotted TypeScript identifier (e.g. `MyElement` or `Namespace.MyElement`). |
| `--type-source-import="<module>"` | _(none)_ | Requires `--type-source`. Also emits `import type { <Name> } from "<module>";` alongside the helper imports. |
| `--config="<path>"` | `fast-convert.config.json` | Path to a JSON configuration file. If omitted, `fast-convert.config.json` in the current directory is used when present. CLI arguments take precedence over config values. |

Only matched `.html` files are converted; non-`.html` files and directories are never matched. The output extension must match the selected syntax: `.html` for `webui-prerelease`/`webui-framework-prerelease` and `.ts` for `fast-v3-ts`. The output parent directory is created automatically if it doesn't exist (`mkdir -p` semantics), and an existing output file is rejected unless `--overwrite` or `"overwrite": true` is used. When a `--templates` pattern matches zero files, a warning is printed but the command does not fail unless every pattern matches zero files.

`webui-framework-prerelease` converts FAST's declarative syntax into the Microsoft WebUI Framework's own declarative runtime syntax (`webui-prerelease` remains unchanged — it emits HTML for WebUI's separate FAST parser plugin instead). When `webui-framework-prerelease` strips an unsupported `f-slotted`/`f-children` directive, the CLI prints `Warning: <message>` to stderr for each stripped directive without failing the command.

`--type-source` exists so templates that combine more than one differently-named
`ref`/`children`/`slotted` directive (which otherwise fail to type-check once a
real `TSource` is supplied, because `html<TSource, TParent>` infers a single
`TSource` for the whole tagged template) can be generated already type-checked
against a concrete element type. See
[`microsoft-fast-convert` DESIGN.md](../../crates/microsoft-fast-convert/DESIGN.md#explicit-tsource-generic).

### Convert configuration file

`fast-convert.config.json` follows the same precedence and path-resolution rules as `fast-build.config.json`: CLI arguments override config values, and `templates`/`output` paths from config are resolved relative to the config file directory.

```json
{
    "syntax": "fast-v3-ts",
    "templates": "src/**/*.html",
    "output": "generated/*.template.ts",
    "overwrite": false,
    "type-source": "MyElement",
    "type-source-import": "./my-element.js"
}
```

Only `syntax`, `templates`, `output`, `overwrite`, `type-source`,
`type-source-import`, and `typed` are allowed. Values must be strings except
`overwrite` and `typed`, which must be JSON booleans.

For declaration-emitting consumers, use `--typed --type-source=MyElement`.
The converter WASM's `convert_template_with_options` accepts an appended
optional `typed` boolean. `convert_stylesheet(css, "fast-v3-ts", "styles",
true)` emits an `ElementStyles` annotation. Existing calls remain untyped;
typed exports are tested with TypeScript `isolatedDeclarations`.

### Running converter fixtures locally

Build the package WASM, then run the fixture validation:

```shell
npm run build -w @microsoft/fast-build
npm run test:fixtures:convert -w @microsoft/fast-build
```

The fixture tests run `fast convert` from fixture directories that contain
`fast-convert.config.json`, so they verify the same default config discovery used
by `fast build`. Generated fixture output is written under
`packages/fast-build/test/.fixture-output/` and removed by the tests.
`test/fixtures/convert/type-source.test.js` additionally type-checks
`--type-source` output with the TypeScript compiler API against a companion
element type, using a separate `test/.fixture-output-type-source/` directory.

## Template syntax

Bindings and FAST directive markup inside HTML comments are unsupported.
Commenting out bound markup does not reliably disable its bindings and can cause
rendering errors or client hydration mismatches. Remove unused bound markup
instead, and keep explanatory comments free of binding syntax and FAST directive
tags.

Template syntax follows the FAST declarative HTML format. See the
[`@microsoft/fast-element` declarative documentation](../fast-element/docs/declarative/syntax.md)
for full documentation on bindings, conditionals, repeats, and directives.

---

### Overview (`packages/fast-element/README.md`)

# FAST Element

[](https://opensource.org/licenses/MIT)
[](https://badge.fury.io/js/%40microsoft%2Ffast-element)

The `fast-element` library is a lightweight means to easily build performant, memory-efficient, standards-compliant Web Components. FAST Elements work in every major browser and can be used in combination with any front-end framework or even without a framework.

## Installation

### From NPM

To install the latest `fast-element` library using `npm`:

```shell
npm install --save @microsoft/fast-element
```

Within your JavaScript or TypeScript code, you can then import library APIs like this:

```ts
import { FASTElement } from '@microsoft/fast-element';
```

### From CDN

A pre-bundled script that contains all APIs needed to build web components with FAST Element is available on CDN. You can use this script by adding [`type="module"`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) to the script element and then importing from the CDN.

```html
<!DOCTYPE html>
<html lang="en">
    <head>
        <script type="module">
          import { FASTElement } from "https://cdn.jsdelivr.net/npm/@microsoft/fast-element/dist/fast-element.min.js";

          // your code here
        </script>
    </head>
    
</html>
```

The markup above always references the latest release. When deploying to production, you will want to ship with a specific version. Here's an example of the markup for that:

```html
<script type="module" src="https://cdn.jsdelivr.net/npm/@microsoft/fast-element@1.6.2/dist/fast-element.min.js"></script>
```

:::note
For simplicity, examples throughout the documentation will assume the library has been installed from NPM, but you can always replace the import location with the CDN URL.
:::

:::tip
Looking for a quick guide on building components?  Check out [our Cheat Sheet](../resources/cheat-sheet.md#building-components).
:::

## Browser Requirements

FAST Element v3 assumes a client-side browser `Window` runtime with native
`globalThis`, Custom Elements, DOM, Shadow DOM, and `requestAnimationFrame`.
The `FAST` object is now a module-scoped export (not on `globalThis`). If you
need to support an older browser without `globalThis`, load that polyfill before
importing `@microsoft/fast-element`.

The FAST Element client runtime is not intended to execute in workers,
server-side JavaScript runtimes, or other non-window hosts. Use server-side
rendering tools to produce HTML for the browser, and run FAST Element in the
client window where custom elements connect, render, update, and hydrate.

## Debug entrypoint

The declarative attribute fixture covers server-side omission of null/missing
attributes and subsequent hydration updates. Explicit empty strings remain
present, and omitted attributes retain binding slots. See the
[server-rendering guide](https://www.fast.design/docs/3.x/declarative-templates/server-rendering/)
for the rendering contract.

`@microsoft/fast-element/debug.js` exports `enableDebug()` instead of configuring
FAST at import time. The development root export and debug rollup bundle still
enable debug behavior automatically.

```ts
import { enableDebug } from "@microsoft/fast-element/debug.js";

enableDebug();
```

## Server-rendered hydration

Call `enableHydration()` from `@microsoft/fast-element/hydration.js` before
components connect to reuse their server-rendered DOM. Ordered sibling-bounded
views use pointer traversal and consume native markers without factory-index
arrays; unusual boundaries and potentially mutating cleanup retain the live
Range fallback. Nested and adjacent repeats pair only their own server ranges,
preserving SSR nodes while reconciling missing or excess items.

Call `enableHydration()` before components are registered with the platform to
also enable pointer-only native marker cleanup for FAST components that do not
observe `data-fe`. Observation tracking is opt-in and excluded from client-only
`FASTElement` bundles. Earlier registrations still hydrate correctly through
the conservative fallback, as do unknown registration, observed markers,
customized built-ins, and overridden attribute methods. Cleanup remains
synchronous.

Existing FAST 3 marker output and opt-in `markers_v2` remain supported without
application changes. See the [server-rendering guide](https://www.fast.design/docs/3.x/declarative-templates/server-rendering/)
and [contributor performance workloads](./docs/template-bindings.md#hydration-cpu-regression-coverage).
Contributor-facing internals separate DOM traversal, binding target mapping,
and repeat-range discovery; the opt-in benchmark spec is independent of the
deterministic correctness and allocation regression spec.

## Export Sizes

Bundle sizes for each tree-shakeable export are tracked in [`SIZES.md`](./SIZES.md) and regenerated on every build. See the [Export Sizes](https://www.fast.design/docs/3.x/resources/export-sizes/) documentation page for the latest numbers.

## Root Imports and Path Exports

The root `@microsoft/fast-element` entrypoint exports the FAST Element
implementation APIs, including the element base class, kernel, controller,
definition APIs, template APIs, binding helpers, directives, styles, and schema
helpers. The FAST element registry is also available from
`@microsoft/fast-element/registry.js` for focused definition lookups and
`fastElementRegistry.whenRegistered(tagName)` registration promises.
Declarative, hydration, context, and dependency injection APIs are available
from their focused path exports.

Focused package path exports remain available for consumers that want to import
a narrower entrypoint directly. The website's
[Path Exports](https://www.fast.design/docs/3.x/advanced/path-exports/) page is
generated from `package.json` and lists each supported path.

## Dynamic Style Application

Import `css`, `CSSTemplateTag`, `CSSValue`, and style APIs such as
`ElementStyles`, `CSSDirective`, `cssDirective`, `ComposableStyles`,
`HostBehavior`, `HostController`, `StyleStrategy`, and `StyleTarget` from
`@microsoft/fast-element`:

```ts
import { ElementStyles, css } from "@microsoft/fast-element";
```

When runtime state or external signals need to add or remove styles, create the
`ElementStyles` with `css` and toggle it through
`this.$fastController.addStyles()` / `this.$fastController.removeStyles()` from
the element lifecycle or change handlers.

`css` templates remain static style definitions. Runtime CSS bindings and
behavior-producing CSS directives are no longer supported; keep the condition on
the element and toggle a separate `ElementStyles` instance through the
controller when styles need to change.

## Declarative HTML

Bindings and FAST directive markup inside HTML comments are unsupported in
declarative templates. Commenting out bound markup does not reliably disable its
bindings; remove unused markup instead. See the
[template syntax restrictions](./docs/declarative/syntax.md#html-comments).

FAST Element publishes its declarative HTML runtime from
`@microsoft/fast-element/declarative.js`. This entrypoint exports the
functional APIs for declarative templates: `declarativeTemplate()`,
`TemplateParser`, and related configuration types. `attributeMap()` and
`observerMap()` are available from their own focused path exports. The
declarative runtime is pure at import time; declarative APIs lazily install only
declarative debug messages. Hydration is separate and remains opt-in through
`enableHydration()` from `@microsoft/fast-element/hydration.js`.

```ts
import { FASTElement } from "@microsoft/fast-element";
import { declarativeTemplate } from "@microsoft/fast-element/declarative.js";

class MyElement extends FASTElement {}

MyElement.define({
    name: "my-element",
    template: declarativeTemplate(),
});
```

`declarativeTemplate()` automatically defines FAST's internal native
`<f-template>` publisher in the relevant registry, resolves the matching
`<f-template name="my-element">`, and keeps the definition template concrete
before `define()` resolves. If multiple matching `<f-template>` elements are
connected, the first connected element supplies the template and later duplicates
do not reassign it. Consumers should not import or define the `<f-template>`
implementation directly.

Declarative schema behavior is enabled with define extensions:

```ts
import { attributeMap } from "@microsoft/fast-element/attribute-map.js";
import { declarativeTemplate } from "@microsoft/fast-element/declarative.js";
import { observerMap } from "@microsoft/fast-element/observer-map.js";

MyElement.define(
    {
        name: "my-element",
        template: declarativeTemplate(),
    },
    [attributeMap(), observerMap()],
);
```

`attributeMap()` creates `@attr`-style accessors for leaf bindings, and
`observerMap()` creates deep observable accessors for discovered root
properties. Declarative templates assign `definition.schema` during template
resolution so these extensions always have schema data when used with
`declarativeTemplate()`. For non-declarative/manual schema use, import `Schema`
from `@microsoft/fast-element` and pass it on the element definition;
`observerMap()` can also receive
`observerMap({ schema })` directly. When both extensions are present, attribute
mapping runs before observer mapping.

Declarative utilities such as `deepMerge` are available from
`@microsoft/fast-element/declarative-utilities.js`. See
[`docs/declarative/syntax.md`](./docs/declarative/syntax.md) for declarative implementation
details and the
[Declarative HTML docs](https://fast.design/docs/3.x/declarative-templates/overview/)
for guides on writing f-templates, defining declarative elements, and
server-side rendering. Declarative event bindings use `$e` for the DOM event
object and `$c` for the execution context.

## Prerendered Content Optimization

Hydration of prerendered content is **opt-in**. Call `enableHydration()` from `@microsoft/fast-element/hydration.js` before any FAST elements connect to activate the hydration path:

```typescript
import { enableHydration } from "@microsoft/fast-element/hydration.js";

const hydration = enableHydration();

await hydration.whenHydrated();
console.log("hydration complete");
```

By default, hydration handles the initial prerendered batch and then no-ops
after the active hydration batch completes. If your app streams Declarative
Shadow DOM after the initial batch, keep the hydration hook active. In this
mode, `enableHydration().whenHydrated()` intentionally remains pending because
hydration never reaches a global completion point.

```typescript
import { enableHydration, StopHydration } from "@microsoft/fast-element/hydration.js";

enableHydration({
    stopHydration: StopHydration.never,
});
```

FAST Element 3.x data-free hydration markers are the only format recognized
by default. Server output that still emits the legacy FAST Element 2.x
indexed markers will fail to hydrate unless you opt into that reader on its
dedicated export path — an interoperability enhancement for backend systems
that have not yet adopted the data-free format:

```typescript
import { enableHydration, markers_v2 } from "@microsoft/fast-element/hydration.js";

enableHydration({ markers: markers_v2 });
```

Because `markers_v2` is only referenced when explicitly imported, its legacy
parsing logic is tree-shaken out of the bundle for consumers who don't use it.

When using `@microsoft/fast-build`, set `"markers_v2": true` in
`fast-build.config.json` so the renderer and client use the same format.

When hydration is enabled and a FAST element connects with an existing shadow root (from server-side rendering or declarative shadow DOM), `ElementController` detects this and hydrates instead of re-rendering. Two properties on the controller let you inspect the result:

- **`isPrerendered: Promise<boolean>`** — resolves `true` when the element had a declarative shadow root (DSD) at connect time, regardless of whether hydration ran.
- **`isHydrated: Promise<boolean>`** — resolves `true` only when hydration actually ran successfully.

This enables several optimizations:

- **Hydration instead of re-render**: The template uses `hydrate()` to map existing DOM nodes to binding targets rather than cloning new DOM.
- **Declarative template resolution**: `declarativeTemplate()` waits for the
  matching `<f-template>` before `define()` completes, so connected elements
  hydrate with a concrete template.
- **Attribute skip**: `onAttributeChangedCallback()` skips processing during initial upgrade when the element is prerendered, since server-rendered attribute values are already correct.
- **Binding skip**: `HTMLBindingDirective.bind()` skips `updateTarget` for `attribute` and `booleanAttribute` aspect types when the view is prerendered.

### Hydration Mismatch Diagnostics

If a prerendered DOM diverges from the client template in a way FAST cannot
reconcile (the `render()` empty-boundary and `repeat()` count-mismatch cases
recover silently), `HydrationBindingError` or `HydrationTargetElementError` is
thrown. By default the message is a single line pointing at the opt-in
`hydrationDebugger()`. Install the debugger to get a rich
"Expected … / Received …" report with the SSR HTML snippet and structured
`expected` / `received` fields on the thrown error:

```typescript
import { enableHydration, hydrationDebugger } from "@microsoft/fast-element/hydration.js";

enableHydration({ debugger: hydrationDebugger() });
```

The debugger module is tree-shaken out of production hydration bundles when
not imported, so the rich diagnostic helpers only land in builds that opt in.

Component authors can await both promises to distinguish prerendered content from successful hydration:

```typescript
const controller = this.$fastController;
const prerendered = await controller.isPrerendered;
const hydrated = await controller.isHydrated;

if (prerendered && !hydrated) {
    // Had DSD but hydration wasn't enabled — client-side rendered
}
```

Custom directives can also await `controller.isPrerendered` and `controller.isHydrated` (both `Promise<boolean>` on the `ViewController` interface) to determine how the view's content was rendered.

## Define Extensions

The static `define()` method on a `FASTElement` subclass accepts an optional second argument — an array of extension callbacks that are invoked with the resolved element definition before the element is registered with the platform. This enables a plugin pattern where reusable behaviors can hook into element registration.

```typescript
import { FASTElement, type FASTElementExtension } from "@microsoft/fast-element";

function logger(): FASTElementExtension {
    return definition => {
        console.log(`Defining element: ${definition.name}`);
    };
}

class MyComponent extends FASTElement {
    // component code
}

MyComponent.define({ name: "my-component", template, styles }, [logger()]);
```
Each extension receives the full `FASTElementDefinition`, which includes the resolved element name, type, template, styles, and attribute metadata. Extensions run before `customElements.define()`, so any setup they perform is available when existing DOM elements are upgraded.

---

### Overview (`packages/fast-router/README.md`)

# FAST Router

The `@microsoft/fast-router` package contains a history-based navigation and routing solution designed around Web Components. By using `fast-router`, you can create multi-page and full application experiences. The router works with any Web Components, but has special support for Web Components built on FAST.

## Installation

### From NPM

To install the `fast-router` library using `npm`:

```shell
npm install --save @microsoft/fast-router
```

Within your JavaScript or TypeScript code, you can then import library APIs like this:

```ts
import { FASTRouter } from '@microsoft/fast-router';
```

Looking for a setup that integrates with a particular front-end framework or bundler? Check out [our integration docs](https://fast.design/docs/integrations/introduction).

## Configuration at a Glance

The router is currently in `alpha` while we address a few bugs, finish up some final polish, and write the full documentation. Below is a quick sample of how to configure the router, to help get you going while we complete the full documentation.

#### A Sample Route Configuration

```
/* Detailed source-code truncated for AI context efficiency. */
```

#### Using the Configuration with a Router

```ts
import { FASTElement, customElement } from '@microsoft/fast-element/fast-element.js';
import { css } from '@microsoft/fast-element/css.js';
import { html } from '@microsoft/fast-element/html.js';
import { FASTRouter } from '@microsoft/fast-router';
import { AppRouterConfiguration } from './routes';

FASTRouter;

const template = html<MainApplication>`
    <fast-router :config=${x => x.routerConfiguration}></fast-router>
`;

const styles = css`
  :host {
    contain: content;
  }

  :host, fast-router {  
    display: block;
    width: 100%;
    height: 100%;
  }
`;

@customElement({
  name: 'main-application',
  template,
  styles
})
export class MainApplication extends FASTElement {
  routerConfiguration = new AppRouterConfiguration();
}
```

---

### Overview (`packages/fast-test-harness/README.md`)

# FAST Test Harness

[](https://opensource.org/licenses/MIT)

The `fast-test-harness` package is a Playwright testing harness for FAST Element web components with CSR and SSR support.

## Requirements

- Node.js 22.18 or later
- Playwright 1.56 or later

## Installation

To install `fast-test-harness` using `npm`:

```shell
npm install --save-dev @microsoft/fast-test-harness
```

## Test directory setup

The harness serves a Vite dev server from a `test/` directory in your project. CSR and SSR modes use different entry points from the same directory.

```
test/
├── index.html              # CSR: loads main.ts
├── ssr.html                # SSR: template with comment placeholders
├── vite.config.ts          # Vite config (shared by both modes)
└── src/
    ├── main.ts             # CSR: registers components, applies theme
    ├── entry-client.ts     # SSR: registers components for hydration
    └── entry-server.ts     # SSR: exports render() for fixture generation
```

## Writing tests

Import `test` and `expect` from the harness. Configure the component tag name with `test.use()`, then call `fastPage.setTemplate()` in each test to render it.

```ts
import { expect, test } from "@microsoft/fast-test-harness";

test.describe("Button", () => {
    test.use({ tagName: "my-button", innerHTML: "Click me" });

    test("should render", async ({ fastPage }) => {
        await fastPage.setTemplate();
        await expect(fastPage.element).toBeVisible();
    });

    test("should accept attributes", async ({ fastPage }) => {
        await fastPage.setTemplate({
            attributes: { appearance: "primary", disabled: true },
        });
        await expect(fastPage.element).toHaveAttribute("appearance", "primary");
    });

    test("should work inside a form", async ({ fastPage }) => {
        await fastPage.setTemplate(`
            <form>
                <my-button type="submit">Submit</my-button>
            </form>
        `);
        await expect(fastPage.element).toBeVisible();
    });
});
```

Use `updateTemplate()` to modify attributes or innerHTML after the initial render without navigating away from the page:

```ts
await fastPage.setTemplate();
await fastPage.updateTemplate(fastPage.element, { attributes: { disabled: true } });
```

The `toHaveCustomState` assertion checks `ElementInternals` custom states:

```ts
await expect(element).toHaveCustomState("checked");
```

## Fixture options

| Option | Type | Default | Description |
| -------- | ------ | --------- | ------------- |
| `base` | `string` | `"/"` | Base path for the test page and SSR endpoint |
| `tagName` | `string` | `""` | Custom element tag name |
| `innerHTML` | `string` | `""` | Default inner HTML |
| `waitFor` | `string[]` | `[]` | Additional elements to wait for before testing |
| `ssr` | `boolean` | `false` | Use SSR mode (or set `PLAYWRIGHT_TEST_SSR=true`) |

### CSR files

**`index.html`** loads a script that registers your components:

```html
<!doctype html>
<html lang="en">
    <head><meta charset="UTF-8" /></head>
    <body>
        <script type="module" src="/src/main.ts"></script>
    </body>
</html>
```

**`main.ts`** registers components and applies global config. The body starts empty; `setTemplate()` injects HTML per test.

```ts
import "./define-all.js";
import { setTheme } from "./theme.js";
setTheme(lightTheme);
```

### SSR files

**`ssr.html`** contains comment placeholders the server fills in per request:

```html
<!doctype html>
<html lang="en">
    <head>
        <title></title>
        
    </head>
    <body>
        
        
        <script type="module" src="/src/entry-client.ts"></script>
    </body>
</html>
```

**`entry-client.ts`** imports the harness SSR entry (which enables hydration) and registers components. Component definition modules should use `template: declarativeTemplate()`; this automatically defines FAST's internal `<f-template>` publisher.

```ts
import "@microsoft/fast-test-harness/ssr/entry-client.js";
import { declarativeTemplate } from "@microsoft/fast-element/declarative.js";

import { MyButton, definition } from "../../src/button/index.js";

MyButton.define({
    name: definition.name,
    template: declarativeTemplate(),
});
```

**`entry-server.ts`** exports a `render()` function that the server calls for each `setTemplate()` request. It returns three strings that get injected into `ssr.html`:

```ts
export function render(queryObj: Record<string, string>): {
    template: string;    // <f-template> HTML → 
    fixture: string;     // rendered element HTML → 
    preloadLinks: string; // <link> tags → 
};
```

Use `createSSRRenderer` from the harness to build the `render()` function. It scans for component build artifacts (f-templates, stylesheets) and uses the `@microsoft/fast-build` WASM renderer to produce declarative shadow DOM on each request.

**Multi-component package** (all components in one package):

```ts
import { createSSRRenderer } from "@microsoft/fast-test-harness/ssr/render.js";

const { render } = createSSRRenderer({
    packageName: "@my-scope/web-components",
    tagPrefix: "my",
});

export { render };
```

**Per-component packages** (each component is a separate npm package):

```ts
import { createSSRRenderer } from "@microsoft/fast-test-harness/ssr/render.js";

const { render } = createSSRRenderer({
    tagPrefix: "my",
    components: [
        { name: "button", packageName: "@my-scope/button" },
        { name: "checkbox", packageName: "@my-scope/checkbox" },
    ],
});

export { render };
```

## Server

The package includes a Node.js HTTP server with Vite middleware that handles both CSR page serving and SSR fixture generation. Run it directly or let Playwright manage it via `webServer`:

```ts
// playwright.config.ts
export default defineConfig({
    webServer: {
        command: "fast-test-harness",
        port: 3278,
        reuseExistingServer: true,
    },
});
```

For custom setup, import `startServer`:

```ts
import { startServer } from "@microsoft/fast-test-harness/server.mjs";
await startServer(process.cwd(), "./test", "./test/vite.config.ts", {
    port: 4000,
    debug: true,
});
```

One server can host several test directories at separate paths. Set the matching
`base` fixture option for each test group.

```ts
await startServer(process.cwd(), process.cwd(), "./vite.config.ts", {
    routes: [
        { base: "/button/", root: "./packages/button/test" },
        { base: "/dialog/", root: "./packages/dialog/test" },
    ],
});

test.use({ base: "/button/", tagName: "my-button" });
```

| Parameter | Default | Description |
| --------- | ------- | ----------- |
| `cwd` | `process.cwd()` | Static file serving root |
| `root` | `<cwd>/test` | Vite root (contains `index.html`, `ssr.html`) |
| `configFile` | Vite auto-discovery | Vite config path |
| `options.port` | `3278` | Server port |
| `options.base` | `/` | Base URL path |
| `options.debug` | `false` | Write SSR fixtures to `temp/` for inspection |
| `options.routes` | Single route from `root` and `base` | Test roots keyed by URL base path |

### CLI flags

```
fast-test-harness [command] [options]

Commands:
  serve                    Start the test harness dev server (default)
  generate-templates       Generate <f-template> HTML files from compiled templates
  generate-stylesheets     Generate CSS files from compiled ElementStyles
  generate-webui-templates Generate WebUI-compatible DSD templates

Serve options:
  -p, --port <number>    Server port (default: 3278)
  -b, --base <path>      Base URL path (default: /)
  -r, --root <path>      Vite root directory (default: <cwd>/test)
  -c, --config <path>    Vite config file path (default: Vite auto-discovery)
  -d, --debug            Write SSR fixtures to temp/ for inspection
  -v, --version          Show version number
  -h, --help             Show help message
```

CLI flags take precedence over environment variables.

`generate-templates` preserves browser-valid `<template>` wrappers and strips
static wrappers even when the opening or closing tag includes ASCII whitespace
before `>`.

| Environment variable | Default | Description |
| -------------------- | ------- | ----------- |
| `PORT` | `3278` | Server port (overridden by `--port`) |
| `BASE` | `/` | Base URL path (overridden by `--base`) |
| `FAST_DEBUG` | — | Set `"true"` to enable debug mode (overridden by `--debug`) |
| `PLAYWRIGHT_TEST_SSR` | — | Set `"true"` for SSR mode |

## SSR renderer

**`createSSRRenderer(options)`** scans for component build artifacts and returns a `{ render }` object compatible with the server's `entry-server.ts` contract. It uses the `@microsoft/fast-build` WASM module to parse f-templates and render them into declarative shadow DOM, including wrapper tags whose opening or closing `>` is preceded by ASCII whitespace.

| Option | Type | Description |
| -------- | ------ | ------------- |
| `tagPrefix` | `string` | Tag name prefix for custom elements (e.g., `"fluent"`, `"contoso"`) |
| `packageName` | `string?` | Monolithic package name — scans subdirectories for component artifacts. Mutually exclusive with `components`. |
| `components` | `ComponentRegistration[]?` | Explicit list of per-component packages. Mutually exclusive with `packageName`. |
| `distDir` | `string?` | Artifact directory relative to the package root (default: `"dist/esm"`). Only used with `packageName`. |
| `themeStylesheet` | `string?` | URL or package specifier for a global theme stylesheet. |

## Exports

| Specifier | Contents |
| ----------- | ---------- |
| `@microsoft/fast-test-harness` | `test`, `expect`, `CSRFixture`, `SSRFixture`, `toHaveCustomState`, `installDomShim`, `createSSRRenderer` |
| `@microsoft/fast-test-harness/build/*.js` | `installDomShim`, `generateStylesheets`, `generateFTemplates`, `generateWebuiTemplates`, `definitionAsyncResolver`, `shadowOptionsToAttributes`, `ShadowOptionsResolver` |
| `@microsoft/fast-test-harness/fixtures/*.js` | `CSRFixture`, `SSRFixture`, `toHaveCustomState`, extended `test` and `expect` |
| `@microsoft/fast-test-harness/ssr/render.js` | `createSSRRenderer`, `renderTemplate`, `buildEntryHtml`, `buildState` |
| `@microsoft/fast-test-harness/ssr/entry-client.js` | Enables FAST Element hydration for SSR pages |
| `@microsoft/fast-test-harness/server.mjs` | `startServer` |
| `@microsoft/fast-test-harness/playwright.config.mjs` | Shared Playwright configuration |
| `@microsoft/fast-test-harness/vite.config.mjs` | Shared Vite configuration |
| `@microsoft/fast-test-harness/public/*` | Static assets (base CSS) |

---

### Overview (`sites/benchmarks/README.md`)

# Benchmarking FAST templates and rendering scenarios

This package benchmarks FAST Element and FAST HTML rendering scenarios. It uses Playwright to automate Chrome, collects CDP trace data, computes timing statistics, and generates an interactive HTML report.

## Prerequisites

- Node.js `>=22.12.0`
- npm `>=10`
- Dependencies installed from repo root:

```bash
npm install
```

## Running benchmarks

From this folder (`sites/benchmarks`):

```bash
npm run bench
```

This will:

1. Build the scenarios with Vite (into `server/dist`)
2. Start the static server on `http://localhost:5174`
3. Run all discovered scenarios through Playwright
4. Print stats tables to the console
5. Generate an interactive HTML report at `results/latest.html`

### Iteration count

Default is 50 iterations per benchmark. Override with `BENCH_ITERATIONS`:

```bash
BENCH_ITERATIONS=100 npm run bench
```

### Running specific scenarios

Pass scenario names as arguments to filter which benchmarks run:

```bash
npm run bench -- basic attr-reflect
```

Each argument is matched as a substring, so `basic` runs `basic/csr` and `basic/hydration`. You can also target a specific variant:

```bash
npm run bench -- basic/csr
```

## Running from repo root

```bash
npm run bench -w @microsoft/fast-bench
```

## Project structure

```text
src/
  bench.ts        Runner orchestrator (Playwright + CDP)
  chart.ts        SVG chart rendering
  report.ts       HTML report assembly
  trace.ts        CDP trace event parsing + stats
  scenarios/
    harness.ts    Shared benchmark runtime
    tree.ts       Tree data generator for scenarios
    report.css    Report styles (inlined into output)
    report.js     Report interaction (inlined into output)
    index.html    Dev server landing page
    basic/        Scenario directories...
    attr-reflect/
    bind-event/
    dot-syntax/
    ref-slotted/
    repeat/
    when/
```

Each scenario follows a consistent structure:

```text
<scenario>/
  element.ts        Shared element class definition
  template.html     <f-template> for hydration variants
  csr/
    index.html      Client-side rendering entry
    main.ts         CSR variant script
  hydration/
    index.html      SSR + hydration entry (uses )
    main.ts         Hydration variant script
    render.ts       SSR HTML generator for Vite build-time rendering
```

## Output

The report at `results/latest.html` (symlinked to the most recent timestamped run) includes:

- **Overlaid line charts** per scenario with all variants (csr, hydration) on shared axes
- **Hover-to-emphasize** and **click-to-select** variant interaction
- **Winner table** showing the best value per metric/stat, color-coded by variant
- **Variant drill-down** — click a variant to see its full stats

Metrics collected per iteration:

| Metric | Description |
| --- | --- |
| Scripting | JS execution (EvaluateScript, FunctionCall, etc.) |
| Layout | Layout computation |
| Style Recalc | Style recalculation |
| Paint | Paint, compositing, layerization |
| Total (trace) | Sum of the above four |
| User Measure | Duration of the `bench` performance.measure |
| FCP | First Contentful Paint (relative to navigation start) |
| LCP | Largest Contentful Paint (relative to navigation start) |
| DCL | DOMContentLoaded (relative to navigation start) |

Summary statistics: Min, Median, Mean, Geometric Mean, P95, Max. All values are in milliseconds.

## Dev server

For iterating on scenarios without running the full benchmark:

```bash
npm run serve
```

This starts Vite on `http://localhost:5173` with hot reload.

---

### Overview (`sites/website/README.md`)

# Website

This website is built using [11ty](https://www.11ty.dev/), a modern static website generator.

## Installation

Run the following commands in the **root directory**:

```sh
npm ci
npm run build
```

## Local Development

```sh
npm start
```

## Build

```sh
npm run build
```

This command generates static content into the `build` directory and can be served using any static content hosting service.

## Version Banners

The site supports configurable banners on documentation pages to communicate version status (e.g., stable, legacy, prerelease). Banners are defined in `src/_data/versionBanners.js` and rendered via `src/_includes/version-banner.njk`.

### Configuration

Edit `src/_data/versionBanners.js` to add, remove, or modify banners. Each version key maps to a configuration object:

```js
"3.x": {
    enabled: false,             // Toggle the banner on/off
    type: "stable",             // "legacy" | "stable" | "prerelease"
    message: "You are viewing the current stable version of FAST.",
}
```

| Type | Color | Use case |
|------|-------|----------|
| `legacy` | Gray | Previous versions — links to latest docs |
| `stable` | Green | Current stable release |
| `prerelease` | Amber | Upcoming / release candidate versions |

Prerelease banners should include any version-specific copy directly in the message.

### Styles

Banner CSS lives in `src/css/version-banner.css` and is loaded on all pages via `root.njk`.

---

### Overview (`crates/microsoft-fast-build/benchmark-baselines/README.md`)

# Renderer performance baselines

Run all commands from the repository root. These are explicit measurements,
not portable timing assertions or automatically refreshed golden files.

```sh
npm run build -w @microsoft/fast-build
npm run bench:render -w @microsoft/fast-build -- --case=url_sink_siblings --output=/tmp/fast-render.json
npm run bench:render -w @microsoft/fast-build -- --case=url_sink_siblings --check-scaling
cargo bench --manifest-path crates/microsoft-fast-build/Cargo.toml --bench render
```

The native Criterion groups separate rendering with parsed state, state parsing
plus rendering, and locator construction. The Node runner calls the packaged
WASM export in a fresh `--expose-gc` child for each sample, warms it once with up
to 1,000 instances (configurable with `--warmup-count`), forces
GC, and reports median/p95 wall time, CPU time, JSON stringify time, input/output
bytes, throughput, before/after memory, process peak RSS, and parent-sampled RSS
(100 ms on macOS/Linux). Peak RSS includes warmup and verification, not just the
measured call. No in-child timer is used to observe a blocked WASM call.
Sampled RSS is `null` if the child exits before a sample or the platform is not
macOS/Linux. Process peak RSS remains available independently of timer sampling.
Node throughput uses the requested rendered-instance count (not only custom
host count); Criterion reports instances/second for render phases and template
definitions/second for locator construction.

`--case`, `--counts`, and `--samples` narrow a run. Both marker modes always run.
Omit `--case` to run the full matrix; repeat/state-clone workloads can be very
expensive, so begin with the primary URL regression on a development machine.
Definitions use 50/200/1,000 definitions with payloads 1/20; other cases use
1,000/5,000/20,000 instances. State overlays run with 0/200 extra root keys, with
and without host attributes. `corpus.json` is the shared recipe used by native
benchmarks, Rust parity tests, and the Node fixture generator.

Use `--compare=<baseline.json>` to enforce output hash/length parity and report
speedups. `--check-scaling` explicitly checks the URL case's 20k/5k ratio <= 5
and fits `setup + coefficient * count^exponent` from all three sizes, requiring
exponent <= 1.15. Timing checks are opt-in: do not enable them on unpinned PR
runners. At least three samples on otherwise idle, stable hardware are recommended.
Output paths are created exclusively; a run never overwrites an existing baseline.
Reports snapshot the starting git revision, dirty-worktree flag, and WASM
SHA-256. A dirty worktree can include benchmark helpers, reports, or generated
files; it does not necessarily mean the renderer implementation is uncommitted.
Use the artifact hash and source provenance together.

## Local before/after measurements

The checked-in `aarch64-apple-darwin-before.json` and
`aarch64-apple-darwin-after.json` measure the URL sibling regression on an Apple
M3 Pro with Node 22.22.1, three fresh-child samples per size/mode, and a
1,000-instance warmup. These are local macOS measurements, not Linux/reference
machine results or full-corpus performance claims.

| Marker mode | Instances | Before median (ms) | After median (ms) | Speedup |
| --- | ---: | ---: | ---: | ---: |
| v3 | 1,000 | 299.682 | 7.999 | 37.47x |
| v3 | 5,000 | 7,091.213 | 32.416 | 218.75x |
| v3 | 20,000 | 116,906.540 | 122.098 | 957.48x |
| v2 | 1,000 | 287.428 | 8.046 | 35.72x |
| v2 | 5,000 | 7,037.736 | 33.219 | 211.86x |
| v2 | 20,000 | 115,477.367 | 122.144 | 945.42x |

All six before/after output hashes and byte lengths match. The optimized
20k/5k ratios are 3.77 (v3) and 3.68 (v2), with fitted exponents 0.99 and
0.96 respectively. Both pass the 1.15 exponent threshold. The original v3
ratio is 16.49 with exponent 2.02; its
`--check-scaling` run intentionally failed after writing the baseline report.

Process peak RSS at 20,000 instances was 106.06 -> 108.94 MiB (v3) and
99.17 -> 114.52 MiB (v2). This scanner change does not demonstrate a memory
reduction. Peak RSS includes warmup and hash verification; shorter optimized
calls also make 100 ms RSS samples sparse or unavailable.

The before artifact was built from `a38c2f1aea2840ea530de42d055f0a03cefe5872`
before renderer edits, with the new benchmark helpers present. Its WASM SHA-256 is
`c749f46306b561bb55e45700cf19f7ed3db8ad67d01cd8e9a3b7198943c4ca51`.
The after artifact was built from `3e9117770a8da29c369d3d31a04e37da25fa08fb`;
its WASM SHA-256 is
`c128e5d88ff457dedc0549438ec9e2d11450e0a89e997899b003898e587063bc`.
Both reports retain their starting provenance even if the worktree changes
during measurement.

To reproduce an optimized comparison after building the package:

```sh
node packages/fast-build/test/performance/render-entry.mjs --case=url_sink_siblings --compare=crates/microsoft-fast-build/benchmark-baselines/aarch64-apple-darwin-before.json --output=/tmp/fast-render-after.json --check-scaling
```

## Profiling the remaining workloads

The `aarch64-apple-darwin-*-profile.json` reports were captured after the scanner
fix at `a58548a5cec9f4508fd46693f9ec63443e07b0b6`. Five reports contain 36
fresh-child packaged-WASM measurements in both marker modes; the native report
summarizes six symbolized CPU captures and separate Criterion quick estimates.
No renderer optimization was made during this investigation.

The WASM runs use three samples and a 250-instance warmup. Repeat and plain
controls use 250/1,000 instances, state cases use 1,000/5,000 hosts with 0/200
extra root keys, and definitions use 50/200/1,000 templates with payloads 1/20.
These bounded sizes avoid multiplying an already expensive state-cloning path
into an unhelpful full-matrix run. They do not establish 20k acceptance targets.

| Packaged-WASM workload | Instances | Extra root keys | v3 median (ms) | v2 median (ms) |
| --- | ---: | ---: | ---: | ---: |
| Repeated custom elements | 1,000 | 0 | 422.71 | 431.95 |
| Bound plain elements | 1,000 | 0 | 15.06 | 14.81 |
| Attribute overlays | 1,000 | 0 | 4.30 | 4.37 |
| Attribute overlays | 1,000 | 200 | 35.25 | 35.27 |
| No attribute overlays | 1,000 | 200 | 3.70 | 3.84 |
| Many definitions, payload 20 | 1,000 | 0 | 43.68 | 46.72 |

### Findings and next optimization

Child-state construction is the strongest measured next target. In native v3
profiles, `build_custom_element_child_root` occurs in 1,075/2,001 main-thread
samples (53.72%) for repeated custom elements and 1,205/2,049 (58.81%) for
attribute overlays with 200 root keys. Its descendant stacks include
`RawTable::clone`, `Vec::clone`, `String::clone`, and allocator/copy routines.
Separate destruction stacks and frequent free routines show additional cleanup
work outside those inclusive counts.

The repeat fixture's root contains the entire `items` array. Every attributed
child clones that root before overlaying host attributes; increasing the
number of items therefore increases both the number and size of those copies.
Packaged-WASM repeat times rise from 53.55 to 422.71 ms (v3) and 45.86 to
431.95 ms (v2) for a 4x instance increase. This is evidence for the remaining
state-copying hazard, not a fitted 1k/5k/20k scaling claim. Removing attributes
is not a valid optimization because it would change state semantics.

The overlay controls reinforce this finding: adding 200 unused root keys
increases v3 time from 4.30 to 35.25 ms at 1,000 attributed hosts, while the
no-overlay case changes only from 3.40 to 3.70 ms. Output hashes within each
overlay/no-overlay workload are unchanged by those extra unused keys.
Borrowed child-state overlays should be the next focused optimization, with
state precedence/inheritance parity preserved.

The many-definition case has a different profile. Native locator construction
takes about 0.243 ms for 1,000 definitions with payload 20, versus about
34.48 ms for rendering with an already prepared locator. Code-sample
preprocessing appears in 1,257/2,148 (58.52%) locator-phase samples, but that
phase is small here; its percentage must not be interpreted as 58.52% of
end-to-end rendering. The render profile instead contains string searching,
attribute parsing/binding resolution, escaping, and copying. Compiled
templates, parse-once attributes, and buffered sinks remain relevant follow-ons.

Native quick estimates are independent, low-sample diagnostic runs; do not
subtract them to infer isolated parsing costs. Native sampling percentages
are inclusive stack frequencies, not exclusive CPU time, allocation counts,
or WASM phase percentages. Zero observed frames do not prove zero work,
especially with inlining. Native allocator behavior does not establish WASM
memory behavior. Raw captures remain local; the compact report retains their
hashes, selected symbols/counts, compiler/build flags, and binary provenance.

### Reproducing the investigation

Use new output paths; these commands do not refresh the checked-in reports:

```sh
npm run bench:render -w @microsoft/fast-build -- --case=repeat_custom_elements --counts=250,1000 --samples=3 --warmup-count=250 --output=/tmp/fast-repeat-profile.json
npm run bench:render -w @microsoft/fast-build -- --case=plain_bound_elements --counts=250,1000 --samples=3 --warmup-count=250 --output=/tmp/fast-plain-profile.json
npm run bench:render -w @microsoft/fast-build -- --case=large_state_overlay --counts=1000,5000 --samples=3 --warmup-count=250 --output=/tmp/fast-overlay-profile.json
npm run bench:render -w @microsoft/fast-build -- --case=large_state_no_overlay --counts=1000,5000 --samples=3 --warmup-count=250 --output=/tmp/fast-no-overlay-profile.json
npm run bench:render -w @microsoft/fast-build -- --case=many_definitions --samples=3 --warmup-count=250 --output=/tmp/fast-definitions-profile.json
CARGO_PROFILE_BENCH_DEBUG=true RUSTFLAGS="-C force-frame-pointers=yes" cargo bench --manifest-path crates/microsoft-fast-build/Cargo.toml --bench render -- '^repeat_custom_elements/v3/render/1000/payload1/root0$' --profile-time 8 --noplot
```

For a native CPU capture, run the final command in one terminal. Once Criterion
prints `Profiling for`, attach macOS `sample <benchmark-pid> 3 1 -file <new-path>`
from another terminal. Sample the benchmark executable, not Cargo. Building
first with the same environment and `--no-run --message-format=json` reveals
its path in the `compiler-artifact` record. A direct invocation of that binary
must include `--bench`, otherwise Criterion performs a correctness run rather
than a profiling loop. The profiling environment is opt-in and does not change
production WASM build settings or add dependencies.

The six filters used for CPU captures were:

```text
^repeat_custom_elements/v3/render/1000/payload1/root0$
^plain_bound_elements/v3/render/1000/payload1/root0$
^large_state_overlay/v3/render/1000/payload1/root200$
^large_state_no_overlay/v3/render/1000/payload1/root200$
^many_definitions/v3/locator/1000/payload20/root0$
^many_definitions/v3/render/1000/payload20/root0$
```

Replace `--profile-time 8` with `--quick` for diagnostic timing estimates.
The compact native report sums counts across call-graph entries for each
named non-recursive function; recursive frame totals must not be summed as if
they represented distinct samples. Platform-specific Linux profiling remains
outstanding; native allocation baselines are described below.

## Native allocation baselines

`aarch64-apple-darwin-allocations.json` records 30 isolated release-build samples
using `allocation-counter` 0.8.1. Each request starts a fresh native process;
the feature-gated example and its integration test are the only executables
that use this development allocator. No library allocator, WASM export,
production build setting, or rendering behavior changes.

Run from the repository root, writing only to a new output path:

```sh
node crates/microsoft-fast-build/benches/profile-allocations.mjs --output=/tmp/fast-allocations.json
cargo run --manifest-path crates/microsoft-fast-build/Cargo.toml --release --features allocation-profiling --example profile-allocations -- --case=large_state_overlay --count=1000 --root-keys=200 --mode=v2 --phase=render --output=/tmp/fast-overlay-allocations.json
cargo test --manifest-path crates/microsoft-fast-build/Cargo.toml --features allocation-profiling --test allocation-profiling
node --test crates/microsoft-fast-build/benches/profile-allocations.test.mjs
```

Single-request options are `--case`, `--count`, `--payload`, `--root-keys`,
`--mode=v3|v2`, `--phase=render|parse_state_and_render|locator`, and `--output`,
all in `--option=value` form. Defaults are repeat/250/payload 1/root 0/v3/render.
Counts/payloads must be positive; only definition workloads accept payload
changes, and only large-state workloads accept root-key changes. Unknown,
duplicate, or invalid options fail explicitly. Reports refuse overwrites,
including a second exclusive-create check at write time.

Runner matrix/provenance/output-safety tests also run through
`npm run test:node -w @microsoft/fast-build`; they do not invoke Cargo.
The feature-enabled Rust integration test above exercises the actual counter.

The matrix covers repeat/plain controls at 100/250/1,000 instances, overlays
with/without attributes and 0/200 extra root keys at 1,000 hosts, state parsing
plus rendering at 1,000 repeat/plain items, and all three phases for 1,000
definitions with payload 20. Every case runs in both marker modes. One sample
per request is recorded; these counters are not timing medians.

### Measurement boundaries and interpretation

Fixture generation, pre-parsed state, and prepared locators are outside the
measurement. `render` counts only rendering; `parse_state_and_render` also
counts parsing the state JSON; `locator` counts cloning/preprocessing templates
and building the new locator, not template-JSON parsing or rendering.
Locator output is validated by rendering afterward, outside the counter.
Output hashes and byte lengths are checked against ordinary native rendering
in default tests, without asserting platform-specific allocation thresholds.

The returned HTML string or locator stays alive at the counter boundary:
`retainedBytes` includes its capacity, not just logical HTML length, and does
not indicate a leak. `peakLiveBytes` excludes inputs allocated before the
phase; it is not total process heap, RSS, or WASM memory pages. Byte and block
peaks are independent maxima. Cumulative `totalBytes` and `totalBlocks` count
allocation events, including replacement allocations during reallocation,
not the number or size of currently live objects. This profiler captures the
current thread only; future threaded rendering would require another strategy.
The counter uses allocate/copy/free reallocation rather than in-place system
reallocation: event totals and temporary old/new-buffer overlap reflect that
instrumentation strategy, not necessarily the production allocator's peaks.
It does not collect allocation-site stacks or measure bytes copied/allocator
overhead, and should not be used for uninstrumented speed comparisons.

Provenance includes starting commit/dirty status, release executable SHA-256,
Cargo.lock SHA-256, compiler, target, and allocator identification. The matrix
rejects changed provenance or duplicate samples. The checked-in captures were
made with the new harness uncommitted against renderer source
`8b9c524f3a6a7544919588e708c4ad0c98a8197b`; their binary/lock hashes identify
the measured development artifact. Neither captured timing nor allocation
data is silently regenerated by tests.

### Findings

| Native v3 render workload | Instances | Extra root keys | Allocation events | Cumulative MiB | Peak newly-live MiB |
| --- | ---: | ---: | ---: | ---: | ---: |
| Repeated custom elements | 250 | 0 | 1,016,297 | 83.61 | 1.11 |
| Repeated custom elements | 1,000 | 0 | 15,315,047 | 1,265.75 | 4.45 |
| Bound plain elements | 1,000 | 0 | 147,047 | 11.02 | 2.73 |
| Attribute overlays | 1,000 | 0 | 62,913 | 3.02 | 0.48 |
| Attribute overlays | 1,000 | 200 | 1,462,913 | 122.14 | 0.48 |
| No attribute overlays | 1,000 | 200 | 41,012 | 1.54 | 0.28 |
| Definitions, payload 20 | 1,000 | 0 | 893,012 | 63.03 | 4.21 |

The 4x repeat increase produces about 15x more allocation events/bytes, while
plain controls remain approximately proportional to instance count. Adding
200 unused root keys multiplies attributed-host allocation volume by about
40x, yet leaves the no-attribute control unchanged. Within each state control,
unused keys do not change output hashes. Both marker modes show the same
state-copying pattern; native locator counters are identical across modes
because marker rendering is outside that phase.

This strengthens the case for borrowed child-state overlays as the next
runtime optimization. It is a baseline, not the proposed 50% allocation
reduction or any 20k/stable-host/Linux/WASM acceptance claim.

## Output compatibility and remaining work

Correctness runs in normal Rust/Node tests at 0/1/2/1,000 instances in both marker
modes. The shared `benches/fixtures/expected-baseline.json` records pre-optimization
SHA-256, byte length, host count, binding/repeat marker counts, and attribute marker
counts. It also verifies normal/legacy-stream byte parity. Regeneration is explicit:

```sh
node packages/fast-build/test/performance/render-entry.mjs --golden=/tmp/fast-golden.json
```

Review changes against the checked-in golden; do not replace it just to make a
regression pass. Profiles and output hashes must be compared with the same
toolchain and fixture recipe. The runner cannot isolate internal WASM phases,
WASM memory pages (not exported), native allocation counts, or file writes; those
require separate profiling. The schema does not invent measurements for them.

Rust parity tests also render every remaining-workload WASM report record and
verify its output hash, bytes, and marker counts, including the larger
definition payloads and state-overlay controls. They do not assert timing.

The completed optimization addresses directive discovery only. Compiled templates, buffered
recursive writes, state overlays, prepared WASM handles, and genuinely incremental
sessions remain separate work. `stream: true` still materializes all chunks.

---

### Overview (`examples/csr/todo-app/README.md`)

# Todo app tutorial

A To-Do app, written entirely with `fast-element`.

> Note: A step by step tutorial will be coming to the site soon. In the mean
> time, you can run `npm install` and then `npm start` to see the example.

> Note: This example uses an LSP, to enable this in VS Code try the following:
> - Open a javascript/typescript file and use the command palette to `Select
>   typescript version` and choose the local workspace version.

## Design system

This example consumes the shared `@microsoft/fast-examples-design-system`
workspace package. The design-system package is **CSS-only** — there are no
JavaScript or TypeScript exports. `src/main.ts` imports
`@microsoft/fast-examples-design-system/tokens.css` once, and the rest of the
app references the registered `--fast-*` design tokens through `var(...)`.

The app uses the **light** theme. `<html data-theme="light">` is set
statically in [`index.html`](./index.html); the app does not implement a
theme toggle. (The shared design-system package supports dark and
system-preference themes via the same `data-theme` attribute — see
[`examples/design-system/README.md`](../design-system/README.md) — but this
example deliberately keeps the surface area minimal and demonstrates only
token consumption.)

For the shared package overview, the token catalog, and authoring rules,
see [`examples/design-system/README.md`](../design-system/README.md) and
[`examples/design-system/DESIGN.md`](../design-system/DESIGN.md).

## Token usage

The todo app styles use shared tokens for layout, surfaces, typography, and
interaction states. For example:

- App shell surface: `--fast-background-layer-primary-solid`,
  `--fast-foreground-ctrl-neutral-primary-rest`,
  `--fast-stroke-divider-subtle`, `--fast-corner-large`,
  `--fast-shadow-card-rest`, `--fast-padding-content-medium`.
- Primary action (Add): `--fast-background-ctrl-brand-rest`,
  `--fast-foreground-ctrl-on-brand-rest`, `--fast-stroke-divider-brand`,
  `--fast-background-ctrl-brand-hover`, `--fast-background-ctrl-brand-pressed`.
- Typography: `--fast-text-style-default-regular-font-family`,
  `--fast-text-global-body3-font-size` paired with
  `--fast-text-global-body3-line-height`,
  `--fast-text-global-display2-font-size` paired with
  `--fast-text-global-display2-line-height`.
- Destructive action (per-row delete button):
  `--fast-status-danger-tint-foreground` (red text at rest),
  `--fast-status-danger-tint-background` (subtle red hover fill),
  `--fast-status-danger-tint-stroke` (focus outline).
- Focus rings: `--fast-ctrl-focus-outer-stroke` paired with
  `--fast-ctrl-focus-outer-stroke-width`.
- Motion: `--fast-duration-fast` and `--fast-curve-easy-ease` for hover and
  press transitions.

No design value (color, font size, line height, padding, gap, corner,
stroke width, shadow, duration, or curve) is hard-coded in the app's
component styles.

---

### Overview (`examples/csr/todo-mobx-app/README.md`)

# MobX Todo App (FAST)

A small Todo app that uses **[MobX](https://mobx.js.org/)** as its state library and **[`@microsoft/fast-element`](../../../packages/fast-element)** for its Web Components. It is the MobX counterpart to [`examples/csr/todo-app`](../todo-app), and the two render an identical UI — the same `<h1>FAST Todos</h1>`, `<todo-form>` (input + "Add Todo"), `<select>` filter (All / Active / Completed), and `<ul class="todo-list">` of rows with a checkbox, description, and `×` button. Like every example app it consumes the shared [`@microsoft/fast-examples-design-system`](../../design-system) tokens for styling.

The example shows that you do **not** need a custom decorator or any bridge code to integrate MobX with `@microsoft/fast-element` — a single `autorun` per component, set up in `connectedCallback` and disposed in `disconnectedCallback`, is all that is needed.

## Running

```bash
# from the monorepo root
npm ci
npm run build -w @microsoft/fast-element
npm start -w @microsoft/fast-todo-mobx-app-example
```

The Vite dev server runs at <http://localhost:9001>.

To produce a production build:

```bash
npm run build -w @microsoft/fast-todo-mobx-app-example
```

The output is written to `examples/csr/todo-mobx-app/www/`.

## The pattern, in one component

`<todo-app>` mirrors the slices of MobX state it renders into FAST `@observable` fields with a single `autorun` set up in `connectedCallback`. The template binds to those plain FAST observables as usual.

```typescript
import { FASTElement, observable } from "@microsoft/fast-element";
import { autorun } from "mobx";
import { type Todo, type TodoListFilter, todoStore } from "./state/index.js";

export class TodoApp extends FASTElement {
    @observable public items: readonly Todo[] = [];
    @observable public activeFilter: TodoListFilter = "all";

    private _disposer?: () => void;

    public connectedCallback(): void {
        this._disposer = autorun(() => {
            this.items = todoStore.filtered.map(t => ({
                id: t.id,
                description: t.description,
                done: t.done,
            }));
            this.activeFilter = todoStore.activeFilter;
        });
        super.connectedCallback();
    }

    public disconnectedCallback(): void {
        super.disconnectedCallback();
        this._disposer?.();
        this._disposer = undefined;
    }

    public activeFilterChanged(
        _prev: TodoListFilter | undefined,
        next: TodoListFilter | undefined,
    ): void {
        if (next !== undefined && next !== todoStore.activeFilter) {
            todoStore.setFilter(next);
        }
    }
}
```

That is the entire integration. The template binds `${x => x.items}`, `${x => x.activeFilter}`, etc. exactly as it would for any other FAST element.

### Why this works

- `autorun` runs immediately, then re-runs whenever any MobX-observable it read changes.
- Each re-run reassigns FAST `@observable` fields, which fires FAST's own change notification, which patches the bound DOM.
- The `.map(...)` copies each todo into a plain `{id, description, done}` object — that simultaneously creates a fresh array reference on every run (so FAST always sees the assignment) and ensures the autorun depends on every observable field it serializes.
- Calling `autorun` *before* `super.connectedCallback()` ensures the mirror fields have correct values before the template binds, avoiding any initial flicker.
- The disposer returned by `autorun` is stored on the element and released on disconnect, so reactions never outlive the element.

The `<select>` element uses a `twoWay` binding to `activeFilter`. `activeFilterChanged` propagates user changes back to the MobX store (gated by an equality check, so the autorun's store-driven assignment never loops).

## What the app demonstrates

| Feature | Where to look |
|---|---|
| `makeAutoObservable` store with observables, computeds, and actions inferred automatically | [`src/state/todo-store.ts`](./src/state/todo-store.ts) |
| `autorun` persisting to `localStorage` and hydrating on load | [`src/state/persistence.ts`](./src/state/persistence.ts) |
| `autorun` bridging MobX → FAST in a component | [`src/todo-app.ts`](./src/todo-app.ts) |
| UI-local FAST `@observable` for the input draft (deliberately not in the MobX store) | [`src/todo-form.ts`](./src/todo-form.ts) |
| Filtered list view backed by a MobX computed | [`src/state/todo-store.ts`](./src/state/todo-store.ts) (`get filtered`) |
| Two-way binding from a `<select>` back into the MobX store | [`src/todo-app.template.ts`](./src/todo-app.template.ts), [`src/todo-app.ts`](./src/todo-app.ts) (`activeFilterChanged`) |
| Styling exclusively via the shared design-system tokens | [`src/*.styles.ts`](./src), [`index.html`](./index.html), [`src/main.ts`](./src/main.ts) |

## Project layout

```
examples/csr/todo-mobx-app/
├── index.html                     # mounts <todo-app>, sets data-theme="light"
├── package.json
├── tsconfig.json
├── vite.config.ts
├── README.md                      # this file
├── DESIGN.md                      # why the autorun pattern, lifecycle details
└── src/
    ├── design-system.d.ts         # module shim for the tokens stylesheet import
    ├── exports.ts                 # barrel for tooling
    ├── main.ts                    # entry — imports tokens.css, wires storage, defines <todo-app>
    ├── state/                     # MobX layer (framework-agnostic)
    │   ├── index.ts
    │   ├── persistence.ts
    │   └── todo-store.ts
    ├── todo-app.{ts,template.ts,styles.ts}
    └── todo-form.{ts,template.ts,styles.ts}
```

See [DESIGN.md](./DESIGN.md) for an explanation of why this pattern is sufficient.

## License

MIT — see the [monorepo root](../../../LICENSE).

---

### Overview (`examples/ssr/chat-app/README.md`)

# Chat App Example

A small declarative FAST chat demo that pre-renders its initial markup with `@microsoft/fast-build` and streams canned assistant replies with a hidden iframe plus `document.write()`.

## Design system

This example consumes the shared `@microsoft/fast-examples-design-system`
workspace package. The design-system package is **CSS-only** — `src/main.ts`
imports `@microsoft/fast-examples-design-system/tokens.css` once, and
`public/styles.css` references the registered `--fast-*` tokens through
`var(...)`.

The app uses the **dark** theme statically. `<html data-theme="dark">` is set
in [`entry.html`](./entry.html), so the FAST build step carries that attribute
into the generated `index.html`. The example does not implement a runtime
theme toggle.

For the shared package overview, the token catalog, and authoring rules, see
[`../../design-system/README.md`](../../design-system/README.md) and
[`../../design-system/DESIGN.md`](../../design-system/DESIGN.md).

## What it demonstrates

- declarative FAST custom elements via subclass `define()` calls + `@microsoft/fast-element/declarative.js` `<f-template>`s
- initial markup rendered from `entry.html` + `templates.html`
- chunked assistant response streaming with the Jake Archibald iframe technique
- mixed native HTML and FAST custom elements in each canned reply
- exact-match canned prompts with a fallback response

## Suggested prompts

Use these exact prompts to walk through the conversation:

- `Hi`
- `How are you?`
- `What's the weather like?`
- `Tell me a joke`
- `What can you do?`
- `Goodbye`

## Run locally

From the repository root:

```bash
npm run build -w @microsoft/fast-chat-app-example
npm run start -w @microsoft/fast-chat-app-example
```

Or from this folder:

```bash
npm run build
npm start
```

The build first regenerates `index.html` from `entry.html`, `state.json`, and `templates.html`, then runs TypeScript and Vite.

## Files

- `entry.html` — source document for the FAST build step
- `state.json` — initial state used while pre-rendering the page shell
- `templates.html` — declarative FAST templates for the custom elements
- `build-markup.mjs` — runs `@microsoft/fast-build` and injects the templates into `index.html`
- `public/styles.css` — token-based shared stylesheet for the page shell and component shadow roots
- `src/` — runtime classes, canned conversation data, and hydration bootstrap
- `index.html` — generated pre-rendered page used by Vite

See [DESIGN.md](./DESIGN.md) for architecture details, design-system notes, and the canned conversation data.

---

### Overview (`examples/ssr/webui-todo-app/README.md`)

# WebUI Todo App

A Todo app demonstrating FAST declarative HTML templates with
[webui](https://github.com/microsoft/webui) prerendering and hydration.

This example shows how to combine `@microsoft/fast-element/declarative.js` declarative templates
with `@microsoft/webui` for server-side prerendering, producing a fast initial
render that hydrates into a fully interactive FAST web component application.

## Features

- **Declarative templates**: Uses `.html` and `.css` files instead of
  imperative `html`/`css` tagged template literals
- **Server-side prerendering**: `webui serve` compiles declarative templates
  and renders initial state into static HTML
- **Client-side hydration**: `@microsoft/fast-element/declarative.js` picks up prerendered DOM
  and attaches FAST reactive bindings
- **Todo functionality**: Add items via a form, filter by status (all,
  active, completed), toggle completion via native checkbox, delete items

## Prerequisites

From the monorepo root, install dependencies and build packages:

```bash
npm ci
npm run build
```

## Running

```bash
# Build client bundle and start the webui dev server
npm start -w @microsoft/fast-webui-todo-app-example
```

The app will be available at `http://localhost:8081`.

For development with live reloading, run the client and server in separate
terminals:

```bash
# Terminal 1: Watch and rebuild client bundle
npm run start:client -w @microsoft/fast-webui-todo-app-example

# Terminal 2: Start webui dev server with --watch
npm run start:server -w @microsoft/fast-webui-todo-app-example
```

## Design system

This example consumes the shared `@microsoft/fast-examples-design-system`
workspace package. The design-system package is **CSS-only** — there are no
JavaScript or TypeScript exports. `src/index.ts` imports
`@microsoft/fast-examples-design-system/tokens.css` once, and the rest of the
app references the registered `--fast-*` design tokens through `var(...)`.

The app uses the **light** theme. `<html data-theme="light">` is set
statically in [`src/index.html`](./src/index.html); the app does not implement
a runtime theme toggle. (The shared design-system package supports dark and
system-preference themes via the same `data-theme` attribute — see
[`../../design-system/README.md`](../../design-system/README.md) — but this
example deliberately keeps the SSR surface area minimal and demonstrates only
token consumption.)

For the shared package overview, the token catalog, and authoring rules, see
[`../../design-system/README.md`](../../design-system/README.md) and
[`../../design-system/DESIGN.md`](../../design-system/DESIGN.md).

## Architecture

### Server-side (`webui serve`)

The `webui` CLI serves the app with the `--plugin=fast` flag, which enables
FAST-aware template processing:

1. Scans `./src` for declarative HTML templates (`.html` files wrapped in
   `<f-template>` or containing `<template shadowrootmode="open">`)
2. Reads initial state from `./data/state.json`
3. Renders templates server-side with `{{}}` bindings resolved from state
4. Injects Declarative Shadow DOM for instant first paint
5. Serves the bundled client assets from `./dist`

`src/index.ts` imports `@microsoft/fast-examples-design-system/tokens.css`.
When esbuild bundles the entry point, it emits both `dist/index.js` and
`dist/index.css`. `src/index.html` links `/index.css` so the shared `--fast-*`
tokens are available during prerendering and after hydration.

### Templates (`src/todo-app/`, `src/todo-item/`)

Each component uses co-located files:

- `*.html` — Declarative template with `<template shadowrootmode="open">`
  and FAST bindings
- `*.css` — Scoped styles loaded via `<link rel="stylesheet">` in the shadow
  DOM
- `*.ts` — Component class using `FASTElement` with `define()`

### Client entry (`src/index.ts`)

Bootstraps hydration by:

1. Enabling hydration with `enableHydration({ markers: markers_v2 })` — the
   `markers_v2` reader is required because the `webui --plugin=fast` server
   still emits FAST Element 2.x indexed hydration markers
2. Importing components, which register themselves via subclass `define()` calls
   using `declarativeTemplate()` and `observerMap()`
3. Resolving matching `<f-template>` definitions to hydrate prerendered shadow DOM

### Binding syntax

| Syntax | Scope | Example |
|---|---|---|
| `{{expr}}` | Server + client | `{{title}}` — HTML-escaped value |
| `{{{expr}}}` | Server + client | Raw unescaped HTML |
| `{expr}` | Client-only | `{onClick(e)}` — event handlers, refs |
| `@event="{handler}"` | Client-only | `@submit="{onSubmit()}"`, `@change="{onToggleChange()}"` |
| `?attr="{{expr}}"` | Server + client | `?disabled="{{!description}}"`, `?checked="{{state == 'done'}}"` |
| `f-ref="{prop}"` | Client-only | `f-ref="{addInput}"` — element reference |
| `$e` | Event arg | `@input="{onInput($e)}"` — current event |

### Template directives

| Directive | Purpose | Example |
|---|---|---|
| `<for each="item in items">` | Iteration | `<for each="item in items"><todo-item>...</todo-item></for>` |
| `<if condition="expr">` | Conditional | `<if condition="state == 'done'">...</if>` |

---

### Packages Fast Element Docs Architecture Intro (`packages/fast-element/docs/architecture/intro.md`)

# Introduction

This document (and the linked documents) explains how the exports and side effects of `@microsoft/fast-element` are used to create custom elements.

`@microsoft/fast-element` is designed to run in a client-side browser `Window`
runtime. Its element lifecycle, rendering, and update queue assume browser DOM,
Custom Elements, Shadow DOM, and `requestAnimationFrame` are available. Workers,
server-side JavaScript runtimes, and other non-window hosts are not supported
targets for the FAST Element client runtime.

## Glossary

- [Overview](./overview.md): How the `@microsoft/fast-element` should be used by a developer and what code is executed during the first render.
- [`FASTElement`](./fastelement.md): How the `FASTElement` is architected.
- [`html` tagged template literal](./html-tagged-template-literal.md): How the `html` tagged template literal takes and converts the contents into a `ViewTemplate`.
- [`Updates` queue](./updates.md): How updates to attributes and observables are processed.

---

### Packages Fast Element Docs Architecture Overview (`packages/fast-element/docs/architecture/overview.md`)

# General FAST usage

`FASTElement` is an extension of `HTMLElement` which makes use of Custom Element APIs native to the browser. It also supplies the following methods:

- The `define` method combines the Custom Element name, template, style, and other options into a `FASTElementDefinition`, then uses the native Custom Element [`define()`](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define) to register the Custom Element with a Custom Element Registry.
- The `from` method allows the use of Customized Built-in elements, which extend from native elements such as `HTMLButtonElement`.

### Creating a Custom Element from FASTElement

A basic developer flow for defining a custom element looks like this:

```mermaid
flowchart TD
    A[Create a <code>FASTElement</code> web component by extending the <code>FASTElement</code> class] --> F
    F[Prepare the definition with template and styles] --> G[Define the component in the browser with <code>define()</code>]
```

Let's take a look at the definition step to see what the FAST architecture is doing at this stage.

### Defining a Custom Element

The subclass `define()` method creates a new `FASTElementDefinition`, which includes all metadata needed for the element (such as templates, attributes, and styles), and registers it with the configured Custom Element Registry. The resulting object can be retrieved via `ElementController.definition`.

## A Custom Element in JavaScript is sent to the Browser

Let's step back from defining the Custom Element and consider what is happening when we import from the `@microsoft/fast-element` package.

The FAST Element client runtime is expected to run in the browser `Window`.
Custom element definition, connection, rendering, and update scheduling all rely
on browser APIs such as the Custom Element Registry, DOM, Shadow DOM, and
`requestAnimationFrame`.

First, a global `FAST` property will be created if one does not already exist, typically in browser on the `window`.

Additionally, when Custom Elements are included in a script a few things might happen even before a Custom Element gets detected by the browser. First, there are initial side effects caused by the use of decorators. These include the `attr` decorator from `@microsoft/fast-element` and the `observable` decorator from `@microsoft/fast-element`.

Here is a basic flow of what code is executed and when during initial load of a script that contains a FAST defined Custom Element:

```mermaid
flowchart TD
    A@{ shape: circle, label: "The browser loads the JavaScript file containing FAST and FAST Custom Element definitions" }
    B@{ shape: rect, label: "The FAST global is added to the window" }
    A --> B
    C@{ shape: rect, label: "A Custom Element executes the <code>compose</code> step"}
    B --> C
    D@{ shape: procs, label: "<ul style='text-align: left'><li>Any defined observable decorators are added to the FAST global</li><li>An attribute decorator locates the associated Custom Elements constructor which it uses to push itself to the Custom Elements attribute collection</li></ul>"}
    C --> D
    F@{ shape: rect, label: "An HTML tagged template literal is executed for the FAST Custom Element and applied to the definition" }
    D --> F
    G@{ shape: rect, label: "The <code>define</code> step is hit and the <code>customElement</code> is registered with the Custom Element Registry" }
    F --> G
    H@{ shape: rect, label: "A Custom Element is detected on the page and the browser initializes it" }
    I@{ shape: dbl-circ, label: "The lifecycle steps for <code>FASTElement</code> are executed" }
    G --> H
    H --> I
```

---

### Sites Website Src Docs 2.X Getting Started (`sites/website/src/docs/2.x/getting-started.md`)

---
layout: 2x
eleventyNavigation:
  key: getting-started2x
  title: Getting Started
  order: 2
navigationOptions:
  activeKey: getting-started2x
permalink: false
---

---

### Sites Website Src Docs 3.X Getting Started (`sites/website/src/docs/3.x/getting-started.md`)

---
layout: 3x
eleventyNavigation:
  key: getting-started3x
  title: Getting Started
  order: 2
navigationOptions:
  activeKey: getting-started3x
permalink: false
---

---

### Sites Website Src Docs 1.X Api Fast Colors.Histogram.Gethistogramindex (`sites/website/src/docs/1.x/api/fast-colors.histogram.gethistogramindex.md`)

---
id: fast-colors.histogram.gethistogramindex
title: Histogram.getHistogramIndex property
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [Histogram](./fast-colors.histogram.md) &gt; [getHistogramIndex](./fast-colors.histogram.gethistogramindex.md)

## Histogram.getHistogramIndex property

<b>Signature:</b>

```typescript
getHistogramIndex: (r: number, g: number, b: number) => number;
```

---

### Sites Website Src Docs 1.X Api Fast Colors.Matchlightnessindex (`sites/website/src/docs/1.x/api/fast-colors.matchlightnessindex.md`)

---
id: fast-colors.matchlightnessindex
title: matchLightnessIndex() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [matchLightnessIndex](./fast-colors.matchlightnessindex.md)

## matchLightnessIndex() function

Takes the input color and compares it to each color in the reference array to find the index with the closest Lightness value in HSL color space

<b>Signature:</b>

```typescript
export declare function matchLightnessIndex(input: ColorRGBA64, reference: ColorRGBA64[]): number;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  input | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |
|  reference | [ColorRGBA64](./fast-colors.colorrgba64.md)\[\] |  |

<b>Returns:</b>

number

---

### Sites Website Src Docs 1.X Api Fast Element.Executioncontext.Index (`sites/website/src/docs/1.x/api/fast-element.executioncontext.index.md`)

---
id: fast-element.executioncontext.index
title: ExecutionContext.index property
hide_title: true
layout: 1x
---


[@microsoft/fast-element](./fast-element.md) &gt; [ExecutionContext](./fast-element.executioncontext.md) &gt; [index](./fast-element.executioncontext.index.md)

## ExecutionContext.index property

The index of the current item within a repeat context.

<b>Signature:</b>

```typescript
index: number;
```

---

### Sites Website Src Docs 1.X Api Fast Element.Htmldirective.Targetindex (`sites/website/src/docs/1.x/api/fast-element.htmldirective.targetindex.md`)

---
id: fast-element.htmldirective.targetindex
title: HTMLDirective.targetIndex property
hide_title: true
layout: 1x
---


[@microsoft/fast-element](./fast-element.md) &gt; [HTMLDirective](./fast-element.htmldirective.md) &gt; [targetIndex](./fast-element.htmldirective.targetindex.md)

## HTMLDirective.targetIndex property

The index of the DOM node to which the created behavior will apply.

<b>Signature:</b>

```typescript
targetIndex: number;
```

---

### Sites Website Src Docs 1.X Api Fast Element.Nodebehaviorfactory.Targetindex (`sites/website/src/docs/1.x/api/fast-element.nodebehaviorfactory.targetindex.md`)

---
id: fast-element.nodebehaviorfactory.targetindex
title: NodeBehaviorFactory.targetIndex property
hide_title: true
layout: 1x
---


[@microsoft/fast-element](./fast-element.md) &gt; [NodeBehaviorFactory](./fast-element.nodebehaviorfactory.md) &gt; [targetIndex](./fast-element.nodebehaviorfactory.targetindex.md)

## NodeBehaviorFactory.targetIndex property

The index of the DOM node to which the created behavior will apply.

<b>Signature:</b>

```typescript
targetIndex: number;
```

---

### Sites Website Src Docs 1.X Api Fast Element.Splice.Index (`sites/website/src/docs/1.x/api/fast-element.splice.index.md`)

---
id: fast-element.splice.index
title: Splice.index property
hide_title: true
layout: 1x
---


[@microsoft/fast-element](./fast-element.md) &gt; [Splice](./fast-element.splice.md) &gt; [index](./fast-element.splice.index.md)

## Splice.index property

The index that the splice occurs at.

<b>Signature:</b>

```typescript
index: number;
```

---

### Sites Website Src Docs 1.X Api Fast Foundation.Datagrid.Focuscolumnindex (`sites/website/src/docs/1.x/api/fast-foundation.datagrid.focuscolumnindex.md`)

---
id: fast-foundation.datagrid.focuscolumnindex
title: DataGrid.focusColumnIndex property
hide_title: true
layout: 1x
---


[@microsoft/fast-foundation](./fast-foundation.md) &gt; [DataGrid](./fast-foundation.datagrid.md) &gt; [focusColumnIndex](./fast-foundation.datagrid.focuscolumnindex.md)

## DataGrid.focusColumnIndex property

The index of the column that will receive focus the next time the grid is focused. This value changes as focus moves to different rows within the grid. Changing this value when focus is already within the grid moves focus to the specified column.

<b>Signature:</b>

```typescript
focusColumnIndex: number;
```

---

### Sites Website Src Docs 1.X Api Fast Foundation.Datagrid.Focusrowindex (`sites/website/src/docs/1.x/api/fast-foundation.datagrid.focusrowindex.md`)

---
id: fast-foundation.datagrid.focusrowindex
title: DataGrid.focusRowIndex property
hide_title: true
layout: 1x
---


[@microsoft/fast-foundation](./fast-foundation.md) &gt; [DataGrid](./fast-foundation.datagrid.md) &gt; [focusRowIndex](./fast-foundation.datagrid.focusrowindex.md)

## DataGrid.focusRowIndex property

The index of the row that will receive focus the next time the grid is focused. This value changes as focus moves to different rows within the grid. Changing this value when focus is already within the grid moves focus to the specified row.

<b>Signature:</b>

```typescript
focusRowIndex: number;
```

---

### Sites Website Src Docs 1.X Api Fast Foundation.Datagridrow.Rowindex (`sites/website/src/docs/1.x/api/fast-foundation.datagridrow.rowindex.md`)

---
id: fast-foundation.datagridrow.rowindex
title: DataGridRow.rowIndex property
hide_title: true
layout: 1x
---


[@microsoft/fast-foundation](./fast-foundation.md) &gt; [DataGridRow](./fast-foundation.datagridrow.md) &gt; [rowIndex](./fast-foundation.datagridrow.rowindex.md)

## DataGridRow.rowIndex property

The index of the row in the parent grid. This is typically set programmatically by the parent grid.

<b>Signature:</b>

```typescript
rowIndex: number;
```

---

### Sites Website Src Docs 1.X Api Fast Foundation.Listbox.Selectedindex (`sites/website/src/docs/1.x/api/fast-foundation.listbox.selectedindex.md`)

---
id: fast-foundation.listbox.selectedindex
title: Listbox.selectedIndex property
hide_title: true
layout: 1x
---


[@microsoft/fast-foundation](./fast-foundation.md) &gt; [Listbox](./fast-foundation.listbox.md) &gt; [selectedIndex](./fast-foundation.listbox.selectedindex.md)

## Listbox.selectedIndex property

The index of the selected option.

<b>Signature:</b>

```typescript
selectedIndex: number;
```

---

### Sites Website Src Docs 1.X Api Index (`sites/website/src/docs/1.x/api/index.md`)

---
id: index
title: API Reference
hide_title: true
layout: 1x
---


[Home](./index.md)

## API Reference

## Packages

|  Package | Description |
|  --- | --- |
|  [@microsoft/fast-animation](./fast-animation.md) |  |
|  [@microsoft/fast-colors](./fast-colors.md) |  |
|  [@microsoft/fast-components](./fast-components.md) |  |
|  [@microsoft/fast-element](./fast-element.md) |  |
|  [@microsoft/fast-foundation](./fast-foundation.md) |  |

---

### Sites Website Src Docs 1.X Components Getting Started (`sites/website/src/docs/1.x/components/getting-started.md`)

---
id: components-quickstart
title: Components QuickStart
eleventyNavigation:
  key: components-quickstart1x
  parent: components1x
  title: Components QuickStart
navigationOptions:
  activeKey: components-quickstart1x
description: The @microsoft/fast-components library contains Web Components built on top of our standard component and design system foundation.
keywords:
    - getting started
layout: 1x
---

[](https://opensource.org/licenses/MIT)
[](https://www.npmjs.com/package/@microsoft/fast-components)

The `@microsoft/fast-components` library contains Web Components built on top of our standard component and design system foundation. `@microsoft/fast-components` expresses the FAST design language (FAST Frame). 

## Installation

### From NPM

To install the components:

```shell
npm install --save @microsoft/fast-components
```

```shell
yarn add @microsoft/fast-components
```

To use a Web Component as a custom element in HTML, the custom element must be registered. Importing the necessary component definition into your JavaScript bundle and registering it with a `DesignSystem` will register the custom element with the platform. Here's how to do that for `@microsoft/fast-components`:

```js
import { 
    fastButton, 
    provideFASTDesignSystem 
} from "@microsoft/fast-components";

provideFASTDesignSystem()
    .register(
        fastButton()
    );
```

As a shortcut, if you wish to easily register all available components, rather than registering each one, you can use the following pattern:

```js
import { 
    allComponents, 
    provideFASTDesignSystem 
} from "@microsoft/fast-components";

provideFASTDesignSystem().register(allComponents);
```

:::note
When working with a tree-shaking supporting bundler such as Webpack or Rollup, you will want to import and register the individual components. This will ensure that any unused components are tree-shaken out of your builds.
:::

:::tip
Looking for a setup that integrates with a particular front-end framework or bundler? Check out [our integration docs](../integrations/introduction.md).
:::

### From CDN

A pre-bundled script that contains all APIs needed to use the components is available on CDN. You can use this script by adding [`type="module"`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) to the script element and then importing from the CDN. Here's what that would look like for the FAST Web Components:

```html
<!DOCTYPE html>
<html lang="en">
    <head>
        <script type="module" src="https://cdn.jsdelivr.net/npm/@microsoft/fast-components/dist/fast-components.min.js"></script>
    </head>
    
</html>
```

The markup above always references the latest release of the components. When deploying to production, you will want to ship with a specific version. Here's an example of the markup for that:

```html
<script type="module" src="https://cdn.jsdelivr.net/npm/@microsoft/fast-components@2.16.0/dist/fast-components.min.js"></script>
```

When using FAST from CDN, there is no need to register the components. The CDN script includes code that automatically sets up the design system and registers all the components.

:::note
For simplicity, examples throughout the documentation will assume the library has been installed from NPM, but you can always replace the import location with the CDN URL.
:::

## Add components

With the components registered, add any component to the HTML. That's it! For a comprehensive list of all elements, see the [Components](./fast-accordion.mdx) section.

```html

<fast-button>Hello world</fast-button>

```

---

### Sites Website Src Docs 1.X Design Systems Overview (`sites/website/src/docs/1.x/design-systems/overview.md`)

---
id: overview
title: What is a Design System?
eleventyNavigation:
  key: overview1x
  parent: design-systems1x
  title: What is a Design System?
navigationOptions:
  activeKey: overview1x
description: A Design System can generally be thought of as a collection of resources for interactive media that promotes brand alignment.
keywords:
  - design systems
layout: 1x
---

A Design System can be generally thought of as a collection of interactive media resources that promotes brand alignment. While that definition is intentionally broad, in UI development, Design Systems manifest as component libraries surrounded by usage guidance and design principles.

## How does FAST facilitate development of design systems?

FAST helps by both providing a highly configurable design system that you can drop into any app and by providing a set of building blocks you can use to construct your own design system from scratch, with very little work.

## A highly configurable design system

[FAST Frame](./fast-frame.md) is the name of our highly configurable design system. It's made up of a set of web components and accompanying design tokens. The visual design can be impacted in myriad ways using the exported [Design Tokens](./design-tokens.md), element templates and styles can be augmented or overridden, and shadow roots can be opened or closed as necessary for your application. If you’re looking to get up and running with FAST Web Components and the FAST Frame design system, [start here](./fast-frame.md).

### Design Tokens

Design Tokens are powerful tools that are used to express design abstractions like color, typography, spacing units, and other design-led values. FAST exposes powerful tools for creating and using Design Tokens for your Design System. FAST Frame leverages FAST's design tokens extensively. FAST Frame's use of design tokens is so extensive that you might be able to create your own design system simply by modifying the existing tokens. Of course, you can always create your own tokens and even base your tokens on compositions of existing tokens. To learn more [see our documentation on design tokens](./design-tokens.md).

## Your own design system based on FAST components

If you need more control than you can get through modifying design token values or recipes, you can wrap your styling around the foundation components. By exporting raw JavaScript Custom Element classes, `@microsoft/fast-foundation` handles the business-logic driving a large catalog of UI components. These Custom Element classes can be taken as-is and composed with your templates and styles to match your application or library requirements, reducing the development time and overhead of creating your own design system. For example, rather than implementing a Tree View from scratch, you can use the Foundation Tree View class and simply compose it with your own CSS to create a reusable web component as part of your own system.

---

### Sites Website Src Docs 1.X Fast Element Getting Started (`sites/website/src/docs/1.x/fast-element/getting-started.md`)

---
id: getting-started
title: Getting Started with FAST Element
eleventyNavigation:
  key: getting-started1x
  parent: fast-element1x
  title: Getting Started with FAST Element
navigationOptions:
  activeKey: getting-started1x
description: The fast-element library is a lightweight means to easily build performant, memory-efficient, standards-compliant Web Components.
keywords:
   - getting started
layout: 1x
---

[](https://opensource.org/licenses/MIT)
[](https://badge.fury.io/js/%40microsoft%2Ffast-element)

The `fast-element` library is a lightweight means to easily build performant, memory-efficient, standards-compliant Web Components. FAST Elements work in every major browser and can be used in combination with any front-end framework or even without a framework.

## Installation

### From NPM

To install the `fast-element` library, use either `npm` or `yarn` as follows:

```shell
npm install --save @microsoft/fast-element
```

```shell
yarn add @microsoft/fast-element
```

Within your JavaScript or TypeScript code, you can then import library APIs like this:

```ts
import { FASTElement } from '@microsoft/fast-element';
```

:::tip
Looking for a setup that integrates with a particular front-end framework or bundler? Check out [our integration docs](../integrations/introduction.md).
:::

### From CDN

A pre-bundled script that contains all APIs needed to build web components with FAST Element is available on CDN. You can use this script by adding [`type="module"`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) to the script element and then importing from the CDN.

```html
<!DOCTYPE html>
<html lang="en">
    <head>
        <script type="module">
          import { FASTElement } from "https://cdn.jsdelivr.net/npm/@microsoft/fast-element/dist/fast-element.min.js";

          // your code here
        </script>
    </head>
    
</html>
```

The markup above always references the latest release. When deploying to production, you will want to ship with a specific version. Here's an example of the markup for that:

```html
<script type="module" src="https://cdn.jsdelivr.net/npm/@microsoft/fast-element@1.6.2/dist/fast-element.min.js"></script>
```

:::note
For simplicity, examples throughout the documentation will assume the library has been installed from NPM, but you can always replace the import location with the CDN URL.
:::

:::tip
Looking for a quick guide on building components?  Check out [our Cheat Sheet](../resources/cheat-sheet.md#building-components).
:::

---

### Sites Website Src Docs 2.X Api Fast Element.Executioncontext.Index (`sites/website/src/docs/2.x/api/fast-element.executioncontext.index.md`)

---
id: "fast-element.executioncontext.index"
title: "ExecutionContext.index property"
layout: 2x-api
eleventyNavigation:
  key: "api2xfast-element.executioncontext.index"
  parent: "api2xfast-element"
  title: "ExecutionContext.index property"
navigationOptions:
  activeKey: "api2xfast-element.executioncontext.index"
---


[@microsoft/fast-element](../fast-element/index.html) &gt; [ExecutionContext](../fast-element.executioncontext/index.html) &gt; [index](../fast-element.executioncontext.index/index.html)

## ExecutionContext.index property

The index of the current item within a repeat context.

**Signature:**

```typescript
index: number;
```

---

### Sites Website Src Docs 2.X Api Fast Element.Splice.Index (`sites/website/src/docs/2.x/api/fast-element.splice.index.md`)

---
id: "fast-element.splice.index"
title: "Splice.index property"
layout: 2x-api
eleventyNavigation:
  key: "api2xfast-element.splice.index"
  parent: "api2xfast-element"
  title: "Splice.index property"
navigationOptions:
  activeKey: "api2xfast-element.splice.index"
---


[@microsoft/fast-element](../fast-element/index.html) &gt; [Splice](../fast-element.splice/index.html) &gt; [index](../fast-element.splice.index/index.html)

## Splice.index property

**Signature:**

```typescript
index: number;
```

---

### Sites Website Src Docs 2.X Api Index (`sites/website/src/docs/2.x/api/index.md`)

---
id: "index"
title: "API Reference"
layout: 2x
eleventyNavigation:
  key: "api2xapi2x"
  parent: "api2x"
  title: "@microsoft/fast-element"
navigationOptions:
  activeKey: "api2xapi2x"
---


[Home](./index/)

## API Reference

## Packages

<table><thead><tr><th>

Package


</th><th>

Description


</th></tr></thead>
<tbody><tr><td>

[@microsoft/fast-element](./fast-element/)


</td><td>


</td></tr>
</tbody></table>

---

### Sites Website Src Docs 3.X Api Fast Element.Defaultexecutioncontext.Index (`sites/website/src/docs/3.x/api/fast-element.defaultexecutioncontext.index.md`)

---
id: "fast-element.defaultexecutioncontext.index"
title: "DefaultExecutionContext.index property"
layout: 3x-api
eleventyNavigation:
  key: "api3xfast-element.defaultexecutioncontext.index"
  parent: "api3xfast-element"
  title: "DefaultExecutionContext.index property"
navigationOptions:
  activeKey: "api3xfast-element.defaultexecutioncontext.index"
---


[@microsoft/fast-element](../fast-element/index.html) &gt; [DefaultExecutionContext](../fast-element.defaultexecutioncontext/index.html) &gt; [index](../fast-element.defaultexecutioncontext.index/index.html)

## DefaultExecutionContext.index property

The index of the current item within a repeat context.

**Signature:**

```typescript
index: number;
```

---

### Sites Website Src Docs 3.X Api Fast Element.Executioncontext.Index (`sites/website/src/docs/3.x/api/fast-element.executioncontext.index.md`)

---
id: "fast-element.executioncontext.index"
title: "ExecutionContext.index property"
layout: 3x-api
eleventyNavigation:
  key: "api3xfast-element.executioncontext.index"
  parent: "api3xfast-element"
  title: "ExecutionContext.index property"
navigationOptions:
  activeKey: "api3xfast-element.executioncontext.index"
---


[@microsoft/fast-element](../fast-element/index.html) &gt; [ExecutionContext](../fast-element.executioncontext/index.html) &gt; [index](../fast-element.executioncontext.index/index.html)

## ExecutionContext.index property

The index of the current item within a repeat context.

**Signature:**

```typescript
index: number;
```

---

### Sites Website Src Docs 3.X Api Fast Element.Splice.Index (`sites/website/src/docs/3.x/api/fast-element.splice.index.md`)

---
id: "fast-element.splice.index"
title: "Splice.index property"
layout: 3x-api
eleventyNavigation:
  key: "api3xfast-element.splice.index"
  parent: "api3xfast-element"
  title: "Splice.index property"
navigationOptions:
  activeKey: "api3xfast-element.splice.index"
---


[@microsoft/fast-element](../fast-element/index.html) &gt; [Splice](../fast-element.splice/index.html) &gt; [index](../fast-element.splice.index/index.html)

## Splice.index property

**Signature:**

```typescript
index: number;
```

---

### Sites Website Src Docs 3.X Api Index (`sites/website/src/docs/3.x/api/index.md`)

---
id: "index"
title: "API Reference"
layout: 3x
eleventyNavigation:
  key: "api3xapi3x"
  parent: "api3x"
  title: "@microsoft/fast-element"
navigationOptions:
  activeKey: "api3xapi3x"
---


[Home](./index/)

## API Reference

## Packages

<table><thead><tr><th>

Package


</th><th>

Description


</th></tr></thead>
<tbody><tr><td>

[@microsoft/fast-element](./fast-element/)


</td><td>

Core APIs for building standards-based Web Components with FAST Element.


</td></tr>
</tbody></table>

---

### Sites Website Src Docs 3.X Declarative Templates Overview (`sites/website/src/docs/3.x/declarative-templates/overview.md`)

---
id: declarative-templates-overview
title: Declarative HTML Overview
layout: 3x
eleventyNavigation:
  key: declarative-templates-overview3x
  parent: declarative-templates3x
  title: Overview
navigationOptions:
  activeKey: declarative-templates-overview3x
description: An overview of FAST's declarative HTML authoring model for web components.
keywords:
  - declarative
  - html
  - templates
  - web components
  - f-template
---

{% raw %}

# Declarative HTML Overview

FAST Element provides two ways to author web component templates:

1. **Imperative** — JavaScript tagged template literals using the `html` function.
2. **Declarative** — Plain HTML `<f-template>` elements parsed at runtime.

The declarative model moves template authoring from JavaScript into HTML. Because templates are expressed as standard markup, they can be rendered by any server-side technology without running the FAST Element client runtime — enabling true stack-agnostic server-side rendering. Hydration and client rendering still run in the browser `Window`.

## When to Use Declarative Templates

Choose declarative HTML when:

- You want **server-rendered initial HTML** that hydrates on the client.
- Your rendering pipeline does not run JavaScript (e.g. Rust, Go, or .NET servers).
- You prefer authoring templates in HTML files rather than JavaScript modules.
- You need the same template to be consumable by both a build tool and the browser.

The imperative `html` tagged template remains the right choice for purely client-side applications where templates are authored alongside component logic in TypeScript.

## Hello World

A declarative FAST component requires three pieces: a JavaScript class, an `<f-template>` element, and a host element in the page.

**1. Define the component class** (`main.ts`):

```ts
import { attr, FASTElement } from "@microsoft/fast-element";
import { declarativeTemplate } from "@microsoft/fast-element/declarative.js";

class HelloWorld extends FASTElement {
    @attr greeting: string = "Hello";
}

HelloWorld.define({
    name: "hello-world",
    template: declarativeTemplate(),
});
```

**2. Write the template** (`templates.html`):

```html
<f-template name="hello-world">
    <template>
        <p>{{greeting}}, world!</p>
    </template>
</f-template>
```

**3. Use the element in your page** (`index.html`):

```html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"></head>
<body>
    <hello-world greeting="Hi"></hello-world>
    <script type="module" src="./main.ts"></script>
</body>
</html>
```

When the page loads, `declarativeTemplate()` automatically defines FAST's internal `<f-template>` publisher in the relevant registry, finds the `<f-template name="hello-world">` element, parses its inner `<template>`, and resolves the template for the `hello-world` definition. If you call `enableHydration()` before elements connect, matching pre-rendered content is hydrated; otherwise the component renders client-side. Reactive bindings keep the DOM in sync with property changes.

## How It Works

The declarative pipeline follows these steps:

1. **Define** — The component class is registered with `template: declarativeTemplate()`, which tells FAST to wait for a matching `<f-template>` element and automatically defines the `<f-template>` custom element in the registry.
2. **Parse** — When `<f-template>` connects to the DOM, `TemplateParser` converts the declarative markup into the same internal `ViewTemplate` that the imperative `html` tag produces.
3. **Resolve** — The template is resolved through the bridge and assigned to the element definition before `define()` completes.
4. **Render or hydrate** — If `enableHydration()` was called and the page contains pre-rendered content, existing DOM nodes are reused. Otherwise the template renders client-side.

## Declarative vs. Imperative Syntax

The same component can be expressed either way. Here is a side-by-side comparison:

**Imperative:**

```ts
import { attr, FASTElement, html } from "@microsoft/fast-element";

const template = html<NameTag>`
    <h3>${x => x.greeting}</h3>
`;

class NameTag extends FASTElement {
    @attr greeting: string = "Hello";
}

NameTag.define({ name: "name-tag", template });
```

**Declarative:**

```ts
import { attr, FASTElement } from "@microsoft/fast-element";
import { declarativeTemplate } from "@microsoft/fast-element/declarative.js";

class NameTag extends FASTElement {
    @attr greeting: string = "Hello";
}

NameTag.define({
    name: "name-tag",
    template: declarativeTemplate(),
});
```

```html
<f-template name="name-tag">
    <template>
        <h3>{{greeting}}</h3>
    </template>
</f-template>
```

Both produce the same runtime behavior. The declarative version separates the template into HTML, making it available for server-side rendering without JavaScript.

## Next Steps

- [Writing f-templates](./f-templates) — Template syntax, bindings, directives, and expressions.
- [Defining Elements](./defining-elements) — Component registration and extension configuration.
- [Server-Side Rendering](./server-rendering) — Rendering templates on the server and hydrating on the client.

{% endraw %}

---

### Sites Website Src Docs 2.X Api Fast Element Context Index (`sites/website/src/docs/2.x/api/fast-element/context/index.md`)

---
id: "index"
title: "API Reference"
layout: 2x
eleventyNavigation:
  key: "api2x@microsoft/fast-element/context.js2x"
  parent: "api2x"
  title: "@microsoft/fast-element/context.js"
navigationOptions:
  activeKey: "api2x@microsoft/fast-element/context.js2x"
---


[Home](./index/)

## API Reference

## Packages

<table><thead><tr><th>

Package


</th><th>

Description


</th></tr></thead>
<tbody><tr><td>

[@microsoft/fast-element/context.js](./fast-element/)


</td><td>


</td></tr>
</tbody></table>

---

### Sites Website Src Docs 2.X Api Fast Element Di Index (`sites/website/src/docs/2.x/api/fast-element/di/index.md`)

---
id: "index"
title: "API Reference"
layout: 2x
eleventyNavigation:
  key: "api2x@microsoft/fast-element/di.js2x"
  parent: "api2x"
  title: "@microsoft/fast-element/di.js"
navigationOptions:
  activeKey: "api2x@microsoft/fast-element/di.js2x"
---


[Home](./index/)

## API Reference

## Packages

<table><thead><tr><th>

Package


</th><th>

Description


</th></tr></thead>
<tbody><tr><td>

[@microsoft/fast-element/di.js](./fast-element/)


</td><td>


</td></tr>
</tbody></table>

---

### Sites Website Src Docs 3.X Api Fast Element Context Index (`sites/website/src/docs/3.x/api/fast-element/context/index.md`)

---
id: "index"
title: "API Reference"
layout: 3x
eleventyNavigation:
  key: "api3x@microsoft/fast-element/context.js3x"
  parent: "api3x"
  title: "@microsoft/fast-element/context.js"
navigationOptions:
  activeKey: "api3x@microsoft/fast-element/context.js3x"
---


[Home](./index/)

## API Reference

## Packages

<table><thead><tr><th>

Package


</th><th>

Description


</th></tr></thead>
<tbody><tr><td>

[@microsoft/fast-element/context.js](./fast-element/)


</td><td>


</td></tr>
</tbody></table>

---

### Sites Website Src Docs 3.X Api Fast Element Declarative Index (`sites/website/src/docs/3.x/api/fast-element/declarative/index.md`)

---
id: "index"
title: "API Reference"
layout: 3x
eleventyNavigation:
  key: "api3x@microsoft/fast-element/declarative.js3x"
  parent: "api3x"
  title: "@microsoft/fast-element/declarative.js"
navigationOptions:
  activeKey: "api3x@microsoft/fast-element/declarative.js3x"
---


[Home](./index/)

## API Reference

## Packages

<table><thead><tr><th>

Package


</th><th>

Description


</th></tr></thead>
<tbody><tr><td>

[@microsoft/fast-element/declarative.js](./fast-element/)


</td><td>


</td></tr>
</tbody></table>

---

### Sites Website Src Docs 3.X Api Fast Element Di Index (`sites/website/src/docs/3.x/api/fast-element/di/index.md`)

---
id: "index"
title: "API Reference"
layout: 3x
eleventyNavigation:
  key: "api3x@microsoft/fast-element/di.js3x"
  parent: "api3x"
  title: "@microsoft/fast-element/di.js"
navigationOptions:
  activeKey: "api3x@microsoft/fast-element/di.js3x"
---


[Home](./index/)

## API Reference

## Packages

<table><thead><tr><th>

Package


</th><th>

Description


</th></tr></thead>
<tbody><tr><td>

[@microsoft/fast-element/di.js](./fast-element/)


</td><td>


</td></tr>
</tbody></table>

---

### Packages Fast Element Docs ACKNOWLEDGEMENTS (`packages/fast-element/docs/ACKNOWLEDGEMENTS.md`)

# Acknowledgements

There are many great open source projects that have inspired us and enabled us to build FAST. Below are a few that stand out.

* [.NET](https://dotnet.microsoft.com/) - Many thanks to the .NET team for sharing their policies and practices upon which our issue management and release planning docs and practices were based.
* [asap](https://github.com/kriskowal/asap) - An awesome, time-tested async task queue implementation that heavily inspired our DOM update system.
* [Aurelia 1 and Aurelia 2](https://aurelia.io/) - Various details of Aurelia 2's decorator and metadata model inspired us in the design of `fast-element`. Additionally, Aurelia 1's mechanisms for array observation, binding, and template compilation also guided us in our work.
* [faastjs](https://github.com/faastjs) - A project with a similar name but a very different purpose. Their API documentation approach leveraging [api-extractor](https://api-extractor.com/) was a huge help to us.
* [Knockout](https://knockoutjs.com/) - One of the first JavaScript libraries (if not the first) to implement an observer system. The original techniques for observables and computed observables have influenced many libraries over the years. Re-interpreting these ideas in terms of modern JavaScript and DOM has helped us to build a powerful and robust system.
* [lit-html](https://lit-html.polymer-project.org/) - One of the first libraries to leverage standard JavaScript tagged template literals for HTML templates. We were inspired by this technique and wanted to explore whether it could be combined with our idea of arrow function binding expressions.
* [Polymer](https://www.polymer-project.org/) - One of the first libraries (if not the first) to embrace Web Components.
* [Vue](https://vuejs.org/) - We liked the terseness of the `:` and `@` syntax in templates, so we adapted it along with some modifications in our templates.

---

### Packages Fast Element Docs Api Report.Api (`packages/fast-element/docs/api-report.api.md`)

## API Report File for "@microsoft/fast-element"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Packages Fast Element Docs Template Bindings (`packages/fast-element/docs/template-bindings.md`)

# FAST Element Template Bindings Architecture

This document explains how the FAST Element `html` tagged template system stores bindings, applies them to DOM elements, triggers updates on data changes, and handles HTML-specific behaviors like event listeners.

## Overview

The template binding pipeline has five major stages:

1. **Template Authoring** – The `html` tagged template collects binding expressions and builds placeholder-marked HTML.
2. **Compilation** – The compiler parses the placeholder HTML into a `DocumentFragment`, walks the DOM tree, and records where each binding targets.
3. **View Creation** – The compiled result clones the fragment and creates a *targets* object that maps each binding to its DOM node.
4. **Binding (first render)** – Each factory creates a behavior that attaches to its target node: adding event listeners, setting attributes, or observing expressions.
5. **Reactive Updates** – When observed data changes, one-way binding observers notify their directive, which re-evaluates the expression and pushes the new value to the DOM through a "sink" function.

---

## Mermaid Diagrams

### 1. Template Creation & Storage

This diagram shows how the `html` tagged template literal processes interpolated values and stores them as factories keyed by unique IDs.

```mermaid
flowchart TD
    A["html`&lt;div class='${expr}'&gt;${text}&lt;/div&gt;`"] --> B["ViewTemplate.create(strings, values)"]
    B --> C{"For each interpolated value"}
    C -->|Function| D["Wrap in oneWay() → HTMLBindingDirective"]
    C -->|Binding instance| E["Wrap in HTMLBindingDirective"]
    C -->|HTMLDirective| F["Use directly"]
    C -->|Static value| G["Wrap in oneTime() → HTMLBindingDirective"]
    D --> H["directive.createHTML(add)"]
    E --> H
    F --> H
    G --> H
    H --> I["add(factory) assigns unique ID"]
    I --> J["factories Record&lt;string, ViewBehaviorFactory&gt;"]
    I --> K["Returns placeholder marker in HTML string"]
    K --> L["Aspect Detection via lastAttributeNameRegex"]
    L -->|In attribute context| M["HTMLDirective.assignAspect(directive, attrName)"]
    L -->|In text content| N["aspectType = DOMAspect.content"]
    M --> O{"Attribute prefix"}
    O -->|No prefix| P["DOMAspect.attribute"]
    O -->|: prefix| Q["DOMAspect.property"]
    O -->|? prefix| R["DOMAspect.booleanAttribute"]
    O -->|"@" prefix| S["DOMAspect.event"]
    O -->|:classList| T["DOMAspect.tokenList"]
    J --> U["new ViewTemplate(html, factories)"]
```

### 2. Compilation – Walking the DOM & Storing Target Locations

The compiler transforms the placeholder-laden HTML into a `DocumentFragment` and builds a prototype with lazy property descriptors that navigate to target nodes by child index.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### 3. View Creation – Cloning the Fragment & Resolving Targets

```mermaid
flowchart TD
    A["compilationResult.createView(hostBindingTarget?)"] --> B["fragment.cloneNode(true) → new DocumentFragment"]
    B --> C["targets = Object.create(proto)"]
    C --> D["targets.r = fragment (root)"]
    D --> E["targets.h = hostBindingTarget (host element)"]
    E --> F{"For each registered nodeId"}
    F --> G["Access targets[nodeId] — triggers lazy getter chain"]
    G --> H["Getter resolves: this[parentId].childNodes[childIndex]"]
    H --> I["Caches result in targets._nodeId field"]
    I --> J["new HTMLView(fragment, factories, targets)"]

    subgraph "HTMLView Structure"
        K["fragment: DocumentFragment with cloned DOM"]
        L["factories: CompiledViewBehaviorFactory[]"]
        M["targets: ViewBehaviorTargets {nodeId → Node}"]
        N["firstChild / lastChild: boundary nodes"]
        O["source: null (until bound)"]
        P["behaviors: null (created on first bind)"]
    end
    J --> K
    J --> L
    J --> M
```

### 4. Binding – Attaching Behaviors to DOM Nodes

```mermaid
flowchart TD
    A["view.bind(source)"] --> B{"First bind?"}
    B -->|Yes| C["Set view.source = source"]
    C --> D["Create behaviors array"]
    D --> E{"For each factory"}
    E --> F["factory.createBehavior()"]
    F --> G["Select sink from sinkLookup based on aspectType"]
    G --> H["Wrap sink through policy.protect()"]
    H --> I["behavior.bind(controller/view)"]

    B -->|Subsequent| J["Unbind previous, set new source"]
    J --> K["Re-bind existing behaviors"]

    I --> L{"aspectType?"}

    L -->|DOMAspect.event| M["Store controller ref on target node"]
    M --> N["target.addEventListener(targetAspect, directive, options)"]
    N --> O["directive IS the EventListener via handleEvent()"]

    L -->|DOMAspect.content| P["Register unbind handler"]
    P --> Q["Create observer via dataBinding.createObserver()"]

    L -->|attribute / property / etc.| Q

    Q --> R["observer.bind(controller) → evaluates expression"]
    R --> S["updateTarget(target, aspect, value, controller)"]

    subgraph "Sink Functions (sinkLookup)"
        S1["attribute → DOM.setAttribute(target, name, value)"]
        S2["booleanAttribute → DOM.setBooleanAttribute(target, name, value)"]
        S3["property → target[name] = value"]
        S4["content → updateContent() — manages text or composed views"]
        S5["tokenList → updateTokenList() — classList with versioning"]
        S6["event → no-op (handled via addEventListener)"]
    end
```

### 5. Reactive Update Cycle – Change Detection & DOM Updates

```mermaid
sequenceDiagram
    participant Source as Data Source
    participant Observable as Observable System
    participant Observer as ExpressionObserver (OneWayBinding)
    participant Directive as HTMLBindingDirective
    participant Sink as UpdateTarget (sink fn)
    participant DOM as Target DOM Node

    Note over Source,DOM: Initial Bind
    Directive->>Observer: dataBinding.createObserver(directive, directive)
    Observer->>Source: Evaluate expression (tracks property access)
    Source-->>Observer: Return value + record dependencies
    Directive->>Sink: updateTarget(target, aspect, value, controller)
    Sink->>DOM: Apply value (setAttribute, textContent, etc.)

    Note over Source,DOM: Data Change
    Source->>Observable: Property setter triggered
    Observable->>Observer: Notify subscriber of change
    Observer->>Directive: handleChange(binding, observer)
    Directive->>Observer: observer.bind(controller) — re-evaluate
    Observer->>Source: Re-evaluate expression
    Source-->>Observer: Return new value
    Directive->>Sink: updateTarget(target, aspect, newValue, controller)
    Sink->>DOM: Update DOM with new value
```

### 6. Event Handling – Click Events and Other DOM Events

```mermaid
sequenceDiagram
    participant User as User Interaction
    participant DOM as Target DOM Element
    participant Directive as HTMLBindingDirective (EventListener)
    participant Context as ExecutionContext
    participant Binding as dataBinding.evaluate()
    participant Source as Component Source

    Note over DOM: During bind: target.addEventListener("click", directive)
    Note over DOM: directive stores controller ref on target[data]

    User->>DOM: Click event fires
    DOM->>Directive: handleEvent(event)
    Directive->>DOM: Read controller from event.currentTarget[data]
    Directive->>Directive: Check controller.isBound
    Directive->>Context: ExecutionContext.setEvent(event)
    Directive->>Binding: evaluate(controller.source, controller.context)
    Binding->>Source: Execute handler: (s, c) => s.handleClick(c.event)
    Source-->>Binding: Return result
    Binding-->>Directive: Return result
    alt result !== true
        Directive->>DOM: event.preventDefault()
    end
    Directive->>Context: ExecutionContext.setEvent(null)
```

### 7. Content Binding – Template Composition

When a binding expression returns a `ContentTemplate` (e.g., another `ViewTemplate`), the content update sink composes a child view into the DOM.

```mermaid
flowchart TD
    A["updateContent(target, aspect, value, controller)"] --> B{"value is null/undefined?"}
    B -->|Yes| C["Treat as empty string"]
    B -->|No| D{"value.create exists? (ContentTemplate)"}

    D -->|Yes — Template| E["Clear target.textContent"]
    E --> F{"Existing view on target.$fastView?"}
    F -->|No| G["view = value.create()"]
    F -->|Yes, same template| H["Reuse existing view"]
    F -->|Yes, different template| I["Remove old view, create new"]
    G --> J["view.bind(source, context)"]
    I --> J
    J --> K["view.insertBefore(target)"]
    K --> L["Cache: target.$fastView = view, target.$fastTemplate = value"]

    D -->|No — Primitive| M{"Existing composed view?"}
    M -->|Yes| N["view.remove(), view.unbind()"]
    N --> O["target.textContent = value"]
    M -->|No| O
```

---

## Key Data Structures

| Structure | Location | Purpose |
|---|---|---|
| `ViewTemplate` | template.ts | Holds raw HTML + factories record. Entry point for compilation. |
| `factories: Record<string, ViewBehaviorFactory>` | template.ts | Maps unique IDs to binding factories (directives). |
| `CompilationContext` | compiler.ts | Accumulates factories and builds the target prototype during compilation. |
| `targets: ViewBehaviorTargets` | view.ts / html-directive.ts | Maps node IDs (e.g., `"r.0.2"`) to actual DOM nodes in a cloned fragment. |
| `HTMLView` | view.ts | The live view instance: holds the fragment, factories, targets, behaviors, and source. |
| `HTMLBindingDirective` | html-binding-directive.ts | The core binding: acts as factory, behavior, and event listener. |
| `sinkLookup` | html-binding-directive.ts | Maps `DOMAspect` types to DOM update functions. |
| `Binding` (abstract) | binding/binding.ts | Wraps an expression with policy, volatility, and observer creation. |
| `ExpressionObserver` | observation/observable.ts | Tracks dependencies during expression evaluation and notifies on change. |

## Binding Type Summary

| Markup Syntax | Aspect Type | Sink Function | Example |
|---|---|---|---|
| `attr="${x => x.val}"` | `attribute` | `DOM.setAttribute` | `class="${x => x.cls}"` |
| `?attr="${x => x.val}"` | `booleanAttribute` | `DOM.setBooleanAttribute` | `?disabled="${x => x.off}"` |
| `:prop="${x => x.val}"` | `property` | `target[prop] = value` | `:value="${x => x.name}"` |
| `:classList="${x => x.val}"` | `tokenList` | `updateTokenList` | `:classList="${x => x.classes}"` |
| `@event="${x => x.handler}"` | `event` | addEventListener | `@click="${(x,c) => x.onClick(c.event)}"` |
| `${x => x.val}` (in text) | `content` | `updateContent` | `<p>${x => x.msg}</p>` |

---

## Hydration: Attaching Bindings to Server-Rendered DOM

When a page is server-side rendered (SSR) with Declarative Shadow DOM, the HTML arrives in the browser fully formed. Instead of creating new DOM nodes, FAST's hydration system **reuses the existing DOM** and attaches reactive bindings to it. This section explains how hydration markers in the SSR output guide the client-side binding process.

### Enabling Hydration

Hydration is an opt-in feature. Calling `enableHydration()` patches
`ViewTemplate.prototype` with:
1. A `Hydratable` symbol — marks the template as hydration-capable (checked via `isHydratable()`).
2. A `hydrate(firstChild, lastChild, hostBindingTarget?)` method — creates a `HydrationView` instead of an `HTMLView`.

```typescript
import { enableHydration } from "@microsoft/fast-element/hydration.js";

enableHydration();
```

### Hydration Marker Format

The SSR renderer embeds comment nodes and data attributes into the HTML to mark where bindings should attach. These markers encode the **factory index** (position in the compiled factories array) so the client can map each marker back to its corresponding `ViewBehaviorFactory`.

#### Attribute Binding Markers

Elements with attribute/property/event bindings receive a `data-fe` attribute with the binding count:

```html

<div data-fe="2">server-rendered content</div>
```

The attribute marker format is:

| Attribute | Example | Description |
|---|---|---|
| `data-fe` | `data-fe="3"` | Binding count — the number of attribute bindings on the element |

#### Content Binding Markers

Text/template content bindings are wrapped in paired data-free comment nodes (matched by string equality, paired by balanced depth counting):

```html

Hello, World!

```

#### Repeat Directive Markers

Each repeated item is bracketed by data-free repeat markers:

```html

<li>First item</li>


<li>Second item</li>

```

#### Element Boundary Markers

Nested custom elements that also need hydration are demarcated so the parent's walker can skip over them:

```html

<child-element>
  <template shadowrootmode="open">...child shadow DOM...</template>
</child-element>

```

### Hydration Binding Flow

`hydration/traversal.ts` owns pointer navigation and its live Range fallback.
`hydration/target-builder.ts` consumes that traversal to map factories, keeping
direct native marker reads inline. `HydrationView` uses the same range utility
when producing diagnostic fragments, without coupling it to target discovery.

`enableHydration()` replaces the small core `components/element-registration.ts`
strategy with `hydration/attribute-observation.ts`. Client-only `FASTElement`
bundles do not include observation tracking. Immediately before FAST's platform
registration, tracking records only a boolean proving that `data-fe` is
unobserved, after extensions and asynchronous template resolution. The proof is
available during synchronous upgrades and restored if registration fails.
Earlier untracked registrations remain conservative; calling `enableHydration()`
again does not reset existing proof. Hydration never reconstructs the platform
snapshot by rereading `constructor.observedAttributes`.

For a known unobserved `data-fe` attribute and native attribute methods, removal
cannot invoke an attribute-change callback, so pointers remain active.
Registration/lifecycle accessors, custom attribute iterators, unknown registry
wrappers, customized built-ins, and overridden attribute methods remain
conservative. Legacy/custom marker cleanup still captures live boundaries from
the outset. Marker removal is not deferred and callback order is unchanged.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### HydrationView vs HTMLView

```mermaid
flowchart LR
    subgraph "HTMLView (client-rendered)"
        A1["Compiler produces DocumentFragment"] --> A2["fragment.cloneNode(true)"]
        A2 --> A3["Resolve targets via prototype getter chain"]
        A3 --> A4["Create behaviors & bind"]
    end

    subgraph "HydrationView (server-rendered)"
        B1["DOM already exists in shadow root"] --> B2["Bounded pointer DFS scans markers; live Range fallback when needed"]
        B2 --> B3["buildViewBindingTargets maps markers → nodes"]
        B3 --> B4["Create behaviors & bind to existing nodes"]
        B4 --> B5["Marker comments cleared (data set to empty string)"]
    end
```

| Aspect | HTMLView | HydrationView |
|---|---|---|
| **DOM source** | Clones compiled DocumentFragment | Reuses server-rendered DOM in place |
| **Target resolution** | Prototype getters via childNodes indices | Pointer DFS + sequential markers; live Range / generic-strategy fallback |
| **Node creation** | Creates all DOM nodes from scratch | No node creation (reuses existing) |
| **Fragment** | Holds cloned fragment, moved into host | No fragment initially (created only on remove) |
| **Lifecycle** | Ready immediately after creation | Transitions through unhydrated → hydrating → hydrated |
| **Validation** | Compilation guarantees structure | Must validate markers match factories (throws HydrationBindingError) |
| **Boundaries** | Not needed (compiler tracks structure) | `bindingViewBoundaries` stores first/last node pairs for structural directives |

### Content Binding Hydration

When `HTMLBindingDirective.bind()` runs during hydration and the binding returns a `ContentTemplate`, the `updateContent` sink checks for pre-rendered boundaries:

```mermaid
sequenceDiagram
    participant Directive as HTMLBindingDirective
    participant Controller as HydrationView (controller)
    participant Sink as updateContent()
    participant Template as ContentTemplate

    Directive->>Controller: bind(controller)
    Note over Directive: aspectType = DOMAspect.content
    Directive->>Sink: updateTarget(target, aspect, value, controller)
    Sink->>Sink: value is ContentTemplate?

    alt Hydrating & boundaries exist
        Sink->>Controller: Check bindingViewBoundaries[targetNodeId]
        Controller-->>Sink: { first: Node, last: Node }
        Sink->>Template: value.hydrate(first, last)
        Template-->>Sink: HydrationView (reuses existing nodes)
        Sink->>Sink: view.bind(source, context) — attaches to pre-rendered DOM
    else Already hydrated or no boundaries
        Sink->>Template: value.create()
        Template-->>Sink: HTMLView (creates new nodes)
        Sink->>Sink: view.bind + view.insertBefore
    end
```

### Repeat Directive Hydration

The repeat directive scans **forward** from its own content boundary to its
location, pairing top-level ranges with a stack. This avoids reverse collection
and rescanning prefixes belonging to earlier adjacent repeats. Nested markers
remain untouched until child views hydrate. Both unmatched starts and unmatched
ends throw before repeat markers are cleared.

The read-only `collectHydrationRepeatRanges()` helper in
`hydration/repeat-ranges.ts` owns this discovery and validation. `RepeatBehavior`
supplies its own binding boundaries, then clears top-level markers and hydrates,
creates, or removes views. The discovery helper does not alter marker data or
bind views.

```mermaid
flowchart TD
    A["RepeatBehavior.bind(controller)"] --> B{"isHydratable(template) && hydrating?"}
    B -->|Yes| C["hydrateViews(template)"]
    B -->|No| D["refreshAllViews() — normal client path"]

    C --> E["Allocate views array sized to items.length"]
    E --> F["Scan bindingViewBoundaries[targetNodeId].first through location"]
    F --> G{"Repeat marker?"}
    G -->|Start| H["Push start marker"]
    G -->|End| I["Pop start; throw if absent"]
    I --> J{"Stack empty?"}
    J -->|Yes| K["Append top-level range in item order"]
    J -->|No| F
    H --> F
    K --> F
    G -->|Other node| F
    F -->|Reached location| L["Throw if stack nonempty; otherwise clear top-level markers"]
    L --> M["Hydrate overlapping SSR/client ranges in order"]
    M --> N["Create missing client views and remove excess server ranges"]

    subgraph "Result"
        S["Each array item mapped to a HydrationView"]
        T["Views reuse server-rendered DOM between markers"]
        U["Markers cleared to empty strings (invisible in DOM)"]
    end
```

### Hydration CPU regression coverage

`src/hydration/hydration-performance.pw.spec.ts` instruments Range/TreeWalker
creation and native factory-index array allocation across 500 sibling-bounded
views. Those counters must all be zero on the ordinary native path. It also
asserts exact linear repeat predicate visits (four starts and two ends per
four-comment nested item), scope isolation from earlier siblings, nested marker
preservation, malformed-marker diagnostics, installed `markers_v2`, empty items,
and missing/excess reconciliation. Existing target-builder tests compare live
endpoint mutations with the legacy Range walker. The declarative repeat fixture
checks SSR node identity, three nested repeat levels, an empty inner list, and an
adjacent repeat before exercising reactive updates. The co-located
`src/hydration/repeat-ranges.pw.spec.ts` also verifies that successful discovery
leaves native and legacy marker data unchanged and excludes adjacent ranges.

`src/hydration/native-marker-cleanup.pw.spec.ts` exercises a 1,000-record,
three-repeat-level workload with 20 adjacent prefix items: 4,021 FAST elements,
4,020 native attribute markers, and 8,041 hydrated views. Range/TreeWalker setup,
`comparePoint`, and `intersectsNode` counts are all zero; all 7,020 SSR descendant
elements retain their identity. Mutation fixtures require the fallback and
verify immediate insertion/removal, endpoint moves, unstable observation
metadata, method accessors, customized built-ins, and legacy/custom strategies.
Registration-order cases cover disabled tracking, enabling after registration,
repeated enablement after observation changes, and platform registration deferred
until after asynchronous template resolution.
The declarative repeat fixture includes bound FAST child elements, checks zero
live traversal setup, and exercises reactive updates after hydration.

Run focused correctness coverage from the monorepo root:

```sh
npm exec -w @microsoft/fast-element -- playwright test src/hydration/target-builder.pw.spec.ts src/hydration/hydration-performance.pw.spec.ts src/hydration/native-marker-cleanup.pw.spec.ts src/hydration/repeat-ranges.pw.spec.ts src/templating/repeat.pw.spec.ts --project=chromium
```

CPU timings live separately in `src/hydration/hydration-benchmark.pw.spec.ts`
and are opt-in rather than flaky wall-clock CI gates:

```sh
FAST_HYDRATION_BENCHMARK=1 npm exec -w @microsoft/fast-element -- playwright test src/hydration/hydration-benchmark.pw.spec.ts --project=chromium --retries=0
```

The workloads measure 4,000 marker-free sibling views, 4,000 native
attribute/content marker groups, 4,000 nested repeat ranges with stubbed child
hydration, 20 adjacent repeats with 200 flat item ranges each, and a combined
1,000-record page with three repeat levels, 4,000 minimal native custom elements,
and 8,001 hydrated views. Setup, custom-element registration, and template
construction are outside the timed interval; repeat workloads include bind and unbind. Each
workload has one warm-up and ten recorded samples, each in a fresh document so
live Ranges from earlier samples cannot amplify later DOM mutation costs.
Compare the same test on the base and changed revisions on the same browser and
machine. To attribute improvements, also compare traversal-only, native-only,
and repeat-only source variants in an isolated worktree, reversing variant order
for a second pass. The combined workload includes conservative live-Range
fallbacks for custom-element attribute cleanup, not just ordinary element views.
These microbenchmarks time template hydration, not the issue's application
registration or hydration-completion tracking, and should not be presented as
that application's hydration timings.

The separate native FAST workload times bind/unbind for the 4,021-element /
8,041-view case above. Setup and registration are excluded, identity and marker
removal are verified after every sample, and the same fresh-document sampling
rules apply. Use this workload to compare the known-unobserved cleanup path;
the original combined workload intentionally registers ordinary custom elements
outside FAST and therefore retains its conservative fallback.

### Hydration Stage Lifecycle

```mermaid
stateDiagram-v2
    [*] --> unhydrated: HydrationView created

    unhydrated --> hydrating: bind() called
    note right of hydrating
        buildViewBindingTargets() scans DOM
        Markers parsed, targets resolved
        Behaviors created and bound
        Attribute bindings skip DOM update
        (server already set correct values)
    end note

    hydrating --> hydrated: All behaviors bound
    note right of hydrated
        Subsequent bind() calls
        behave like normal HTMLView rebind
        (re-evaluate expressions, update DOM)
    end note

    hydrated --> hydrated: rebind with new source
```

During the `hydrating` stage, attribute and boolean-attribute bindings **skip their initial DOM update** (the server already rendered the correct value). This avoids unnecessary DOM writes during hydration:

```typescript
// In HTMLBindingDirective.bind(), during hydration:
if (isHydrating && (this.aspectType === DOMAspect.attribute ||
                    this.aspectType === DOMAspect.booleanAttribute)) {
    observer.bind(controller);  // Set up observation only
    break;                      // Skip updateTarget — server value is current
}
```

### Error Handling

When the server-rendered DOM doesn't match the client template, hydration throws descriptive errors:

| Error | Cause | Contains |
|---|---|---|
| `HydrationTargetElementError` | `data-fe` specifies a binding count that cannot be satisfied, more content binding markers exist than factories, or an element boundary end marker is missing | Factories array, target node; with `hydrationDebugger()` installed: structured `expected` (string or `HydrationMismatchExpectation`) describing what the walk wanted next, and `received` (`HydrationMismatchActual`) containing an HTML snippet of the offending DOM |
| `HydrationBindingError` | A factory's `targetNodeId` has no matching entry in targets after the SSR DOM walk completes | Factory, cloned fragment, template string; with `hydrationDebugger()` installed: structured `expected` (`HydrationMismatchExpectation` with `tagName` and human-readable `aspect`) and `received` (`HydrationMismatchActual` with an HTML snippet of the SSR view range) |
| `HydrationRepeatError` | A repeat view slot is unexpectedly `null` / `undefined` during rebind or unbind (internal invariant violation). SSR/client item-count mismatches are no longer surfaced as errors — they are reconciled silently by `RepeatBehavior.hydrateViews()` (missing client views are created, extra SSR ranges are removed) | Hydration stage, items length, view states |
| `FAST.error(1210)` | `data-fe` attribute contains a non-numeric or non-positive value | Attribute value |

These errors typically indicate a mismatch between the server-rendered HTML and the client-side template definition.

By default, both errors emit a minimal one-line message that points at the opt-in `hydrationDebugger()`. Install the debugger from `@microsoft/fast-element/hydration.js` and pass it to `enableHydration` to swap in the rich format:

```ts
import { enableHydration, hydrationDebugger } from "@microsoft/fast-element/hydration.js";

enableHydration({ debugger: hydrationDebugger() });
```

With the debugger installed, both errors format their message as:

```
Hydration mismatch in <host-element>.
  Expected: <tag> with <aspect> binding   (or a structural description)
  Received: <SSR HTML snippet>
```

and expose the same information programmatically through the `expected` and `received` fields so tooling can read the structured description without parsing the message string. Keeping the debugger out of the import graph saves ~0.5 KB on the production hydration bundle.

---

### Packages Fast Router Docs Api Report.Api (`packages/fast-router/docs/api-report.api.md`)

## API Report File for "@microsoft/fast-router"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Packages Fast Build Docs Migration Plugin Integrations (`packages/fast-build/docs/migration/plugin-integrations.md`)

# Migrating plugin integration pipelines

## Structured errors

WASM failures now throw JavaScript `Error` objects rather than strings. Read
`error.message` for the previous human-readable text; `String(error)` now has the
standard `Error: ` prefix. Replace message matching with stable `error.code`
checks. Both WASM declaration modules export a `FastBuildError` interface extending
`Error`; it is a type only, not an exported constructor.

Optional `line`/`column` are one-based UTF-16 coordinates, and `length` is a UTF-16
error-token highlight length. CRLF is one break; lone CR/LF also break lines.
Entry and conversion coordinates refer to the complete supplied HTML. A named
custom-element render failure instead refers to its separately supplied `content`.
Use `templateName` to select that source, rather than attaching its coordinates
to the entry or to a full file from which `content` was extracted. Older metadata
does not carry enough provenance to reconstruct those full-file positions.
Do not fabricate HTML locations when these fields are absent (JSON/options,
missing sources, filesystem errors, or separate CSS).

Native Rust `RenderError` and `ConvertError` expose `code()`, `location()` returning
an optional `ErrorLocation`, `template_name()`, and `kind()`. Source-annotated
validation errors may use the new `Located` variant; match `error.kind()` to
inspect the underlying variant. Context fields now use boxed `ErrorContext`
instead of `String`; use `context.to_string()` to read the unchanged snippet and
`String::into()` when constructing a context without source provenance.
Update exhaustive enum matches for `Located`. These are intentional pre-1.0
native API changes. Successful rendering/conversion, warnings, missing-state
behavior, and permissive `parse_f_templates` parsing are unchanged.

## Attribute output changes

Missing and explicit `null` bindings now omit the entire attribute, including
mixed literal/binding values. To intentionally keep `href=""`, provide `""`
instead of null. JSON booleans on known HTML boolean attributes use presence:
false omits `disabled`, true emits it. ARIA/ordinary attribute booleans remain
textual. Use FAST's `?name` syntax for matching client-side truthy/falsy behavior.
Author bindings resolving to absence suppress matching template-host defaults.
Remove wrapper regular expressions that strip empty values: they would erase
intentional empty strings. Hydration slot counts remain unchanged.

## Typed converter output

The default output remains unchanged. Opt into `typed: true` (or `--typed`)
for explicit `ElementViewTemplate<TSource>` / `ElementStyles` annotations and
type-only imports, then remove wrapper string replacements. Supply
`type_source`/`--type-source` when strict source-property checking is required.
Rust `ConvertOptions` struct literals must include the new `typed` field or
use `..ConvertOptions::default()`.
The pre-1.0 native error enums also gain integration-related variants; update
exhaustive `RenderError` / `ConvertError` matches accordingly.

## Caller-owned host markup

Replace throwaway-host rendering and substring extraction with
`render_shadow_root` (WASM) or `render_shadow_root_*_with_locator` (Rust).
Pass resolved component state and insert the returned complete DSD `<template>`
into the host you own. The fragment does not include host/default attributes
or light-DOM children.

## Persisted template metadata

`parse_f_templates` keeps its JSON array shape and existing fields, adding
per-record `formatVersion: 1` and `bindings`. Preserve these fields when
persisting or constructing a keyed map. Unsupported/malformed explicit versions
now fail before rendering. Unversioned legacy maps remain supported, but cannot
receive stale-version protection. Regenerate metadata on format changes rather
than rewriting a version number onto incompatible data.

Bindings describe names, expression kinds, paths, and repeat scopes. Unknown
types and state optionality are explicitly null, not inferred declarations.
Repeat collections alone have a known array requirement. Complex/client
references are lexical descriptions; metadata is not a full state schema or
syntax-validation certificate. Use application declarations for definitive
type/requiredness checks.

Each newly parsed binding now includes an authored `span` with half-open `start`
and `end` positions in the complete input string. Offsets are zero-based UTF-16;
lines and UTF-16 columns are one-based. Use the original input, not the returned
trimmed `content`, when slicing or attaching diagnostics. The range covers the
trimmed expression without braces; repeat bindings locate only the iterable.
CRLF counts as one line break and two offset units; lone CR and LF each count
as a line break. Raw attribute entities are not decoded.

Format version 1 is unchanged, and renderers still accept older records without
spans. Regenerate persisted metadata to obtain authored locations; preserve spans
when mapping or serializing records. Native `BindingMetadata` struct literals
must now supply the public `span: SourceSpan` field; prefer `parse_f_templates`
to constructing descriptive metadata manually. Generated WASM declarations expose
`TemplateSourceSpan` and `TemplateSourcePosition`.

---

### Packages Fast Element Docs Architecture Fastelement (`packages/fast-element/docs/architecture/fastelement.md`)

# FASTElement

The `FASTElement` is our extension of the `HTMLElement`. As such it leverages the lifecycles but also requires additional setup before before the class `constructor` or the `connectedCallback` method is executed which are explained in the [overview](./overview.md). This document explains specifically what `FASTElement` leverages inside the `HTMLElement`s lifecycle hooks.

For an explanation into `HTMLElement` lifecycle hooks refer to the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks).

Because `FASTElement` extends `HTMLElement`, it is a browser `Window` runtime
API. It is not intended to execute in workers, server-side JavaScript runtimes,
or other non-window hosts where custom element lifecycle callbacks and animation
frame scheduling are unavailable.

## A Custom Element is Detected by the Browser

Because the `FASTElement` is an extension of the `HTMLElement`, it makes use of the same lifecycle hooks and extends them with `$fastController`. It also initializes using another class `ElementController`, the methods this are called during the custom elements native `constructor`, `connectedCallback`, `disconnectedCallback`, and `attributeChangedCallback` lifecycle hooks.

### 🔄 **Lifecycle**: Initialization

```mermaid
flowchart TD
    A[A <code>FASTElement</code> web component is added to the <code>DOM</code>] --> B
    B[<code>FASTElement</code> initializes the <code>ElementController.forCustomElement</code> passing the Custom Element instance] --> C
    B --> F[Observables applied to the <code>FASTElement</code> are updated on the FAST global without values]
    C{Is an <code>ElementController</code> available?}
    C --> |yes|E
    C --> |no|D
    D[Initialize a new <code>ElementController</code> referred to as setting an element controller strategy]
    D --> F
    E[<code>ElementController</code> captures the Custom Element instance and the definition and attaches them to the <code>$fastController</code> which is then attached to the instance]
```

### 🔄 **Lifecycle**: Component is connected

```mermaid
flowchart TD
    A[browser <code>HTMLElement</code>'s <code>connectedCallback</code> is called] --> B
    B[<code>this.$fastController.connect</code> in FASTElement is called] --> C
    B --> D
    B --> E
    B --> F
    C[bind observables by capturing public own Custom Element properties and setting those values through the matching accessors]
    D[connect behaviors by call the <code>connectedCallback</code> on all behaviors]
    E[render template, execute an <code>ElementViewTemplate</code>'s render method]
    F[add styles either as an appended <code>StyleElement</code> node or an <code>adoptedStylesheet</code> which may include and attach behaviors]
```

#### Render Template

The rendering of the template on the `ElementController` is by the `renderTemplate` method which is called during the `ElementController.connect` method which is triggered by `HTMLElement`s `connectedCallback` lifecycle.

The `renderTemplate` identifies the Custom Element, and the shadow root associated with the Custom Element. This then places a rendering of the template (an `ElementView`) onto the internal `view` of the controller. When creating the `ElementView`/`HTMLView` using the `ViewTemplate.render`, the `Compiler.compile()` method identifies a `DocumentFragment` either by using an existing `<template>` tag, or creating one to wrap the contents of the shadow root. A new `CompilationContext` is created and the `compileAttributes` function is called, this results in the replacement of the placeholder attributes initally set-up during the pre-render step with their values if a value has been assigned. The factories with the associated nodes identified are then passed to the context. The view then binds all behaviors to the source element. The `CompilationContext.createView` is executed with the `DocumentFragment` as the root, and returns an `HTMLView`. This `HTMLView` includes an `appendTo` method to attach the fragment to the host element, which it then does. It should be noted that the compiled HTML is a `string`, which when set on the `DocumentFragment` as `innerHTML`, this allows the browser to dictate the creation of HTML nodes.

### 🔄 **Lifecycle**: Component is disconnected

When a component is disconnected, a cleanup step is created to remove associated behaviors.

### 🔄 **Lifecycle**: Attribute has been changed

Attributes have an `AttributeDefinition` which allows for converters, attachment of the `<attributName>Changed` aspect of the `@attr` decorator among other capabilities.

```mermaid
flowchart TD
    A[The browser <code>HTMLElement</code>'s <code>attributeChangedCallback</code> is called] --> B
    B[<code>this.$fastController.onAttributeChangedCallback</code> in <code>FASTElement</code> is called] --> C
    C[calls the attribute definitions <code>onAttributeChangedCallback</code> method with the updated value] --> D
    D[An <code>Updates.enqueue</code> is called which places the update in the task queue which is then executed, these are performed async unless otherwise specified]
```

These changes are observed and similar to the way `Observables` work, they utilize an `Accessor` pattern which has a `getValue` and `setValue` in which DOM updates are applied.

Observable backing slots such as `_foo` are FAST-owned internal state. The
controller's connection-time observable binding only replays public own
properties that shadow prototype accessors; it does not normalize backing slots
into public property assignments. This keeps attribute converter output in its
already-converted model form while preserving pre-upgrade public property
assignments and opt-in extension behavior.

---

### Packages Fast Element Docs Architecture Html Tagged Template Literal (`packages/fast-element/docs/architecture/html-tagged-template-literal.md`)

# `html` tagged template literal

The `html` export from `@microsoft/fast-element` is used to create the template logic for the custom element.

## Pre-processing the `html` tagged template literal contents

Before the template can be used it goes through a step to convert it into a `ViewTemplate` which it does via the `ViewTemplate.create()` method. This is then used during the `compose` step, before `FASTElement` is instantiated.

During the static `ViewTemplate.create()` method (called by the `html` tag), the following happens for each string:
- Factories with unique IDs are created for each tag template literal argument (or `TemplateValue`) which matches with the corresponding string
- A binding is created from the `TemplateValue`

The `Compiler.compile()` method is called lazily the first time the template is rendered (via `ViewTemplate.compile()`, which is triggered by `ViewTemplate.create()` instance method or `ViewTemplate.render()`).

A resulting string using a `createHTML()` function is produced using the `HTMLDirective`s executed for each factory. The behavior is augmented by the previous string from the `html` tag template which determines the aspect if one exists, these aspects are the `@`, `:`, or other binding aspect attached to attributes.

The `createHTML()` function utilizes a `Markup` attribute which is assigned to a factory's unique ID. The strings are concatenated and passed to a new `ViewTemplate` with all the factories (empty until one is assigned) that act as a dictionary with the unique IDs as the key to look up each factory once it has been created. The string this creates is injected into a `<template>` as `innerHTML`, which allows the browser to create the nodes and placeholder factory IDs, with the only `DOM` node that is explicitly created being the wrapping `<template>` element.

## Directives

The `HTMLBindingDirective` applies bindings to items identified as various `TemplateValue`s within the `html` tagged template. The `createHTML` step uses the factory associated with the binding to create strings in the markup using the factory's ID.

```mermaid
flowchart TD
    A[A <code>new HTMLBindingDirective</code> is created with a data binding which has a policy, options, <code>createObserver</code>, and an evaluate method assigned to the passed arrow function such as <pre>x => x.foo</pre>]
    B[<code>oneTime</code> binding passes the corresponding tag template argument, an arrow function]
    C[<code>oneWay</code> binding passes a copy of the corresponding tag template argument, an arrow function]
    D[An already specified binding such as a <code>repeat</code> or <code>when</code> directive is passed]
    A --> B
    A --> C
    A --> D
    E[When a <code>createObserver</code> is called, an <code>Observable.binding</code> is created passing the arrow function to be evaluated and the subscriber to be notified]
    C --> E
    F[When a <code>createObserver</code> is called, the instance of the one time binding is returned which includes a bind method returning the arrow function executed against the controller source and context]
    B --> F
```

---

### Packages Fast Element Docs Architecture Updates (`packages/fast-element/docs/architecture/updates.md`)

# `Updates`

The `Updates` API batches FAST Element DOM work in the client-side browser
`Window` runtime. Queued work includes updates to attributes, observables, and
observed arrays. The async queue is aligned to `requestAnimationFrame`, which is
expected to be available in the supported runtime.

FAST Element is not intended to run its client runtime in workers, server-side
JavaScript runtimes, or other non-window hosts. Code that needs server rendering
should generate HTML for the browser, then let the browser window run FAST
Element, connect custom elements, and process queued updates.

## Attributes

An attribute change may be queued when the value of the attribute is updated. This change is triggered by `HTMLElement` lifecycle hook `attributeChangedCallback`. The `Updates` queue is used to try to reflect the attribute with the updated value onto the element using `DOM` APIs.

## Observables

The `Reflect` API is used to override `defineProperty` in order to observe a property on an Custom Element, this overrides the getter and setter, which allows subscribers to be notified of changes. Any changes which `set` the value are passed to the `Updates` queue.

---

### Packages Fast Element Docs Arrays Api Report.Api (`packages/fast-element/docs/arrays/api-report.api.md`)

## API Report File for "@microsoft/fast-element"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Packages Fast Element Docs Context Api Report.Api (`packages/fast-element/docs/context/api-report.api.md`)

## API Report File for "@microsoft/fast-element"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Packages Fast Element Docs Declarative Api Report.Api (`packages/fast-element/docs/declarative/api-report.api.md`)

## API Report File for "@microsoft/fast-element"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Packages Fast Element Docs Declarative Design (`packages/fast-element/docs/declarative/design.md`)

# Declarative HTML Design

This document is intended for contributors who want to understand the internal
architecture of the declarative runtime and schema-driven map extensions in
`@microsoft/fast-element`. It covers the feature's purpose, core concepts, data
flow, and its integration with the rest of `@microsoft/fast-element`.

## Table of Contents

1. [Overview](#overview)
2. [Goals](#goals)
3. [Core Concepts](#core-concepts)
4. [Package Structure](#package-structure)
5. [Exports and Public API](#exports-and-public-api)
6. [Template Syntax](#template-syntax)
7. [Data Flow](#data-flow)
8. [Template Parsing Pipeline](#template-parsing-pipeline)
9. [Schema and Observer Map](#schema-and-observer-map)
10. [Lifecycle](#lifecycle)
11. [Integration with fast-element](#integration-with-fast-element)
12. [Hydration Model](#hydration-model)
13. [Testing Architecture](#testing-architecture)
14. [Further Reading](#further-reading)

---

## Overview

`@microsoft/fast-element` lets you write FAST Web Component
templates as plain HTML rather than JavaScript `html` tagged template literals.
The browser-side JS bundle defines FAST's internal native `<f-template>`
publisher on demand. It parses declarative template markup at runtime and
returns a `ViewTemplate` to the waiting FAST element definition through the
registry-aware declarative template bridge.

```html

<my-component greeting="Hello">
    <template shadowrootmode="open">
        Hello
    </template>
</my-component>


<f-template name="my-component">
    <template>{{greeting}}</template>
</f-template>
```

---

## Goals

| Goal | Description |
|---|---|
| **Server-agnostic rendering** | Templates are plain HTML strings with no dependency on Node.js or any specific SSR framework. |
| **Progressive enhancement** | Components can be server-rendered and then hydrated client-side without a full re-render. |
| **FAST parity** | The declarative syntax maps 1-to-1 to FAST Element directive helpers (`repeat`, `when`, `slotted`, `children`, `ref`) exported from `@microsoft/fast-element`. |
| **Minimal authoring overhead** | Component authors write HTML, not tagged template strings, while retaining full reactive capabilities. |

---

## Core Concepts

### `<f-template>` — the internal template publisher

`<f-template>` is an internal custom element implemented as a lightweight native
`HTMLElement`. It is defined automatically by `declarativeTemplate()` in the same
`CustomElementRegistry` as the FAST element definition. Consumers should not
import, subclass, or define the implementation directly.

When connected to the DOM it:

1. Registers itself with the declarative template bridge using its registry and
   `name` attribute.
2. Publishes a template when a matching FAST element definition requests one.
3. Delegates parsing of the inner `<template>` tag to `TemplateParser`, which
   converts declarative bindings into FAST `ViewTemplate` strings and values.
4. Runs definition-scoped schema transforms, such as `attributeMap()` and
   `observerMap()`, before returning the concrete `ViewTemplate`.

When multiple connected `<f-template>` publishers share the same `name`, the
bridge resolves pending definitions from the first connected publisher and keeps
the resolved template stable. Later duplicate publishers do not reassign the
definition template.

### `TemplateParser` — declarative HTML parser

A standalone class that converts declarative HTML template markup into the
`strings` and `values` arrays that `ViewTemplate.create()` consumes. It is used
by the internal `<f-template>` publisher but can also be used independently for
programmatic template compilation. The parsing pipeline is fully synchronous —
no promises are allocated during template resolution. A `StringsAccumulator`
tracks the running concatenation of preceding HTML, eliminating repeated O(N)
`join("")` calls at each binding site. `createTemplate()` lazily installs the
declarative runtime's debug messages; hydration support is installed only by
`enableHydration()`.

### `Schema` — JSON schema builder

Built during declarative template parsing, one `Schema` instance per
`<f-template>`. Non-declarative callers can also create and attach a `Schema`
manually. It records every binding path discovered in the template or supplied
by code and constructs a JSON Schema-compatible data structure. This schema:

- Describes the shape of each root property referenced in the template.
- Tracks repeat context chains (parent/child array relationships).
- Uses an instance-level `schemaMap` for its own property schemas.
- Registers itself in the module-level `schemaRegistry` (keyed by custom element name) for cross-element `$ref` resolution.

`FASTElementDefinition.schema` is optional. `declarativeTemplate()` assigns it
automatically after parsing; manual schema users can pass `schema` in the
definition object.

### `ObserverMap` — automatic observable setup

An optional layer that uses the `Schema` to automatically:

- Call `Observable.defineProperty()` for every root property on the element prototype.
- Install property-change handlers that wrap newly assigned objects/arrays in `Proxy` instances.
- Propagate deep property mutations back through FAST's observable system so bindings re-render.

Enabled via the `observerMap()` definition extension exported from
`@microsoft/fast-element/observer-map.js`. Calling `observerMap()` without
arguments observes all root properties discovered in the template or supplied
schema.

#### Path-level observation control

The `ObserverMapConfig` interface accepts an optional `schema` for
non-declarative/manual schema use and an optional `properties` key that maps
root property names to a recursive path tree controlling observation
granularity:

```typescript
MyElement.define(
    {
        name: "my-element",
        template: declarativeTemplate(),
    },
    [
        observerMap({
            properties: {
                user: {
                    name: true,          // user.name — observed
                    details: {
                        age: true,       // user.details.age — observed
                        history: false,  // user.details.history — NOT observed
                    },
                },
                // root properties not listed here are skipped
            },
        }),
    ],
);
```

Each path entry can be:
- **`true`** — observe this path and all descendants (unless overridden deeper).
- **`false`** — skip this path and all descendants (unless overridden deeper).
- **`ObserverMapPathNode`** — an object with an optional `$observe` boolean and child property overrides, allowing alternating opt-in/opt-out to arbitrary depth.

When `properties` is omitted, all root properties are observed. When
`properties` is present but empty (`{ properties: {} }`), no root properties
are observed.

Observer-map-managed array updates replace the array reference when `deepMerge`
receives a new array. This avoids mutating an existing observed array while it
may be notifying subscribers and lets repeat bindings observe the new array
reference. Replaced arrays are wrapped with the schema for the assigned
property, and array observer subscriptions are installed once per array so
reprocessing does not duplicate accessors or notification work.

For non-declarative elements, pass a schema directly to `observerMap()`:

```typescript
import { FASTElement, Schema } from "@microsoft/fast-element";
import { observerMap } from "@microsoft/fast-element/observer-map.js";

class MyElement extends FASTElement {}

const schema = new Schema("my-element");
schema.addPath({
    rootPropertyName: "user",
    pathConfig: {
        type: "default",
        parentContext: null,
        currentContext: null,
        path: "user.name",
    },
    childrenMap: null,
});

MyElement.define({ name: "my-element" }, [observerMap({ schema })]);
```

The resolution algorithm walks the schema and configuration tree in parallel:
1. If `properties` is present and a root property is not listed, it is skipped.
2. `true`/`false` booleans apply to the entire subtree.
3. `$observe` on a node object controls the current level; children inherit when unspecified.
4. Paths in the config but not in the schema are silently ignored (forward-compatible).

### `AttributeMap` — automatic `@attr` definitions

An optional layer that uses the `Schema` to automatically register `@attr`-style reactive properties for every **leaf binding** in the template — i.e. simple expressions like `{{foo}}` or `id="{{foo-bar}}"` that have no nested properties, no explicit type, and no child element references.

- By default (`attribute-name-strategy: "camelCase"`), the binding key is treated as a camelCase property name and the HTML attribute name is derived by converting it to kebab-case (e.g. `{{fooBar}}` → property `fooBar`, attribute `foo-bar`). This matches the build-time `--attribute-name-strategy` option in `@microsoft/fast-build`.
- When `attribute-name-strategy` is `"none"`, the **attribute name** and **property name** are both the binding key exactly as written in the template (e.g. `{{foo-bar}}` → attribute `foo-bar`, property `foo-bar`). No normalization is applied.
- Because HTML attributes are case-insensitive, binding keys should use lowercase names (optionally dash-separated) when using the `"none"` strategy.
- Properties already decorated with `@attr` or `@observable` are left untouched.
- `FASTElementDefinition.attributeLookup` is keyed by the HTML attribute name, and `propertyLookup` is keyed by the JS property name so `attributeChangedCallback` correctly delegates to the new `AttributeDefinition`.

Enabled via the `attributeMap()` definition extension exported from
`@microsoft/fast-element/attribute-map.js`. Calling `attributeMap()` without
arguments uses the default `"camelCase"` strategy. To preserve binding keys
exactly as written, pass `attributeMap({ "attribute-name-strategy": "none" })`.
Outside declarative templates, `attributeMap()` uses the optional `schema` on the
FAST element definition.

### Syntax constants (`syntax.ts`)

All delimiters used by the parser are defined in a single `Syntax` interface and exported as named constants from `syntax.ts`. This makes the syntax pluggable and easy to audit.

| Constant | Value | Use |
|---|---|---|
| `openExpression` / `closeExpression` | `{{` / `}}` | Default (SSR-compatible) binding |
| `unescapedOpenExpression` / `unescapedCloseExpression` | `{{{` / `}}}` | Raw HTML binding |
| `clientSideOpenExpression` / `clientSideCloseExpression` | `{` / `}` | Client-only (event / attribute directive) binding |
| `repeatDirectiveOpen` / `repeatDirectiveClose` | `<f-repeat` / `</f-repeat>` | Repeat directive |
| `whenDirectiveOpen` / `whenDirectiveClose` | `<f-when` / `</f-when>` | When directive |
| `attributeDirectivePrefix` | `f-` | Attribute directive prefix |
| `eventArgAccessor` | `$e` | DOM event argument |
| `executionContextAccessor` | `$c` | Execution context argument |

---

## Package Structure

```
packages/fast-element/
├── src/
│   ├── components/
│   │   ├── schema.ts          # Shared Schema class + schemaRegistry
│   │   └── definition-schema-transforms.ts # Definition-scoped schema transform storage
│   ├── declarative/
│       ├── index.ts           # Public declarative entrypoint implementation
│       ├── interfaces.ts      # Message enum (error codes)
│       ├── debug.ts           # Human-readable declarative debug messages
│       ├── template.ts        # declarativeTemplate(), internal <f-template> publisher, lifecycle orchestration
│       ├── template-bridge.ts # Registry/name bridge between definitions and publishers
│       ├── template-parser.ts # TemplateParser — converts declarative HTML to ViewTemplate strings/values
│       ├── observer-map.ts    # observerMap() implementation
│       ├── attribute-map.ts   # attributeMap() implementation
│       ├── observer-map-utilities.ts # Shared observer-map helpers
│       ├── utilities.ts       # Declarative parsing helpers
│       └── syntax.ts          # Syntax delimiter constants
│   └── hydration/
│       ├── markers.ts         # Default 3.x marker reader and marker strategy contract
│       └── markers-v2.ts      # Opt-in 2.x indexed marker reader
├── scripts/
│   └── declarative/           # Fixture build + webui integration scripts
└── test/
    └── declarative/fixtures/  # One directory per feature, each with spec + index.html + main.ts
```

### Module dependency direction

The default `declarativeTemplate()` path avoids importing optional map
implementations. Map helpers attach schema transforms to the definition only
when the consumer passes them as define extensions.

```
declarative/template.ts ──imports──▶ components/definition-schema-transforms.ts (schema transform reads)
declarative/template.ts ──imports──▶ components/schema.ts (Schema)
declarative/attribute-map.ts ──imports──▶ components/definition-schema-transforms.ts (register attribute-map transform)
declarative/observer-map.ts ──imports──▶ components/definition-schema-transforms.ts (register observer-map transform)
declarative/observer-map.ts ──imports──▶ components/schema.ts (Schema types)
declarative/attribute-map.ts ──imports──▶ components/schema.ts (Schema types)
declarative/utilities.ts ──imports──▶ components/schema.ts (schemaRegistry for cross-element $ref resolution)
```

Schema transforms run in deterministic order. `attributeMap()` runs before
`observerMap()`, so generated attributes are available to observer mapping.

---

## Exports and Public API

```typescript
import {
    declarativeTemplate,
    TemplateParser,
    type ResolvedStringsAndValues,
} from "@microsoft/fast-element/declarative.js";
import {
    Schema,
    schemaRegistry,
    type CachedPathMap,
    type JSONSchema,
} from "@microsoft/fast-element/schema.js";
import { type FASTElementExtension } from "@microsoft/fast-element";
import {
    attributeMap,
    type AttributeMapConfig,
} from "@microsoft/fast-element/attribute-map.js";
import {
    observerMap,
    type ObserverMapConfig,
    type ObserverMapPathEntry,
    type ObserverMapPathNode,
} from "@microsoft/fast-element/observer-map.js";
```

Declarative template helpers, map helpers, and their configuration types are
available from focused path exports.

Primary declarative exports intended for application code:

| Export | Purpose |
|---|---|
| `declarativeTemplate()` | `@microsoft/fast-element/declarative.js` template resolver for subclass `define()` calls; auto-defines the internal `<f-template>` publisher and waits for the matching template. |
| `TemplateParser` | `@microsoft/fast-element/declarative.js` standalone parser that converts declarative HTML into `ViewTemplate` strings/values. Can be used independently of `<f-template>` for programmatic template compilation. |
| `Schema` | `@microsoft/fast-element/schema.js` JSON schema builder that records binding paths discovered during template parsing. Each instance owns its own schema map and registers itself in the `schemaRegistry` for cross-element `$ref` resolution. |
| `schemaRegistry` | `@microsoft/fast-element/schema.js` module-level `Map<string, Map<string, JSONSchema>>` that indexes schemas by custom element name. Used for cross-element lookups (e.g. nested component `$ref` resolution). |

Hydration marker selection is available from
`@microsoft/fast-element/hydration.js`. FAST Element 3.x data-free markers are
the default; `enableHydration({ markers: markers_v2 })` opts into the FAST Element 2.x
indexed marker reader for staged server/client migrations.

Primary map extension exports:

| Export | Import path | Purpose |
|---|---|---|
| `attributeMap()` | `@microsoft/fast-element/attribute-map.js` | Define extension that registers `@attr`-style properties for leaf bindings discovered during parsing or supplied by `definition.schema`. |
| `observerMap()` | `@microsoft/fast-element/observer-map.js` | Define extension that defines observable root properties and proxy-based deep change tracking from `config.schema`, `definition.schema`, or a declarative template schema. |

The implementation element class (`<f-template>`), `TemplateElement.config()`,
`TemplateElement.options()`, `ElementOptions*`, and
`HydrationLifecycleCallbacks` are not exported from the public declarative
entrypoint. Use `declarativeTemplate()`, `attributeMap()`, `observerMap()`, and
`enableHydration()` instead. The `AttributeMap` and `ObserverMap` implementation
classes are available for advanced scenarios, but application code should
normally use the extension factories.

Additionally, `@microsoft/fast-element` exports these types:

| Type | Source Module | Purpose |
|---|---|---|
| `FASTElementExtension` | `fast-definitions.ts` | Definition extension callback signature used by `attributeMap()` and `observerMap()`. |
| `JSONSchema` | `components/schema.ts` | JSON Schema interface used by `Schema` for property structure. |
| `CachedPathMap` | `components/schema.ts` | `Map<string, Map<string, JSONSchema>>` — the shape of the schema registry. |

The map configuration types are exported from the same map-specific paths:

| Type | Import path | Purpose |
|---|---|---|
| `ObserverMapConfig` | `@microsoft/fast-element/observer-map.js` | Configuration object for `observerMap()`; accepts optional `schema` and `properties` keys. |
| `ObserverMapPathEntry` | `@microsoft/fast-element/observer-map.js` | `boolean \| ObserverMapPathNode` — a node in the observation path tree. |
| `ObserverMapPathNode` | `@microsoft/fast-element/observer-map.js` | Object node with optional `$observe` and child property overrides. |
| `AttributeMapConfig` | `@microsoft/fast-element/attribute-map.js` | Configuration object for `attributeMap()`; accepts `attribute-name-strategy`. |

---

## Template Syntax

The declarative syntax is a superset of HTML with three binding delimiters:

| Syntax | Example | Behaviour |
|---|---|---|
| `{{expr}}` | `{{greeting}}` | SSR-compatible content / attribute binding |
| `{{{expr}}}` | `{{{rawHtml}}}` | Unescaped HTML (wraps in `<div :innerHTML>`) |
| `{expr}` | `@click="{handleClick($e)}"` | Client-only binding (events, attribute directives) |

### Directives

Bindings and FAST directive markup inside HTML comments are unsupported. The
string-based parsers do not reliably exclude comment contents, so commenting out
bound markup can still affect binding discovery and hydration. See the
[HTML comment restrictions](./syntax.md#html-comments).

| Directive | Example |
|---|---|
| `<f-when value="{{expr}}">` | Conditional rendering |
| `<f-repeat value="{{item in list}}">` | List rendering |
| `f-slotted="{prop}"` | Slotted nodes attribute directive |
| `f-children="{prop}"` | Children attribute directive |
| `f-ref="{prop}"` | Element ref attribute directive |

For full syntax reference see [syntax.md](./syntax.md).

---

## Data Flow

The high-level data flow from authoring to interactive component:

```mermaid
flowchart TD
    A["Author writes declarative HTML
using f-template with binding expressions"] --> B["Server renders hydratable HTML
with fe:b comments and data-fe attributes"]
    B --> C[Browser loads JS bundle]
    C --> D["MyElement.define called
with template: declarativeTemplate()"]
    D --> E["declarativeTemplate() defines internal f-template
in the target registry"]
    E --> F["f-template connects to DOM
→ registers publisher with bridge"]
    F --> G["definition requests template
via registry + name bridge"]
    G --> H[transformInnerHTML normalises HTML entities]
    H --> I["TemplateParser parses bindings/directives
builds Schema, strings, values"]
    I --> J["Run definition schema transforms
attributeMap before observerMap"]
    J --> K["ViewTemplate.create(strings, values)
returned to definition"]
    K --> L["FASTElementDefinition.define
registers element with platform"]
    L --> M{"enableHydration() called?"}
    M -- yes --> N["ElementController hydrates existing DOM
via template.hydrate()"]
    M -- no --> O["ElementController client-side renders
existing DSD is not reused"]
    N --> P[Interactive component]
    O --> P
```

---

## Template Parsing Pipeline

The internal `<f-template>` publisher orchestrates the pipeline by creating a
`TemplateParser` instance and delegating all parsing logic to it. The recursive
parsing context is encapsulated in a `TemplateResolutionContext` object internal
to the parser, keeping method signatures lean.

### Architecture

The parsing pipeline is split across two classes plus definition-scoped
transforms:

- **Internal `<f-template>` publisher** (`template.ts`) — Custom element
  lifecycle, registry/name bridge registration, template publication, and
  schema-transform execution. It is a native `HTMLElement`, not a `FASTElement`.
- **`TemplateParser`** (`template-parser.ts`) — Synchronous template parser:
  converts declarative HTML into `strings`/`values` arrays for
  `ViewTemplate.create()`. Uses a `StringsAccumulator` to track the running
  previous-string in O(1) per binding site instead of O(N) `join("")` calls.
  Independently testable without DOM.
- **Schema transforms** (`definition-options.ts`) — Extension-provided callbacks run
  after parsing and before `ViewTemplate.create()`. `attributeMap()` runs before
  `observerMap()`.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### TemplateParser method decomposition

| Method | Visibility | Role |
|---|---|---|
| `parse()` | public | Entry point: parses declarative HTML into `{ strings, values }`. |
| `createTemplate()` | public | Creates a `ViewTemplate` from resolved strings and values, lazily installing declarative debug messages. |
| `resolveStringsAndValues()` | private | Creates `strings`/`values` arrays and delegates to `resolveInnerHTML()`. |
| `resolveInnerHTML()` | private | Recursive HTML parser that dispatches to data binding or template directive handlers. |
| `resolveDataBinding()` | private | Thin dispatcher that routes to `resolveContentBinding()`, `resolveAttributeBinding()`, or `resolveAttributeDirectiveBinding()`. |
| `resolveContentBinding()` | private | Handles `{{expression}}` in text content. |
| `resolveAttributeBinding()` | private | Handles `{{expression}}` in HTML attributes; dispatches to `resolveEventBinding()` or `resolveAccessBinding()` based on aspect. |
| `resolveAttributeDirectiveBinding()` | private | Handles `f-children`, `f-slotted`, `f-ref` directives. |
| `resolveAccessBinding()` | private | Shared helper for access-type bindings (content, boolean-attribute fallback, default attribute). |
| `resolveEventBinding()` | private | Handles event bindings (`@event`), including arg parsing and owner resolution. |
| `resolveTemplateDirective()` | private | Handles `<f-when>` and `<f-repeat>` directives. |
| `resolveAttributeDirective()` | private | Creates FAST `children()`, `slotted()`, or `ref()` directives. |

### TemplateResolutionContext

The `TemplateResolutionContext` interface (internal to `TemplateParser`) groups the stable fields that flow through the recursive parsing pipeline:

```typescript
interface TemplateResolutionContext {
    parentContext: string | null;  // Current repeat item alias (e.g. "item")
    level: number;          // Nesting depth for repeat directives
    schema: Schema;         // JSON schema builder for property tracking
}
```

`rootPropertyName` is intentionally kept separate because it is selectively mutated per branch and must not leak across sibling binding resolutions.

### Key parsing functions (utilities.ts)

| Function | Role |
|---|---|
| `getNextBehavior(innerHTML)` | Top-level scanner: returns the next `DataBindingBehaviorConfig` or `TemplateDirectiveBehaviorConfig`, or `null` when done. |
| `getNextDataBindingBehavior(innerHTML)` | Identifies whether the next binding is `{{}}`, `{{{}}}`, or `{}` and classifies it as content/attribute/attributeDirective. |
| `getNextDirectiveBehavior(innerHTML)` | Finds the next `<f-when>` or `<f-repeat>` and its matching close tag. |
| `bindingResolver(...)` | Builds a `(x, c) => value` closure for a given path; also calls `schema.addPath()`. |
| `pathResolver(path, contextPath, level, schema)` | Returns a closure that traverses an object using dot-notation, handling repeat context levels. |
| `getBooleanBinding(...)` | Returns a `(x, c) => boolean` closure for `<f-when>` expressions. |
| `assignObservables(schema, rootSchema, data, target, rootProperty)` | Wraps objects/arrays in `Proxy` for deep observation. |
| `deepMerge(target, source)` | Merges source into an existing proxy, preserving proxy identity and triggering observable notifications. |
| `transformInnerHTML(html)` | Normalises HTML-encoded operator characters (`&gt;`, `&lt;`, etc.) used in `<f-when>` expressions. |
| `escapeBracesInCodeElements(html)` | Replaces `{` / `}` characters inside every `<code>` element with `&#123;` / `&#125;` so binding-like syntax in code samples renders literally rather than being interpreted as FAST bindings. Client-side half of a two-stage escape — the brace escape mirrors the server-side pass in `microsoft-fast-build` (necessary client-side because `&#123;` / `&#125;` decode back to literal `{` / `}` in the DOM and `.innerHTML` does not re-encode them). The angle-bracket escape for FAST directive tags (`<f-when>`, `</f-when>`, `<f-repeat>`, `</f-repeat>`) inside `<code>` runs only on the server because the DOM serializer re-encodes `<` / `>` in text content automatically. Real HTML elements (`<button>`) and custom elements inside `<code>` keep their angle brackets and continue to render as live DOM elements. Modeled on Microsoft WebUI's `webui-press` markdown renderer. |

### Binding classification

```
innerHTML token
  ├── {{{ ... }}}  → unescaped content binding  (innerHTML div)
  ├── {{ ... }}    → default binding
  │     ├── attr="{{expr}}"    → attribute binding   (aspect: null / ":" / "?")
  │     └── {{expr}} in text  → content binding
  └── { ... }      → client-side binding
        ├── @event="{handler(...)}"  → event binding (aspect "@")
        └── f-dir="{prop}"           → attribute directive binding
```

---

## Schema and Observer Map

The `Schema` class accumulates all binding paths discovered during parsing into an instance-level JSON Schema map (`schemaMap`) indexed by `rootPropertyName → JSONSchema`. Each `Schema` instance also registers itself in the module-level `schemaRegistry` (keyed by custom element name) for cross-element `$ref` resolution.

```mermaid
flowchart LR
    A["Template binding\nuser.details.age"] --> B[bindingResolver]
    B --> C[schema.addPath\ntype:'access'\npath:'user.details.age'\nrootProperty:'user']
    C --> D["schema.schemaMap\n{'user' => JSONSchema}"]
    C --> D2["schemaRegistry\n{'my-el' => schemaMap}"]
    D --> E[ObserverMap.defineProperties]
    E --> E1["applyConfigToSchema\nstamps $observe: false on excluded schema nodes"]
    E1 --> F[Observable.defineProperty on prototype\nfor 'user']
    E1 --> G[install instanceResolverChanged handler]
    G --> H["when user= is set:\nassignObservables checks schema.$observe\n→ Proxy wraps observed paths only\ndeep mutations → Observable.notify"]
```

For a deep dive into the schema structure, context tracking, and proxy system
see
[schema-observer-map.md](./schema-observer-map.md).

### `$observe` flag on schema nodes

When an `ObserverMapConfig` with a `properties` key is provided, `ObserverMap.defineProperties()` calls `applyConfigToSchema()` to stamp `$observe: false` on excluded schema nodes **before** the proxy system runs. This is a one-time pre-processing pass that walks the config and schema trees in parallel:

- `false` in the config → `$observe: false` is stamped recursively on the node and all its descendants.
- `$observe: false` on a config node → the schema node is stamped, and unlisted children inherit the stamp.
- `true` in the config → no stamp needed (observed is the default).
- Config paths not in the schema are silently ignored.

**Convention: stamp-only-when-excluding.** The `$observe` flag is only ever set to `false` — it is never explicitly set to `true`. Absence of `$observe` (i.e. `undefined`) means the node is observed. This means:

- When Observer Map is enabled without a `properties` tree, `applyConfigToSchema`
  is never called and no schema nodes are mutated — zero overhead for the
  common case.
- The proxy system uses `isSchemaExcluded(schema)` (checks `$observe === false` with no observed descendants) as the single predicate for all skip/suppress decisions.
- Schema nodes without `$observe` are always treated as observed.

### AttributeMap and leaf bindings

When `attributeMap()` is enabled with a declarative template, it registers a
definition schema transform. With a manually supplied definition schema, it runs
immediately. The extension constructs an `AttributeMap` implementation and calls
`defineProperties()`. It iterates `Schema.getRootProperties()` and skips any
property whose schema entry contains `properties`, `type`, or `anyOf` — keeping
only plain leaf bindings. For each leaf:

1. The schema key is used as the **JS property name**.
2. The **HTML attribute name** depends on the `attribute-name-strategy`:
   - `"camelCase"` (default): the attribute name is derived by converting the camelCase property name to kebab-case (e.g. `fooBar` → `foo-bar`).
   - `"none"`: the attribute name equals the property name (e.g. `foo-bar` → `foo-bar`).
3. A new `AttributeDefinition` is registered via `Observable.defineProperty`.
4. `FASTElementDefinition.attributeLookup` is keyed by the HTML attribute name and `propertyLookup` is keyed by the JS property name so `attributeChangedCallback` can route attribute changes to the correct property.

When using the `"none"` strategy, property names may contain dashes and must be
accessed via bracket notation (e.g. `element["foo-bar"]`). When using
`"camelCase"`, property names are standard JS identifiers (e.g.
`element.fooBar`).

Schema transforms run in deterministic order. When both extensions are supplied,
attribute mapping runs before observer mapping.

---

## Lifecycle

```mermaid
sequenceDiagram
    participant App as Application JS
    participant FER as FASTElementDefinition
    participant FTE as internal f-template
    participant EC as ElementController
    participant Hydration as enableHydration().whenHydrated()

    App->>Hydration: const hydration = enableHydration() [optional]
    App->>FER: MyElement.define({name:'my-el', template: declarativeTemplate()}, [attributeMap(), observerMap()])
    note over FER: definition composed; resolver waits for template

    DOM->>FTE: f-template connected to DOM
    FTE->>FTE: bridge matches registry + name
    FTE->>FTE: parse template → schema → transforms → ViewTemplate
    FTE->>FER: return viewTemplate to resolver
    FER->>FER: customElements.define('my-el', MyElement)

    DOM->>EC: element instance connects with existing shadow root
    EC->>EC: isPrerendered = true (existing shadow root detected)
    alt enableHydration() was called
        EC->>EC: template.hydrate() — maps existing DOM to binding targets
        EC->>Hydration: resolve active batch when all pending elements finish
    else hydration not enabled
        EC->>EC: client-side render; isHydrated = false
    end
```

### Promise readiness reference

| Promise | Import path | Resolves when |
|---|---|---|
| `enableHydration().whenHydrated("my-element")` | `@microsoft/fast-element/hydration.js` | Hydration work for that tag name completes. |
| `enableHydration().whenHydrated()` | `@microsoft/fast-element/hydration.js` | The active hydration batch completes. |

By default, hydration no-ops for later prerendered batches after the initial
batch completes. Set
`enableHydration({ stopHydration: StopHydration.never })` when Declarative Shadow
DOM may be streamed into the page after the initial hydration batch. In that
mode, `enableHydration().whenHydrated()` intentionally remains pending because
there is no global completion point.

For usage examples see
[lifecycle.md](./lifecycle.md).

---

## Integration with fast-element

The declarative runtime is a thin orchestration layer on top of
`@microsoft/fast-element`. It does not re-implement any reactive primitives; it
converts declarative HTML syntax into the same data structures that `html`
tagged templates produce.

| fast-element primitive | How the declarative runtime uses it |
|---|---|
| `FASTElement` | Base class for user components; the internal `<f-template>` publisher is a native `HTMLElement` |
| `FASTElementDefinition.register()` / template resolvers | Deferred element registration — element waits for its template |
| `FASTElementDefinition.schema` | Optional schema used by schema-driven extensions; assigned automatically by `declarativeTemplate()` and available for manual schemas |
| `FASTElementExtension` | Extension callback mechanism used by `attributeMap()` and `observerMap()` to attach schema transforms before template resolution or consume manually supplied schemas |
| `ViewTemplate.create(strings, values)` | Compiles the resolved strings/values arrays into a `ViewTemplate` |
| `ElementController` | Automatically detects prerendered content (`isPrerendered`) and hydrates server-rendered DOM using `fe-b` comment/dataset markers via `template.hydrate()` |
| `Observable.defineProperty()` | Defines observable root properties on element prototypes (ObserverMap) |
| `Observable.getNotifier()` | Triggers change notifications from proxy handlers |
| `when(expr, template)` | FAST directive used for `<f-when>` |
| `repeat(expr, template)` | FAST directive used for `<f-repeat>` |
| `slotted(options)` | FAST directive used for `f-slotted` |
| `children(prop)` | FAST directive used for `f-children` |
| `ref(prop)` | FAST directive used for `f-ref` |

### Deferred template attachment via define

Standard subclass `define()` calls return a `Promise` that resolves immediately when a concrete template is provided at definition time. When `template: declarativeTemplate()` is used, the `Promise` resolves after the matching `<f-template>` supplies a concrete template through the bridge. This unified API replaces the previous `defineAsync()` / `composeAsync()` methods.

---

## Hydration Model

When declarative templates are used, the server must render:

1. The custom element tag with its attributes and initial state.
2. A `<template shadowrootmode="open">` containing pre-rendered HTML annotated with FAST's hydration markers.
3. An `<f-template>` element somewhere in the page that carries the template definition.

With `declarativeTemplate()`, connection gating happens before platform registration: the resolver waits for the matching `<f-template>` and keeps the definition concrete before elements can connect. Hydration can therefore start immediately when `ElementController.connect()` runs. The `defer-hydration` and `needs-hydration` attributes are no longer needed in server-rendered markup.

### Hydration marker formats

`enableHydration()` uses the FAST Element 3.x data-free marker reader by
default. The marker strategy is shared by target discovery and nested repeat
hydration so a view uses one consistent format throughout its hydration walk.
The optional `markers_v2` strategy contains the legacy indexed-marker parsing logic and
is selected with `enableHydration({ markers: markers_v2 })`.

**Content bindings** use HTML comments (data-free, matched by string equality):

```


```

**Attribute bindings** use a single `data-fe` dataset attribute with binding count:

```html
<el data-fe="3">
```

**Repeat directives** wrap each item in comment pairs:
```

...item DOM...

```

For detailed examples see
[rendering.md](./rendering.md).

---

## Testing Architecture

Each feature is verified by a **Playwright** integration test against a live
Vite dev server. The `test/declarative/fixtures/` directory contains one
subdirectory per feature:

```
test/declarative/fixtures/<feature>/
├── <feature>.spec.ts        # Playwright test
├── entry.html               # Entry template with root custom elements
├── fast-build.config.json   # Build configuration for @microsoft/fast-build
├── index.html               # Pre-rendered page (GENERATED by scripts/declarative/build-fixtures.js — do not edit)
├── main.ts                  # Component definitions, declarativeTemplate(), extensions, and enableHydration() setup
├── state.json               # Initial state for server-side rendering
└── templates.html           # Declarative <f-template> definitions
```

Fixtures are auto-discovered by scanning for directories that contain `entry.html`, `templates.html`, `state.json`, and `fast-build.config.json`. Both the build script and the Vite config pick up new fixtures automatically — no registration step is needed.

For fixtures that use SSR-style pre-rendered HTML,
`scripts/declarative/build-fixtures.js` invokes `@microsoft/fast-build` with
`--config` pointing to each fixture's `fast-build.config.json` to generate
`index.html` from the configured source files.

### WebUI Integration Tests

A separate integration test suite validates that `@microsoft/webui` can build and render the same fixture templates that `@microsoft/fast-build` processes. This is split into two steps:

1. **Build** (`npm run build:fixtures:webui`) — runs
   `scripts/declarative/build-fixtures-with-webui.js`, which extracts
   `<f-template>` elements, converts each component template with
   `fast convert --syntax=webui-prerelease`, builds each fixture with
   `webui build --plugin=fast`, renders the protocol with `state.json`, and
   writes the output alongside `main.ts` and assets to
   `temp/integrations/webui/fixtures/`.
2. **Test** (`npm run test:webui-integration`) — builds the fixtures, then runs
   the same Playwright specs against the webui-rendered output served by a Vite
   dev server on port 5174 (configured in
   `playwright.declarative.webui.config.ts`).

Fixtures that intentionally contain invalid FAST declarative templates are skipped in
the WebUI build because `fast convert` validates and rejects them before WebUI
renders. Run locally with `npm run test:webui-integration` or via the
`ci-webui-integration.yml` GitHub Action on PRs and pushes to `main`.

#### Skipped tests

Some tests are conditionally skipped when running under the webui integration
config. The `playwright.declarative.webui.config.ts` file sets
`process.env.FAST_WEBUI_INTEGRATION = "true"`, and individual tests check this
variable with `test.skip()` to opt out of cases that exercise known differences
between `fast-build` and `webui` rendering:

- **`errors.spec.ts` — "throws an error when no template element is present"**: webui does not render `<f-template>` elements that lack a `<template>` child, so the expected error is never thrown.

### Hydration readiness

Fixtures that exercise prerendered output wait for hydration to complete before
running assertions. Each `main.ts` calls `enableHydration()` and then awaits
the returned controller's `whenHydrated()` promise to set a global flag, and each spec file calls
`page.waitForFunction()` after `page.goto()` to block until the flag is set.
See [test/declarative/fixtures/README.md](../../test/declarative/fixtures/README.md)
for the implementation pattern.

See
[test/declarative/fixtures/WRITING_FIXTURES.md](../../test/declarative/fixtures/WRITING_FIXTURES.md)
for the complete fixture authoring guide,
[test/declarative/fixtures/README.md](../../test/declarative/fixtures/README.md)
for a quick reference, and
[test/declarative/fixtures/extensions/observer-map-deep-merge/README.md](../../test/declarative/fixtures/extensions/observer-map-deep-merge/README.md)
for an example of a complex multi-feature fixture.

---

## Further Reading

| Document | Topic |
|---|---|
| [syntax.md](./syntax.md) | Installation, syntax reference, hydration promises, usage examples |
| [rendering.md](./rendering.md) | Hydratable HTML format: comment markers, dataset attributes, directive markers |
| [lifecycle.md](./lifecycle.md) | Phase-by-phase rendering lifecycle, hydration readiness, performance notes |
| [schema-observer-map.md](./schema-observer-map.md) | Deep dive into Schema JSON structure, ObserverMap proxy system, debugging |
| [test/declarative/fixtures/README.md](../../test/declarative/fixtures/README.md) | Quick reference for fixture structure |
| [test/declarative/fixtures/WRITING_FIXTURES.md](../../test/declarative/fixtures/WRITING_FIXTURES.md) | Complete guide to writing new Playwright fixture tests |
| [test/declarative/fixtures/extensions/observer-map-deep-merge/README.md](../../test/declarative/fixtures/extensions/observer-map-deep-merge/README.md) | Complex deep-merge fixture: observable arrays, nested repeats, conditionals |

---

### Packages Fast Element Docs Declarative Lifecycle (`packages/fast-element/docs/declarative/lifecycle.md`)

# Rendering Lifecycle

This document describes the declarative rendering lifecycle inside
`@microsoft/fast-element`.

## Overview

The FAST Element rendering lifecycle involves a coordinated process between the
core runtime and its declarative entrypoint:

- **`@microsoft/fast-element`**: Provides the core `FASTElement` base class and
  element definition system.
- **`@microsoft/fast-element/declarative.js`**: Provides the `f-template`
  custom element that processes HTML templates and attaches them to FAST
  elements as a `ViewTemplate` in lieu of an `html` template created during
  a subclass `define()` call. The preferred path uses `declarativeTemplate()` so
  the subclass `define()` call waits for the matching declarative template and keeps
  the definition concrete before registration completes.

## Lifecycle Phases

Given a DOM which includes an `f-template` and a component:

```html
<my-component text="Hello World">
    <template shadowrootmode="open">
        <h1>Hello World</h1>
    </template>
</my-component>

<f-template name="my-component">
    <template>
        <h1>{{text}}</h1>
    </template>
</f-template>
```

The following phases will then be kicked off once the JavaScript is parsed.

### Phase 1: Definition Resolution

Custom elements begin their lifecycle by composing a definition that points at
`declarativeTemplate()`. The resolver waits for a matching declarative template
and returns a concrete `ViewTemplate` before the platform registration step.

```typescript
// Custom element class definition
class MyComponent extends FASTElement {
    @attr text: string = "";
}

// Register with the declarative template bridge
MyComponent.define({
    name: "my-component",
    template: declarativeTemplate(),
});
```

Key characteristics of this phase:
- The element definition stays unresolved until a matching declarative template is available
- The resolved template is concrete before platform registration completes

### Phase 2: Declarative Template Bridge

`declarativeTemplate()` from `@microsoft/fast-element/declarative.js`
automatically ensures that `f-template` is defined in the same registry as the
FAST element being composed.

### Phase 3: Template Processing and Attachment

When an `f-template` element is connected to the DOM, it initiates the template attachment process.

The lifecycle flow during this phase:

1. **Template Discovery**: The resolver waits for a matching
   `<f-template name="...">` in the same registry as the element definition.
2. **Template Element Connection**: The matching `f-template` element's
   `connectedCallback()` registers it with the declarative template bridge.
3. **Template Processing**: The bridge reads and transforms the markup, builds
   the schema, applies `observerMap()` / `attributeMap()` behavior, and resolves
   data bindings, directives, and other template features into the `ViewTemplate`
   model which is also used by the `@microsoft/fast-element` `html` tag template.
4. **Template Attachment**: The concrete `ViewTemplate` is returned to
   the subclass `define()` call, which assigns it to the definition before platform
   registration completes.

### Phase 4: Composition Completion

Once the template is attached to the partial definition, the element completes its composition:

1. **`compose()` Execution**: The element definition internally completes its composition process
2. **Platform Registration**: The completed element definition is fully registered with the platform's custom element registry

### Phase 5: Element Instantiation and Hydration

When custom elements are instantiated in the DOM, the following occurs:

1. **Element Creation**: The platform creates instances of the custom element
2. **Prerendered Content Detection**: `ElementController` detects the existing shadow root from SSR — `isPrerendered` resolves `true`
3. **Hydration Check**: If `enableHydration()` was called and the template is hydratable, the element hydrates — `isHydrated` resolves `true`. Otherwise it falls back to client-side rendering.
4. **Concrete Template Ready**: Because `declarativeTemplate()` resolved during
   definition, `connect()` starts with the final template already attached.
5. **Hydration**: `ElementController` uses `template.hydrate()` to create a
   `HydrationView` that maps existing DOM nodes to binding targets using `fe:b`
   / `fe:/b` markers

The DOM after hydration should look like this:

```html
<my-component text="Hello World">
    <template shadowrootmode="open">
        <h1>Hello World</h1>
    </template>
</my-component>
```

## Key Integration Points

### Fast Element Registry

The `fastElementRegistry` serves as the central coordination point between the
two packages and is available to consumers from
`@microsoft/fast-element/registry.js`:

- Stores partial element definitions created by `define()`
- Provides lookup mechanism via `register()` for template attachment
- Resolves `fastElementRegistry.whenRegistered(tagName)` when a matching
  definition is registered
- Maintains the registry of all FAST element definitions

### Observable Pattern

Both packages use the Observable pattern for coordination:

- Element definition template assignment notifies observers that are waiting for a concrete template
- Template attachment triggers observable notifications to complete the lifecycle

## Error Handling

The lifecycle includes error handling for missing components:

- Template elements throw errors if no corresponding element definition is found
- Element definitions can exist without templates (partial state)

## Performance Considerations

The asynchronous nature of the lifecycle provides several performance benefits:

- **Progressive Enhancement**: Elements can be registered before templates are loaded
- **Code Splitting**: Templates can be loaded separately from element definitions  
- **Reduced Blocking**: Template processing doesn't block element registration
- **Hydration Optimization**: Server-side rendered content can be hydrated efficiently

This coordinated lifecycle enables powerful scenarios like server-side rendering, progressive enhancement, and dynamic template loading while maintaining the reactive capabilities of FAST Element.

## Hydration promise APIs

FAST Element exposes promises for hydration readiness points that are useful to
application code.

Hydration must be explicitly opted into by calling `enableHydration()`. Await
the returned controller's `whenHydrated()` promise when code needs to run after
the active hydration batch completes. Pass a tag name to `whenHydrated(tagName)`
when code needs to wait for a specific FAST element.

```typescript
import { enableHydration } from "@microsoft/fast-element/hydration.js";

const hydration = enableHydration();
await hydration.whenHydrated("my-component");
await hydration.whenHydrated();
```

By default, hydration no-ops for later prerendered batches after the initial
batch completes. Set `stopHydration: StopHydration.never` in
`enableHydration()` when streaming Declarative Shadow DOM should continue
hydrating after the initial batch. In that mode, `hydration.whenHydrated()`
intentionally remains pending because hydration has no global completion point.

---

### Packages Fast Element Docs Declarative Rendering (`packages/fast-element/docs/declarative/rendering.md`)

# Non-browser HTML rendering

1. [Initial State](#initial-state)
2. [Hydrating Comments and Datasets](#hydration-comments-and-datasets)

This document details information on rendering hydratable content and includes some pointers on how Dependency Injection can be used to create services that hydrate a custom elements state. Non-browser rendering in this context means producing HTML that a browser can parse and hydrate later; it does not mean running the FAST Element client runtime in a worker, server-side JavaScript runtime, or other non-window host.

## Initial State

To create initial state this should be added somewhere accessible by your service, in this example a `<script>` tag can be used to provide a global initial state.

Example:
```html
<script>
    window.__INITIAL_STATE__ = {
        text: "Hello world"
    }
</script>
```

Add a Dependency Injection service in your bundle to access properties in your state.

Simple example (`initial-state.ts`):
```typescript
import { DI } from "@microsoft/fast-element/di.js";

interface InitialState {
    text: string;
}

export interface IInitialStateService {
  init(): InitialState;
}

export class InitialStateService implements IInitialStateService {
    private initialState: any;

    constructor() {
        this.initialState = window.__INITIAL_STATE__;
    }

    public init(...keys: Array<string>): InitialState {
        const config: any = {};

        for (let key of keys) {
            config[key] = this.initialState[key];
        }

        return config;
    }
}

export const initialStateFactory = DI.createContext<IInitialStateService>(
  'i-initial-state-service',
  (x) => x.singleton(InitialStateService)
);
```

Include the DI service to your component.

Example:
```typescript
import { attr, FASTElement, Observable } from "@microsoft/fast-element";
import {
    initialStateFactory,
    InitialStateService,
    type IInitialStateService,
} from "./initial-state.js";
import { inject } from "@microsoft/fast-element/di.js";

export class MyComponent extends FASTElement {
    @inject(initialStateFactory) initialStateService!: InitialStateService;

    @attr
    text: string = "";

    service!: IInitialStateService;

    connectedCallback() {
        super.connectedCallback();

        this.loadItemFromInitialState();
    }

    loadItemFromInitialState(): void {
        const initialState = this.initialStateService.init(["text"]);

        this.text = initialState.text;
    }
}

MyComponent.define({
    name: "my-component",
    template: declarativeTemplate(),
});
```

When the element connects, `ElementController` automatically detects the
existing shadow root from SSR and sets `isPrerendered = true`.
`declarativeTemplate()` keeps the definition template concrete before
registration completes, so the element can hydrate the prerendered shadow root
immediately. The `defer-hydration` and `needs-hydration` attributes are no
longer needed.

## Hydration Comments and Datasets

When hydrating the HTML, FAST uses `ElementController` which detects an
existing shadow root (from SSR or declarative shadow DOM) and sets
`isPrerendered = true`. It then uses `template.hydrate()` to create a
`HydrationView` that maps existing DOM nodes to binding targets using hydration
"markers" such as comments and dataset attributes. By default the declarative
runtime in `@microsoft/fast-element` assumes component hydration will occur, so
rendering hydratable markup is required.

### Bindings

#### Content Bindings

Content binding markers are represented using HTML comments. These comments are used to indicate where dynamic content exists in the template. Markers carry no embedded data — they are fixed strings matched by string equality (not regex).

* Start binding: ``
* End binding: ``

Binding pairs are matched using balanced depth counting: each start marker increments a depth counter and each end marker decrements it. When the counter returns to zero the pair is complete.

##### Content Binding Marker Examples

**Note**
Examples shown below mostly skip the wrapping custom element and the internal template element with `shadowrootmode="open"`.

Typically along with the content from the examples below, the rendering should include:

```html
<my-component>
    <template shadowrootmode="open" shadowroot="open">
        
    </template>
</my-component>
```

**Simple content example**

Content bindings such as:
```html
<h1>{{text}}</h1>
```

When combined with state such as:
```json
{
    "text": "Hello world"
}
```

Should result in:
```html
<h1>Hello world</h1>
```

#### Attribute Bindings

Attribute bindings are tracked using a single dataset attribute: `data-fe="N"` where `N` is the number of attribute bindings on the element.

##### Examples

###### Single attribute example

Attribute binding such as:
```html
<h1 greeting="{{greeting}}"></h1>
```

When combined with state such as:
```json
{
    "greeting": "Hello"
}
```

Should result in:

```html
<h1 data-fe="1" greeting="Hello"></h1>
```

###### Multiple attribute bindings

When multiple attribute bindings exist on the same element:
```html
<h1 greeting="{{greeting}}" subtitle="{{subtitle}}" punctuation="{{punctuation}}"></h1>
```

When combined with state such as:
```json
{
    "greeting": "Hello",
    "subtitle": "world",
    "punctuation": "!"
}
```

Should result in:

```html
<h1 data-fe="3" greeting="Hello" subtitle="world" punctuation="!"></h1>
```

**Mixed attribute and content example**

Multiple attributes and content bindings such as:
```html
<div show="{{show}}" appearance="{{appearance}}" punctuation="{{punctuation}}">
    <h1>{{text}}</h1>
    <span>{{subtitle}}</span>
    <span>{{punctuation}}</span>
</div>
```

Should result in:
```html
<div data-fe="3" show appearance="large" punctuation="!">
    <h1>Hello</h1>
    <span>world</span>
    <span>!</span>
</div>
```

### Directives

Directives are treated differently from bindings as they include a template. This means that in addition to the binding used to determine the logic for the directive FAST also requires a separate marker for the directive itself to demarkate the beginning and end of the template.

#### Repeat

Example repeat binding:
```html
<f-repeat value="{{item in list}}">
    <span>{{item}}</span>
</f-repeat>
```

Combined with state:
```json
[
    "Bob",
    "Alice",
    "Sue"
]
```

Should result in:
```html


<span>
    Bob
</span>


<span>
    Alice
</span>


<span>
    Sue
</span>


```

Note that the repeat markers are data-free — they carry no index or ID. Pairing uses balanced depth counting. Additionally, a binding wraps the repeat markers; even if the array is empty, this binding must be rendered.

Example result of an empty array:
```html


```

#### When

The when directive is either present in the DOM or not, and therefore does not need an extra marker for the template.

Example when binding:
```html
<f-when value="{{show}}">
    <span>{{text}}</span>
</f-when>
```

Combined with state:
```json
{
    "show": true,
    "text": "Hello world"
}
```

Should result in:
```html

<span>
    Hello world
</span>

```

If the when is evaluated to `falsy` then we can safely leave the binding markers only.

Example state:
```json
{
    "show": false,
    "text": "Hello world"
}
```

Should result in:
```html


```

### Host attributes from `<f-template>`

Build-time renderers (e.g. `@microsoft/fast-build`) forward attributes declared on the inner `<template>` element of an `<f-template>` onto the rendered host element opening tag.

Example template:
```html
<f-template name="my-button">
    <template tabindex="0" ?disabled="{{isDisabled}}">
        <button><slot></slot></button>
    </template>
</f-template>
```

Combined with author HTML `<my-button></my-button>` and state:
```json
{
    "isDisabled": true
}
```

Should result in:
```html
<my-button tabindex="0" disabled defer-hydration needs-hydration>
    <template shadowrootmode="open" shadowroot="open">
        <button><slot></slot></button>
    </template>
</my-button>
```

Rules:
- Client-only attributes (`@event`, `:prop`, `f-ref`, `f-slotted`, `f-children`) are skipped — they have no meaning on a server-rendered host element.
- Author attributes on the host element always win on conflicts (case-insensitive name match; the dedupe key for `?name="{{expr}}"` is the bare `name`).
- Static `name="value"` is forwarded verbatim (HTML-escaped); static boolean `name` is emitted bare.
- `name="{{expr}}"` is resolved against the element's initial child state; primitives are emitted as `name="value"`, `Array` / `Object` / `Null` and missing values are stripped.
- `?name="{{expr}}"` is evaluated as a boolean against the same state; the bare `name` (without `?`) is emitted when truthy and skipped when falsy.

### Client Side Bindings

Client side bindings are bindings which the client needs, but they are not necessary as part of an initial render. These must still be accounted for when creating hydration comments however, as the template needs to know which elements to attach these bindings to. There are two types of client side bindings, events and attribute directives. These do not require state as they are bound to class methods or properties.

#### Event Bindings

Event bindings such as `@keydown` and `@click` can be represented with hydration comments.

Example event binding:
```html
<button @click="{handleClick($e)}">Button</button>
```

Should result in:
```html
<button data-fe="1">Button</button>
```

#### Attribute Directives

Attribute directives such as `f-slotted` and `f-ref` can be represented with hydration comments.

Example `f-ref` binding:
```html
<button f-ref="{button}">Button</button>
```

Should result in:
```html
<button data-fe="1">Button</button>
```

#### More Examples

##### Nested Whens

Example when binding:
```html
<f-when value="{{show}}">
    <span>{{text}}</span>
    <f-when value="{{showInternal}}">
        <span>{{internalText}}</span>
    </f-when>
</f-when>
```

Combined with state:
```json
{
    "show": true,
    "text": "Hello world",
    "showInternal": true,
    "internalText": "Hello pluto"
}
```

Should result in:
```html

<span>
    Hello world
</span>
    
    <span>
        Hello pluto
    </span>
    

```

##### Nested Repeats

Example when binding:
```html
<f-repeat value="{{item in items}}">
    <div>
        <span>{{item.name}}</span>
        <f-when value="{{!!item.nested}}">
            <ul>
                <f-repeat value="{{person in item.nested}}">
                    <li>{{person.name}}</li>
                </f-repeat>
            </ul>
        </f-when>
    </div>
</f-repeat>
```

Combined with state:
```json
{
    "items": [
        {
            "name": "Bob"
        },
        {
            "name": "Alice"
        },
        {
            "name": "Sue",
            "nested": [
                {
                    "name": "Amy"
                },
                {
                    "name": "Clarice"
                },
                {
                    "name": "Lawrence"
                }
            ]
        }
    ]
}
```

Should result in:
```html

    
    <div>
        <span>Bob</span>
        
    </div>
    
    <div>
        <span>Alice</span>
        
    </div>
    
    <div>
        <span>Sue</span>
        
            <ul>
                
                
                <li>
                    Amy
                </li>
                
                
                <li>
                    Clarice
                </li>
                
                
                <li>
                    Lawrence
                </li>
                
                
            </ul>
        
    </div>
    

```

##### Nested components with `<slot>`

This example shows the wrapping custom element tag as well as the template component with `shadowrootmode="open"` for the sake of illustrating an example that would exist in the DOM.

Example template of component "nested-component":
```html
<f-when value="{{showButton}}">
    <my-button appearance="{{appearance}}">{{text}}</my-button>
</f-when>
```

Example template of component "my-button":
```html
<button class="{{appearance}}">
    <slot></slot>
</button>
```

Combined with state:
```json
{
    "showButton": true,
    "text": "Hello world",
    "appearance": "fancy"
}
```

Should result in:
```html
<nested-components>
    <template shadowrootmode="open" shadowroot="open">
        
        <my-button data-fe="1" appearance="fancy">
            <template shadowrootmode="open" shadowroot="open">
                <button class="default" data-fe="1">
                    <slot></slot>
                </button>
            </template>
            Hello world
        </my-button>
        
    </template>
</nested-components>
```

## Rendering Lifecycle

For information about the declarative rendering lifecycle inside
`@microsoft/fast-element`, see
[lifecycle.md](./lifecycle.md).

---

### Packages Fast Element Docs Declarative Schema Observer Map (`packages/fast-element/docs/declarative/schema-observer-map.md`)

# Schema and Observer Map Architecture

This document provides a technical explainer for how the `Schema` and
`ObserverMap` classes work together to describe data objects and automatically
observe them in FAST elements. Declarative `<f-template>` markup creates schemas
automatically, but the schema and observer map implementation are factored so
they can also be used without declarative templating.

## Table of Contents

1. [Overview](#overview)
2. [The Schema Class](#the-schema-class)
3. [The Observer Map Class](#the-observer-map-class)
4. [Integration with f-template](#integration-with-f-template)
5. [Initial Path Processing Flow](#initial-path-processing-flow)
6. [Dynamic Path Processing Updates](#dynamic-path-processing-updates)
7. [Observable Proxy System](#observable-proxy-system)
8. [Examples](#examples)
9. [Technical Details](#technical-details)

## Overview

The Schema and Observer Map architecture enables automatic observation of complex nested data objects in FAST HTML templates. This system solves the problem of manually tracking all the binding paths used in declarative HTML templates, automatically creating observables for nested properties that are referenced in the template bindings.

**Important**: This system is designed specifically for observable data objects (objects, arrays, and primitives). It explicitly does not handle binding paths that are assumed to be functions, methods, or other non-data constructs like event handlers.

### Key Components

- **Schema Class**: Generates JSON schemas that describe the structure and binding paths of data objects based on template analysis or manually registered paths
- **Observer Map Class**: Uses the schema information to automatically define observable properties and create proxies for nested object observation
- **f-template Integration**: Template processing automatically populates schemas and configures observer maps during template compilation
- **Map helpers**: `@microsoft/fast-element` exposes the map helpers independently from declarative templating

### Supported Data Types

The system automatically handles:
- **Objects**: Nested object structures with observable properties
- **Arrays**: Arrays with observable mutations and nested object elements  
- **Primitives**: String, number, boolean values as object properties

### Explicitly Not Handled

The system does not process:
- **Function bindings**: Event handlers and method calls like `@click="{handleClick()}"`
- **Context paths**: Bindings using the `$c` prefix (e.g., `$c.parent.showNames`) resolve directly from the `ExecutionContext` and are not part of the data model
- **Computed expressions**: Complex expressions that evaluate to non-data values
- **Non-observable constructs**: Any binding assumed to reference functions or non-data objects

## The Schema Class

The `Schema` class is responsible for building JSON Schema definitions that map the structure of data objects used in template bindings. It analyzes binding paths from template processing and constructs schemas that describe:

- Root properties and their nested structures
- Array contexts for repeat operations
- Object property relationships
- Cross-references to child components

**Important**: Each schema created corresponds to a property that will belong to the custom element's class. The schema describes the expected structure and relationships of data that will be assigned to that property, enabling automatic observation of nested objects and arrays within that property's data structure.

### Core Methods

#### Constructor
```typescript
constructor(name: string)
```
Creates a new schema instance for a specific custom element name and initializes an instance-level `schemaMap`. The instance also registers itself in the module-level `schemaRegistry` for cross-element `$ref` resolution. `FASTElementDefinition.schema` is optional; declarative templates assign it after parsing, while manual schema users can pass one in the element definition or directly to `observerMap({ schema })`.

#### addPath
```typescript
public addPath(config: RegisterPathConfig)
```
Registers a binding path discovered during template processing. The configuration includes:
- `pathConfig`: Describes the path type (`access`, `default`, `repeat`, `event`)
- `rootPropertyName`: The root property this path belongs to
- `childrenMap`: Information about child components referenced in this path

**Note**: Only `access`, `default`, and `repeat` path types result in schema entries. Event paths are identified but not processed since they represent function calls rather than observable data.

#### getSchema
```typescript
public getSchema(rootPropertyName: string): JSONSchema | null
```
Retrieves the JSON schema for a specific root property.

### Path Types

The schema handles different types of binding paths:

- **`access`/`default`**: Direct property access like `{{user.name}}`
- **`repeat`**: Array iteration contexts like `{{item}}` within `<f-repeat>`
- **`event`**: Event handler bindings like `@click="{handleClick()}"` - **Note: These are explicitly not processed by the schema system as they are assumed to be functions rather than observable data objects**

### Schema Structure

Generated schemas follow JSON Schema format with FAST-specific extensions:

```typescript
{
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "$id": "https://fast.design/schemas/my-element/users.json",
  "type": "array",
  "$ref": "#/$defs/user",
  "$defs": {
    "user": {
      "$fast_context": "users",
      "$fast_parent_contexts": [null],
      "type": "object",
      "properties": {
        "name": {},
        "details": {
          "type": "object", 
          "properties": {
            "age": {}
          }
        }
      }
    }
  }
}
```

**Note on Property Types**: Properties accessed through binding paths (like `name` and `age` above) are defined with empty objects `{}` rather than specific JSON Schema types. This is because it's not possible to determine the exact primitive type (string, number, boolean, etc.) from the path syntax alone. The system focuses on structural relationships rather than specific data types for leaf properties.

## The Observer Map Class

The `ObserverMap` class uses schema information to automatically configure observable properties on custom element prototypes. It creates the infrastructure needed to observe nested object changes without manual setup.

### Constructor
```typescript
constructor(classPrototype: any, schema: Schema, config?: ObserverMapConfig)
```
Creates an observer map instance that will configure the provided class prototype using the schema information.

### defineProperties
```typescript
public defineProperties(): void
```
The main method that:
1. Iterates through all root properties defined in the schema (each schema instance contains multiple root property schemas)
2. Defines observable properties using FAST Element's `Observable.defineProperty` (an alternative to the `@observable` decorator syntax used in custom element classes)
3. Sets up property change handlers that create proxies for nested objects

### Property Change Handling

When a root property transitions from `undefined` to a defined value, the observer map:
1. Analyzes the schema to understand the expected object structure
2. Creates proxies using the `assignObservables` utility function
3. Establishes deep observation of nested properties based on the schema of that root property

## Integration with f-template and manual schemas

The Schema and Observer Map classes integrate seamlessly with the f-template system, but they are not tied to it:

### Template Processing Flow

1. **Template Parsing**: When an `f-template` element is processed, it creates a `Schema` instance
2. **Binding Discovery**: As template bindings are processed, paths are registered with `schema.addPath()`
3. **Observer Map Creation**: If enabled, an `ObserverMap` is instantiated with the populated schema
4. **Property Definition**: The observer map defines observable properties on the custom element prototype

### Configuration

Observer Map functionality is enabled through the `observerMap()` definition
extension exported from `@microsoft/fast-element/observer-map.js`:

```typescript
import { declarativeTemplate } from "@microsoft/fast-element/declarative.js";
import { observerMap } from "@microsoft/fast-element/observer-map.js";

MyElement.define(
  {
    name: "my-custom-element",
    template: declarativeTemplate(),
  },
  [observerMap()]
);
```

When the `properties` key is omitted, all root properties discovered in the
template are observed. Add a `properties` object to opt into selective
observation behavior.

For non-declarative/manual schema use, pass the schema in the observer map
configuration:

```typescript
import { FASTElement, Schema } from "@microsoft/fast-element";
import { observerMap } from "@microsoft/fast-element/observer-map.js";

class MyElement extends FASTElement {}

const schema = new Schema("my-custom-element");
schema.addPath({
  rootPropertyName: "user",
  pathConfig: {
    type: "default",
    parentContext: null,
    currentContext: null,
    path: "user.name",
  },
  childrenMap: null,
});

MyElement.define(
  {
    name: "my-custom-element",
  },
  [observerMap({ schema })]
);
```

You can also attach a manual schema to the FAST element definition. This is the
path used automatically by `declarativeTemplate()` after it parses a template:

```typescript
MyElement.define(
  {
    name: "my-custom-element",
    schema,
  },
  [observerMap()]
);
```

## Initial Path Processing Flow

Here's how binding paths flow through the system during initial template processing:

1. **Template Binding**: `{{user.details.personal.name}}`
2. **Path Analysis**: Utilities identify root property (`user`) and nested path (`details.personal.name`)
3. **Type Check**: Confirms this is a data binding (not an event handler like `@click="{handleClick()}"`)
4. **Schema Registration**: 
   ```typescript
   schema.addPath({
     pathConfig: {
       type: "access",
       currentContext: null,
       parentContext: null,
       path: "user.details.personal.name"
     },
     rootPropertyName: "user",
     childrenMap: null
   });
   ```
5. **Schema Building**: Creates nested object structure in JSON schema
6. **Observable Definition**: Observer map makes `user` property observable
7. **Proxy Creation**: When `user` is assigned, proxies are created for deep observation

### Event Handler and Context Path Exclusion

Event handlers are identified but explicitly excluded from schema processing:
- **Template Binding**: `@click="{handleClick()}"`
- **Path Analysis**: Utilities identify this as an event handler
- **Type Check**: Confirms this is type `"event"`
- **Schema Registration**: **Skipped** - Event handlers are not added to schemas since they represent function calls

Context paths (`$c` prefix) are also excluded from schema processing:
- **Template Binding**: `{{$c.parent.showNames}}` or `@click="{$c.parent.handleClick($c.event)}"`
- **Path Analysis**: Utilities detect the `$c.` prefix
- **Schema Registration**: **Skipped** - These paths resolve from the `ExecutionContext`, not from observable data properties

## Dynamic Path Processing Updates

After initial schema creation and observer map setup, the system continues to dynamically update observation as data structures evolve:

### Runtime Object Assignment

When nested objects or array items become defined after initial setup:

1. **Property Assignment**: A previously undefined nested property gets assigned a value
   ```typescript
   // Initially: user.details was undefined
   user.details = { age: 30, location: { city: "Seattle" } };
   ```

2. **Schema Consultation**: The system consults the existing schema for this root property to understand expected nested structure

3. **Proxy Creation**: New proxies are automatically created for the newly assigned nested objects based on the schema definition

4. **Deep Observation Extension**: Observation is extended to all nested properties defined in the schema

### Array Item Addition

When new items are added to observed arrays:

1. **Array Mutation**: Items are added via push, splice, or direct assignment
   ```typescript
   users.push({ name: "John", details: { age: 25 } });
   ```

2. **Array Observer Trigger**: The array proxy detects the mutation and triggers observation setup

3. **Item Processing**: Each new array item is processed according to the array's context schema definition

4. **Nested Object Proxying**: New nested objects within array items are automatically proxied based on the schema structure

## Observable Proxy System

The proxy system in `utilities.ts` provides the deep observation capabilities:

### assignObservables Function

```typescript
export function assignObservables(
    schema: JSONSchema | JSONSchemaDefinition,
    rootSchema: JSONSchema,
    data: any,
    target: any,
    rootProperty: string
): typeof Proxy
```

This function:
- Analyzes the data type (object, array, primitive)
- Creates proxies for objects and arrays
- Establishes property observation for nested structures
- Handles array mutations and object property changes

### Proxy Behavior

Proxied objects:
- Trigger Observable notifications when properties change
- Automatically proxy newly assigned nested objects
- Track array mutations and splice operations
- Maintain references to root properties for change notifications

## Examples

### Basic Object Observation

**Template:**
```html
<f-template name="user-profile">
  <template>
    <div>{{user.name}} - {{user.details.age}} years old</div>
    <div>Location: {{user.details.location.city}}</div>
  </template>
</f-template>
```

**Generated Schema Structure:**
```typescript
// Root property: "user"
{
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "$id": "https://fast.design/schemas/user-profile/user.json",
  "type": "object",
  "properties": {
    "name": {},
    "details": {
      "type": "object",
      "properties": {
        "age": {},
        "location": {
          "type": "object",
          "properties": {
            "city": {}
          }
        }
      }
    }
  }
}
```

### Array with Repeat Context

**Template:**
```html
<f-template name="user-list">
  <template>
    <f-repeat value="{{user in users}}">
      <div>{{user.name}} has {{user.posts.length}} posts</div>
    </f-repeat>
  </template>
</f-template>
```

**Generated Schema Structure:**
```typescript
// Root property: "users"
{
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "$id": "https://fast.design/schemas/user-list/users.json",
  "type": "array",
  "$ref": "#/$defs/user",
  "$defs": {
    "user": {
      "$fast_context": "users",
      "$fast_parent_contexts": [null],
      "type": "object",
      "properties": {
        "name": {},
        "posts": {
          "type": "array"
        }
      }
    }
  }
}
```

### Nested Repeat Contexts

**Template:**
```html
<f-template name="complex-data">
  <template>
    <f-repeat value="{{user in users}}">
      <div>{{user.name}}</div>
      <f-repeat value="{{post in user.posts}}">
        <div>{{post.title}} - {{post.metadata.views}} views</div>
      </f-repeat>
    </f-repeat>
  </template>
</f-template>
```

This creates nested context definitions where the `post` context understands its relationship to the parent `user` context.

## Technical Details

### Schema Registry

The `Schema` module exports a module-level `schemaRegistry`:
```typescript
export const schemaRegistry: CachedPathMap = new Map();
```

Each `Schema` instance owns an instance-level `schemaMap: Map<string, JSONSchema>` and registers itself in `schemaRegistry` on construction.

The registry structure is: `Map<customElementName, Map<rootPropertyName, JSONSchema>>`

**Rationale for Module-level Registry**: The registry allows cross-element `$ref` resolution for nested components inside f-templates. When an object or array is passed to another custom element within an f-template, that nested component needs to observe the entire root property's structure based on the binding paths within that nested component. The registry allows all components to access and contribute to the same schema definitions, ensuring consistent observation behavior across component boundaries.

### Context Tracking

The schema system tracks binding contexts using special metadata:
- `$fast_context`: The array property name that created this context
- `$fast_parent_contexts`: Chain of parent contexts leading to the root

### Performance Considerations

- **Lazy Proxy Creation**: Proxies are only created when objects are assigned to observable properties
- **Weak Map Caching**: The system uses WeakMaps to avoid memory leaks when tracking proxied objects
- **Schema Reuse**: Schemas are generated once per custom element and reused across instances

### Memory Management

- **WeakMap Usage**: `objectTargetsMap` and `observedArraysMap` use WeakMaps to automatically clean up references
- **Proxy Identification**: Proxies are marked with `$isProxy` to prevent double-proxying
- **Reference Tracking**: Target elements and root properties are tracked for proper change notification

## Debugging and Troubleshooting

### Schema Inspection

You can inspect generated schemas using the module-level `schemaRegistry` import:

```typescript
import { schemaRegistry } from "@microsoft/fast-element";

// Get all schemas for an element:
const elementSchemas = schemaRegistry.get('my-element');
const userSchema = elementSchemas?.get('users');
console.log(JSON.stringify(userSchema, null, 2));
```

### Observer Map Status

`observerMap()` is applied as a definition extension before the element is
registered. There is no public `TemplateElement.options()` state to inspect.
To verify that observer mapping ran, inspect the generated schema and the
observable accessors on the element prototype:

```typescript
import { Observable, schemaRegistry } from "@microsoft/fast-element";

const schemas = schemaRegistry.get("my-element");
const accessors = Observable.getAccessors(MyElement.prototype).map(a => a.name);
console.log(schemas, accessors);
```

### Proxy Detection

Objects processed by the system will have a `$isProxy` property:
```typescript
console.log('Is proxied:', myObject.$isProxy === true);
```

---

### Packages Fast Element Docs Declarative Syntax (`packages/fast-element/docs/declarative/syntax.md`)

# FAST Element Declarative HTML

[](https://opensource.org/licenses/MIT)
[](https://badge.fury.io/js/%40microsoft%2Ffast-element)

The declarative entrypoint in `@microsoft/fast-element` interprets FAST
declarative HTML syntax as a template for a FAST web component.

This document focuses on declarative-runtime implementation details:
template structure, prerendered markup requirements, hydration promise APIs,
binding configuration, syntax, and integration testing.

For package installation, using `declarativeTemplate()`, extension setup, and
the package-level hydration overview, see the
[FAST Element README](../../README.md#declarative-html) and
[Prerendered Content Optimization](../../README.md#prerendered-content-optimization).
For user-facing guides covering f-template syntax, element definition, and
server-side rendering, see the
[Declarative HTML docs](https://fast.design/docs/3.x/declarative-templates/overview/).

## Template Structure

After importing the declarative APIs as shown in the README, templates are
associated with an element through
`<f-template name="[custom-element-name]"><template>...</template></f-template>`.
The host custom element should be defined with
`template: declarativeTemplate()`. This automatically defines `<f-template>` in
the relevant registry and waits for the matching declarative template when it is
already present or inserted later.

The `@microsoft/fast-element` entrypoint itself remains
side-effect free at import time. Declarative APIs lazily install declarative
debug messages when they create templates. Hydratable `ViewTemplate` support is
installed only when `enableHydration()` is called from
`@microsoft/fast-element/hydration.js`.

`observerMap()` and `attributeMap()` are available from
`@microsoft/fast-element/observer-map.js` and
`@microsoft/fast-element/attribute-map.js`, including when using the maps
without declarative templates.

Example:
```html
<my-custom-element greeting="Hello world">
    <template shadowrootmode="open">
        Hello world
    </template>
</my-custom-element>
<f-template name="my-custom-element">
    <template>{{greeting}}</template>
</f-template>
```

The legacy `defer-hydration` and `needs-hydration` attributes are no longer
required.

## HTML Comments

Bindings and FAST directive markup inside HTML comments are unsupported. This
includes double-brace and triple-brace bindings, client-only bindings, and
commented-out elements containing bindings or directives.

The declarative parsers scan template strings and do not reliably exclude
comments. A comment such as `` can still contribute a binding,
leading to unexpected evaluation, rendering errors, or hydration mismatches.
Remove unused bound markup rather than commenting it out, and keep explanatory
comments free of binding syntax and FAST directive tags.

## Non-browser HTML Rendering

One of the benefits of FAST declarative HTML templates is that the server can
be stack agnostic because JavaScript does not need to be interpreted to emit
the initial HTML. This does not mean the FAST Element client runtime runs on the
server: custom element definition, hydration, client rendering, and reactive
updates still run in the browser `Window`. The declarative runtime expects
hydratable comment markers and datasets when prerendered content is generated.
For the required marker format and initial-state application details, see
[rendering.md](./rendering.md).

## Hydration promise APIs

FAST Element's declarative APIs expose hydration readiness promises that are
useful to application code.

Hydration is opt-in. Call `enableHydration()` before FAST elements connect when
you want prerendered Declarative Shadow DOM to be reused, then await
the returned controller's `whenHydrated()` promise when code needs to run after
the active hydration batch:

```typescript
import { enableHydration } from "@microsoft/fast-element/hydration.js";

const hydration = enableHydration();
await hydration.whenHydrated();
```

The hydration hook no-ops for new prerendered elements after the initial
hydration batch completes by default. Streaming scenarios that append hydratable
Declarative Shadow DOM later can keep the hook active:

```typescript
import { enableHydration, StopHydration } from "@microsoft/fast-element/hydration.js";

enableHydration({
    stopHydration: StopHydration.never,
});
```

When `StopHydration.never` is used, `enableHydration().whenHydrated()`
intentionally remains pending because hydration has no global completion point.

FAST Element 3.x data-free hydration markers are selected by default. Existing
server output that uses FAST Element 2.x indexed markers can be hydrated by
selecting the v2 marker reader:

```typescript
import { enableHydration, markers_v2 } from "@microsoft/fast-element/hydration.js";

enableHydration({ markers: markers_v2 });
```

Set `"markers_v2": true` in the matching `@microsoft/fast-build`
configuration so the generated HTML uses the same marker format.

## `observerMap`

When the `observerMap()` extension is applied to an element definition,
it automatically sets up deep reactive observation for root properties
discovered in the template. Declarative templates assign `definition.schema`
during template resolution, so `observerMap()` has schema data automatically.
For non-declarative/manual schemas, import from
`@microsoft/fast-element/observer-map.js` and pass `observerMap({ schema })`.

```typescript
import { observerMap } from "@microsoft/fast-element/observer-map.js";
```

For finer control, pass a configuration object with a `properties` key that maps root property names to a recursive path tree:

```typescript
UserProfile.define(
    {
        name: "user-profile",
        template: declarativeTemplate(),
    },
    [
        observerMap({
            properties: {
                user: {
                    name: true,          // user.name — observed
                    details: {
                        age: true,       // user.details.age — observed
                        history: false,  // user.details.history — NOT observed
                    },
                },
                // root properties not listed here are skipped
            },
        }),
    ],
);
```

Each path entry can be:
- **`true`** — observe this path and all descendants.
- **`false`** — skip this path and all descendants.
- **An object** with an optional `$observe` boolean and child property overrides.

Use `$observe: false` on a node to skip it by default, then re-include specific children:

```typescript
observerMap({
    properties: {
        analytics: {
            charts: {
                $observe: false,       // charts NOT observed by default
                activeChart: true,     // ...except activeChart IS observed
            },
        },
    },
});
```

When `properties` is omitted, all root properties are observed. When
`properties` is present but empty (`{ properties: {} }`), no root properties
are observed.

When observer-map data is updated with `deepMerge`, array properties are replaced
rather than updated in place. This avoids synchronous reentrant array work and
allows repeat bindings to observe the new array reference. Replacement arrays
are processed through observerMap so nested item properties and subsequent array
mutations remain observable.

Manual schema example:

```typescript
import { FASTElement, Schema } from "@microsoft/fast-element";
import { observerMap } from "@microsoft/fast-element/observer-map.js";

class MyElement extends FASTElement {}

const schema = new Schema("my-element");
schema.addPath({
    rootPropertyName: "user",
    pathConfig: {
        type: "default",
        parentContext: null,
        currentContext: null,
        path: "user.name",
    },
    childrenMap: null,
});

MyElement.define({ name: "my-element" }, [observerMap({ schema })]);
```

## `attributeMap`

When the `attributeMap()` extension is applied to an element definition,
it automatically creates reactive `@attr` properties for every **leaf binding**
in the template — simple expressions like `{{foo}}` or `id="{{fooBar}}"` that
have no nested properties. Declarative templates provide the schema
automatically. For non-declarative/manual schemas, place the optional `schema`
on the FAST element definition and import `attributeMap()` from
`@microsoft/fast-element`.

```typescript
import { attributeMap } from "@microsoft/fast-element/attribute-map.js";
```

By default, the binding key is treated as a camelCase property name and the HTML
attribute name is derived by converting it to kebab-case. Properties already
decorated with `@attr` or `@observable` on the class are left untouched.

```typescript
MyElement.define(
    {
        name: "my-element",
        template: declarativeTemplate(),
    },
    [attributeMap()],
);
```

With the template:

```html
<f-template name="my-element">
    <template>
        <p>{{greeting}}</p>
        <p>{{firstName}}</p>
    </template>
</f-template>
```

This registers `greeting` (attribute `greeting`, property `greeting`) and
`firstName` (attribute `first-name`, property `firstName`) as `@attr`
properties on the element prototype, enabling `setAttribute("first-name",
"Jane")` to trigger a template re-render automatically.

### `attribute-name-strategy`

The `attribute-name-strategy` configuration option controls how template binding
keys map to HTML attribute names. This matches the build-time
`--attribute-name-strategy` option in `@microsoft/fast-build`.

| Strategy | Behaviour | Example |
|---|---|---|
| `"camelCase"` (default) | Binding key is the camelCase property; attribute name is derived as kebab-case | `{{fooBar}}` → property `fooBar`, attribute `foo-bar` |
| `"none"` | Binding key used as-is for both property and attribute | `{{foo-bar}}` → property `foo-bar`, attribute `foo-bar` |

```typescript
MyElement.define(
    {
        name: "my-element",
        template: declarativeTemplate(),
    },
    [
        attributeMap({
            "attribute-name-strategy": "none",
        }),
    ],
);
```

When using the `"none"` strategy, property names may contain dashes and must be
accessed via bracket notation (e.g. `element["foo-bar"]`).

## Syntax

All bindings use a handlebars-like syntax.

Some bindings are only relevant to the browser, such as for click handlers or other pieces of dynamic interaction. As such, their bindings use single curly braces `{}`, this is to prevent an intial SSR (Server Side Rendering) or other build time rendering technologies from needing to interpret them.

If a binding is relevant to both client and the back end rendering engine, it will use `{{}}` or `{{{}}}` depending on what type of data injection is being done.

Browser-only bindings:
- Event bindings
- Attribute directives

### Content binding

```html
{{text}}
```

### Event binding

Event bindings must include the `()` as well as being preceeded by `@` in keeping with the `@microsoft/fast-element` tagged template syntax.

```html
<button @click="{handleClick()}"></button>
```

You can pass the DOM event object, the execution context, or both as arguments. Any other argument is treated as a binding expression and resolved against the current data source.

**`$e` — DOM event object (preferred):**
```html
<button @click="{handleClick($e)}"></button>
```

**`$c` — execution context:**
```html
<button @click="{handleClick($c)}"></button>
```

**`$c.somePath` — a property of the execution context (e.g. `$c.parent`, `$c.event`):**
```html
<button @click="{handleClick($c.parent)}"></button>
```

**Multiple arguments:**
```html
<button @click="{handleClick($e, $c)}"></button>
```

**Arbitrary binding expressions** — any token that is not `$e` or `$c` is resolved as a binding path on the data source:
```html
<button @click="{handleClick(user.id)}"></button>
```

Use `$e` for the DOM event object.

### Directives

Directives are assumed to be either an attribute directive or a directive that also serves a template. Both are prepended by `f-`. The logic of these directives and what their use cases are is explained in the [FAST html documentation](https://fast.design/docs/getting-started/html-directives).

Attribute directives are part of [client side binding](#syntax) and therefore use the `{}` syntax.

Attribute directives include:
- **slotted**

    Example:
    ```html
    <slot f-slotted="{slottedNodes}"></slot>
    <slot f-slotted="{slottedNodes filter elements()}"></slot>
    <slot f-slotted="{slottedNodes filter elements(div, p)}"></slot>
    ```

- **children**

    Example:
    ```html
    <ul f-children="{listItems}"><f-repeat value="{{item in list}}"><li>{{item}}</li></f-repeat></ul>
    <ul f-children="{listItems filter elements()}"><f-repeat value="{{item in list}}"><li>{{item}}</li></f-repeat></ul>
    <ul f-children="{listItems filter elements(li)}"><f-repeat value="{{item in list}}"><li>{{item}}</li></f-repeat></ul>
    ```

- **ref**

    Example:
    ```html
    <video f-ref="{video}"></video>
    ```

Template directives include:
- **when**

    Example:
    ```html
    <f-when value="{{show}}">Hello world</f-when>
    <f-when value="{{!show}}">Goodbye world</f-when>
    ```

The following operators can also be used:
- `==`
- `!=`
- `>=`
- `>`
- `<=`
- `<`
- `||`
- `&&`

Where the right operand can be either a reference to a value (string e.g. `{{foo == 'bar'}}`, boolean e.g. `{{foo == true}}`, number e.g. `{{foo == 3}}`) or another binding value.

- **repeat**

    Example:
    ```html
    <ul><f-repeat value="{{item in list}}"><li>{{item}}</li></f-repeat></ul>
    ```

    Bindings inside `<f-repeat>` without a context prefix resolve to the custom element. For example, `{{title}}` below resolves to the host element's `title` property:

    ```html
    <ul><f-repeat value="{{item in list}}"><li>{{item}} - {{title}}</li></f-repeat></ul>
    ```

### Execution Context Access

In imperative fast-element templates, every binding expression receives both the data source and the execution context: `${(x, c) => c.parent.handleClick(c.event)}`. Declarative `<f-template>` expressions can access the same execution context using the `$c` prefix.

This is particularly useful inside `<f-repeat>`, where `$c.parent` refers to the parent view-model (typically the host element) and `$c.event` provides the DOM event.

Event handler with context access:

```html
<f-repeat value="{{item in items}}">
    <button @click="{$c.parent.handleItemClick($c.event)}">{{item.name}}</button>
</f-repeat>
```

Conditional rendering using a host property inside a repeat:

```html
<f-repeat value="{{item in items}}">
    <f-when value="{{$c.parent.showNames}}">
        <span>{{item.name}}</span>
    </f-when>
</f-repeat>
```

### Unescaped HTML

You can add unescaped HTML using triple braces, this will create an additional `div` element as the HTML needs an element to bind to. Where possible it is advisable to not use unescaped HTML and instead use other binding techniques.

Example:
```html
{{{html}}}
```

### Code samples inside `<code>`

Any text or attribute value inside a `<code>` element has its `{` and `}` characters automatically replaced with the HTML numeric character references `&#123;` and `&#125;` before template parsing. As a result, binding delimiters (`{{...}}`, `{{{...}}}`, `{...}`) inside `<code>` are rendered as literal text rather than being interpreted as FAST bindings — making `<code>` blocks safe for embedding code samples that contain binding-like syntax. No marker attribute is needed.

In addition, the build-time renderer (`@microsoft/fast-build`) entity-escapes the `<` and `>` of every **FAST directive tag** (`<f-when>`, `</f-when>`, `<f-repeat>`, `</f-repeat>`) it finds inside `<code>`, so authors can write the directive literally without manually entity-encoding the angle brackets. Tag-name matching is case-insensitive. Non-directive elements inside `<code>` — real HTML elements such as `<button>` and custom elements such as `<my-widget>` — keep their angle brackets and continue to render as live DOM elements; only brace-binding syntax in their attribute values is neutralised.

The brace escape is applied symmetrically by both the server-side renderer and the client-side `<f-template>` parser, so binding positions stay in sync between SSR and hydration. The directive-tag angle escape only needs to run on the server: the DOM serializer re-encodes `<`/`>` in text content, so the client-side parser never sees a raw `<f-when>` inside `<code>` regardless of what the page source contained. This behaviour mirrors how Microsoft WebUI's `webui-press` markdown renderer transparently escapes the same characters inside code spans and code fences.

Example:
```html
<f-template name="docs-page">
    <template>
        <h1>{{title}}</h1>
        <pre><code>span {{greeting}} /span</code></pre>
        <pre><code><f-when value="{{flag}}">wrapped</f-when></code></pre>
        <pre><code>Try: <button class="demo">click</button></code></pre>
    </template>
</f-template>
```

The `<h1>` binds to `title`, the first `<code>` displays the literal text `span {{greeting}} /span`, the second displays the literal text `<f-when value="{{flag}}">wrapped</f-when>`, and the third renders a live `<button>` element alongside the surrounding sample text.

## Writing Components

When writing components with the intention of using the declarative HTML syntax, it is imperative that components are written with styling and rendering of the component to be less reliant on any JavaScript state management. An example of this is relying on `elementInterals` state to style a component.

## WebUI Integration Testing

The fixture tests in `test/declarative/fixtures/` are also validated against
[`@microsoft/webui`](https://github.com/microsoft/webui) to ensure
cross-renderer compatibility. The build step renders each fixture's templates
with `webui build --plugin=fast`, then the existing Playwright specs run
against the webui-rendered output.

```shell
# Build fixtures with webui and run Playwright tests
npm run test:webui-integration -w @microsoft/fast-element

# Or run the steps separately
npm run build:fixtures:webui -w @microsoft/fast-element
npm exec -w @microsoft/fast-element -- playwright test --config=playwright.declarative.webui.config.ts
```

This is also run automatically in CI via the `ci-webui-integration.yml` GitHub Action on pull requests and pushes to `main`.

Some tests are conditionally skipped during webui integration runs due to known
rendering differences between `fast-build` and `webui`. The
`playwright.declarative.webui.config.ts` file sets
`FAST_WEBUI_INTEGRATION=true`, and affected tests use `test.skip()` with a
descriptive reason. See the WebUI Integration Tests section in
[design.md](./design.md) for the full list.

---

### Packages Fast Element Docs Di Api Report.Api (`packages/fast-element/docs/di/api-report.api.md`)

## API Report File for "@microsoft/fast-element"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Packages Fast Element Docs Migration Fast Element 2 (`packages/fast-element/docs/migration/fast-element-2.md`)

# Changes in FASTElement 2.0

## Breaking Changes

* `HTMLDirective` - The `targetIndex: number` property has been replaced by a `targetId: string` property. The `createBehavior` method no longer takes a target `Node` but instead takes a `BehaviorTargets` instance. The actual target can be looked up on the `BehaviorTargets` instance by indexing with the `targetId` property.
* `compileTemplate()` - Internals have been significantly changed. The implementation no longer uses a TreeWalker. The return type has change to an `HTMLTemplateCompilationResult` with different properties.
* `View` and `HTMLView` - Type parameters added to enable strongly typed views based on their data source. The constructor of `HTMLView` has a new signature based on changes to the compiler's output. Internals have been cleaned up and no longer rely on the Range type.
* `ElementViewTemplate`, `SyntheticViewTemplate`, and `ViewTemplate` - Added type parameters throughout. Logic to instantiate and apply behaviors moved out of the template and into the view where it can be lazily executed. Removed the ability of the `render` method to take a string id of the node to render to. You must provide a node.
* `DOM` - Tree Walker methods are no longer used and are thus removed. The API for removing child nodes has been removed as well since it was only used in one place and could be inlined. The helper `createCustomAttributePlaceholder()` no longer requires an attribute name. It will be uniquely generated internally.
* `class` - Bindings to `class` are now more nuanced. Binding directly to `class` will simply set the `className` property. If you need to bind to `class` knowing that manual JS will also manipulate the `classList` in addition to the binding, then you should now bind to `:classList` instead. This allows for performance optimizations in the simple, most common case.
* `Behavior` and `ViewBehavior` - `Behavior` now requires an `ExecutionContext` for `unbind`. Behaviors can be used for elements or views. `ViewBehavior` has been introduced for use exclusively with views, and provides some optimization opportunities.
* `RefBehavior` has been replaced with `RefDirective`. The directive also implements `ViewBehavior` allowing a single directive instance to be shared across all template instances that use the ref.
* Removed `SlottedBehavior` and `ChildrenBehavior` have been replaced with `SlottedDirective` and `ChildrenDirective`. These directives allow a single directive instance to be shared across all template instances that use the ref.
* Removed `AttachedBehaviorHTMLDirective` and `AttachedBehaviorType` since they are no longer used in the new directive/behavior architecture for ref, slotted, and children.
* Renamed `Notifier#source` to `Notifier#subject` to align with other observable terminology and prevent name clashes with `BindingObserver` properties.

---

### Packages Fast Element Docs Migration Fast Element 3 (`packages/fast-element/docs/migration/fast-element-3.md`)

# Migrating from previous versions

## FASTGlobal version tracking (v2 → v3)

### Removed API

| Removed | Replacement |
|---|---|
| `FAST.versions` | No replacement. Multiple FAST versions on the same page are unsupported in v3. |

### Removed configuration

| Removed | Replacement |
|---|---|
| `fast-kernel="share"` / `fast-kernel="share-v2"` / `fast-kernel="isolate"` | No replacement. FAST now uses a single shared kernel contract, and multiple FAST versions on the same page are unsupported. |

### Migration steps

1. Remove any runtime checks that read `FAST.versions`.
2. Fix duplicate FAST installs in your bundler or dependency graph instead of relying on version tracking at runtime.
3. Remove any `fast-kernel` script attributes. They no longer affect FAST initialization.

## Native globals and scheduler requirements (v2 → v3)

### Changed behavior

- **Browser `Window` runtime required**: `@microsoft/fast-element` is a
  client-side browser runtime. It expects browser DOM, Custom Elements, Shadow
  DOM, and scheduling APIs such as `requestAnimationFrame`.
- **Native `globalThis` required**: `@microsoft/fast-element` no longer installs
  a `globalThis` polyfill as a side effect.
- **No idle-callback polyfill**: FAST Element v3 no longer installs or depends
  on a `requestIdleCallback` / `cancelIdleCallback` fallback. The async
  `Updates` queue schedules work with `globalThis.requestAnimationFrame`.

### Migration steps

1. Verify that the browsers you support provide native `globalThis` and
   `requestAnimationFrame`.
2. If you still target an older browser without `globalThis`, load that polyfill
   before importing `@microsoft/fast-element`.
3. Do not import or run the FAST Element client runtime in workers,
   server-side JavaScript runtimes, or other non-window hosts. SSR tools may
   emit HTML, but hydration and client rendering run in the browser `Window`.
4. You do not need to polyfill `requestIdleCallback` or `cancelIdleCallback`
   for FAST Element itself. Only provide them if your application or another
   dependency calls those APIs directly.

## Declarative HTML moved into fast-element (v3)

Declarative HTML APIs now ship from focused `@microsoft/fast-element` package
path exports instead of the removed `@microsoft/fast-html` package.

### Import changes

| Before | After |
|---|---|
| `@microsoft/fast-html` | `@microsoft/fast-element/declarative.js` |
| `@microsoft/fast-html/utilities.js` | `@microsoft/fast-element/declarative-utilities.js` |

Core FAST Element helpers are available from the root package export:

| API | Import path |
|---|---|
| `Updates` | `@microsoft/fast-element` |
| `Observable`, `observable` | `@microsoft/fast-element` |
| `attr`, `AttributeDefinition`, converters, `ValueConverter` | `@microsoft/fast-element` |
| `Binding`, `oneWay`, `oneTime`, `listener` | `@microsoft/fast-element` |
| `DOM`, `DOMAspect`, `DOMPolicy` | `@microsoft/fast-element` |
| `Schema`, `schemaRegistry`, schema types | `@microsoft/fast-element` |
| `css` | `@microsoft/fast-element` |
| `html`, `ViewTemplate`, `HTMLView` | `@microsoft/fast-element` |
| `Compiler`, `HTMLDirective`, `htmlDirective`, templating/view types | `@microsoft/fast-element` |
| `render`, `RenderBehavior`, `RenderDirective` | `@microsoft/fast-element` |
| `enableHydration`, `deferHydrationAttribute`, `HydrationTracker`, hydration types | `@microsoft/fast-element/hydration.js` |
| `ArrayObserver` | `@microsoft/fast-element` |
| `volatile` | `@microsoft/fast-element` |
| `children` | `@microsoft/fast-element` |
| `elements`, `NodeObservationDirective` | `@microsoft/fast-element` |
| `ref` | `@microsoft/fast-element` |
| `slotted` | `@microsoft/fast-element` |
| `when` | `@microsoft/fast-element` |
| `repeat` | `@microsoft/fast-element` |

### Migration steps

1. Update declarative runtime imports to
   `@microsoft/fast-element/declarative.js`.
2. Update declarative utility imports such as `deepMerge` to
   `@microsoft/fast-element/declarative-utilities.js`.
3. Keep importing FAST Element APIs such as `FASTElement`, `FAST`,
   `ElementController`, definition/controller types, `attr`, `Schema`, and
   `observable` from `@microsoft/fast-element`.
4. Call `enableHydration()` from `@microsoft/fast-element/hydration.js` when
   prerendered content should be hydrated.

## `deepMerge` array replacement

When an array's contents change, `deepMerge` replaces the owning property's
array rather than mutating the existing array in place. This affects both
`observerMap()`-managed data and direct consumers of the exported helper.
Previously captured array references retain the old data; mutating them no
longer updates the owning object. Deeply equal arrays are left unchanged.

Re-read the array from its owner after merging:

```ts
import { deepMerge } from "@microsoft/fast-element/declarative-utilities.js";

const user = { orders: [{ id: 101 }] };
const oldOrders = user.orders;

deepMerge(user, { orders: [{ id: 103 }] });

// oldOrders still contains order 101 and is disconnected from user.orders.
user.orders.push({ id: 104 });
```

For `observerMap()`-managed properties, the owning property's notification
causes `f-repeat` bindings to observe the replacement array automatically.
Direct `deepMerge` consumers must still arrange their own change notifications;
the helper does not make plain objects observable.

## Optional helper and removed path exports (v2 → v3)

FAST Element v3 adds focused flat path exports for optional helpers and removes
older nested or unused package exports. Root imports for core FAST Element APIs
remain supported, but code that imports helper APIs from older nested paths must
move to the flat path exports.

### Import changes

| Before | After |
|---|---|
| `@microsoft/fast-element/binding/two-way.js` | `@microsoft/fast-element/two-way.js` |
| `@microsoft/fast-element/binding/signal.js` | `@microsoft/fast-element/signal.js` |
| Deep directive imports | `@microsoft/fast-element/children.js`, `@microsoft/fast-element/repeat.js`, `@microsoft/fast-element/when.js`, `@microsoft/fast-element/ref.js`, `@microsoft/fast-element/slotted.js`, or `@microsoft/fast-element/node-observation.js` |
| Declarative map helpers from old declarative surfaces | `@microsoft/fast-element/attribute-map.js` and `@microsoft/fast-element/observer-map.js` |

### Removed package exports

| Removed | Replacement |
|---|---|
| `@microsoft/fast-element/install-element-hydration.js` | No side-effect import. Call `enableHydration()` from `@microsoft/fast-element/hydration.js` when SSR content should hydrate. |
| `@microsoft/fast-element/install-hydratable-view-templates.js` | No side-effect import. `enableHydration()` installs hydratable template support. |
| `@microsoft/fast-element/element-hydration.js` | `@microsoft/fast-element/hydration.js` for public hydration APIs. |
| `@microsoft/fast-element/metadata.js` | No supported public replacement. |
| `@microsoft/fast-element/testing.js` | No supported public replacement. |
| `@microsoft/fast-element/pending-task.js` | No supported public replacement. |

### Migration steps

1. Replace older nested helper imports with the flat path exports shown above.
2. Remove hydration side-effect imports and call `enableHydration()` before FAST
   elements connect when SSR content should hydrate.
3. Remove imports from deleted package exports. If your app depended on one of
   those internals, move that usage into app-owned code or a supported public
   API.

## `attribute-name-strategy` default changed (v2 → v3)

The declarative attribute map default changed from `"none"` to `"camelCase"`.
With the default strategy, a binding key such as `{{firstName}}` maps to the
`firstName` property and the `first-name` HTML attribute. In v2-style
declarative templates that relied on literal attribute names, this can change
which property receives data.

### Migration steps

1. Audit declarative templates for binding keys that contain hyphens or that
   intentionally matched attribute names exactly.
2. If you want the v2 behavior, configure the client definition extension with
   `attributeMap({ "attribute-name-strategy": "none" })`.
3. If server-rendered HTML is generated with `@microsoft/fast-build`, pass
   `--attribute-name-strategy=none` so server and client mapping agree.

## `TemplateOptions` removal (v3)

### Removed APIs

| Removed | Replacement |
|---|---|
| `TemplateOptions` | No replacement |
| `PartialFASTElementDefinition.templateOptions` | No replacement |
| `FASTElementDefinition.templateOptions` | No replacement |

### Changed behavior

- Subclass `define()` calls no longer use `templateOptions` to delay platform
  definition or connection.
- Elements can still be defined before a template is attached; a later
  `FASTElementDefinition.template` update notifies connected elements so they
  can render or hydrate with the new template.

### Migration steps

1. Remove `templateOptions` from element definitions.
2. Continue calling `define({ name })` when a definition needs to exist before
   its template is attached.
3. If a template is supplied later, assign `FASTElementDefinition.template` (or
   use the declarative runtime that does so for you).

## `FASTElementDefinition.isRegistered` removal (v3)

### Removed APIs

| Removed | Replacement |
|---|---|
| `FASTElementDefinition.isRegistered` | `fastElementRegistry.whenRegistered(tagName)`, `fastElementRegistry.getByType(type)`, or `fastElementRegistry.getForInstance(instance)` |

### Migration steps

1. Import `fastElementRegistry` from `@microsoft/fast-element/registry.js`.
2. Use `fastElementRegistry.whenRegistered(tagName)` when code needs to wait for
   a definition by tag name.
3. Use `fastElementRegistry.getByType(type)` or
   `fastElementRegistry.getForInstance(instance)` when code already has a
   constructor or element instance.

## Declarative TemplateElement API removal (v3)

### Removed APIs

| Removed | Replacement |
|---|---|
| `TemplateElement` public export | `declarativeTemplate()` on each FAST element definition |
| `TemplateElement.define({ name: "f-template" })` | No manual definition; `declarativeTemplate()` defines FAST's internal `<f-template>` publisher in the target registry |
| `TemplateElement.config(callbacks)` / `HydrationLifecycleCallbacks` | `enableHydration().whenHydrated(tagName)` for tag-specific hydration waits and `enableHydration().whenHydrated()` for the active hydration batch |
| `TemplateElement.options(...)`, `ElementOptions`, `ElementOptionsDictionary` | Define extensions: `attributeMap(...)` and `observerMap(...)` passed as the second argument to `define()` |
| `AttributeMap` / `ObserverMap` exports from the old declarative public surface | `attributeMap()` / `observerMap()` extension helpers and their config types |

### Migration steps

1. Replace manual `<f-template>` registration with `template: declarativeTemplate()`:

   ```typescript
   // Before
   import { TemplateElement } from "@microsoft/fast-element";
   TemplateElement.define({ name: "f-template" });

   MyElement.define({ name: "my-element" });

   // After
   import { declarativeTemplate } from "@microsoft/fast-element/declarative.js";

   MyElement.define({
       name: "my-element",
       template: declarativeTemplate(),
   });
   ```

2. Replace `TemplateElement.options()` with definition extensions:

   ```typescript
   import { attributeMap } from "@microsoft/fast-element/attribute-map.js";
   import { declarativeTemplate } from "@microsoft/fast-element/declarative.js";
   import { observerMap } from "@microsoft/fast-element/observer-map.js";

   MyElement.define(
       {
           name: "my-element",
           template: declarativeTemplate(),
       },
       [attributeMap(), observerMap()],
   );
   ```

   `attributeMap()` is imported from
   `@microsoft/fast-element/attribute-map.js` and `observerMap()` from
   `@microsoft/fast-element/observer-map.js` for declarative templates,
   manually supplied schemas, or both. `FASTElementDefinition.schema` is optional;
   `declarativeTemplate()` assigns it automatically, and `observerMap()` can
   take a manual schema with `observerMap({ schema })`.

3. Replace `TemplateElement.config()` with `enableHydration().whenHydrated(tagName)`
   for tag-specific hydration waits and `enableHydration().whenHydrated()` for the
   active hydration batch.
   Hydration is not installed by `declarative.js`; call `enableHydration()`
   before elements connect when SSR content should hydrate.

## Debug entrypoint explicit enablement (v3)

### Import changes

| Before | After |
|---|---|
| `import "@microsoft/fast-element";` | `import { enableDebug } from "@microsoft/fast-element/debug.js"; enableDebug();` |

### Migration steps

1. Replace setup-only `debug.js` imports with an explicit `enableDebug()` call.
2. Keep using the root package `development` export or debug rollup bundle when
   you want debug behavior enabled automatically.

## Declarative event handler `e` removal (v3)

### Removed behavior

| Removed | Replacement |
|---|---|
| Bare `e` event arguments in declarative event handlers | `$e` |
| `TemplateParser.hasDeprecatedEventSyntax` | No replacement |

Only `$e` and `$c` are reserved event handler arguments in declarative
templates. Bare `e` now resolves like any other binding path on the current
data source.

### Migration steps

1. Replace declarative event bindings such as
   `@click="{handleClick(e)}"` with `@click="{handleClick($e)}"`.
2. Remove any `TemplateParser.hasDeprecatedEventSyntax` checks or warnings from
   custom tooling.

## Prerendered Content Optimization (v2 → v3)

### Removed and moved APIs

| 2.x API | 3.x guidance |
|---|---|
| `HydratableElementController` | `ElementController` (prerendered path built in) |
| `HydrationControllerCallbacks` | Call `enableHydration()` and await the returned controller's `whenHydrated()` promise |
| `needsHydrationAttribute` | No replacement. Existing shadow root detection sets `ElementController.isPrerendered`. |
| Root `deferHydrationAttribute` export | Import `deferHydrationAttribute` from `@microsoft/fast-element/hydration.js` only if you still need the legacy attribute string. New server-rendered markup should omit `defer-hydration`. |

### Removed side-effect imports

| Import | Replacement |
|---|---|
| `@microsoft/fast-element/install-hydration.js` | No replacement needed — prerendered path is built into `ElementController` |
| `@microsoft/fast-element/install-hydratable-view-templates.js` | No replacement needed — `enableHydration()` installs hydratable template support |

Use `enableHydration()` from `@microsoft/fast-element/hydration.js` when SSR
content should hydrate. The declarative entrypoint no longer installs hydration
automatically.

### Changed behavior

- **`attributeChangedCallback` during upgrade**: When `isPrerendered` is true and the element has not yet connected, attribute change callbacks are suppressed. After connection, all attribute changes are processed normally.
- **Declarative template resolution**: `declarativeTemplate()` waits for the
  matching `<f-template>` before `define()` completes, so connected elements
  hydrate with a concrete template. No `defer-hydration` attribute is needed.
- **Binding evaluation with existing shadow root**: When an existing shadow root is detected, `attribute` and `booleanAttribute` bindings skip their initial DOM update. All other binding types (event, content, property, tokenList) run normally.

### New APIs

- **`ElementController.isPrerendered`** (`Promise<boolean>`): Resolves to `true` when the element had a declarative shadow root at connect time, or `false` when the component was client-side rendered.
- **`ElementController.isHydrated`** (`Promise<boolean>`): Resolves to `true` only when hydration ran successfully.
- **`ViewController.isPrerendered`** (`Promise<boolean> | undefined`): Available to custom directives. Resolves to `true` when the view's content was prerendered, `false` otherwise.
- **`ViewController.isHydrated`** (`Promise<boolean> | undefined`): Available to custom directives. Resolves to `true` only when hydration ran successfully.

### Migration steps

1. Remove `HydratableElementController.install()` calls.
2. Remove `import "@microsoft/fast-element/install-hydration.js"` side-effect imports.
3. Replace `element.$fastController instanceof HydratableElementController` checks with `await element.$fastController.isPrerendered`.
4. Remove `defer-hydration` and `needs-hydration` attributes from server-rendered markup.

## Hydration Marker Format (v3)

### Changed format

The hydration markers embedded in SSR output have been simplified from verbose, index-embedded comment markers to compact, data-free sequential markers.

#### Comment markers

| Marker type | Old format | New format |
|---|---|---|
| Content binding start | `` | `` |
| Content binding end | `` | `` |
| Repeat item start | `` | `` |
| Repeat item end | `` | `` |
| Element boundary start | `` | `` |
| Element boundary end | `` | `` |

#### Attribute binding markers

| Old format | New format |
|---|---|
| `data-fe-b="0 1 2"` (space-separated indices) | `data-fe="N"` (binding count) |
| `data-fe-b-0` (enumerated, one per factory) | `data-fe="N"` |
| `data-fe-c-0-3` (compact, start index + count) | `data-fe="N"` |

### Removed APIs

| Export | Replacement |
|---|---|
| `HydrationMarkup.contentBindingStartMarker(index, scopeId)` | `HydrationMarkup.contentBindingStartMarker()` |
| `HydrationMarkup.contentBindingEndMarker(index, scopeId)` | `HydrationMarkup.contentBindingEndMarker()` |
| `HydrationMarkup.isContentBindingStartMarker(data)` | `HydrationMarkup.isContentBindingStartMarker(data)` (unchanged signature, new implementation) |
| `HydrationMarkup.isContentBindingEndMarker(data)` | `HydrationMarkup.isContentBindingEndMarker(data)` (unchanged signature, new implementation) |
| `HydrationMarkup.parseAttributeBinding(element)` | `HydrationMarkup.parseAttributeBindingCount(element)` |
| `HydrationMarkup.parseRepeatStartMarker(data)` | `HydrationMarkup.isRepeatViewStartMarker(data)` |
| `HydrationMarkup.parseRepeatEndMarker(data)` | `HydrationMarkup.isRepeatViewEndMarker(data)` |
| `HydrationMarkup.parseElementBoundaryStartMarker(content)` | `HydrationMarkup.isElementBoundaryStartMarker(node)` |
| `HydrationMarkup.parseElementBoundaryEndMarker(content)` | `HydrationMarkup.isElementBoundaryEndMarker(node)` |

### Impact

This is a **breaking change** for SSR output format. Any system that produces or parses hydration markers must be updated to use the new format. The `@microsoft/fast-build` Rust crate and WASM binary have been updated accordingly.

- Marker parsing uses string equality checks (`data === "fe:b"`) instead of regex
- Start/end pairing uses balanced depth counting instead of embedded IDs
- The hydration walker uses a sequential factory pointer instead of index-based lookup
- SSR and client versions must match — mixing old SSR output with new client code (or vice versa) will fail

## Async define/compose/register API (v3)

### Removed APIs

| Removed | Replacement |
|---|---|
| `FASTElement.defineAsync()` | Subclass `define()` calls |
| `FASTElement.compose()` and subclass `compose()` calls | Subclass `define()` calls |
| `FASTElementDefinition.composeAsync()` | Subclass `define()` calls |
| `FASTElementDefinition.registerAsync()` | `FASTElementDefinition.register()` (same `Promise<Function>` return type) |

### Changed behavior

- Subclass **`define()`** calls return `Promise<TType>` only for code that
  explicitly needs to observe registration completion. When
  `template: declarativeTemplate()` is used, that Promise resolves after the
  matching `<f-template>` supplies the concrete template.
- Subclass compose helpers are no longer part of the public authoring surface; use subclass `define()` for registration.
- **`@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

1. Replace `defineAsync()` calls with `define()`:

   ```typescript
    // Before
    MyElement.defineAsync({
        name: "my-element",
        templateOptions: "defer-and-hydrate",
    });

    // After
    MyElement.define({
        name: "my-element",
        template: declarativeTemplate(),
    });
   ```

2. Replace subclass `compose()` calls that immediately register an element with
   `define()`:

   ```typescript
    // Before
    MyElement.compose({
        name: "my-element",
        template,
        styles,
    }).define();

    // After
    MyElement.define({
        name: "my-element",
        template,
        styles,
    });
   ```

3. Replace `FASTElementDefinition.composeAsync()` calls that register an element
   with subclass `define()`:

   ```typescript
   // Before
   (await FASTElementDefinition.composeAsync(MyElement, {
       name: "my-element",
       template,
       styles,
   })).define();

   // After
   MyElement.define({
       name: "my-element",
       template,
       styles,
   });
   ```

4. Replace `registerAsync()` calls with `register()`:

   ```typescript
   // Before
   const el = await FASTElementDefinition.registerAsync(name);

   // After
   const el = await FASTElementDefinition.register(name);
   ```

5. Replace `FASTElementDefinition.compose()` calls that chain `.define()` with
   subclass `define()`:

   ```typescript
    // Before
    FASTElementDefinition.compose(MyElement, options).define();

    // After
    MyElement.define(options);
   ```

## Dynamic stylesheet behaviors (v3)

### Removed API

| Removed | Replacement |
|---|---|
| `ElementStyles.withBehaviors()` | Move the runtime condition into the element and call `this.$fastController.addStyles()` / `this.$fastController.removeStyles()` directly. |
| `ElementStyles.behaviors` | Move any runtime behavior out of the stylesheet and into the element or controller lifecycle. |
| CSS bindings in `css` (for example ``css`color: ${x => x.color}```
/* Detailed source-code truncated for AI context efficiency. */
```ts
toView(value: any) {
    return value ? "" : null;
}

fromView(value: any) {
    return !!value;
}
```

`booleanConverter` v2 → v3 result differences:

| Call | v2 result | v3 result |
|---|---|---|
| `fromView("false")` | `false` | `true` |
| `fromView("")` | `true` | `false` |
| `fromView(NaN)` | `true` | `false` |
| `toView(true)` (or any truthy) | `"true"` | `""` |
| `toView(false)` (or any falsy) | `"false"` | `null` |

> **Note**: For `mode: "boolean"`, FAST writes attributes via `DOM.setBooleanAttribute` (presence-based) and reads them as `value !== null`, so the `mode: "boolean"` reflection path does **not** route through `booleanConverter.toView()` or `booleanConverter.fromView()`. The converter methods still apply to property assignment (`el.bool = X` runs `fromView(X)`), explicit calls (`booleanConverter.fromView(x)`), and `booleanConverter` paired with `mode: "reflect"` (which calls `toView`).

### Migration steps

1. Audit `boolean`-mode attributes for the literal string `"false"` in templates or SSR HTML — the resulting property will be `true`, not `false`. To express the falsy state, omit the attribute entirely (or call `element.removeAttribute(name)`). Setting `element.bool = false` continues to remove the reflected attribute.
2. Audit code that calls `booleanConverter.toView()` directly or pairs `booleanConverter` with `mode: "reflect"`. The output strings are no longer `"true"` / `"false"`.
3. If you need a tri-state attribute (`true` / `false` / unset) that preserves an explicit `"false"` string value, use `nullableBooleanConverter` with `mode: "reflect"` instead of `mode: "boolean"`.

---

### Packages Fast Element Docs Migration Fast Html (`packages/fast-element/docs/migration/fast-html.md`)

# Migrating from previous versions

## Hydration Marker Format (v1-alpha → v1)

The SSR output format for hydration markers has been simplified. If you have any tooling that inspects or generates hydration markers, update it to use the new format.

| Old marker | New marker |
|---|---|
| `` | `` |
| `` | `` |
| `` | `` |
| `` | `` |
| `data-fe-b="0 1 2"` / `data-fe-b-0` / `data-fe-c-0-3` | `data-fe="N"` |

The `@microsoft/fast-build` WASM binary emits the new markers automatically. Rebuild all fixtures and SSR output after upgrading.

See the [`@microsoft/fast-element` migration guide](./fast-element-3.md#hydration-marker-format-v3) for full details on API changes.

## Prerendered Content Optimization (v1-alpha → v1)

### Removed exports

| Export | Replacement |
|---|---|
| `RenderableFASTElement` | Extend `FASTElement` |

### Removed concepts

| Concept | Replacement |
|---|---|
| `prepare()` lifecycle hook | Set state in `connectedCallback`; the reactive system updates the DOM |
| `defer-hydration` attribute in rendered markup | Template-pending guard in `ElementController.connect()` |
| `needs-hydration` attribute in rendered markup | `hasExistingShadowRoot` detection in `ElementController` |
| `waitForAncestorHydration()` | Not needed — prerendered content is correct regardless of connection order |

### Migration steps

1. Replace `RenderableFASTElement(MyComponent).defineAsync({...})` with
   `MyComponent.define({...})` and use `declarativeTemplate()` for declarative
   templates. If code explicitly observes the Promise returned by `define()`,
   it resolves after the matching `<f-template>` supplies the concrete template.

   ```typescript
   // Before
   import { RenderableFASTElement } from "@microsoft/fast-html";
   RenderableFASTElement(MyComponent).defineAsync({
       name: "my-component",
       templateOptions: "defer-and-hydrate",
   });

   // After
   MyComponent.define({
       name: "my-component",
       template: declarativeTemplate(),
   });
   ```

2. Remove `prepare()` methods. Move any initialization logic to `connectedCallback`:

   ```typescript
   // Before
   class MyComponent extends FASTElement {
       async prepare() {
           this.data = await fetchData();
       }
   }

   // After
   class MyComponent extends FASTElement {
       connectedCallback() {
           super.connectedCallback();
           this.loadData();
       }
       async loadData() {
           this.data = await fetchData();
       }
   }
   ```

3. Remove `defer-hydration` and `needs-hydration` attributes from server-rendered markup:

   ```html
   
   <my-component defer-hydration needs-hydration text="Hello">
       <template shadowrootmode="open">...</template>
   </my-component>

   
   <my-component text="Hello">
       <template shadowrootmode="open">...</template>
   </my-component>
   ```

4. Await `$fastController.isPrerendered` to detect prerendered components:

   ```typescript
   connectedCallback() {
       super.connectedCallback();
       this.$fastController.isPrerendered.then(prerendered => {
           if (!prerendered) {
               this.fetchData();
           }
       });
   }
   ```

## Modularize Schema, ObserverMap, and AttributeMap

### Import changes

Configuration types have moved from `template.ts` to their owning modules. If you import types directly from internal paths, update your imports:

| Before | After |
|---|---|
| `import type { ObserverMapConfig } from "./template.js"` | `import type { ObserverMapConfig } from "./observer-map.js"` |
| `import type { AttributeMapConfig } from "./template.js"` | `import type { AttributeMapConfig } from "./attribute-map.js"` |

Public declarative imports now come from
`@microsoft/fast-element/declarative.js` rather than
`@microsoft/fast-html`, and declarative utilities come from
`@microsoft/fast-element/declarative-utilities.js`. Map extensions come from
`@microsoft/fast-element/attribute-map.js` and
`@microsoft/fast-element/observer-map.js`.

### Schema changes

`Schema.jsonSchemaMap` (static property) has been replaced by:
- An instance-level `schemaMap` on each `Schema` instance (private)
- A module-level `schemaRegistry` export for cross-element lookups

| Before | After |
|---|---|
| `Schema.jsonSchemaMap.get('my-element')` | `import { schemaRegistry } from "@microsoft/fast-element"; schemaRegistry.get('my-element')` |

### Public exports

The public entrypoint exports the functional declarative API:

| Export | Purpose |
|---|---|
| `declarativeTemplate()` | Resolves `<f-template>` markup for a FAST element definition |
| `attributeMap()` | Definition extension for automatic `@attr` property registration |
| `observerMap()` | Definition extension for automatic deep observation |
| `Schema` | JSON schema builder class |
| `schemaRegistry` | Module-level registry for cross-element schema lookups |
| `JSONSchema` | JSON Schema type interface |
| `CachedPathMap` | Schema registry map type |

## Simplified ObserverMap and AttributeMap defaults

The explicit `ObserverMapOption.all` and `AttributeMapOption.all` constants have
been removed. Calling `observerMap()` with no arguments observes every
discovered root property, and calling `attributeMap()` with no arguments maps
every discovered leaf binding.

| Before | After |
|---|---|
| `observerMap(ObserverMapOption.all)` | `observerMap()` |
| `attributeMap(AttributeMapOption.all)` | `attributeMap()` |

## Attribute name strategy default changed

The default `attribute-name-strategy` for declarative attribute mapping is now
`"camelCase"` instead of `"none"`. A binding key such as `{{firstName}}` maps to
the `firstName` property and the `first-name` HTML attribute by default. If your
templates depended on literal attribute names, opt back in to the old behavior:

```ts
import { attributeMap } from "@microsoft/fast-element/attribute-map.js";

MyElement.define(
    {
        name: "my-element",
        template: declarativeTemplate(),
    },
    [attributeMap({ "attribute-name-strategy": "none" })],
);
```

When using `@microsoft/fast-build`, keep the server and client settings aligned:

```bash
fast build --attribute-name-strategy=none
```

## Declarative TemplateElement API removal

The public declarative API is now the functional API. The `<f-template>`
implementation is internal and is defined automatically by `declarativeTemplate()`.

| Removed | Replacement |
|---|---|
| `TemplateElement` public export | `declarativeTemplate()` on each FAST element definition |
| `TemplateElement.define({ name: "f-template" })` | No manual definition; `declarativeTemplate()` defines the internal publisher in the target registry |
| `TemplateElement.config(callbacks)` / `HydrationLifecycleCallbacks` | `enableHydration().whenHydrated(tagName)` for tag-specific hydration waits and `enableHydration().whenHydrated()` for the active hydration batch |
| `TemplateElement.options({ "my-el": { attributeMap, observerMap } })` | Define extensions: `MyElement.define(definition, [attributeMap(...), observerMap(...)])` |
| `ElementOptions` / `ElementOptionsDictionary` | No replacement |
| `AttributeMap` / `ObserverMap` class exports from the old declarative public surface | `attributeMap()` / `observerMap()` extension helpers and their config types |

Hydration is also no longer installed by `@microsoft/fast-element`.
Call `enableHydration()` from `@microsoft/fast-element/hydration.js` before FAST
elements connect when prerendered Declarative Shadow DOM should be reused.

## Schema-driven maps and optional definition schema

`attributeMap()` and `observerMap()` are now schema-driven extensions that are
factored away from declarative templating. Import them from
`@microsoft/fast-element` for declarative or non-declarative use:

```ts
import { attributeMap } from "@microsoft/fast-element/attribute-map.js";
import { observerMap } from "@microsoft/fast-element/observer-map.js";
```

`FASTElementDefinition.schema` is optional. `declarativeTemplate()` assigns it
automatically when it parses `<f-template>` markup. Manual schema users can pass
a schema in the element definition, and `observerMap()` can also take a schema
directly in configuration:

```ts
import { FASTElement, Schema } from "@microsoft/fast-element";
import { observerMap } from "@microsoft/fast-element/observer-map.js";

class MyElement extends FASTElement {}

const schema = new Schema("my-element");
schema.addPath({
    rootPropertyName: "user",
    pathConfig: {
        type: "default",
        parentContext: null,
        currentContext: null,
        path: "user.name",
    },
    childrenMap: null,
});

MyElement.define({ name: "my-element" }, [observerMap({ schema })]);
```

---

### Packages Fast Element Docs Styles Api Report.Api (`packages/fast-element/docs/styles/api-report.api.md`)

## API Report File for "@microsoft/fast-element"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Sites Website Src Docs 1.X Apps And Experiences (`sites/website/src/docs/1.x/apps-and-experiences.md`)

---
layout: 1x
eleventyNavigation:
  key: apps-and-experiences1x
  title: Apps and Experiences
navigationOptions:
  activeKey: apps-and-experiences1x
permalink: false
---

---

### Sites Website Src Docs 1.X Community (`sites/website/src/docs/1.x/community.md`)

---
layout: 1x
eleventyNavigation:
  key: community1x
  title: Community
navigationOptions:
  activeKey: community1x
permalink: false
---

---

### Sites Website Src Docs 1.X Components (`sites/website/src/docs/1.x/components.md`)

---
layout: 1x
eleventyNavigation:
  key: components1x
  title: Components
navigationOptions:
  activeKey: components1x
permalink: false
---

---

### Sites Website Src Docs 1.X Design Systems (`sites/website/src/docs/1.x/design-systems.md`)

---
layout: 1x
eleventyNavigation:
  key: design-systems1x
  title: Design Systems
navigationOptions:
  activeKey: design-systems1x
permalink: false
---

---

### Sites Website Src Docs 1.X Design (`sites/website/src/docs/1.x/design.md`)

---
layout: 1x
eleventyNavigation:
  key: design1x
  title: Design
navigationOptions:
  activeKey: design1x
permalink: false
---

---

### Sites Website Src Docs 1.X Fast Element (`sites/website/src/docs/1.x/fast-element.md`)

---
layout: 1x
eleventyNavigation:
  key: fast-element1x
  title: FAST Element
navigationOptions:
  activeKey: fast-element1x
permalink: false
---

---

### Sites Website Src Docs 1.X Integrations (`sites/website/src/docs/1.x/integrations.md`)

---
layout: 1x
eleventyNavigation:
  key: integrations1x
  title: Integrations
navigationOptions:
  activeKey: integrations1x
permalink: false
---

---

### Sites Website Src Docs 1.X Introduction (`sites/website/src/docs/1.x/introduction.md`)

---
id: introduction
title: Introduction
eleventyNavigation:
  key: introduction1x
  title: Introduction
navigationOptions:
  activeKey: introduction1x
layout: 1x
---

## Where should I start?

Pick the statement you most identify with, and follow the links where they lead. Come back and explore another topic at any time. Or, [click here](#what-is-fast) to learn more about FAST.


* "I just want ready-made components!"
  * [Jump to the component docs.](./components/getting-started.md)
* "I want to build my own design system."
  * [Jump to the design system docs.](./design-systems/overview.md)
* "I want to build my own components."
  * [Jump to the fast-element docs.](./fast-element/getting-started.md)
* "I need to integrate FAST with another framework or build system."
  * [Jump to the integration docs.](./integrations/introduction.md)
* "I want to look at a quick reference."
  * [Jump to the Cheat Sheet](./resources/cheat-sheet.md)
* "I want to contribute to FAST."
  * [Jump to the contributor guide.](./community/contributor-guide.md)

## What is FAST?

FAST is a collection of technologies built on Web Components and modern Web Standards, designed to help you efficiently tackle some of the most common challenges in website and application design and development.

### What are Web Components?

"Web Components" is an umbrella term that refers to a collection of web standards focused on enabling the creation of custom HTML elements. Some of the standards that are under the umbrella include the ability to define new HTML tags, plug into a standard component lifecycle, encapsulate HTML rendering and CSS, parameterize CSS, skin components, and more. Each of these platform features is defined by the W3C and has shipped in every major browser today.

### How does FAST leverage Web Components?

One of FAST's driving principals is "strive to adopt open, web standards-based approaches as much as possible." To that end, FAST is built directly on the W3C Web Component standards mentioned above, and does not create its own component model. This allows components built with FAST to function the same as built-in, native HTML elements. You do not need a framework to use FAST components, but you can use them in combination with any framework or library of your choice.

### How can FAST help me?

To understand how FAST can help you, let's take a look at the **FAST tech stack from top to bottom**. 

At the top of the stack, FAST provides a set of Web Components: **`@microsoft/fast-components`**. This library includes a common set of components found in many websites and apps.

```mermaid
flowchart
  subgraph FAST [ ]
    direction TB
    FastComponents("@microsoft/fast-components\n(Component library that implements FAST Frame Design System)")
  end

  style FAST fill:transparent,stroke:none
  style FastComponents fill:#f4f4f4,stroke:#fb356d,stroke-width:3px,color:#333
```

Example components include button, card, modal, menu, tab, tree-view, and more. `@microsoft/fast-components` provides an industry-focused design system, which we call "FAST Frame". If you're looking to integrate FAST components into an existing site or app, or if you need more control over the theme of the components, this is the option you'll want to start with.

**What if you're not just looking for a set of components to use, but you also need to implement a custom *design system*?** 

This is where the second level of the stack comes into play. **`@microsoft/fast-foundation`** provides foundational building blocks that can be assembled to create new design systems and component libraries. 

```mermaid
flowchart
  subgraph FAST [ ]
    direction TB
    FastComponents("@microsoft/fast-components\n(Component library that implements FAST Frame Design System)")
    FastFoundation("@microsoft/fast-foundation\n(Building blocks for custom design systems/component libraries)")
    FastComponents -.-> FastFoundation
  end

  style FAST fill:transparent,stroke:none
  style FastComponents fill:#f4f4f4,stroke:#f4f4f4,color:#333
  style FastFoundation fill:#f4f4f4,stroke:#fb356d,stroke-width:3px,color:#333
```

For example, if you wanted to implement Google's Material Design, you could do that using `@microsoft/fast-foundation`; you could also implement something like Twitter Bootstrap. `@microsoft/fast-components` assemble the building blocks of `@microsoft/fast-foundation` to create its component sets. 

**What types of building blocks are we talking about though?** 

Perhaps the most valuable feature of the foundation is that it provides base component behaviors and templates for the standard components. So, if you want to implement a tree-view in your design system, for example, you would use the foundation base component behavior and template, but combine it with your own styles. 

The foundation components implement the state management, accessibility, keyboard navigation, and extensibility/composition model so you don't have to write that code. Additionally, foundation provides facilities for dynamic style behaviors, CSS property management, algorithmic color, RTL, high contrast, and more. You don't have to write any of that. Just assemble the building blocks and add your styles to create your own component library, expressing your own design system. So far we've talked about using existing components and creating new design systems and component libraries from existing pieces. But FAST enables you to create completely new Web Components as well. 

Enter **`@microsoft/fast-element`**, the lowest level part of the FAST tech stack. This is a lightweight library for building performant, memory-efficient, standards-compliant Web Components.

```mermaid
flowchart
  subgraph FAST [ ]
    direction TB
    FastComponents("@microsoft/fast-components\n(Component library that implements FAST Frame Design System)")
    FastFoundation("@microsoft/fast-foundation\n(Building blocks for custom design systems/component libraries)")
    FastElement("@microsoft/fast-element\n(Lightweight library for building custom Web Components)")
    FastComponents -.-> FastFoundation -.-> FastElement 
  end

  style FAST fill:transparent,stroke:none
  style FastComponents fill:#f4f4f4,stroke:#f4f4f4,color:#333
  style FastFoundation fill:#f4f4f4,stroke:#f4f4f4,color:#333
  style FastElement fill:#f4f4f4,stroke:#fb356d,stroke-width:3px,color:#333
```

`@microsoft/fast-element` provides a thin layer of opinion on top of Web Components, lifting the level of abstraction just enough to make it easier and faster to build components. `@microsoft/fast-element` helps by providing attribute/property syncing, rich Model-View-ViewModel (MVVM), efficient template rendering/update, style composition, and much more. The entire `@microsoft/fast-element` library, *without* tree-shaking, is around 10kb minified and GZipped. It was designed for tree-shaking from the beginning, so any feature you don't use when building a component will be removed during build, allowing for highly efficient optimized payloads as small as 4.5k.

<hr />

## Joining the community

Looking to get answers to questions or engage with us in realtime? Our community is most active [on Discord](https://discord.gg/FcSNfg4). Submit requests and issues on [GitHub](https://github.com/Microsoft/fast/issues/new/choose), or join us by contributing on [some good first issues via GitHub](https://github.com/Microsoft/fast/labels/community:good-first-issue).

We look forward to building an amazing open source community with you!

---

### Sites Website Src Docs 1.X Resources (`sites/website/src/docs/1.x/resources.md`)

---
layout: 1x
eleventyNavigation:
  key: resources1x
  title: Resources
navigationOptions:
  activeKey: resources1x
permalink: false
---

---

### Sites Website Src Docs 1.X Tools (`sites/website/src/docs/1.x/tools.md`)

---
layout: 1x
eleventyNavigation:
  key: tools1x
  title: Tools
navigationOptions:
  activeKey: tools1x
permalink: false
---

---

### Sites Website Src Docs 2.X Advanced (`sites/website/src/docs/2.x/advanced.md`)

---
layout: 2x
eleventyNavigation:
  key: advanced2x
  title: Advanced Concepts
  order: 3
navigationOptions:
  activeKey: advanced2x
permalink: false
---

---

### Sites Website Src Docs 2.X Api (`sites/website/src/docs/2.x/api.md`)

---
layout: 2x
eleventyNavigation:
  key: api2x
  title: API Reference
  order: 4
navigationOptions:
  activeKey: api2x
permalink: false
---

---

### Sites Website Src Docs 2.X Community (`sites/website/src/docs/2.x/community.md`)

---
layout: 2x
eleventyNavigation:
  key: community2x
  title: Community Contribution
navigationOptions:
  activeKey: community2x
permalink: false
---

---

### Sites Website Src Docs 2.X Integrations (`sites/website/src/docs/2.x/integrations.md`)

---
id: integrations
title: Integrations
layout: 2x
eleventyNavigation:
  key: integrations2x
  title: Integrations
navigationOptions:
  activeKey: integrations2x
keywords:
  - integrations
  - angular
  - asp.net
  - aurelia 2
  - ember
  - react
  - rollup
  - svelte
  - vite
  - vue
  - webpack
  - web components
---

# Integrations

If your project includes one of the popular frameworks below, we've included some helpful tips.

Natively supported, no additional configuration needed:

- ASP.NET
- Ember
- Svelte
- Vite
- Vue
- Webpack

## Angular

[Angular](https://angular.io/) works well with web components, 

To work with typings within Angular, check out their documentation on [custom typings](https://angular.io/guide/elements#typings-for-custom-elements).

## Aurelia 2

FAST works flawlessly with Aurelia 2, with full integration into the binding engine and component model.

### Enabling two-way bindings

Aurelia knows by default how to listen for changes in native elements. Now we need to teach it how to listen for changes in FAST elements. You can do so by [extending its templating syntax](https://docs.aurelia.io/examples/integration/ms-fast). 

You can either use a [wrapper](https://www.npmjs.com/package/aurelia-fast-adapter) developed by the community or teach Aurelia manually:

### Import and register `aurelia-fast-adapter`

Start by installing the adapter

```ts
npm install aurelia-fast-adapter
```

and then simply register it from your `src/main.ts`:

```ts
// src/main.ts

import { FASTAdapter } from 'aurelia-fast-adapter';

Aurelia
  .register(FASTAdapter) // add this line
  // other registrations...
  .start();
```

If you use FAST in its default configuration that's all you need to do. But if you changed the prefix of your components to something else, you can customize the adapter as such:

```ts
// src/main.ts

import { FASTAdapter } from 'aurelia-fast-adapter';

Aurelia
  .register(FASTAdapter.customize({withPrefix: 'my-custom-prefix'}) // customized with prefix
  .start();
```

Also, in case you have local components that require two-way binding, you can adjust the adapter before to register it as such:

```ts
// src/main.ts

import { FASTAdapter } from 'aurelia-fast-adapter';

// this line will tell the adapter that it must use two-way binding on the <my-custom-prefix-date-field> component and use this two-way binding on the `value` property. It's possible to add several properties at once if necessary
FASTAdapter.tags['DATE-FIELD'] = ['value'];

Aurelia
  .register(FASTAdapter.customize({withPrefix: 'my-custom-prefix'})
  .start();
```

Congratulations! You're now set up to use FAST and Aurelia 2!

### Manually teach Aurelia 2 about two-way binding:

If the example doesn't seem obvious, the following prerequisite reads are recommended:

* [extending Aurelia templating syntax](https://docs.aurelia.io/app-basics/extending-templating-syntax)

The following is a code example of how to teach Aurelia to work seamlessly with Microsoft FAST.

```
/* Detailed source-code truncated for AI context efficiency. */
```

## React

See the [React documentation](https://react.dev/reference/react-dom/components#custom-html-elements) on including custom elements.

## Rollup

In your `rollup.config.js` file in the root of your project folder can look something like this:

```js
import transformTaggedTemplate from 'rollup-plugin-transform-tagged-template';
import typescript from '@rollup/plugin-typescript';
import resolve from '@rollup/plugin-node-resolve';
import cleaner from 'rollup-plugin-cleaner';
import copy from 'rollup-plugin-copy';
import serve from 'rollup-plugin-serve';
import terser from '@rollup/plugin-terser';

export default {
  input: 'src/main.ts',
  output: {
    file: 'dist/bundle.js',
    name: 'bundle',
    format: 'umd',
    sourcemap: true
  },
  plugins: [
    transformTaggedTemplate({
      tagsToProcess: ['html','css'],
      parserOptions: {
        sourceType: "module",
        plugins: [
            "typescript",
            [
                "decorators",
                { decoratorsBeforeExport: true }
            ]
        ]
      },
      transformer(data) {
          data = data.replace(/\s([{}()>~+=^$:!;])\s/gm, '$1');
          data = data.replace(/([",[]])\s+/gm, '$1');
          data = data.replace(/\s{2,}/gm, ' ');
          return data.trim();
      }
    }),
    typescript(),
    resolve(),
    cleaner({
      targets: [
      'dist'
      ]
    }),
    copy({
      targets: [
        { src: 'index.html', dest: 'dist' },
      ]
    }),
    serve({
      open: true,
      contentBase: 'dist'
    }),
    terser(),
  ]
};
```

Let's go over a few of the plugins we would suggest using:
- `transformTaggedTemplate` minifies content within tagged templates (e.g. html and css)
- `typescript` allows us to write our source files in TypeScript.
- `resolve` allows us to import modules installed from npm, like `@microsoft/fast-element`.

## TypeScript

Here's an example starter `tsconfig.json` that you can use:

```json
{
  "compilerOptions": {
    "pretty": true,
    "target": "ES2015",
    "module": "ES2015",
    "moduleResolution": "node",
    "importHelpers": true, // when using decorators this allows for the smallest footprint using tslib
    "experimentalDecorators": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "noEmitOnError": true,
    "strict": true,
    "outDir": "dist/build",
    "rootDir": "src",
    "lib": [
      "dom",
      "esnext"
    ]
  },
  "include": [
    "src"
  ]
}
```

Note the inclusion of `"dom"` and `"experimentalDecorators"`.

You can learn more about `tsconfig.json` options in [the official TypeScript documentation](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html).

:::note
Do not set `useDefineForClassFields` to `true` in your `tsconfig.json` if you are using decorators (e.g. `ExperimentalDecorators`). These two features conflict at present. This will be resolved in future versions of TypeScript and FAST.
:::

---

### Sites Website Src Docs 2.X Introduction (`sites/website/src/docs/2.x/introduction.md`)

---
id: introduction
title: Introduction
layout: 2x
eleventyNavigation:
  key: introduction2x
  title: Introduction
  order: 1
navigationOptions:
  activeKey: introduction2x
keywords:
  - introduction
  - web components
---

# Introduction

## What is FAST?

FAST is a collection of technologies built on Web Components and modern Web Standards, designed to help you efficiently tackle some of the most common challenges in website and application design and development.

### What are Web Components?

"Web Components" is an umbrella term that refers to a collection of web standards focused on enabling the creation of custom HTML elements. Some of the standards that are under the umbrella include the ability to define new HTML tags, plug into a standard component lifecycle, encapsulate HTML rendering and CSS, parameterize CSS, skin components, and more. Each of these platform features is defined by the W3C and has shipped in every major browser today.

### How does FAST leverage Web Components?

`@microsoft/fast-element` provides a thin layer of opinion on top of Web Components, lifting the level of abstraction just enough to make it easier and faster to build components by providing:

- Attribute/property syncing
- Rich Model-View-ViewModel (MVVM) support
- Efficient template rendering/update
- Style composition
- Elements refs, template directives, and much more.

`@microsoft/fast-element` was designed for tree-shaking from the beginning, so any feature you don't use when building a component will be removed during build, allowing for highly efficient optimized payloads. See the [Export Sizes](/docs/2.x/resources/export-sizes/) page for detailed per-export bundle sizes.

One of FAST's driving principles is "strive to adopt open, web standards-based approaches as much as possible." To that end, FAST is built directly on the W3C Web Component standards mentioned above, and does not create its own component model. This allows components built with FAST to function the same as built-in, native HTML elements. You do not need a framework to use FAST components, but you can use them in combination with any framework or library of your choice.

---

### Sites Website Src Docs 2.X Migration Guide (`sites/website/src/docs/2.x/migration-guide.md`)

---
id: migration-guide
title: Migration Guide
layout: 2x
eleventyNavigation:
  key: migration-guide2x
  title: Migration Guide
navigationOptions:
  activeKey: migration-guide2x
keywords:
  - migrate
  - migration
  - web components
---

# Migrating from 1.x to 2.x

## Breaking Changes

### `cssPartial`

The `cssPartial` export no longer exists, in its place use `css.partial`.

1.x Example:
```ts
import { cssPartial } from "@microsoft/fast-element";

cssPartial`
:host {
  color: red;
}`;
```

2.x Example:
```ts
import { css } from "@microsoft/fast-element";

css.partial`
:host {
  color: red;
}`;
```

### `CSSDirective`

The `CSSDirective` has been updated to need to be defined. Additionally it cannot be extended from and must use `implements`.

1.x Example:
```ts
import { CSSDirective } from "@microsoft/fast-element"

class MyCSSDirective extends CSSDirective {
    createCSS() {
      return "color: red;"
    }
}

export const myCssDirective = new MyCSSDirective();
```

2.x Example:
```ts
import { CSSDirective } from "@microsoft/fast-element"

class MyCSSDirective implements CSSDirective {
    createCSS() {
      return "color: red;"
    }
}

CSSDirective.define(MyCSSDirective);

export const myCssDirective = new MyCSSDirective();
```

### `CSSDirective` with behaviors

Behaviors have been extracted from `CSSDirective` so that they can be used in a modular fashion. The API has also been updated to be more intuitive and re-use methods that are common for web components (see `connectedCallback` in the 2.x example below).

1.x Example:
```ts
import { CSSDirective } from "@microsoft/fast-element"

class MyCSSDirective extends CSSDirective {
  public cssProperty: string = "background";

  createCSS() {
    return `display: block; color: red;`
  }

  createBehavior() {
    var that = this;

    return {
      bind(el) {
        el.style.setProperty(that.cssProperty, "yellow")
      },
      unbind(el) {
        el.style.removeProperty(that.cssProperty);
      }
    }
  }
}

export const myCssDirective = new MyCSSDirective();
```

2.x Example:
```ts
import { css, CSSDirective, AddBehavior, HostBehavior } from "@microsoft/fast-element"

const cssProperty: string = "background";

const myCssBehavior: HostBehavior = {
  connectedCallback: (controller) => {
    controller.addStyles(css`:host {${cssProperty}: yellow }`)
  },
  disconnectedCallback: (controller) => {
    controller.removeStyles(css`:host {${cssProperty}: yellow }`)
  }
}

class MyCSSDirective implements CSSDirective {
  createCSS(add: AddBehavior) {
    add(myCssBehavior);
    return `display: block; color: red;`
  }
}

CSSDirective.define(MyCSSDirective);

export const myCssDirective = new MyCSSDirective();
```

## Suggested Changes

While some of the APIs remain available, we suggest going forward that certain patterns be updated.

### `@customElement`

We prefer using `FASTElement` and its `.define()` method over the `@customElement` decorator (which is still used under the hood). We believe this more closely matches with how you define custom elements using the native `customElements.define()`.

1.x Example:
```ts
import { FASTElement, customElement } from '@microsoft/fast-element';

@customElement('my-component')
export class MyComponent extends FASTElement {}
```

2.x Example:
```ts
import { FASTElement } from "@microsoft/fast-element";

class MyComponent extends FASTElement {}

MyComponent.define({
  name: "my-component"
});
```

---

### Sites Website Src Docs 2.X Resources (`sites/website/src/docs/2.x/resources.md`)

---
layout: 2x
eleventyNavigation:
  key: resources2x
  title: Resources
navigationOptions:
  activeKey: resources2x
permalink: false
---

---

### Sites Website Src Docs 3.X Advanced (`sites/website/src/docs/3.x/advanced.md`)

---
layout: 3x
eleventyNavigation:
  key: advanced3x
  title: Advanced Concepts
  order: 3
navigationOptions:
  activeKey: advanced3x
permalink: false
---

---

### Sites Website Src Docs 3.X Api (`sites/website/src/docs/3.x/api.md`)

---
id: api-reference
title: API Reference
layout: 3x
eleventyNavigation:
  key: api3x
  title: API Reference
  order: 4
navigationOptions:
  activeKey: api3x
permalink: /docs/3.x/api/overview/
description: FAST Element 3.x API reference and package export guide.
keywords:
  - API
  - reference
  - exports
  - imports
  - stability
---

# API Reference

Use this page to choose the right FAST Element import path and then browse the
generated API reference for the public surface of each entrypoint.

## Root vs. path exports

The root package export, `@microsoft/fast-element`, is the primary entrypoint for
FAST Element's component authoring APIs. It is the best default when you are
building custom elements with `FASTElement`, `html`, `css`, `attr`, directives,
observables, state helpers, and other core primitives.

FAST Element 3.x also publishes focused path exports. Use a path export when you
want a smaller, feature-specific entrypoint or when the API is path-only. The
path-only entrypoints should always be imported from their documented package
paths rather than from the package root.

## Common import choices

| Need | Import from | Reference |
|---|---|---|
| Core component authoring APIs | `@microsoft/fast-element` | [Root API reference](/docs/3.x/api/fast-element/) |
| Declarative HTML templates | `@microsoft/fast-element/declarative.js` | [Declarative API reference](/docs/3.x/api/fast-element/declarative/) and [Declarative HTML overview](/docs/3.x/declarative-templates/overview/) |
| Server-rendered hydration | `@microsoft/fast-element/hydration.js` | [Hydration flow](/docs/3.x/declarative-templates/server-rendering/#hydration-flow) and [path export list](/docs/3.x/advanced/path-exports/) |
| W3C Context protocol helpers | `@microsoft/fast-element/context.js` | [Context API reference](/docs/3.x/api/fast-element/context/) |
| Dependency injection container APIs | `@microsoft/fast-element/di.js` | [DI API reference](/docs/3.x/api/fast-element/di/) and [Dependency Injection guide](/docs/3.x/advanced/dependency-injection/) |
| Individual core features, such as `html`, `css`, `attr`, or directives | The matching path export, such as `@microsoft/fast-element/html.js` | [Path exports](/docs/3.x/advanced/path-exports/) |

## Stability tags

The generated API pages include release-tag callouts from API Extractor:

- **Public** APIs are the supported surface for production code.
- **Beta** APIs are preview APIs that can change based on feedback.
- **Alpha** APIs are early previews and should be treated as less stable than
  beta APIs.
- **Internal** APIs are not intended for application code, even when they appear
  in a type signature or generated page.

Prefer public APIs when possible. If a generated page includes a beta or alpha
notice, review the callout before depending on that symbol in production code.

## Generated API docs

The API reference pages are generated from FAST Element's API Extractor output
and should not be edited by hand. Start with the generated
[`@microsoft/fast-element` root reference](/docs/3.x/api/fast-element/) for the
main package surface, then use the path-export references for focused APIs:

- [`@microsoft/fast-element/declarative.js`](/docs/3.x/api/fast-element/declarative/)
- [`@microsoft/fast-element/context.js`](/docs/3.x/api/fast-element/context/)
- [`@microsoft/fast-element/di.js`](/docs/3.x/api/fast-element/di/)

For the complete list of supported package paths, see the
[Path Exports](/docs/3.x/advanced/path-exports/) page.

---

### Sites Website Src Docs 3.X Community (`sites/website/src/docs/3.x/community.md`)

---
layout: 3x
eleventyNavigation:
  key: community3x
  title: Community Contribution
navigationOptions:
  activeKey: community3x
permalink: false
---

---

### Sites Website Src Docs 3.X Declarative Templates (`sites/website/src/docs/3.x/declarative-templates.md`)

---
layout: 3x
eleventyNavigation:
  key: declarative-templates3x
  title: Declarative HTML
  order: 3
navigationOptions:
  activeKey: declarative-templates3x
permalink: false
---

---

### Sites Website Src Docs 3.X Integrations (`sites/website/src/docs/3.x/integrations.md`)

---
id: integrations
title: Integrations
layout: 3x
eleventyNavigation:
  key: integrations3x
  title: Integrations
navigationOptions:
  activeKey: integrations3x
keywords:
  - integrations
  - angular
  - asp.net
  - aurelia 2
  - ember
  - react
  - rollup
  - svelte
  - vite
  - vue
  - webpack
  - web components
---

# Integrations

If your project includes one of the popular frameworks below, we've included some helpful tips.

Natively supported, no additional configuration needed:

- ASP.NET
- Ember
- Svelte
- Vite
- Vue
- Webpack

## Angular

[Angular](https://angular.io/) works well with web components, 

To work with typings within Angular, check out their documentation on [custom typings](https://angular.io/guide/elements#typings-for-custom-elements).

## Aurelia 2

FAST works flawlessly with Aurelia 2, with full integration into the binding engine and component model.

### Enabling two-way bindings

Aurelia knows by default how to listen for changes in native elements. Now we need to teach it how to listen for changes in FAST elements. You can do so by [extending its templating syntax](https://docs.aurelia.io/examples/integration/ms-fast). 

You can either use a [wrapper](https://www.npmjs.com/package/aurelia-fast-adapter) developed by the community or teach Aurelia manually:

### Import and register `aurelia-fast-adapter`

Start by installing the adapter

```ts
npm install aurelia-fast-adapter
```

and then simply register it from your `src/main.ts`:

```ts
// src/main.ts

import { FASTAdapter } from 'aurelia-fast-adapter';

Aurelia
  .register(FASTAdapter) // add this line
  // other registrations...
  .start();
```

If you use FAST in its default configuration that's all you need to do. But if you changed the prefix of your components to something else, you can customize the adapter as such:

```ts
// src/main.ts

import { FASTAdapter } from 'aurelia-fast-adapter';

Aurelia
  .register(FASTAdapter.customize({withPrefix: 'my-custom-prefix'}) // customized with prefix
  .start();
```

Also, in case you have local components that require two-way binding, you can adjust the adapter before to register it as such:

```ts
// src/main.ts

import { FASTAdapter } from 'aurelia-fast-adapter';

// this line will tell the adapter that it must use two-way binding on the <my-custom-prefix-date-field> component and use this two-way binding on the `value` property. It's possible to add several properties at once if necessary
FASTAdapter.tags['DATE-FIELD'] = ['value'];

Aurelia
  .register(FASTAdapter.customize({withPrefix: 'my-custom-prefix'})
  .start();
```

Congratulations! You're now set up to use FAST and Aurelia 2!

### Manually teach Aurelia 2 about two-way binding:

If the example doesn't seem obvious, the following prerequisite reads are recommended:

* [extending Aurelia templating syntax](https://docs.aurelia.io/app-basics/extending-templating-syntax)

The following is a code example of how to teach Aurelia to work seamlessly with Microsoft FAST.

```
/* Detailed source-code truncated for AI context efficiency. */
```

## React

See the [React documentation](https://react.dev/reference/react-dom/components#custom-html-elements) on including custom elements.

## Rollup

In your `rollup.config.js` file in the root of your project folder can look something like this:

```js
import transformTaggedTemplate from 'rollup-plugin-transform-tagged-template';
import typescript from '@rollup/plugin-typescript';
import resolve from '@rollup/plugin-node-resolve';
import cleaner from 'rollup-plugin-cleaner';
import copy from 'rollup-plugin-copy';
import serve from 'rollup-plugin-serve';
import terser from '@rollup/plugin-terser';

export default {
  input: 'src/main.ts',
  output: {
    file: 'dist/bundle.js',
    name: 'bundle',
    format: 'umd',
    sourcemap: true
  },
  plugins: [
    transformTaggedTemplate({
      tagsToProcess: ['html','css'],
      parserOptions: {
        sourceType: "module",
        plugins: [
            "typescript",
            [
                "decorators",
                { decoratorsBeforeExport: true }
            ]
        ]
      },
      transformer(data) {
          data = data.replace(/\s([{}()>~+=^$:!;])\s/gm, '$1');
          data = data.replace(/([",[]])\s+/gm, '$1');
          data = data.replace(/\s{2,}/gm, ' ');
          return data.trim();
      }
    }),
    typescript(),
    resolve(),
    cleaner({
      targets: [
      'dist'
      ]
    }),
    copy({
      targets: [
        { src: 'index.html', dest: 'dist' },
      ]
    }),
    serve({
      open: true,
      contentBase: 'dist'
    }),
    terser(),
  ]
};
```

Let's go over a few of the plugins we would suggest using:
- `transformTaggedTemplate` minifies content within tagged templates (e.g. html and css)
- `typescript` allows us to write our source files in TypeScript.
- `resolve` allows us to import modules installed from npm, like `@microsoft/fast-element`.

## TypeScript

Here's an example starter `tsconfig.json` that you can use:

```json
{
  "compilerOptions": {
    "pretty": true,
    "target": "ES2015",
    "module": "ES2015",
    "moduleResolution": "node",
    "importHelpers": true, // when using decorators this allows for the smallest footprint using tslib
    "experimentalDecorators": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "noEmitOnError": true,
    "strict": true,
    "outDir": "dist/build",
    "rootDir": "src",
    "lib": [
      "dom",
      "esnext"
    ]
  },
  "include": [
    "src"
  ]
}
```

Note the inclusion of `"dom"` and `"experimentalDecorators"`.

You can learn more about `tsconfig.json` options in [the official TypeScript documentation](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html).

:::note
Do not set `useDefineForClassFields` to `true` in your `tsconfig.json` if you are using decorators (e.g. `ExperimentalDecorators`). These two features conflict at present. This will be resolved in future versions of TypeScript and FAST.
:::

---

### Sites Website Src Docs 3.X Introduction (`sites/website/src/docs/3.x/introduction.md`)

---
id: introduction
title: Introduction
layout: 3x
eleventyNavigation:
  key: introduction3x
  title: Introduction
  order: 1
navigationOptions:
  activeKey: introduction3x
keywords:
  - introduction
  - web components
---

# Introduction

## What is FAST?

FAST is a collection of technologies built on Web Components and modern Web Standards, designed to help you efficiently tackle some of the most common challenges in website and application design and development.

### What are Web Components?

"Web Components" is an umbrella term that refers to a collection of web standards focused on enabling the creation of custom HTML elements. Some of the standards that are under the umbrella include the ability to define new HTML tags, plug into a standard component lifecycle, encapsulate HTML rendering and CSS, parameterize CSS, skin components, and more. Each of these platform features is defined by the W3C and has shipped in every major browser today.

### How does FAST leverage Web Components?

`@microsoft/fast-element` provides a thin layer of opinion on top of Web Components, lifting the level of abstraction just enough to make it easier and faster to build components by providing:

- Attribute/property syncing
- Rich Model-View-ViewModel (MVVM) support
- Efficient template rendering/update
- Style composition
- Elements refs, template directives, and much more.

The entire `@microsoft/fast-element` library, without tree-shaking, is around 10kb minified and GZipped. It was designed for tree-shaking from the beginning, so any feature you don't use when building a component will be removed during build, allowing for highly efficient optimized payloads as small as 4.5k.

One of FAST's driving principles is "strive to adopt open, web standards-based approaches as much as possible." To that end, FAST is built directly on the W3C Web Component standards mentioned above, and does not create its own component model. This allows components built with FAST to function the same as built-in, native HTML elements. You do not need a framework to use FAST components, but you can use them in combination with any framework or library of your choice.

---

### Sites Website Src Docs 3.X Migration Guide (`sites/website/src/docs/3.x/migration-guide.md`)

---
layout: 3x
eleventyNavigation:
  key: migration-guide3x
  title: Migration Guide
  order: 8
navigationOptions:
  activeKey: migration-guide3x
permalink: false
---

---

### Sites Website Src Docs 3.X Resources (`sites/website/src/docs/3.x/resources.md`)

---
layout: 3x
eleventyNavigation:
  key: resources3x
  title: Resources
navigationOptions:
  activeKey: resources3x
permalink: false
---

---

### Sites Website Src Docs 1.X Api Fast Animation.Animate. Constructor  (`sites/website/src/docs/1.x/api/fast-animation.animate._constructor_.md`)

---
id: fast-animation.animate._constructor_
title: Animate.(constructor)
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [Animate](./fast-animation.animate.md) &gt; [(constructor)](./fast-animation.animate._constructor_.md)

## Animate.(constructor)

Constructs a new instance of the `Animate` class

<b>Signature:</b>

```typescript
constructor(element: HTMLElement, options?: AnimateConfig, effectTiming?: EffectTiming);
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  element | HTMLElement |  |
|  options | AnimateConfig |  |
|  effectTiming | EffectTiming |  |

---

### Sites Website Src Docs 1.X Api Fast Animation.Animate.Addkeyframes (`sites/website/src/docs/1.x/api/fast-animation.animate.addkeyframes.md`)

---
id: fast-animation.animate.addkeyframes
title: Animate.addKeyframes property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [Animate](./fast-animation.animate.md) &gt; [addKeyframes](./fast-animation.animate.addkeyframes.md)

## Animate.addKeyframes property

adds a set of keyframes to set of animation keyframes the animation should execute

<b>Signature:</b>

```typescript
addKeyframes: (keyframes: Array<Partial<Keyframe>>) => void;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animate.Cancel (`sites/website/src/docs/1.x/api/fast-animation.animate.cancel.md`)

---
id: fast-animation.animate.cancel
title: Animate.cancel property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [Animate](./fast-animation.animate.md) &gt; [cancel](./fast-animation.animate.cancel.md)

## Animate.cancel property

cancels the animation

<b>Signature:</b>

```typescript
cancel: () => void;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animate.Effecttiming (`sites/website/src/docs/1.x/api/fast-animation.animate.effecttiming.md`)

---
id: fast-animation.animate.effecttiming
title: Animate.effectTiming property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [Animate](./fast-animation.animate.md) &gt; [effectTiming](./fast-animation.animate.effecttiming.md)

## Animate.effectTiming property

Stores animation timing functions

<b>Signature:</b>

```typescript
effectTiming: EffectTiming;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animate.Finish (`sites/website/src/docs/1.x/api/fast-animation.animate.finish.md`)

---
id: fast-animation.animate.finish
title: Animate.finish property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [Animate](./fast-animation.animate.md) &gt; [finish](./fast-animation.animate.finish.md)

## Animate.finish property

finishes the animation

<b>Signature:</b>

```typescript
finish: () => void;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animate.Keyframeeffect (`sites/website/src/docs/1.x/api/fast-animation.animate.keyframeeffect.md`)

---
id: fast-animation.animate.keyframeeffect
title: Animate.keyframeEffect property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [Animate](./fast-animation.animate.md) &gt; [keyframeEffect](./fast-animation.animate.keyframeeffect.md)

## Animate.keyframeEffect property

Returns the key frame effect object

<b>Signature:</b>

```typescript
get keyframeEffect(): KeyframeEffect;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animate.Keyframes (`sites/website/src/docs/1.x/api/fast-animation.animate.keyframes.md`)

---
id: fast-animation.animate.keyframes
title: Animate.keyframes property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [Animate](./fast-animation.animate.md) &gt; [keyframes](./fast-animation.animate.keyframes.md)

## Animate.keyframes property

Returns the animation's keyframes

<b>Signature:</b>

```typescript
get keyframes(): Keyframe[];
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animate (`sites/website/src/docs/1.x/api/fast-animation.animate.md`)

---
id: fast-animation.animate
title: Animate class
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [Animate](./fast-animation.animate.md)

## Animate class

Base animate type. This is extended by [AnimateTo](./fast-animation.animateto.md) and [AnimateFrom](./fast-animation.animatefrom.md).

<b>Signature:</b>

```typescript
export default abstract class Animate 
```

## Constructors

|  Constructor | Modifiers | Description |
|  --- | --- | --- |
|  [(constructor)(element, options, effectTiming)](./fast-animation.animate._constructor_.md) |  | Constructs a new instance of the <code>Animate</code> class |

## Properties

|  Property | Modifiers | Type | Description |
|  --- | --- | --- | --- |
|  [addKeyframes](./fast-animation.animate.addkeyframes.md) |  | (keyframes: Array&lt;Partial&lt;Keyframe&gt;&gt;) =&gt; void | adds a set of keyframes to set of animation keyframes the animation should execute |
|  [cancel](./fast-animation.animate.cancel.md) |  | () =&gt; void | cancels the animation |
|  [effectTiming](./fast-animation.animate.effecttiming.md) |  | EffectTiming | Stores animation timing functions |
|  [finish](./fast-animation.animate.finish.md) |  | () =&gt; void | finishes the animation |
|  [keyframeEffect](./fast-animation.animate.keyframeeffect.md) |  | KeyframeEffect | Returns the key frame effect object |
|  [keyframes](./fast-animation.animate.keyframes.md) |  | Keyframe\[\] | Returns the animation's keyframes |
|  [mode](./fast-animation.animate.mode.md) |  | AnimationMode | Tracks if the animation should animate toward an elements natural position or away from it |
|  [onCancel](./fast-animation.animate.oncancel.md) |  | () =&gt; void | Callback to call when the animation is canceled |
|  [onFinish](./fast-animation.animate.onfinish.md) |  | () =&gt; void |  |
|  [options](./fast-animation.animate.options.md) |  | AnimateConfig | Stores animation options |
|  [pause](./fast-animation.animate.pause.md) |  | () =&gt; void | pauses the animation |
|  [play](./fast-animation.animate.play.md) |  | () =&gt; void | plays the animation |
|  [reverse](./fast-animation.animate.reverse.md) |  | () =&gt; void | reverses an animation |

---

### Sites Website Src Docs 1.X Api Fast Animation.Animate.Mode (`sites/website/src/docs/1.x/api/fast-animation.animate.mode.md`)

---
id: fast-animation.animate.mode
title: Animate.mode property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [Animate](./fast-animation.animate.md) &gt; [mode](./fast-animation.animate.mode.md)

## Animate.mode property

Tracks if the animation should animate toward an elements natural position or away from it

<b>Signature:</b>

```typescript
protected mode: AnimationMode;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animate.Oncancel (`sites/website/src/docs/1.x/api/fast-animation.animate.oncancel.md`)

---
id: fast-animation.animate.oncancel
title: Animate.onCancel property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [Animate](./fast-animation.animate.md) &gt; [onCancel](./fast-animation.animate.oncancel.md)

## Animate.onCancel property

Callback to call when the animation is canceled

<b>Signature:</b>

```typescript
onCancel: () => void;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animate.Onfinish (`sites/website/src/docs/1.x/api/fast-animation.animate.onfinish.md`)

---
id: fast-animation.animate.onfinish
title: Animate.onFinish property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [Animate](./fast-animation.animate.md) &gt; [onFinish](./fast-animation.animate.onfinish.md)

## Animate.onFinish property

<b>Signature:</b>

```typescript
get onFinish(): () => void;

set onFinish(callback: () => void);
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animate.Options (`sites/website/src/docs/1.x/api/fast-animation.animate.options.md`)

---
id: fast-animation.animate.options
title: Animate.options property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [Animate](./fast-animation.animate.md) &gt; [options](./fast-animation.animate.options.md)

## Animate.options property

Stores animation options

<b>Signature:</b>

```typescript
options: AnimateConfig;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animate.Pause (`sites/website/src/docs/1.x/api/fast-animation.animate.pause.md`)

---
id: fast-animation.animate.pause
title: Animate.pause property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [Animate](./fast-animation.animate.md) &gt; [pause](./fast-animation.animate.pause.md)

## Animate.pause property

pauses the animation

<b>Signature:</b>

```typescript
pause: () => void;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animate.Play (`sites/website/src/docs/1.x/api/fast-animation.animate.play.md`)

---
id: fast-animation.animate.play
title: Animate.play property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [Animate](./fast-animation.animate.md) &gt; [play](./fast-animation.animate.play.md)

## Animate.play property

plays the animation

<b>Signature:</b>

```typescript
play: () => void;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animate.Reverse (`sites/website/src/docs/1.x/api/fast-animation.animate.reverse.md`)

---
id: fast-animation.animate.reverse
title: Animate.reverse property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [Animate](./fast-animation.animate.md) &gt; [reverse](./fast-animation.animate.reverse.md)

## Animate.reverse property

reverses an animation

<b>Signature:</b>

```typescript
reverse: () => void;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animatefrom (`sites/website/src/docs/1.x/api/fast-animation.animatefrom.md`)

---
id: fast-animation.animatefrom
title: AnimateFrom class
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateFrom](./fast-animation.animatefrom.md)

## AnimateFrom class

An animation from provided property values to the element's current values. Extends [Animate](./fast-animation.animate.md).

<b>Signature:</b>

```typescript
export default class AnimateFrom extends Animate 
```

## Properties

|  Property | Modifiers | Type | Description |
|  --- | --- | --- | --- |
|  [mode](./fast-animation.animatefrom.mode.md) |  | AnimationMode |  |

---

### Sites Website Src Docs 1.X Api Fast Animation.Animatefrom.Mode (`sites/website/src/docs/1.x/api/fast-animation.animatefrom.mode.md`)

---
id: fast-animation.animatefrom.mode
title: AnimateFrom.mode property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateFrom](./fast-animation.animatefrom.md) &gt; [mode](./fast-animation.animatefrom.mode.md)

## AnimateFrom.mode property

<b>Signature:</b>

```typescript
protected mode: AnimationMode;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animategroup. Constructor  (`sites/website/src/docs/1.x/api/fast-animation.animategroup._constructor_.md`)

---
id: fast-animation.animategroup._constructor_
title: AnimateGroup.(constructor)
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateGroup](./fast-animation.animategroup.md) &gt; [(constructor)](./fast-animation.animategroup._constructor_.md)

## AnimateGroup.(constructor)

Constructs a new instance of the `AnimateGroup` class

<b>Signature:</b>

```typescript
constructor(animations: Array<AnimateTo | AnimateFrom>);
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  animations | Array&lt;AnimateTo \| AnimateFrom&gt; |  |

---

### Sites Website Src Docs 1.X Api Fast Animation.Animategroup.Cancel (`sites/website/src/docs/1.x/api/fast-animation.animategroup.cancel.md`)

---
id: fast-animation.animategroup.cancel
title: AnimateGroup.cancel property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateGroup](./fast-animation.animategroup.md) &gt; [cancel](./fast-animation.animategroup.cancel.md)

## AnimateGroup.cancel property

Cancels all animations in the group

<b>Signature:</b>

```typescript
cancel: () => void;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animategroup.Finish (`sites/website/src/docs/1.x/api/fast-animation.animategroup.finish.md`)

---
id: fast-animation.animategroup.finish
title: AnimateGroup.finish property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateGroup](./fast-animation.animategroup.md) &gt; [finish](./fast-animation.animategroup.finish.md)

## AnimateGroup.finish property

Finishes all animations in the group

<b>Signature:</b>

```typescript
finish: () => void;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animategroup (`sites/website/src/docs/1.x/api/fast-animation.animategroup.md`)

---
id: fast-animation.animategroup
title: AnimateGroup class
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateGroup](./fast-animation.animategroup.md)

## AnimateGroup class

Groups [AnimateTo](./fast-animation.animateto.md) and [AnimateFrom](./fast-animation.animatefrom.md) instances, providing a single API to operate on all of them.

<b>Signature:</b>

```typescript
declare class AnimateGroup 
```

## Constructors

|  Constructor | Modifiers | Description |
|  --- | --- | --- |
|  [(constructor)(animations)](./fast-animation.animategroup._constructor_.md) |  | Constructs a new instance of the <code>AnimateGroup</code> class |

## Properties

|  Property | Modifiers | Type | Description |
|  --- | --- | --- | --- |
|  [cancel](./fast-animation.animategroup.cancel.md) |  | () =&gt; void | Cancels all animations in the group |
|  [finish](./fast-animation.animategroup.finish.md) |  | () =&gt; void | Finishes all animations in the group |
|  [onFinish](./fast-animation.animategroup.onfinish.md) |  | () =&gt; void | The onFinish callback. |
|  [pause](./fast-animation.animategroup.pause.md) |  | () =&gt; void | Pauses all animations in the group |

## Methods

|  Method | Modifiers | Description |
|  --- | --- | --- |
|  [play()](./fast-animation.animategroup.play.md) |  | Play the group of animations |
|  [reverse()](./fast-animation.animategroup.reverse.md) |  | Reverses all animations in the group |

---

### Sites Website Src Docs 1.X Api Fast Animation.Animategroup.Onfinish (`sites/website/src/docs/1.x/api/fast-animation.animategroup.onfinish.md`)

---
id: fast-animation.animategroup.onfinish
title: AnimateGroup.onFinish property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateGroup](./fast-animation.animategroup.md) &gt; [onFinish](./fast-animation.animategroup.onfinish.md)

## AnimateGroup.onFinish property

The onFinish callback.

<b>Signature:</b>

```typescript
get onFinish(): () => void;

set onFinish(callback: () => void);
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animategroup.Pause (`sites/website/src/docs/1.x/api/fast-animation.animategroup.pause.md`)

---
id: fast-animation.animategroup.pause
title: AnimateGroup.pause property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateGroup](./fast-animation.animategroup.md) &gt; [pause](./fast-animation.animategroup.pause.md)

## AnimateGroup.pause property

Pauses all animations in the group

<b>Signature:</b>

```typescript
pause: () => void;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animategroup.Play (`sites/website/src/docs/1.x/api/fast-animation.animategroup.play.md`)

---
id: fast-animation.animategroup.play
title: AnimateGroup.play() method
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateGroup](./fast-animation.animategroup.md) &gt; [play](./fast-animation.animategroup.play.md)

## AnimateGroup.play() method

Play the group of animations

<b>Signature:</b>

```typescript
play(): void;
```
<b>Returns:</b>

void

---

### Sites Website Src Docs 1.X Api Fast Animation.Animategroup.Reverse (`sites/website/src/docs/1.x/api/fast-animation.animategroup.reverse.md`)

---
id: fast-animation.animategroup.reverse
title: AnimateGroup.reverse() method
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateGroup](./fast-animation.animategroup.md) &gt; [reverse](./fast-animation.animategroup.reverse.md)

## AnimateGroup.reverse() method

Reverses all animations in the group

<b>Signature:</b>

```typescript
reverse(): void;
```
<b>Returns:</b>

void

---

### Sites Website Src Docs 1.X Api Fast Animation.Animatesequence. Constructor  (`sites/website/src/docs/1.x/api/fast-animation.animatesequence._constructor_.md`)

---
id: fast-animation.animatesequence._constructor_
title: AnimateSequence.(constructor)
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateSequence](./fast-animation.animatesequence.md) &gt; [(constructor)](./fast-animation.animatesequence._constructor_.md)

## AnimateSequence.(constructor)

Constructs a new instance of the `AnimateSequence` class

<b>Signature:</b>

```typescript
constructor(animations: Array<AnimateTo | AnimateFrom>);
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  animations | Array&lt;AnimateTo \| AnimateFrom&gt; |  |

---

### Sites Website Src Docs 1.X Api Fast Animation.Animatesequence.Cancel (`sites/website/src/docs/1.x/api/fast-animation.animatesequence.cancel.md`)

---
id: fast-animation.animatesequence.cancel
title: AnimateSequence.cancel property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateSequence](./fast-animation.animatesequence.md) &gt; [cancel](./fast-animation.animatesequence.cancel.md)

## AnimateSequence.cancel property

Cancels all animations in the sequence

<b>Signature:</b>

```typescript
cancel: () => void;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animatesequence.Finish (`sites/website/src/docs/1.x/api/fast-animation.animatesequence.finish.md`)

---
id: fast-animation.animatesequence.finish
title: AnimateSequence.finish property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateSequence](./fast-animation.animatesequence.md) &gt; [finish](./fast-animation.animatesequence.finish.md)

## AnimateSequence.finish property

Finishes all animations in the sequence

<b>Signature:</b>

```typescript
finish: () => void;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animatesequence (`sites/website/src/docs/1.x/api/fast-animation.animatesequence.md`)

---
id: fast-animation.animatesequence
title: AnimateSequence class
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateSequence](./fast-animation.animatesequence.md)

## AnimateSequence class

Animate a collection of [AnimateTo](./fast-animation.animateto.md) and [AnimateFrom](./fast-animation.animatefrom.md) in sequence.

<b>Signature:</b>

```typescript
declare class AnimateSequence 
```

## Constructors

|  Constructor | Modifiers | Description |
|  --- | --- | --- |
|  [(constructor)(animations)](./fast-animation.animatesequence._constructor_.md) |  | Constructs a new instance of the <code>AnimateSequence</code> class |

## Properties

|  Property | Modifiers | Type | Description |
|  --- | --- | --- | --- |
|  [cancel](./fast-animation.animatesequence.cancel.md) |  | () =&gt; void | Cancels all animations in the sequence |
|  [finish](./fast-animation.animatesequence.finish.md) |  | () =&gt; void | Finishes all animations in the sequence |
|  [onFinish](./fast-animation.animatesequence.onfinish.md) |  | () =&gt; void | onFinish callback method |
|  [pause](./fast-animation.animatesequence.pause.md) |  | () =&gt; void | Pauses all animations in the sequence |
|  [play](./fast-animation.animatesequence.play.md) |  | () =&gt; void | Play the sequence of animations |
|  [reverse](./fast-animation.animatesequence.reverse.md) |  | () =&gt; void | Play the sequence in reverse |

---

### Sites Website Src Docs 1.X Api Fast Animation.Animatesequence.Onfinish (`sites/website/src/docs/1.x/api/fast-animation.animatesequence.onfinish.md`)

---
id: fast-animation.animatesequence.onfinish
title: AnimateSequence.onFinish property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateSequence](./fast-animation.animatesequence.md) &gt; [onFinish](./fast-animation.animatesequence.onfinish.md)

## AnimateSequence.onFinish property

onFinish callback method

<b>Signature:</b>

```typescript
onFinish: () => void;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animatesequence.Pause (`sites/website/src/docs/1.x/api/fast-animation.animatesequence.pause.md`)

---
id: fast-animation.animatesequence.pause
title: AnimateSequence.pause property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateSequence](./fast-animation.animatesequence.md) &gt; [pause](./fast-animation.animatesequence.pause.md)

## AnimateSequence.pause property

Pauses all animations in the sequence

<b>Signature:</b>

```typescript
pause: () => void;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animatesequence.Play (`sites/website/src/docs/1.x/api/fast-animation.animatesequence.play.md`)

---
id: fast-animation.animatesequence.play
title: AnimateSequence.play property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateSequence](./fast-animation.animatesequence.md) &gt; [play](./fast-animation.animatesequence.play.md)

## AnimateSequence.play property

Play the sequence of animations

<b>Signature:</b>

```typescript
play: () => void;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animatesequence.Reverse (`sites/website/src/docs/1.x/api/fast-animation.animatesequence.reverse.md`)

---
id: fast-animation.animatesequence.reverse
title: AnimateSequence.reverse property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateSequence](./fast-animation.animatesequence.md) &gt; [reverse](./fast-animation.animatesequence.reverse.md)

## AnimateSequence.reverse property

Play the sequence in reverse

<b>Signature:</b>

```typescript
reverse: () => void;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Animateto (`sites/website/src/docs/1.x/api/fast-animation.animateto.md`)

---
id: fast-animation.animateto
title: AnimateTo class
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateTo](./fast-animation.animateto.md)

## AnimateTo class

An animation to provided property values from the element's current values. Extends [Animate](./fast-animation.animate.md).

<b>Signature:</b>

```typescript
export default class AnimateTo extends Animate 
```

## Properties

|  Property | Modifiers | Type | Description |
|  --- | --- | --- | --- |
|  [mode](./fast-animation.animateto.mode.md) |  | AnimationMode |  |

---

### Sites Website Src Docs 1.X Api Fast Animation.Animateto.Mode (`sites/website/src/docs/1.x/api/fast-animation.animateto.mode.md`)

---
id: fast-animation.animateto.mode
title: AnimateTo.mode property
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [AnimateTo](./fast-animation.animateto.md) &gt; [mode](./fast-animation.animateto.mode.md)

## AnimateTo.mode property

<b>Signature:</b>

```typescript
protected mode: AnimationMode;
```

---

### Sites Website Src Docs 1.X Api Fast Animation.Cubicbezier (`sites/website/src/docs/1.x/api/fast-animation.cubicbezier.md`)

---
id: fast-animation.cubicbezier
title: cubicBezier() function
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [cubicBezier](./fast-animation.cubicbezier.md)

## cubicBezier() function

Get a cubic bezier curve, formatted as a string, by name.

<b>Signature:</b>

```typescript
export declare function cubicBezier(name: "linear" | "easeOut" | "easeOutSmooth" | "easeIn" | "drillIn" | "backToApp" | "appToApp" | "fastIn" | "fastOut" | "fastInOut" | "exponential" | "fastInFortySevenPercent" | "exponentialReversed" | "navPane" | /* @deprecated */ string): string;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  name | "linear" \| "easeOut" \| "easeOutSmooth" \| "easeIn" \| "drillIn" \| "backToApp" \| "appToApp" \| "fastIn" \| "fastOut" \| "fastInOut" \| "exponential" \| "fastInFortySevenPercent" \| "exponentialReversed" \| "navPane" \| /\* @deprecated \*/ string | the name of the bezier curve to use. |

<b>Returns:</b>

string

---

### Sites Website Src Docs 1.X Api Fast Animation.Fadein (`sites/website/src/docs/1.x/api/fast-animation.fadein.md`)

---
id: fast-animation.fadein
title: fadeIn() function
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [fadeIn](./fast-animation.fadein.md)

## fadeIn() function

Creates an animation to fade an element into view

<b>Signature:</b>

```typescript
export declare function fadeIn(element: HTMLElement, effectTiming?: EffectTiming): AnimateTo;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  element | HTMLElement |  |
|  effectTiming | EffectTiming |  |

<b>Returns:</b>

AnimateTo

---

### Sites Website Src Docs 1.X Api Fast Animation.Fadeout (`sites/website/src/docs/1.x/api/fast-animation.fadeout.md`)

---
id: fast-animation.fadeout
title: fadeOut() function
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [fadeOut](./fast-animation.fadeout.md)

## fadeOut() function

Creates an animation to fade an element out of view

<b>Signature:</b>

```typescript
export declare function fadeOut(element: HTMLElement, effectTiming?: EffectTiming): AnimateTo;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  element | HTMLElement |  |
|  effectTiming | EffectTiming |  |

<b>Returns:</b>

AnimateTo

---

### Sites Website Src Docs 1.X Api Fast Animation (`sites/website/src/docs/1.x/api/fast-animation.md`)

---
id: fast-animation
title: fast-animation 
hide_title: false
layout: 1x
---




## Classes

|  Class | Description |
|  --- | --- |
|  [Animate](./fast-animation.animate.md) | Base animate type. This is extended by [AnimateTo](./fast-animation.animateto.md) and [AnimateFrom](./fast-animation.animatefrom.md). |
|  [AnimateFrom](./fast-animation.animatefrom.md) | An animation from provided property values to the element's current values. Extends [Animate](./fast-animation.animate.md). |
|  [AnimateGroup](./fast-animation.animategroup.md) | Groups [AnimateTo](./fast-animation.animateto.md) and [AnimateFrom](./fast-animation.animatefrom.md) instances, providing a single API to operate on all of them. |
|  [AnimateSequence](./fast-animation.animatesequence.md) | Animate a collection of [AnimateTo](./fast-animation.animateto.md) and [AnimateFrom](./fast-animation.animatefrom.md) in sequence. |
|  [AnimateTo](./fast-animation.animateto.md) | An animation to provided property values from the element's current values. Extends [Animate](./fast-animation.animate.md). |
|  [ScrollTrigger](./fast-animation.scrolltrigger.md) | Utility for registering element/callback pairs where the callback will be called on scroll while the element is in view. |
|  [ViewEnterTrigger](./fast-animation.viewentertrigger.md) | Utility for registering element/callback pairs where the callback will be called when the element enters the view-port |
|  [ViewExitTrigger](./fast-animation.viewexittrigger.md) | Utility for registering element/callback pairs where the callback will be invoked when the element exits the view-port |

## Functions

|  Function | Description |
|  --- | --- |
|  [cubicBezier(name)](./fast-animation.cubicbezier.md) | Get a cubic bezier curve, formatted as a string, by name. |
|  [fadeIn(element, effectTiming)](./fast-animation.fadein.md) | Creates an animation to fade an element into view |
|  [fadeOut(element, effectTiming)](./fast-animation.fadeout.md) | Creates an animation to fade an element out of view |

---

### Sites Website Src Docs 1.X Api Fast Animation.Scrolltrigger (`sites/website/src/docs/1.x/api/fast-animation.scrolltrigger.md`)

---
id: fast-animation.scrolltrigger
title: ScrollTrigger class
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [ScrollTrigger](./fast-animation.scrolltrigger.md)

## ScrollTrigger class

Utility for registering element/callback pairs where the callback will be called on scroll while the element is in view.

<b>Signature:</b>

```typescript
export default class ScrollTrigger extends ScrollBase 
```

## Methods

|  Method | Modifiers | Description |
|  --- | --- | --- |
|  [update()](./fast-animation.scrolltrigger.update.md) |  | Check if elements are in view-port and apply scroll method if they are |

---

### Sites Website Src Docs 1.X Api Fast Animation.Scrolltrigger.Update (`sites/website/src/docs/1.x/api/fast-animation.scrolltrigger.update.md`)

---
id: fast-animation.scrolltrigger.update
title: ScrollTrigger.update() method
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [ScrollTrigger](./fast-animation.scrolltrigger.md) &gt; [update](./fast-animation.scrolltrigger.update.md)

## ScrollTrigger.update() method

Check if elements are in view-port and apply scroll method if they are

<b>Signature:</b>

```typescript
protected update(): void;
```
<b>Returns:</b>

void

---

### Sites Website Src Docs 1.X Api Fast Animation.Viewentertrigger (`sites/website/src/docs/1.x/api/fast-animation.viewentertrigger.md`)

---
id: fast-animation.viewentertrigger
title: ViewEnterTrigger class
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [ViewEnterTrigger](./fast-animation.viewentertrigger.md)

## ViewEnterTrigger class

Utility for registering element/callback pairs where the callback will be called when the element enters the view-port

<b>Signature:</b>

```typescript
export default class ViewEnterTrigger extends ScrollBase 
```

## Methods

|  Method | Modifiers | Description |
|  --- | --- | --- |
|  [update()](./fast-animation.viewentertrigger.update.md) |  | Check if elements are in view-port and apply scroll method if they are |

---

### Sites Website Src Docs 1.X Api Fast Animation.Viewentertrigger.Update (`sites/website/src/docs/1.x/api/fast-animation.viewentertrigger.update.md`)

---
id: fast-animation.viewentertrigger.update
title: ViewEnterTrigger.update() method
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [ViewEnterTrigger](./fast-animation.viewentertrigger.md) &gt; [update](./fast-animation.viewentertrigger.update.md)

## ViewEnterTrigger.update() method

Check if elements are in view-port and apply scroll method if they are

<b>Signature:</b>

```typescript
protected update(): void;
```
<b>Returns:</b>

void

---

### Sites Website Src Docs 1.X Api Fast Animation.Viewexittrigger (`sites/website/src/docs/1.x/api/fast-animation.viewexittrigger.md`)

---
id: fast-animation.viewexittrigger
title: ViewExitTrigger class
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [ViewExitTrigger](./fast-animation.viewexittrigger.md)

## ViewExitTrigger class

Utility for registering element/callback pairs where the callback will be invoked when the element exits the view-port

<b>Signature:</b>

```typescript
export default class ViewExitTrigger extends ScrollBase 
```

## Methods

|  Method | Modifiers | Description |
|  --- | --- | --- |
|  [update()](./fast-animation.viewexittrigger.update.md) |  | Check if elements are in view-port and apply scroll method if they are |

---

### Sites Website Src Docs 1.X Api Fast Animation.Viewexittrigger.Update (`sites/website/src/docs/1.x/api/fast-animation.viewexittrigger.update.md`)

---
id: fast-animation.viewexittrigger.update
title: ViewExitTrigger.update() method
hide_title: true
layout: 1x
---


[@microsoft/fast-animation](./fast-animation.md) &gt; [ViewExitTrigger](./fast-animation.viewexittrigger.md) &gt; [update](./fast-animation.viewexittrigger.update.md)

## ViewExitTrigger.update() method

Check if elements are in view-port and apply scroll method if they are

<b>Signature:</b>

```typescript
protected update(): void;
```
<b>Returns:</b>

void

---

### Sites Website Src Docs 1.X Api Fast Colors.Blend (`sites/website/src/docs/1.x/api/fast-colors.blend.md`)

---
id: fast-colors.blend
title: blend() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [blend](./fast-colors.blend.md)

## blend() function

Blend two colors.

<b>Signature:</b>

```typescript
export declare function blend(mode: ColorBlendMode, bottom: ColorRGBA64, top: ColorRGBA64): ColorRGBA64;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  mode | [ColorBlendMode](./fast-colors.colorblendmode.md) |  |
|  bottom | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |
|  top | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |

<b>Returns:</b>

[ColorRGBA64](./fast-colors.colorrgba64.md)

## Remarks

The alpha channel of the input is ignored

---

### Sites Website Src Docs 1.X Api Fast Colors.Blendburn (`sites/website/src/docs/1.x/api/fast-colors.blendburn.md`)

---
id: fast-colors.blendburn
title: blendBurn() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [blendBurn](./fast-colors.blendburn.md)

## blendBurn() function

Blends two colors with the burn mode

<b>Signature:</b>

```typescript
export declare function blendBurn(bottom: ColorRGBA64, top: ColorRGBA64): ColorRGBA64;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  bottom | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |
|  top | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |

<b>Returns:</b>

[ColorRGBA64](./fast-colors.colorrgba64.md)

## Remarks

The alpha channel of the input is ignored

---

### Sites Website Src Docs 1.X Api Fast Colors.Blendburnchannel (`sites/website/src/docs/1.x/api/fast-colors.blendburnchannel.md`)

---
id: fast-colors.blendburnchannel
title: blendBurnChannel() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [blendBurnChannel](./fast-colors.blendburnchannel.md)

## blendBurnChannel() function


<b>Signature:</b>

```typescript
export declare function blendBurnChannel(bottom: number, top: number): number;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  bottom | number |  |
|  top | number |  |

<b>Returns:</b>

number

---

### Sites Website Src Docs 1.X Api Fast Colors.Blendcolor (`sites/website/src/docs/1.x/api/fast-colors.blendcolor.md`)

---
id: fast-colors.blendcolor
title: blendColor() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [blendColor](./fast-colors.blendcolor.md)

## blendColor() function

Blends two colors

<b>Signature:</b>

```typescript
export declare function blendColor(bottom: ColorRGBA64, top: ColorRGBA64): ColorRGBA64;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  bottom | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |
|  top | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |

<b>Returns:</b>

[ColorRGBA64](./fast-colors.colorrgba64.md)

## Remarks

The alpha channel of the input is ignored

---

### Sites Website Src Docs 1.X Api Fast Colors.Blenddarken (`sites/website/src/docs/1.x/api/fast-colors.blenddarken.md`)

---
id: fast-colors.blenddarken
title: blendDarken() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [blendDarken](./fast-colors.blenddarken.md)

## blendDarken() function

Blends two colors with the darken mode

<b>Signature:</b>

```typescript
export declare function blendDarken(bottom: ColorRGBA64, top: ColorRGBA64): ColorRGBA64;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  bottom | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |
|  top | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |

<b>Returns:</b>

[ColorRGBA64](./fast-colors.colorrgba64.md)

## Remarks

The alpha channel of the input is ignored

---

### Sites Website Src Docs 1.X Api Fast Colors.Blenddarkenchannel (`sites/website/src/docs/1.x/api/fast-colors.blenddarkenchannel.md`)

---
id: fast-colors.blenddarkenchannel
title: blendDarkenChannel() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [blendDarkenChannel](./fast-colors.blenddarkenchannel.md)

## blendDarkenChannel() function


<b>Signature:</b>

```typescript
export declare function blendDarkenChannel(bottom: number, top: number): number;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  bottom | number |  |
|  top | number |  |

<b>Returns:</b>

number

---

### Sites Website Src Docs 1.X Api Fast Colors.Blenddodge (`sites/website/src/docs/1.x/api/fast-colors.blenddodge.md`)

---
id: fast-colors.blenddodge
title: blendDodge() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [blendDodge](./fast-colors.blenddodge.md)

## blendDodge() function

Blends two colors with the dodge mode

<b>Signature:</b>

```typescript
export declare function blendDodge(bottom: ColorRGBA64, top: ColorRGBA64): ColorRGBA64;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  bottom | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |
|  top | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |

<b>Returns:</b>

[ColorRGBA64](./fast-colors.colorrgba64.md)

## Remarks

The alpha channel of the input is ignored

---

### Sites Website Src Docs 1.X Api Fast Colors.Blenddodgechannel (`sites/website/src/docs/1.x/api/fast-colors.blenddodgechannel.md`)

---
id: fast-colors.blenddodgechannel
title: blendDodgeChannel() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [blendDodgeChannel](./fast-colors.blenddodgechannel.md)

## blendDodgeChannel() function


<b>Signature:</b>

```typescript
export declare function blendDodgeChannel(bottom: number, top: number): number;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  bottom | number |  |
|  top | number |  |

<b>Returns:</b>

number

---

### Sites Website Src Docs 1.X Api Fast Colors.Blendlighten (`sites/website/src/docs/1.x/api/fast-colors.blendlighten.md`)

---
id: fast-colors.blendlighten
title: blendLighten() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [blendLighten](./fast-colors.blendlighten.md)

## blendLighten() function

Blends two colors with the lighten mode

<b>Signature:</b>

```typescript
export declare function blendLighten(bottom: ColorRGBA64, top: ColorRGBA64): ColorRGBA64;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  bottom | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |
|  top | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |

<b>Returns:</b>

[ColorRGBA64](./fast-colors.colorrgba64.md)

## Remarks

The alpha channel of the input is ignored

---

### Sites Website Src Docs 1.X Api Fast Colors.Blendlightenchannel (`sites/website/src/docs/1.x/api/fast-colors.blendlightenchannel.md`)

---
id: fast-colors.blendlightenchannel
title: blendLightenChannel() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [blendLightenChannel](./fast-colors.blendlightenchannel.md)

## blendLightenChannel() function


<b>Signature:</b>

```typescript
export declare function blendLightenChannel(bottom: number, top: number): number;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  bottom | number |  |
|  top | number |  |

<b>Returns:</b>

number

---

### Sites Website Src Docs 1.X Api Fast Colors.Blendmultiply (`sites/website/src/docs/1.x/api/fast-colors.blendmultiply.md`)

---
id: fast-colors.blendmultiply
title: blendMultiply() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [blendMultiply](./fast-colors.blendmultiply.md)

## blendMultiply() function

Blends two colors with the multiply mode

<b>Signature:</b>

```typescript
export declare function blendMultiply(bottom: ColorRGBA64, top: ColorRGBA64): ColorRGBA64;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  bottom | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |
|  top | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |

<b>Returns:</b>

[ColorRGBA64](./fast-colors.colorrgba64.md)

## Remarks

The alpha channel of the input is ignored

---

### Sites Website Src Docs 1.X Api Fast Colors.Blendmultiplychannel (`sites/website/src/docs/1.x/api/fast-colors.blendmultiplychannel.md`)

---
id: fast-colors.blendmultiplychannel
title: blendMultiplyChannel() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [blendMultiplyChannel](./fast-colors.blendmultiplychannel.md)

## blendMultiplyChannel() function


<b>Signature:</b>

```typescript
export declare function blendMultiplyChannel(bottom: number, top: number): number;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  bottom | number |  |
|  top | number |  |

<b>Returns:</b>

number

---

### Sites Website Src Docs 1.X Api Fast Colors.Blendoverlay (`sites/website/src/docs/1.x/api/fast-colors.blendoverlay.md`)

---
id: fast-colors.blendoverlay
title: blendOverlay() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [blendOverlay](./fast-colors.blendoverlay.md)

## blendOverlay() function

Blends two colors with the overlay mode

<b>Signature:</b>

```typescript
export declare function blendOverlay(bottom: ColorRGBA64, top: ColorRGBA64): ColorRGBA64;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  bottom | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |
|  top | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |

<b>Returns:</b>

[ColorRGBA64](./fast-colors.colorrgba64.md)

## Remarks

The alpha channel of the input is ignored

---

### Sites Website Src Docs 1.X Api Fast Colors.Blendoverlaychannel (`sites/website/src/docs/1.x/api/fast-colors.blendoverlaychannel.md`)

---
id: fast-colors.blendoverlaychannel
title: blendOverlayChannel() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [blendOverlayChannel](./fast-colors.blendoverlaychannel.md)

## blendOverlayChannel() function


<b>Signature:</b>

```typescript
export declare function blendOverlayChannel(bottom: number, top: number): number;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  bottom | number |  |
|  top | number |  |

<b>Returns:</b>

number

---

### Sites Website Src Docs 1.X Api Fast Colors.Blendscreen (`sites/website/src/docs/1.x/api/fast-colors.blendscreen.md`)

---
id: fast-colors.blendscreen
title: blendScreen() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [blendScreen](./fast-colors.blendscreen.md)

## blendScreen() function

Blends two colors with the screen mode

<b>Signature:</b>

```typescript
export declare function blendScreen(bottom: ColorRGBA64, top: ColorRGBA64): ColorRGBA64;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  bottom | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |
|  top | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |

<b>Returns:</b>

[ColorRGBA64](./fast-colors.colorrgba64.md)

## Remarks

The alpha channel of the input is ignored

---

### Sites Website Src Docs 1.X Api Fast Colors.Blendscreenchannel (`sites/website/src/docs/1.x/api/fast-colors.blendscreenchannel.md`)

---
id: fast-colors.blendscreenchannel
title: blendScreenChannel() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [blendScreenChannel](./fast-colors.blendscreenchannel.md)

## blendScreenChannel() function


<b>Signature:</b>

```typescript
export declare function blendScreenChannel(bottom: number, top: number): number;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  bottom | number |  |
|  top | number |  |

<b>Returns:</b>

number

---

### Sites Website Src Docs 1.X Api Fast Colors.Calculateoverlaycolor (`sites/website/src/docs/1.x/api/fast-colors.calculateoverlaycolor.md`)

---
id: fast-colors.calculateoverlaycolor
title: calculateOverlayColor() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [calculateOverlayColor](./fast-colors.calculateoverlaycolor.md)

## calculateOverlayColor() function

Calculate an overlay color that uses rgba (rgb + alpha) that matches the appearance of a given solid color when placed on the same background

<b>Signature:</b>

```typescript
export declare function calculateOverlayColor(rgbMatch: ColorRGBA64, rgbBackground: ColorRGBA64, rgbOverlay?: ColorRGBA64): ColorRGBA64;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  rgbMatch | [ColorRGBA64](./fast-colors.colorrgba64.md) | The solid color the overlay should match in appearance when placed over the rgbBackground |
|  rgbBackground | [ColorRGBA64](./fast-colors.colorrgba64.md) | The background on which the overlay rests |
|  rgbOverlay | [ColorRGBA64](./fast-colors.colorrgba64.md) | The rgb color of the overlay. Typically this is either pure white or pure black and when not provided will be determined automatically. This color will be used in the returned output |

<b>Returns:</b>

[ColorRGBA64](./fast-colors.colorrgba64.md)

The rgba (rgb + alpha) color of the overlay

---

### Sites Website Src Docs 1.X Api Fast Colors.Centeredrescale (`sites/website/src/docs/1.x/api/fast-colors.centeredrescale.md`)

---
id: fast-colors.centeredrescale
title: centeredRescale() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [centeredRescale](./fast-colors.centeredrescale.md)

## centeredRescale() function

Takes an input array of colors and extrapolates them to a larger palette. The mapping first takes the input array and extrapolates between each color so that they are separated by spacing-1 slots. Then it adds to either end enough new colors to make up the desired targetSize. All output color slots between the defined stops are interpolated.

<b>Signature:</b>

```typescript
export declare function centeredRescale(input: ColorRGBA64[], config?: CenteredRescaleConfig): ColorRGBA64[];
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  input | [ColorRGBA64](./fast-colors.colorrgba64.md)\[\] |  |
|  config | [CenteredRescaleConfig](./fast-colors.centeredrescaleconfig.md) |  |

<b>Returns:</b>

[ColorRGBA64](./fast-colors.colorrgba64.md)\[\]

## Example

For an input array with length 5, a targetSize of 17 and spacing of 3 the output would be: 0: scaleColorLight 1: 2: input 0 3: 4: 5: input 1 6: 7: 8: input 2 9: 10: 11: input 3 12: 13: 14: input 4 15: 16: scaleColorDark

---

### Sites Website Src Docs 1.X Api Fast Colors.Centeredrescaleconfig (`sites/website/src/docs/1.x/api/fast-colors.centeredrescaleconfig.md`)

---
id: fast-colors.centeredrescaleconfig
title: CenteredRescaleConfig interface
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [CenteredRescaleConfig](./fast-colors.centeredrescaleconfig.md)

## CenteredRescaleConfig interface


<b>Signature:</b>

```typescript
export interface CenteredRescaleConfig 
```

## Properties

|  Property | Type | Description |
|  --- | --- | --- |
|  [scaleColorDark](./fast-colors.centeredrescaleconfig.scalecolordark.md) | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |
|  [scaleColorLight](./fast-colors.centeredrescaleconfig.scalecolorlight.md) | [ColorRGBA64](./fast-colors.colorrgba64.md) |  |
|  [spacing](./fast-colors.centeredrescaleconfig.spacing.md) | number |  |
|  [targetSize](./fast-colors.centeredrescaleconfig.targetsize.md) | number |  |

---

### Sites Website Src Docs 1.X Api Fast Colors.Centeredrescaleconfig.Scalecolordark (`sites/website/src/docs/1.x/api/fast-colors.centeredrescaleconfig.scalecolordark.md`)

---
id: fast-colors.centeredrescaleconfig.scalecolordark
title: CenteredRescaleConfig.scaleColorDark property
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [CenteredRescaleConfig](./fast-colors.centeredrescaleconfig.md) &gt; [scaleColorDark](./fast-colors.centeredrescaleconfig.scalecolordark.md)

## CenteredRescaleConfig.scaleColorDark property

<b>Signature:</b>

```typescript
scaleColorDark: ColorRGBA64;
```

---

### Sites Website Src Docs 1.X Api Fast Colors.Centeredrescaleconfig.Scalecolorlight (`sites/website/src/docs/1.x/api/fast-colors.centeredrescaleconfig.scalecolorlight.md`)

---
id: fast-colors.centeredrescaleconfig.scalecolorlight
title: CenteredRescaleConfig.scaleColorLight property
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [CenteredRescaleConfig](./fast-colors.centeredrescaleconfig.md) &gt; [scaleColorLight](./fast-colors.centeredrescaleconfig.scalecolorlight.md)

## CenteredRescaleConfig.scaleColorLight property

<b>Signature:</b>

```typescript
scaleColorLight: ColorRGBA64;
```

---

### Sites Website Src Docs 1.X Api Fast Colors.Centeredrescaleconfig.Spacing (`sites/website/src/docs/1.x/api/fast-colors.centeredrescaleconfig.spacing.md`)

---
id: fast-colors.centeredrescaleconfig.spacing
title: CenteredRescaleConfig.spacing property
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [CenteredRescaleConfig](./fast-colors.centeredrescaleconfig.md) &gt; [spacing](./fast-colors.centeredrescaleconfig.spacing.md)

## CenteredRescaleConfig.spacing property

<b>Signature:</b>

```typescript
spacing: number;
```

---

### Sites Website Src Docs 1.X Api Fast Colors.Centeredrescaleconfig.Targetsize (`sites/website/src/docs/1.x/api/fast-colors.centeredrescaleconfig.targetsize.md`)

---
id: fast-colors.centeredrescaleconfig.targetsize
title: CenteredRescaleConfig.targetSize property
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [CenteredRescaleConfig](./fast-colors.centeredrescaleconfig.md) &gt; [targetSize](./fast-colors.centeredrescaleconfig.targetsize.md)

## CenteredRescaleConfig.targetSize property

<b>Signature:</b>

```typescript
targetSize: number;
```

---

### Sites Website Src Docs 1.X Api Fast Colors.Clamp (`sites/website/src/docs/1.x/api/fast-colors.clamp.md`)

---
id: fast-colors.clamp
title: clamp() function
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [clamp](./fast-colors.clamp.md)

## clamp() function

Ensures that an input number does not exceed a max value and is not less than a min value.

<b>Signature:</b>

```typescript
export declare function clamp(i: number, min: number, max: number): number;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  i | number | the number to clamp |
|  min | number | the maximum (inclusive) value |
|  max | number | the minimum (inclusive) value |

<b>Returns:</b>

number

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorblendmode (`sites/website/src/docs/1.x/api/fast-colors.colorblendmode.md`)

---
id: fast-colors.colorblendmode
title: ColorBlendMode enum
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorBlendMode](./fast-colors.colorblendmode.md)

## ColorBlendMode enum

Color blend modes.

<b>Signature:</b>

```typescript
export declare enum ColorBlendMode 
```

## Enumeration Members

|  Member | Value | Description |
|  --- | --- | --- |
|  Burn | <code>0</code> |  |
|  Color | <code>1</code> |  |
|  Darken | <code>2</code> |  |
|  Dodge | <code>3</code> |  |
|  Lighten | <code>4</code> |  |
|  Multiply | <code>5</code> |  |
|  Overlay | <code>6</code> |  |
|  Screen | <code>7</code> |  |

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsl. Constructor  (`sites/website/src/docs/1.x/api/fast-colors.colorhsl._constructor_.md`)

---
id: fast-colors.colorhsl._constructor_
title: ColorHSL.(constructor)
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSL](./fast-colors.colorhsl.md) &gt; [(constructor)](./fast-colors.colorhsl._constructor_.md)

## ColorHSL.(constructor)

Constructs a new instance of the `ColorHSL` class

<b>Signature:</b>

```typescript
constructor(hue: number, sat: number, lum: number);
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  hue | number |  |
|  sat | number |  |
|  lum | number |  |

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsl.Equalvalue (`sites/website/src/docs/1.x/api/fast-colors.colorhsl.equalvalue.md`)

---
id: fast-colors.colorhsl.equalvalue
title: ColorHSL.equalValue() method
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSL](./fast-colors.colorhsl.md) &gt; [equalValue](./fast-colors.colorhsl.equalvalue.md)

## ColorHSL.equalValue() method

Determines if a color is equal to another

<b>Signature:</b>

```typescript
equalValue(rhs: ColorHSL): boolean;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  rhs | [ColorHSL](./fast-colors.colorhsl.md) | the value to compare |

<b>Returns:</b>

boolean

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsl.Fromobject (`sites/website/src/docs/1.x/api/fast-colors.colorhsl.fromobject.md`)

---
id: fast-colors.colorhsl.fromobject
title: ColorHSL.fromObject() method
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSL](./fast-colors.colorhsl.md) &gt; [fromObject](./fast-colors.colorhsl.fromobject.md)

## ColorHSL.fromObject() method

Construct a [ColorHSL](./fast-colors.colorhsl.md) from a config object.

<b>Signature:</b>

```typescript
static fromObject(data: {
        h: number;
        s: number;
        l: number;
    }): ColorHSL | null;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  data | `{ h: number; s: number; l: number; }` |  |

<b>Returns:</b>

[ColorHSL](./fast-colors.colorhsl.md) \| null

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsl.H (`sites/website/src/docs/1.x/api/fast-colors.colorhsl.h.md`)

---
id: fast-colors.colorhsl.h
title: ColorHSL.h property
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSL](./fast-colors.colorhsl.md) &gt; [h](./fast-colors.colorhsl.h.md)

## ColorHSL.h property

<b>Signature:</b>

```typescript
readonly h: number;
```

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsl.L (`sites/website/src/docs/1.x/api/fast-colors.colorhsl.l.md`)

---
id: fast-colors.colorhsl.l
title: ColorHSL.l property
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSL](./fast-colors.colorhsl.md) &gt; [l](./fast-colors.colorhsl.l.md)

## ColorHSL.l property

<b>Signature:</b>

```typescript
readonly l: number;
```

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsl (`sites/website/src/docs/1.x/api/fast-colors.colorhsl.md`)

---
id: fast-colors.colorhsl
title: ColorHSL class
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSL](./fast-colors.colorhsl.md)

## ColorHSL class

This uses Hue values in "degree" format. So expect a range of \[0,360\]. Some other implementations instead uses radians or a normalized Hue with range \[0,1\]. Be aware of this when checking values or using other libraries.

<b>Signature:</b>

```typescript
export declare class ColorHSL 
```

## Constructors

|  Constructor | Modifiers | Description |
|  --- | --- | --- |
|  [(constructor)(hue, sat, lum)](./fast-colors.colorhsl._constructor_.md) |  | Constructs a new instance of the <code>ColorHSL</code> class |

## Properties

|  Property | Modifiers | Type | Description |
|  --- | --- | --- | --- |
|  [h](./fast-colors.colorhsl.h.md) |  | number |  |
|  [l](./fast-colors.colorhsl.l.md) |  | number |  |
|  [s](./fast-colors.colorhsl.s.md) |  | number |  |

## Methods

|  Method | Modifiers | Description |
|  --- | --- | --- |
|  [equalValue(rhs)](./fast-colors.colorhsl.equalvalue.md) |  | Determines if a color is equal to another |
|  [fromObject(data)](./fast-colors.colorhsl.fromobject.md) | <code>static</code> | Construct a [ColorHSL](./fast-colors.colorhsl.md) from a config object. |
|  [roundToPrecision(precision)](./fast-colors.colorhsl.roundtoprecision.md) |  | Returns a new [ColorHSL](./fast-colors.colorhsl.md) rounded to the provided precision |
|  [toObject()](./fast-colors.colorhsl.toobject.md) |  | Returns the [ColorHSL](./fast-colors.colorhsl.md) formatted as an object. |

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsl.Roundtoprecision (`sites/website/src/docs/1.x/api/fast-colors.colorhsl.roundtoprecision.md`)

---
id: fast-colors.colorhsl.roundtoprecision
title: ColorHSL.roundToPrecision() method
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSL](./fast-colors.colorhsl.md) &gt; [roundToPrecision](./fast-colors.colorhsl.roundtoprecision.md)

## ColorHSL.roundToPrecision() method

Returns a new [ColorHSL](./fast-colors.colorhsl.md) rounded to the provided precision

<b>Signature:</b>

```typescript
roundToPrecision(precision: number): ColorHSL;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  precision | number | the precision to round to |

<b>Returns:</b>

[ColorHSL](./fast-colors.colorhsl.md)

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsl.S (`sites/website/src/docs/1.x/api/fast-colors.colorhsl.s.md`)

---
id: fast-colors.colorhsl.s
title: ColorHSL.s property
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSL](./fast-colors.colorhsl.md) &gt; [s](./fast-colors.colorhsl.s.md)

## ColorHSL.s property

<b>Signature:</b>

```typescript
readonly s: number;
```

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsl.Toobject (`sites/website/src/docs/1.x/api/fast-colors.colorhsl.toobject.md`)

---
id: fast-colors.colorhsl.toobject
title: ColorHSL.toObject() method
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSL](./fast-colors.colorhsl.md) &gt; [toObject](./fast-colors.colorhsl.toobject.md)

## ColorHSL.toObject() method

Returns the [ColorHSL](./fast-colors.colorhsl.md) formatted as an object.

<b>Signature:</b>

```typescript
toObject(): {
        h: number;
        s: number;
        l: number;
    };
```
<b>Returns:</b>

`{ h: number; s: number; l: number; }`

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsv. Constructor  (`sites/website/src/docs/1.x/api/fast-colors.colorhsv._constructor_.md`)

---
id: fast-colors.colorhsv._constructor_
title: ColorHSV.(constructor)
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSV](./fast-colors.colorhsv.md) &gt; [(constructor)](./fast-colors.colorhsv._constructor_.md)

## ColorHSV.(constructor)

Constructs a new instance of the `ColorHSV` class

<b>Signature:</b>

```typescript
constructor(hue: number, sat: number, val: number);
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  hue | number |  |
|  sat | number |  |
|  val | number |  |

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsv.Equalvalue (`sites/website/src/docs/1.x/api/fast-colors.colorhsv.equalvalue.md`)

---
id: fast-colors.colorhsv.equalvalue
title: ColorHSV.equalValue() method
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSV](./fast-colors.colorhsv.md) &gt; [equalValue](./fast-colors.colorhsv.equalvalue.md)

## ColorHSV.equalValue() method

Determines if a color is equal to another

<b>Signature:</b>

```typescript
equalValue(rhs: ColorHSV): boolean;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  rhs | [ColorHSV](./fast-colors.colorhsv.md) | the value to compare |

<b>Returns:</b>

boolean

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsv.Fromobject (`sites/website/src/docs/1.x/api/fast-colors.colorhsv.fromobject.md`)

---
id: fast-colors.colorhsv.fromobject
title: ColorHSV.fromObject() method
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSV](./fast-colors.colorhsv.md) &gt; [fromObject](./fast-colors.colorhsv.fromobject.md)

## ColorHSV.fromObject() method

Construct a [ColorHSV](./fast-colors.colorhsv.md) from a config object.

<b>Signature:</b>

```typescript
static fromObject(data: {
        h: number;
        s: number;
        v: number;
    }): ColorHSV | null;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  data | `{ h: number; s: number; v: number; }` |  |

<b>Returns:</b>

[ColorHSV](./fast-colors.colorhsv.md) \| null

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsv.H (`sites/website/src/docs/1.x/api/fast-colors.colorhsv.h.md`)

---
id: fast-colors.colorhsv.h
title: ColorHSV.h property
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSV](./fast-colors.colorhsv.md) &gt; [h](./fast-colors.colorhsv.h.md)

## ColorHSV.h property

<b>Signature:</b>

```typescript
readonly h: number;
```

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsv (`sites/website/src/docs/1.x/api/fast-colors.colorhsv.md`)

---
id: fast-colors.colorhsv
title: ColorHSV class
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSV](./fast-colors.colorhsv.md)

## ColorHSV class

This uses Hue values in "degree" format. So expect a range of \[0,360\]. Some other implementations instead uses radians or a normalized Hue with range \[0,1\]. Be aware of this when checking values or using other libraries.

<b>Signature:</b>

```typescript
export declare class ColorHSV 
```

## Constructors

|  Constructor | Modifiers | Description |
|  --- | --- | --- |
|  [(constructor)(hue, sat, val)](./fast-colors.colorhsv._constructor_.md) |  | Constructs a new instance of the <code>ColorHSV</code> class |

## Properties

|  Property | Modifiers | Type | Description |
|  --- | --- | --- | --- |
|  [h](./fast-colors.colorhsv.h.md) |  | number |  |
|  [s](./fast-colors.colorhsv.s.md) |  | number |  |
|  [v](./fast-colors.colorhsv.v.md) |  | number |  |

## Methods

|  Method | Modifiers | Description |
|  --- | --- | --- |
|  [equalValue(rhs)](./fast-colors.colorhsv.equalvalue.md) |  | Determines if a color is equal to another |
|  [fromObject(data)](./fast-colors.colorhsv.fromobject.md) | <code>static</code> | Construct a [ColorHSV](./fast-colors.colorhsv.md) from a config object. |
|  [roundToPrecision(precision)](./fast-colors.colorhsv.roundtoprecision.md) |  | Returns a new [ColorHSV](./fast-colors.colorhsv.md) rounded to the provided precision |
|  [toObject()](./fast-colors.colorhsv.toobject.md) |  | Returns the [ColorHSV](./fast-colors.colorhsv.md) formatted as an object. |

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsv.Roundtoprecision (`sites/website/src/docs/1.x/api/fast-colors.colorhsv.roundtoprecision.md`)

---
id: fast-colors.colorhsv.roundtoprecision
title: ColorHSV.roundToPrecision() method
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSV](./fast-colors.colorhsv.md) &gt; [roundToPrecision](./fast-colors.colorhsv.roundtoprecision.md)

## ColorHSV.roundToPrecision() method

Returns a new [ColorHSV](./fast-colors.colorhsv.md) rounded to the provided precision

<b>Signature:</b>

```typescript
roundToPrecision(precision: number): ColorHSV;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  precision | number | the precision to round to |

<b>Returns:</b>

[ColorHSV](./fast-colors.colorhsv.md)

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsv.S (`sites/website/src/docs/1.x/api/fast-colors.colorhsv.s.md`)

---
id: fast-colors.colorhsv.s
title: ColorHSV.s property
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSV](./fast-colors.colorhsv.md) &gt; [s](./fast-colors.colorhsv.s.md)

## ColorHSV.s property

<b>Signature:</b>

```typescript
readonly s: number;
```

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsv.Toobject (`sites/website/src/docs/1.x/api/fast-colors.colorhsv.toobject.md`)

---
id: fast-colors.colorhsv.toobject
title: ColorHSV.toObject() method
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSV](./fast-colors.colorhsv.md) &gt; [toObject](./fast-colors.colorhsv.toobject.md)

## ColorHSV.toObject() method

Returns the [ColorHSV](./fast-colors.colorhsv.md) formatted as an object.

<b>Signature:</b>

```typescript
toObject(): {
        h: number;
        s: number;
        v: number;
    };
```
<b>Returns:</b>

`{ h: number; s: number; v: number; }`

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorhsv.V (`sites/website/src/docs/1.x/api/fast-colors.colorhsv.v.md`)

---
id: fast-colors.colorhsv.v
title: ColorHSV.v property
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorHSV](./fast-colors.colorhsv.md) &gt; [v](./fast-colors.colorhsv.v.md)

## ColorHSV.v property

<b>Signature:</b>

```typescript
readonly v: number;
```

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorinterpolationspace (`sites/website/src/docs/1.x/api/fast-colors.colorinterpolationspace.md`)

---
id: fast-colors.colorinterpolationspace
title: ColorInterpolationSpace enum
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorInterpolationSpace](./fast-colors.colorinterpolationspace.md)

## ColorInterpolationSpace enum

Color interpolation spaces

<b>Signature:</b>

```typescript
export declare enum ColorInterpolationSpace 
```

## Enumeration Members

|  Member | Value | Description |
|  --- | --- | --- |
|  HSL | <code>1</code> |  |
|  HSV | <code>2</code> |  |
|  LAB | <code>4</code> |  |
|  LCH | <code>5</code> |  |
|  RGB | <code>0</code> |  |
|  XYZ | <code>3</code> |  |

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorlab. Constructor  (`sites/website/src/docs/1.x/api/fast-colors.colorlab._constructor_.md`)

---
id: fast-colors.colorlab._constructor_
title: ColorLAB.(constructor)
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorLAB](./fast-colors.colorlab.md) &gt; [(constructor)](./fast-colors.colorlab._constructor_.md)

## ColorLAB.(constructor)

Constructs a new instance of the `ColorLAB` class

<b>Signature:</b>

```typescript
constructor(l: number, a: number, b: number);
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  l | number |  |
|  a | number |  |
|  b | number |  |

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorlab.A (`sites/website/src/docs/1.x/api/fast-colors.colorlab.a.md`)

---
id: fast-colors.colorlab.a
title: ColorLAB.a property
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorLAB](./fast-colors.colorlab.md) &gt; [a](./fast-colors.colorlab.a.md)

## ColorLAB.a property

<b>Signature:</b>

```typescript
readonly a: number;
```

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorlab.B (`sites/website/src/docs/1.x/api/fast-colors.colorlab.b.md`)

---
id: fast-colors.colorlab.b
title: ColorLAB.b property
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorLAB](./fast-colors.colorlab.md) &gt; [b](./fast-colors.colorlab.b.md)

## ColorLAB.b property

<b>Signature:</b>

```typescript
readonly b: number;
```

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorlab.Epsilon (`sites/website/src/docs/1.x/api/fast-colors.colorlab.epsilon.md`)

---
id: fast-colors.colorlab.epsilon
title: ColorLAB.epsilon property
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorLAB](./fast-colors.colorlab.md) &gt; [epsilon](./fast-colors.colorlab.epsilon.md)

## ColorLAB.epsilon property

<b>Signature:</b>

```typescript
static readonly epsilon: number;
```

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorlab.Equalvalue (`sites/website/src/docs/1.x/api/fast-colors.colorlab.equalvalue.md`)

---
id: fast-colors.colorlab.equalvalue
title: ColorLAB.equalValue() method
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorLAB](./fast-colors.colorlab.md) &gt; [equalValue](./fast-colors.colorlab.equalvalue.md)

## ColorLAB.equalValue() method

Determines if a color is equal to another

<b>Signature:</b>

```typescript
equalValue(rhs: ColorLAB): boolean;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  rhs | [ColorLAB](./fast-colors.colorlab.md) | the value to compare |

<b>Returns:</b>

boolean

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorlab.Fromobject (`sites/website/src/docs/1.x/api/fast-colors.colorlab.fromobject.md`)

---
id: fast-colors.colorlab.fromobject
title: ColorLAB.fromObject() method
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorLAB](./fast-colors.colorlab.md) &gt; [fromObject](./fast-colors.colorlab.fromobject.md)

## ColorLAB.fromObject() method

Construct a [ColorLAB](./fast-colors.colorlab.md) from a config object.

<b>Signature:</b>

```typescript
static fromObject(data: {
        l: number;
        a: number;
        b: number;
    }): ColorLAB | null;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  data | `{ l: number; a: number; b: number; }` |  |

<b>Returns:</b>

[ColorLAB](./fast-colors.colorlab.md) \| null

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorlab.Kappa (`sites/website/src/docs/1.x/api/fast-colors.colorlab.kappa.md`)

---
id: fast-colors.colorlab.kappa
title: ColorLAB.kappa property
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorLAB](./fast-colors.colorlab.md) &gt; [kappa](./fast-colors.colorlab.kappa.md)

## ColorLAB.kappa property

<b>Signature:</b>

```typescript
static readonly kappa: number;
```

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorlab.L (`sites/website/src/docs/1.x/api/fast-colors.colorlab.l.md`)

---
id: fast-colors.colorlab.l
title: ColorLAB.l property
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorLAB](./fast-colors.colorlab.md) &gt; [l](./fast-colors.colorlab.l.md)

## ColorLAB.l property

<b>Signature:</b>

```typescript
readonly l: number;
```

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorlab (`sites/website/src/docs/1.x/api/fast-colors.colorlab.md`)

---
id: fast-colors.colorlab
title: ColorLAB class
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorLAB](./fast-colors.colorlab.md)

## ColorLAB class

[CIELAB color space](https://en.wikipedia.org/wiki/CIELAB_color_space) This implementation uses the D65 constants for 2 degrees. That determines the constants used for the pure white point of the XYZ space of 0.95047, 1.0, 1.08883. [https://en.wikipedia.org/wiki/Illuminant\_D65](https://en.wikipedia.org/wiki/Illuminant_D65) These constants determine how the XYZ, LCH and LAB colors convert to/from RGB.

<b>Signature:</b>

```typescript
export declare class ColorLAB 
```

## Constructors

|  Constructor | Modifiers | Description |
|  --- | --- | --- |
|  [(constructor)(l, a, b)](./fast-colors.colorlab._constructor_.md) |  | Constructs a new instance of the <code>ColorLAB</code> class |

## Properties

|  Property | Modifiers | Type | Description |
|  --- | --- | --- | --- |
|  [a](./fast-colors.colorlab.a.md) |  | number |  |
|  [b](./fast-colors.colorlab.b.md) |  | number |  |
|  [epsilon](./fast-colors.colorlab.epsilon.md) | <code>static</code> | number |  |
|  [kappa](./fast-colors.colorlab.kappa.md) | <code>static</code> | number |  |
|  [l](./fast-colors.colorlab.l.md) |  | number |  |

## Methods

|  Method | Modifiers | Description |
|  --- | --- | --- |
|  [equalValue(rhs)](./fast-colors.colorlab.equalvalue.md) |  | Determines if a color is equal to another |
|  [fromObject(data)](./fast-colors.colorlab.fromobject.md) | <code>static</code> | Construct a [ColorLAB](./fast-colors.colorlab.md) from a config object. |
|  [roundToPrecision(precision)](./fast-colors.colorlab.roundtoprecision.md) |  | Returns a new [ColorLAB](./fast-colors.colorlab.md) rounded to the provided precision |
|  [toObject()](./fast-colors.colorlab.toobject.md) |  | Returns the [ColorLAB](./fast-colors.colorlab.md) formatted as an object. |

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorlab.Roundtoprecision (`sites/website/src/docs/1.x/api/fast-colors.colorlab.roundtoprecision.md`)

---
id: fast-colors.colorlab.roundtoprecision
title: ColorLAB.roundToPrecision() method
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorLAB](./fast-colors.colorlab.md) &gt; [roundToPrecision](./fast-colors.colorlab.roundtoprecision.md)

## ColorLAB.roundToPrecision() method

Returns a new [ColorLAB](./fast-colors.colorlab.md) rounded to the provided precision

<b>Signature:</b>

```typescript
roundToPrecision(precision: number): ColorLAB;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  precision | number | the precision to round to |

<b>Returns:</b>

[ColorLAB](./fast-colors.colorlab.md)

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorlab.Toobject (`sites/website/src/docs/1.x/api/fast-colors.colorlab.toobject.md`)

---
id: fast-colors.colorlab.toobject
title: ColorLAB.toObject() method
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorLAB](./fast-colors.colorlab.md) &gt; [toObject](./fast-colors.colorlab.toobject.md)

## ColorLAB.toObject() method

Returns the [ColorLAB](./fast-colors.colorlab.md) formatted as an object.

<b>Signature:</b>

```typescript
toObject(): {
        l: number;
        a: number;
        b: number;
    };
```
<b>Returns:</b>

`{ l: number; a: number; b: number; }`

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorlch. Constructor  (`sites/website/src/docs/1.x/api/fast-colors.colorlch._constructor_.md`)

---
id: fast-colors.colorlch._constructor_
title: ColorLCH.(constructor)
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorLCH](./fast-colors.colorlch.md) &gt; [(constructor)](./fast-colors.colorlch._constructor_.md)

## ColorLCH.(constructor)

Constructs a new instance of the `ColorLCH` class

<b>Signature:</b>

```typescript
constructor(l: number, c: number, h: number);
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  l | number |  |
|  c | number |  |
|  h | number |  |

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorlch.C (`sites/website/src/docs/1.x/api/fast-colors.colorlch.c.md`)

---
id: fast-colors.colorlch.c
title: ColorLCH.c property
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorLCH](./fast-colors.colorlch.md) &gt; [c](./fast-colors.colorlch.c.md)

## ColorLCH.c property

<b>Signature:</b>

```typescript
readonly c: number;
```

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorlch.Equalvalue (`sites/website/src/docs/1.x/api/fast-colors.colorlch.equalvalue.md`)

---
id: fast-colors.colorlch.equalvalue
title: ColorLCH.equalValue() method
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorLCH](./fast-colors.colorlch.md) &gt; [equalValue](./fast-colors.colorlch.equalvalue.md)

## ColorLCH.equalValue() method

Determines if one color is equal to another.

<b>Signature:</b>

```typescript
equalValue(rhs: ColorLCH): boolean;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  rhs | [ColorLCH](./fast-colors.colorlch.md) | the color to compare |

<b>Returns:</b>

boolean

---

### Sites Website Src Docs 1.X Api Fast Colors.Colorlch.Fromobject (`sites/website/src/docs/1.x/api/fast-colors.colorlch.fromobject.md`)

---
id: fast-colors.colorlch.fromobject
title: ColorLCH.fromObject() method
hide_title: true
layout: 1x
---


[@microsoft/fast-colors](./fast-colors.md) &gt; [ColorLCH](./fast-colors.colorlch.md) &gt; [fromObject](./fast-colors.colorlch.fromobject.md)

## ColorLCH.fromObject() method

Construct a [ColorLCH](./fast-colors.colorlch.md) from a config object.

<b>Signature:</b>

```typescript
static fromObject(data: {
        l: number;
        c: number;
        h: number;
    }): ColorLCH | null;
```

## Parameters

|  Parameter | Type | Description |
|  --- | --- | --- |
|  data | `{ l: number; c: number; h: number; }` | the config object |

<b>Returns:</b>

[ColorLCH](./fast-colors.colorlch.md) \| null

---

--- METRICS ---
- Files Extracted: 200
- Estimated Token Budget: ~125158 tokens
- Canonical Reference: https://codewiki.google/github.com/microsoft/fast
