A comprehensive web component compiler that transforms TypeScript and JSX code into standards-compliant web components with complete development toolchain.
75
Core decorators and utilities for creating web components with TypeScript and JSX. Stencil provides a comprehensive decorator-based component authoring system with full TypeScript support.
The main decorator for defining a web component class with configuration options.
/**
* The @Component() decorator is used to provide metadata about the component class
* @param opts - Component configuration options
* @returns Class decorator
*/
function Component(opts: ComponentOptions): ClassDecorator;
interface ComponentOptions {
/** Tag name of the web component. Must contain a '-' */
tag: string;
/** Relative URL to external stylesheet file */
styleUrl?: string;
/** Array of stylesheets or mode-specific stylesheets */
styleUrls?: string[] | ModeStyles;
/** Inline CSS styles */
styles?: string | { [modeName: string]: any };
/** Use native shadow DOM encapsulation */
shadow?: boolean | ShadowRootOptions;
/** Use scoped stylesheets without native shadow DOM */
scoped?: boolean;
/** Array of relative paths to asset directories */
assetsDirs?: string[];
/** Enable form-associated component behavior */
formAssociated?: boolean;
}
interface ShadowRootOptions {
/** Mitigate custom element focusability issues */
delegatesFocus?: boolean;
}
interface ModeStyles {
[modeName: string]: string | string[];
}Usage Example:
@Component({
tag: 'my-button',
styleUrl: 'my-button.css',
shadow: true,
})
export class MyButton {
// Component implementation
}Decorators for defining component properties, state, and element references.
/**
* The @Prop() decorator defines component properties/attributes
* @param opts - Property configuration options
* @returns Property decorator
*/
function Prop(opts?: PropOptions): PropertyDecorator;
interface PropOptions {
/** Custom attribute name override */
attribute?: string | null;
/** Allow internal mutation of the prop */
mutable?: boolean;
/** Reflect property changes to attribute */
reflect?: boolean;
}
/**
* The @State() decorator manages internal component state
* @returns Property decorator
*/
function State(): PropertyDecorator;
/**
* The @Element() decorator provides reference to the host element
* @returns Property decorator
*/
function Element(): PropertyDecorator;
/**
* The @AttachInternals() decorator provides access to ElementInternals
* for form-associated components
* @returns Property decorator
*/
function AttachInternals(): PropertyDecorator;Usage Examples:
export class MyComponent {
@Prop() name: string;
@Prop({ reflect: true }) active: boolean;
@State() private count: number = 0;
@Element() el: HTMLElement;
@AttachInternals() internals: ElementInternals;
}Decorators for exposing public methods and watching property changes.
/**
* The @Method() decorator exposes methods on the public API
* @param opts - Method configuration options
* @returns Method decorator
*/
function Method(opts?: MethodOptions): MethodDecorator;
interface MethodOptions {}
/**
* The @Watch() decorator watches for property changes
* @param propName - Name of the property to watch
* @returns Method decorator
*/
function Watch(propName: string): MethodDecorator;Usage Examples:
export class MyComponent {
@Prop() value: string;
@Method()
async reset(): Promise<void> {
this.value = '';
}
@Watch('value')
valueChanged(newValue: string, oldValue: string) {
console.log('Value changed:', oldValue, '->', newValue);
}
}Decorators and utilities for creating and listening to custom events.
/**
* The @Event() decorator creates custom DOM events
* @param opts - Event configuration options
* @returns Property decorator
*/
function Event(opts?: EventOptions): PropertyDecorator;
interface EventOptions {
/** Custom event name override */
eventName?: string;
/** Whether the event bubbles up through the DOM */
bubbles?: boolean;
/** Whether the event is cancelable */
cancelable?: boolean;
/** Whether the event can bubble across shadow DOM boundary */
composed?: boolean;
}
/**
* The @Listen() decorator listens to DOM events
* @param eventName - Name of the event to listen to
* @param opts - Listener configuration options
* @returns Method decorator
*/
function Listen(eventName: string, opts?: ListenOptions): MethodDecorator;
interface ListenOptions {
/** Where to attach the event listener */
target?: ListenTargetOptions;
/** Use capturing phase */
capture?: boolean;
/** Use passive event listener */
passive?: boolean;
}
type ListenTargetOptions = 'body' | 'document' | 'window';
interface EventEmitter<T = any> {
emit: (data?: T) => CustomEvent<T>;
}Usage Examples:
export class MyComponent {
@Event() myCustomEvent: EventEmitter<string>;
@Event({ bubbles: false }) myPrivateEvent: EventEmitter<number>;
@Listen('click')
handleClick(event: MouseEvent) {
this.myCustomEvent.emit('Button clicked!');
}
@Listen('resize', { target: 'window' })
handleResize(event: Event) {
console.log('Window resized');
}
}Functions and utilities for JSX templating and virtual DOM creation.
/**
* JSX pragma function for creating virtual DOM nodes
* @param sel - Element selector or component
* @param data - Element attributes and properties
* @param children - Child elements
* @returns Virtual DOM node
*/
function h(sel: any): VNode;
function h(sel: Node, data: VNodeData | null): VNode;
function h(sel: any, data: VNodeData | null): VNode;
function h(sel: any, text: string): VNode;
function h(sel: any, children: Array<VNode | undefined | null>): VNode;
function h(sel: any, data: VNodeData | null, text: string): VNode;
function h(sel: any, data: VNodeData | null, children: Array<VNode | undefined | null>): VNode;
function h(sel: any, data: VNodeData | null, children: VNode): VNode;
/**
* Host functional component for setting attributes on the host element
*/
declare const Host: FunctionalComponent<HostAttributes>;
interface HostAttributes {
class?: string | { [className: string]: boolean };
style?: { [key: string]: string | undefined };
ref?: (el: HTMLElement | null) => void;
[prop: string]: any;
}
/**
* Fragment functional component for multiple children without wrapper
*/
declare const Fragment: FunctionalComponent<{}>;
/**
* Render virtual DOM tree to a container element
* @param vnode - Virtual DOM tree to render
* @param container - Container element to render into
*/
function render(vnode: VNode, container: Element): void;Usage Examples:
export class MyComponent {
@Prop() items: string[];
render() {
return (
<Host class="my-component">
<div class="header">
<h1>My Component</h1>
</div>
<div class="content">
{this.items.map(item => (
<div class="item" key={item}>
{item}
</div>
))}
</div>
</Host>
);
}
}
// Using Fragment
render() {
return (
<Fragment>
<div>First child</div>
<div>Second child</div>
</Fragment>
);
}Component lifecycle interfaces for handling component state changes.
interface ComponentWillLoad {
/**
* Called once before the component's first render
*/
componentWillLoad(): Promise<void> | void;
}
interface ComponentDidLoad {
/**
* Called once after the component's first render
*/
componentDidLoad(): void;
}
interface ComponentWillUpdate {
/**
* Called before each render (except the first)
*/
componentWillUpdate(): Promise<void> | void;
}
interface ComponentDidUpdate {
/**
* Called after each render (except the first)
*/
componentDidUpdate(): void;
}
interface ComponentInterface {
connectedCallback?(): void;
disconnectedCallback?(): void;
componentWillLoad?(): Promise<void> | void;
componentDidLoad?(): void;
componentWillUpdate?(): Promise<void> | void;
componentDidUpdate?(): void;
componentWillRender?(): Promise<void> | void;
componentDidRender?(): void;
componentShouldUpdate?(newVal: any, oldVal: any, propName: string): boolean | void;
render?(): any;
}Usage Example:
export class MyComponent implements ComponentInterface {
@State() private data: any[] = [];
async componentWillLoad() {
// Load data before first render
this.data = await fetchData();
}
componentDidLoad() {
// Component is ready, set up event listeners
console.log('Component loaded');
}
componentShouldUpdate(newVal: any, oldVal: any, propName: string): boolean {
// Control when component should update
return newVal !== oldVal;
}
render() {
return <div>{this.data.length} items loaded</div>;
}
}Support for functional components with utilities for working with children.
interface FunctionalComponent<T = {}> {
(props: T, children: VNode[], utils: FunctionalUtilities): VNode | VNode[];
}
interface FunctionalUtilities {
/**
* Iterate over children with a callback
*/
forEach: (children: VNode[], cb: (vnode: ChildNode, index: number, array: ChildNode[]) => void) => void;
/**
* Transform children and return new array
*/
map: (children: VNode[], cb: (vnode: ChildNode, index: number, array: ChildNode[]) => ChildNode) => VNode[];
}
interface ChildNode {
vtag?: string | number | Function;
vkey?: string | number;
vtext?: string;
vchildren?: VNode[];
vattrs?: any;
vname?: string;
}Usage Example:
export const AddClass: FunctionalComponent = (_, children, utils) => (
utils.map(children, child => ({
...child,
vattrs: {
...child.vattrs,
class: `${child.vattrs.class} add-class`
}
}))
);
// Usage in JSX
render() {
return (
<AddClass>
<div>This will have 'add-class' added</div>
</AddClass>
);
}Install with Tessl CLI
npx tessl i tessl/npm-stencil--coredocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10