Skip to content

@gluonjs/core / src / GluonElement

Abstract Class: GluonElement<Events> ​

Base class for a stateful Gluon Custom Element with a Shadow DOM render root.

Subclasses declare their input properties, output events, slots, and adopted styles with static fields. Implement the protected render() method for the component template, register connection-owned work with the lifecycle hooks, and call emit for typed native CustomEvent output. Register the class once with defineElement.

Prefer defineGluonElement() when a component does not need inheritance or protected lifecycle/render hooks.

Extends ​

  • HTMLElementBase

Extended by ​

Type Parameters ​

Events ​

Events extends object = Record<string, unknown>

Map from emitted event names to their CustomEvent.detail types.

Constructors ​

Constructor ​

new GluonElement<Events>(): GluonElement<Events>

Creates the render root, finalizes declarations, captures pre-upgrade values, and applies defaults.

Returns ​

GluonElement<Events>

Overrides ​

HTMLElementBase.constructor

Properties ​

renderRoot ​

protected readonly renderRoot: ShadowRoot

Shadow root rendered by update; override createRenderRoot to customize it.


events ​

readonly static events: Readonly<Record<string, EventDeclaration<any>>> = {}

Declares native output events and their propagation, cancellation, and validation rules.


properties ​

readonly static properties: Readonly<Record<string, PropertyDefinition<any>>> = {}

Declares reactive inputs and their attribute conversion, reflection, and validation rules.


shadowRootRegistry? ​

readonly static optional shadowRootRegistry?: GluonElementRegistry

Optional explicit registry associated with this element's ShadowRoot.


slots ​

readonly static slots: SlotDeclarations = {}

Declares required named/default slots and whether the template supplies fallback content.


styles ​

readonly static styles: CSSStyleSheet | readonly CSSStyleSheet[] = []

Lists constructable stylesheets adopted into each instance's render root.

Accessors ​

changedProperties ​

Get Signature ​

get protected changedProperties(): ReadonlyMap<PropertyKey, unknown>

Returns the old values collected for the current update pass.

This is primarily a protected integration point for compatibility layers; native Gluon components should continue to use the lifecycle callbacks and reactive state directly.

Returns ​

ReadonlyMap<PropertyKey, unknown>


updateComplete ​

Get Signature ​

get updateComplete(): Promise<void>

Resolves after the currently scheduled render and its update hooks finish.

Returns ​

Promise<void>


observedAttributes ​

Get Signature ​

get static observedAttributes(): string[]

Attribute names derived from properties; managed by Gluon for the Custom Elements platform.

Returns ​

string[]

Methods ​

attributeChangedCallback() ​

attributeChangedCallback(name, oldValue, value): void

Converts a changed declared attribute and writes the corresponding property.

Parameters ​

name ​

string

oldValue ​

string | null

value ​

string | null

Returns ​

void


beginHydration() ​

beginHydration(): void

Defers the first connection render while official hydration binds declarative Shadow DOM.

Returns ​

void


connectedCallback() ​

connectedCallback(): void

Starts connection-owned reactivity and queues the first render. Prefer onConnected in subclasses.

Returns ​

void


createRenderRoot() ​

protected createRenderRoot(): ShadowRoot

Creates the component render root. Override only when the default open ShadowRoot is unsuitable.

Returns ​

ShadowRoot


disconnectedCallback() ​

disconnectedCallback(): void

Stops connection-owned work and suspends rendering. Prefer onDisconnected in subclasses.

Returns ​

void


emit() ​

protected emit<Name>(type, detail, init?): boolean

Dispatches a typed native CustomEvent using the matching static event declaration.

Events bubble and cross the Shadow DOM boundary by default. The return value is false only when a cancelable event was canceled by a listener.

Type Parameters ​

Name ​

Name extends string

Parameters ​

type ​

Name

detail ​

Events[Name]

init? ​

Omit<CustomEventInit<Events[Name]>, "detail"> = {}

Returns ​

boolean


endHydration() ​

endHydration(): void

Resumes connection rendering after official hydration installs the hydrated root.

Returns ​

void


expose() ​

protected expose<Public>(value): Readonly<Public>

Publishes a frozen, deliberately small public object for use with exposedRef().

Type Parameters ​

Public ​

Public extends object

Parameters ​

value ​

Public

Returns ​

Readonly<Public>


onBeforeUpdate() ​

protected onBeforeUpdate(callback): void

Runs a callback before every update after the first render.

Parameters ​

callback ​

ComponentLifecycleCallback

Returns ​

void


onConnected() ​

protected onConnected(callback): void

Runs a callback once after the first render of each connection.

Parameters ​

callback ​

ComponentLifecycleCallback

Returns ​

void


onDisconnected() ​

protected onDisconnected(callback): void

Runs a callback during disconnection after scoped reactive cleanup and render suspension.

Parameters ​

callback ​

ComponentLifecycleCallback

Returns ​

void


onErrorCaptured() ​

