A library for constructing Web Components
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Core custom element functionality for building reusable web components with lifecycle management, Shadow DOM, and attribute synchronization.
The base class for all FAST custom elements, extending HTMLElement with reactive properties, Shadow DOM support, and lifecycle management.
/**
* The base class for FAST custom elements
* Provides reactive property system, Shadow DOM management, and element lifecycle
*/
class FASTElement extends HTMLElement {
/** The element controller that manages lifecycle and rendering */
readonly $fastController: ElementController;
/** Emits a custom HTML event */
$emit(type: string, detail?: any, options?: Omit<CustomEventInit, "detail">): boolean | void;
/** Called when the element is inserted into the DOM */
connectedCallback(): void;
/** Called when the element is removed from the DOM */
disconnectedCallback(): void;
/** Called when an observed attribute changes */
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
}Usage Examples:
import { FASTElement, customElement, attr, html } from "@microsoft/fast-element";
@customElement("my-button")
export class MyButton extends FASTElement {
@attr disabled: boolean = false;
@attr label: string = "Click me";
connectedCallback() {
super.connectedCallback();
console.log("Button connected to DOM");
}
private handleClick() {
if (!this.disabled) {
this.$emit("button-click", { label: this.label });
}
}
}Decorator function for defining custom elements with templates, styles, and configuration options.
/**
* Decorator for defining custom elements
* @param definition - Element definition with name, template, styles, etc.
* @returns Class decorator that registers the custom element
*/
function customElement(definition: PartialFASTElementDefinition): ClassDecorator;
/**
* Decorator with element name only
* @param name - The custom element tag name
* @returns Class decorator that registers the custom element
*/
function customElement(name: string): ClassDecorator;
interface PartialFASTElementDefinition {
/** The custom element tag name */
name: string;
/** The template for the element */
template?: ViewTemplate;
/** The styles for the element */
styles?: ElementStyles | ElementStyles[];
/** Shadow DOM options */
shadowOptions?: ShadowRootOptions | null;
/** Element registry for dependency injection */
elementOptions?: ElementDefinitionOptions;
}
interface ShadowRootOptions {
mode: "open" | "closed";
delegatesFocus?: boolean;
slotAssignment?: "manual" | "named";
}Usage Examples:
import { FASTElement, customElement, html, css } from "@microsoft/fast-element";
// With full definition
@customElement({
name: "user-card",
template: html<UserCard>`
<div class="card">
<h3>${x => x.name}</h3>
<p>${x => x.email}</p>
</div>
`,
styles: css`
.card {
border: 1px solid #ccc;
padding: 16px;
border-radius: 8px;
}
`,
shadowOptions: {
mode: "open",
delegatesFocus: true
}
})
export class UserCard extends FASTElement {
@attr name: string = "";
@attr email: string = "";
}
// With name only
@customElement("simple-card")
export class SimpleCard extends FASTElement {
// Template and styles can be set via static properties
static template = html`<slot></slot>`;
static styles = css`:host { display: block; }`;
}Internal controller that manages element lifecycle, rendering, and property synchronization.
/**
* Controller that manages FAST element lifecycle and rendering
*/
class ElementController {
/** The element being controlled */
readonly element: HTMLElement;
/** The element definition */
readonly definition: FASTElementDefinition;
/** Whether the element is connected to the DOM */
readonly isConnected: boolean;
/** The element's view if it has a template */
readonly view?: HTMLView;
/** Connect the element (called by connectedCallback) */
connect(): void;
/** Disconnect the element (called by disconnectedCallback) */
disconnect(): void;
/** Handle attribute changes */
onAttributeChangedCallback(name: string, oldValue: string, newValue: string): void;
/** Add a view behavior */
addBehavior(behavior: ViewBehavior): void;
/** Remove a view behavior */
removeBehavior(behavior: ViewBehavior, force?: boolean): void;
}
/**
* Strategy for creating element controllers
*/
interface ElementControllerStrategy {
/** Create a controller for the given element */
create(element: HTMLElement, definition: FASTElementDefinition): ElementController;
}Complete definition of a custom element including its configuration and metadata.
/**
* Complete definition of a FAST custom element
*/
class FASTElementDefinition {
/** The custom element tag name */
readonly name: string;
/** The element type/constructor */
readonly type: Constructable<HTMLElement>;
/** Attribute definitions */
readonly attributes: AttributeDefinition[];
/** Property definitions */
readonly propertyLookup: Record<string, AttributeDefinition>;
/** Attribute lookup by name */
readonly attributeLookup: Record<string, AttributeDefinition>;
/** Template for the element */
readonly template?: ViewTemplate;
/** Styles for the element */
readonly styles?: ElementStyles;
/** Shadow DOM options */
readonly shadowOptions?: ShadowRootOptions;
/** Element definition options */
readonly elementOptions?: ElementDefinitionOptions;
/** Define the custom element */
define(registry?: CustomElementRegistry): this;
}
interface TemplateOptions {
/** Template compilation strategy */
strategy?: CompilationStrategy;
}Registry for managing element definitions and dependency injection.
/**
* Registry for FAST element definitions
*/
const fastElementRegistry: {
/** Register an element definition */
register(definition: FASTElementDefinition): void;
/** Get an element definition by name */
getByName(name: string): FASTElementDefinition | undefined;
/** Get all registered definitions */
getAll(): FASTElementDefinition[];
};
interface TypeRegistry {
/** Register a type with the registry */
register<T>(key: any, value: T): void;
/** Get a type from the registry */
get<T>(key: any): T | undefined;
}Usage Examples:
import { FASTElement, customElement, fastElementRegistry } from "@microsoft/fast-element";
// Register an element
@customElement("my-element")
class MyElement extends FASTElement {}
// Check if element is registered
const definition = fastElementRegistry.getByName("my-element");
if (definition) {
console.log("Element is registered");
}
// Get all registered elements
const allDefinitions = fastElementRegistry.getAll();
console.log(`${allDefinitions.length} elements registered`);Specialized controller for server-side rendering and hydration scenarios.
/**
* Element controller that supports SSR hydration
*/
class HydratableElementController extends ElementController {
/** Whether this controller supports hydration */
readonly needsHydration: boolean;
/** Hydrate the element from server-rendered content */
hydrate(): void;
}interface ElementDefinitionOptions {
/** Base element type to extend */
extends?: string;
}
interface ViewBehavior {
/** Bind the behavior to a source */
bind(source: any, context: ExecutionContext): void;
/** Unbind the behavior */
unbind(source: any): void;
}
interface FASTGlobal {
/** Global element registry */
registry: TypeRegistry;
/** Warning function */
warn(message: string): void;
/** Error function */
error(message: string): void;
}