@gluonjs/core


@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

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();