protected onErrorCaptured(callback): void

Captures descendant component errors; return true to stop propagation to outer boundaries.

Parameters ​

callback ​

ComponentErrorBoundary

Returns ​

void


onUpdated() ​

protected onUpdated(callback): void

Runs a callback after every successful render, including the first render.

Parameters ​

callback ​

ComponentLifecycleCallback

Returns ​

void


render() ​

abstract protected render(): TemplateResult

Returns the template for the current component state.

Returns ​

TemplateResult


renderForServer() ​

renderForServer(): TemplateResult

Returns the component template without browser connection lifecycle for official server rendering.

Returns ​

TemplateResult


requestHotUpdate() ​

requestHotUpdate(): Promise<void>

Requests a render pass after the official Vite runtime patches compatible logic. Application code should use normal reactive or property updates.

Returns ​

Promise<void>


requestUpdate() ​

protected requestUpdate(): Promise<void>

Schedules a deduplicated render and returns the same completion promise exposed by updateComplete.

Returns ​

Promise<void>


setupConnection() ​

protected setupConnection(): void

Initializes work once per connection inside the connection's reactive effect scope.

Returns ​

void


teardownConnection() ​

protected teardownConnection(): void

Releases connection-local references after scoped cleanup and disconnect hooks.

Returns ​

void


update() ​

protected update(): void

Commits the value returned by render into renderRoot.

Returns ​

void

Example ​

Implement a reactive Custom Element with declared properties, events, slots, lifecycle hooks, error boundaries, public exposure, Shadow DOM rendering, and server support:

ts
import {
  GluonElement,
  defineElement,
  exposedRef,
  getPublicInstance,
  html,
  refreshGluonElements,
  renderGluonElementForServer,
  setGluonRenderDebugHook,
  type ComponentErrorBoundary,
  type ComponentErrorInfo,
  type ComponentEventMap,
  type ComponentLifecycleCallback,
  type EventDeclaration,
  type EventDeclarations,
  type GluonElementServerRender,
  type GluonRenderCause,
  type GluonRenderDebugEvent,
  type GluonRenderDebugHook,
  type PropertyConverter,
  type PropertyDeclaration,
  type PropertyDeclarations,
  type PropertyDefinition,
  type PropertyType,
  type SlotDeclaration,
  type SlotDeclarations,
  type ValueRefTarget,
} from '@gluonjs/core';

type ProductProps = { name: string; quantity: number };
type ProductEvents = { select: { id: string } };
type ProductEventMap = ComponentEventMap<ProductEvents>;
const converter: PropertyConverter<string> = { fromAttribute: (value) => value ?? '', toAttribute: (value) => value };
const nameType: PropertyType = String;
const name: PropertyDeclaration<string> = { type: nameType, converter, required: true };
const quantity: PropertyDefinition<number> = { type: Number, default: 1, reflect: true };
const selectEvent: EventDeclaration<ProductEvents['select']> = { bubbles: true, composed: true };
const mediaSlot: SlotDeclaration = { required: false, fallback: true };
const slots = { media: mediaSlot } satisfies SlotDeclarations<'media'>;
const connected: ComponentLifecycleCallback = () => console.log('connected');
const boundary: ComponentErrorBoundary = (info) => { console.error(info.source); return true; };

class ProductCard extends GluonElement<ProductEvents> {
  static override readonly properties = { name, quantity } satisfies PropertyDeclarations<ProductProps>;
  static override readonly events = { select: selectEvent } satisfies EventDeclarations<ProductEvents>;
  static override readonly slots = slots;
  declare name: string;
  declare quantity: number;
  constructor() {
    super();
    this.expose({ select: () => this.emit('select', { id: '42' }) });
    this.onConnected(connected);
    this.onErrorCaptured((info: ComponentErrorInfo) => boundary(info));
  }
  protected render() { return html`<article>${this.name} × ${this.quantity}</article>`; }
}
defineElement('product-card', ProductCard);

const element = document.createElement('product-card') as ProductCard;
const publicTarget: ValueRefTarget<Readonly<{ select(): void }>> = { value: undefined };
const publicRef = exposedRef<{ select(): void }>(publicTarget);
if (typeof publicRef === 'function') publicRef(element);
getPublicInstance<{ select(): void }>(element)?.select();
const eventMap: Partial<ProductEventMap> = { select: new CustomEvent('select', { detail: { id: '42' } }) };
const server: GluonElementServerRender = renderGluonElementForServer(ProductCard, { name: 'Lamp' });
const hook: GluonRenderDebugHook = (event: GluonRenderDebugEvent) => {
  const cause: GluonRenderCause | undefined = event.causes[0];
  console.log(event.element.localName, event.duration, cause);
};
const restore = setGluonRenderDebugHook(hook);
refreshGluonElements();
console.log(server.tagName, server.template, eventMap, publicTarget.value);
if (typeof publicRef === 'function') publicRef(undefined);
restore();

Version-matched documentation. Examples are checked against the public package contracts.