@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
protectedreadonlyrenderRoot:ShadowRoot
Shadow root rendered by update; override createRenderRoot to customize it.
events
readonlystaticevents:Readonly<Record<string,EventDeclaration<any>>> ={}
Declares native output events and their propagation, cancellation, and validation rules.
properties
readonlystaticproperties:Readonly<Record<string,PropertyDefinition<any>>> ={}
Declares reactive inputs and their attribute conversion, reflection, and validation rules.
shadowRootRegistry?
readonlystaticoptionalshadowRootRegistry?:GluonElementRegistry
Optional explicit registry associated with this element's ShadowRoot.
slots
readonlystaticslots:SlotDeclarations={}
Declares required named/default slots and whether the template supplies fallback content.
styles
readonlystaticstyles:CSSStyleSheet| readonlyCSSStyleSheet[] =[]
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
staticobservedAttributes():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()
protectedcreateRenderRoot():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()
protectedemit<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()
protectedexpose<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()
protectedonBeforeUpdate(callback):void
Runs a callback before every update after the first render.
Parameters
callback
Returns
void
onConnected()
protectedonConnected(callback):void
Runs a callback once after the first render of each connection.
Parameters
callback
Returns
void
onDisconnected()
protectedonDisconnected(callback):void
Runs a callback during disconnection after scoped reactive cleanup and render suspension.
Parameters
callback
Returns
void
onErrorCaptured()
protectedonErrorCaptured(callback):void
Captures descendant component errors; return true to stop propagation to outer boundaries.
Parameters
callback
Returns
void
onUpdated()
protectedonUpdated(callback):void
Runs a callback after every successful render, including the first render.
Parameters
callback
Returns
void
render()
abstractprotectedrender():TemplateResult
Returns the template for the current component state.
Returns
renderForServer()
renderForServer():
TemplateResult
Returns the component template without browser connection lifecycle for official server rendering.
Returns
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()
protectedrequestUpdate():Promise<void>
Schedules a deduplicated render and returns the same completion promise exposed by updateComplete.
Returns
Promise<void>
setupConnection()
protectedsetupConnection():void
Initializes work once per connection inside the connection's reactive effect scope.
Returns
void
teardownConnection()
protectedteardownConnection():void
Releases connection-local references after scoped cleanup and disconnect hooks.
Returns
void
update()
protectedupdate():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:
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();