Component API Reference
This document details the exact API signatures, options, and types for Coralite Web Components. Components author their behavior using top-level Named Exports in a <script type="module"> block. The legacy defineComponent wrapper function remains supported for backward compatibility.
For a conceptual guide on how to use dynamic components, see the Components Guide.
Coralite components declare behaviors via top-level named exports:
- Handler Functions:
export function server(ctx),export function client(ctx),export function onError(ctx) - Declarations:
export const attributes = {},export const getters = {},export const style = {},export const slots = {},export const provide = ...,export const consume = ...,export const formControl = true,export const listStrategy = ...
Renamed & Consolidated Keys:
formAssociated has been renamed to formControl (matching user mental model).
reconcile and key have been folded into listStrategy.
The unused state block has been removed.
Any auxiliary exports (e.g. helper functions or constants) are ignored by the compiler and preserved in module scope.
defineComponent Compatibility: The export default defineComponent({ ... }) syntax continues to work seamlessly during the transition period. If a component file defines both, defineComponent takes precedence.
Export Contract & Options #
The compiler recognizes the following 11 component export keys. Note: All components MUST have a hyphen in their name (e.g., <my-component>).
| Export / Option | Form & Type | Description |
|---|---|---|
attributes |
export const attributes: Record<string, AttributeSchema> |
Defines and coerces HTML attributes into JS primitives. |
server |
export function server(ctx: CoraliteServerContext): Promise<Record<string, any>> | Record<string, any> |
Server-side async function for fetching initial state at build time. Stripped from client bundle. |
client |
export function client(ctx: CoraliteClientContext): void | Promise<void> |
Client-side controller. Receives read/write state proxy, DOM refs, and reactive observers. External modules must be loaded with dynamic await import(). |
getters |
export const getters: Record<string, (ctx: CoraliteGetterContext) => any> |
Pure functions for derived state. Receives single context object parameter { state, root, refs, signal, ... }. Must destructure context. |
style |
export const style: Record<string, ((state: ReadonlyState) => string | number | null | undefined | false) | string | number> |
Declarative, reactive CSS properties and CSS Custom Properties (--*). Functions receive state directly and must be synchronous. |
slots |
export const slots: Record<string, CoraliteModuleSlotFunction> |
Functions for processing and transforming slot content. |
formControl(legacy: formAssociated) |
export const formControl = true |
Opt-in flag enabling Form-Associated Custom Elements (FACE). Attaches ElementInternals and integrates with standard HTML forms. |
listStrategy(legacy: reconcile / key) |
export const listStrategy: 'full' | 'minimal' | { mode: 'full' | 'minimal', key?: (item: any) => any } |
Array mutation reconciliation strategy. Controls full re-render vs minimal pattern-matched DOM operations. |
provide |
export const provide: Map<any, any> | Record<string | symbol, any> |
W3C context provider map or object providing context down the DOM tree. |
consume |
export const consume: string[] | Record<string, any> |
W3C context consumer declaration subscribing to context provided by an ancestor. |
onError |
export function onError(ctx: { error: Error, state: Record<string, any>, element?: any, page?: any, root?: any }): string | { template?: string, state?: Record<string, any> } | void |
Component-level error boundary hook invoked on SSR rendering failures in production mode. |
1. attributes #
The attributes block defines the inputs your component accepts from HTML. Coralite automatically coerces, transforms, and validates these values through a robust attribute schema engine.
attributes: {
// Type shorthand syntax
expanded: Boolean,
// Array shorthand syntax (implicit String type & values check)
variant: ['primary', 'secondary', 'danger'],
// Verbose schema definition with transform and validate pipeline
theme: { type: String, default: 'light', values: ['light', 'dark', 'system'] },
maxItems: { type: Number, default: 10, validate: (val) => val > 0 || 'maxItems must be positive' },
apiKey: { type: String, required: true },
slug: {
type: String,
transform: (val) => val.toLowerCase().trim(),
validate: (val) => val.length >= 3 || 'Slug must be at least 3 characters'
}
}
Attribute Schema Configuration #
| Property | Type | Description |
|---|---|---|
type |
Boolean | Number | String |
Primitive constructor used for coercion. Required in verbose schema. |
default |
any |
Default value if attribute is absent. Cannot be combined with required: true (Definition Mutex). |
values |
Array<any> |
Allowed primitive value set. In array shorthand (e.g., status: ['a', 'b']), `type` defaults to `String`. |
required |
boolean |
When true, marks attribute as mandatory. Missing attributes gracefully record an error in state.errors and error_* tokens during runtime. Cannot be combined with default. |
transform |
(val: any) => any |
Synchronous transformation function run after coercion. Must not return a Promise. |
validate |
(val: any) => boolean | string | void |
Synchronous predicate. Returns true/void on success, false for default error, or string for custom error message. |
The 6-Step Attribute Execution Lifecycle Pipeline & Graceful Error Handling #
Attributes execute sequentially through a strict 6-step lifecycle pipeline during component initialization and state changes. When validation fails (e.g., missing required attribute, values enum mismatch, or validate predicate failure), Coralite records the error message gracefully in state.errors and flat error_* tokens without halting SSR or crashing client scripts:
- 1.
requiredCheck: Asserts attribute presence ifrequired: trueis configured. Records"Attribute \"on omission.\" is required." - 2. Type
coerce: Coerces raw attribute string into specified primitive constructor (Boolean,Number, orString). - 3.
transform: Runs custom synchronoustransform(val)function to format or sanitize value. Thrown errors are recorded instate.errorswhile retaining the attempted value. - 4.
valuesCheck: Validates that value exists in allowedvalues: [...]enumeration array. Records formatted expected values error on mismatch. - 5.
validate: Invokes custom synchronousvalidate(val)predicate/function. Returningfalsesets default error message; returning a string records custom message; throwing records error message. - 6. State Application: Applies the validated value or retains attempted input in
state[key]and updates reactivestate.errorsand flaterror_*template tokens.
Graceful Attribute Validation (state.errors & error_* Tokens) #
Coralite provides two zero-overhead mechanisms to display and handle attribute validation feedback:
- JS Access (
state.errors): A reactive dictionary mapping camelCase attribute names to error string messages (e.g.state.errors.age). Implemented as a nested reactiveProxythat automatically tracks getter and observer dependencies on read, symmetrically updates both camelCase and kebab-case flaterror_*tokens on mutation/deletion, and schedules reactive DOM re-renders upon property mutation, deletion, or whole-object assignment (state.errors = { ... }). When all attributes are valid,Object.keys(state.errors).length === 0. - Flat Template Tokens (
): Automatic flat template tokens populated on state in both camelCase and kebab-case aliases (e.g.and{{ error_user-age }}). Default to""(empty string) when valid. - Client Context (
errors): Provided directly in client controller signatures:client: ({ state, errors, ... }) => ....
Coralite maps declared attribute names from camelCase (e.g., isChecked) to their kebab-case equivalent in HTML (e.g., is-checked) and coerces them into JavaScript primitives. Changes to HTML attributes via setAttribute automatically update their values in the component state.
Coercion Logic #
The coercion rules for the supported primitive constructors are detailed below:
-
Boolean: Coerced using
value === '' ? true : (value !== 'false' && value !== null)on both server and client. Empty attributes likedisabledevaluate totrue. - Number: Evaluated using
Number(value). Strings that are not valid numbers resolve toNaN. - String: Evaluated using
String(value).
Coercion Matrix Reference #
| Input HTML Attribute Value | Boolean Coercion | Number Coercion | String Coercion |
|---|---|---|---|
"true" |
true |
NaN |
"true" |
"false" |
false |
NaN |
"false" |
"42" |
true |
42 |
"42" |
"0" |
true |
0 |
"0" |
"" (empty attribute) |
true |
0 |
"" |
null (absent) |
false (or default) |
null (or default) |
null (or default) |
"hello" |
true |
NaN |
"hello" |
Native HTML Boolean Attributes & WAI-ARIA (aria-*) Auto-Removal #
When single reactive state tokens are bound to element attributes within templates, Coralite applies intelligent toggling and auto-removal rules depending on the attribute type:
-
43 Standard Native HTML Boolean Attributes (Presence Toggling):
When bound to a boolean attribute (such as
disabled="",hidden="",required="",allowpaymentrequest=""), if the value resolves to falsy (false,"false",null,"null",undefined,"undefined","",0,"0"), the attribute is completely removed from the element. When truthy, it is rendered as an empty string presence attribute (e.g.disabled="").
Supported 43 Boolean Attributes:allowfullscreen,allowpaymentrequest,async,autofocus,autoplay,checked,compact,controls,credentialless,declare,default,defer,disabled,disablepictureinpicture,disableremoteplayback,formnovalidate,hidden,inert,ismap,itemscope,loop,multiple,muted,nohref,nomodule,noresize,noshade,novalidate,nowrap,open,playsinline,readonly,required,reversed,scoped,seamless,selected,shadowrootclonable,shadowrootdelegatesfocus,shadowrootserializable,truespeed,typemustmatch, andwebkitdirectory. -
WAI-ARIA Attributes Auto-Removal & State Preservation (
aria-*): When anaria-*attribute is bound with a single template token:-
Core ARIA State Attributes (
aria-expanded,aria-pressed,aria-checked,aria-selected): These 4 core attributes format falsy values (false,"false",0,"0") as"false"and preserve"mixed"where applicable. They are removed ONLY when bound values evaluate to nullish or empty (null,undefined,"","null","undefined"). -
Generic ARIA Attributes:
All other
aria-*attributes (e.g.,aria-hidden,aria-disabled,aria-label,aria-valuenow) are completely removed when falsy (false,"false",null,"null",undefined,"undefined",""), while preserving numeric0/"0".
-
Core ARIA State Attributes (
-
Boolean Custom Attributes:
When a custom element attribute is declared as a boolean type in its target component schema (via
Boolean,{ type: Boolean }, or{ type: 'Boolean' }, e.g.<atoll-button loading="">whereloading: Boolean), template bindings automatically evaluate with boolean presence semantics. Falsy values (false,"false",null,undefined,"",0) cause the attribute to be completely removed from the DOM element, while truthy values render as an empty string presence attribute (e.g.loading=""). -
Standard Non-Boolean Attributes & Nullish Attribute Omission (
default: null): Standard custom or non-boolean attributes (e.g.,pattern="",title="") evaluate bound tokens as string values. When an attribute schema specifiesdefault: null(e.g.,pattern: { type: String, default: null }) and no attribute value is provided on the custom element, the token evaluates to nullish (nullorundefined) and Coralite omits/removes the attribute from native DOM nodes, preventing invalid empty attributes likepattern="". Explicit string values (including explicit empty strings likealt=""orplaceholder="") are preserved on DOM elements.
To prevent complex JSON-in-HTML parsing errors and ensure performance, attributes only support String, Number, and Boolean. Use the server block or slots for complex data structures.
Note: If you use the no-hydration attribute, the host tag is completely removed (spliced) and replaced by its contents. Learn more in the SSR Guide.
2. server (Server-Side) #
The server block is used for heavy-lifting, such as database queries or API calls. This code runs only on the server during the build process and is completely removed from the JavaScript sent to the browser. Formerly known as data.
async server(context) {
const users = await db.users.findMany();
return { users };
}
Note: In testing mode, you can override this block for specific components to provide deterministic mock data.
3. getters (Derived State) #
Getters are functions used to calculate derived data. They are reactive; if an attribute or a data value changes, the getter automatically re-calculates. Getters support both synchronous pure functions and asynchronous functions returning Promises.
Anti-Pattern (Passthrough Getters): Getters are strictly for computing derived state. A getter whose body merely returns raw state (e.g. ({ state }) => state.foo) is dead code because is already directly available in template tokens. If a getter can be replaced by a flat template token, delete the getter.
getters: {
visibleUsers: ({ state }) => state.users.slice(0, state.maxItems),
async filteredData: async ({ state, signal }) => {
const res = await fetch(`/api/filter?type=${state.filter}`, { signal })
return res.json()
}
}
When an asynchronous getter is evaluated or observed via observe(key, callback), Coralite tracks dependencies across await points and delivers resolved values to observers. If state changes while an async getter is in-flight, stale resolutions are automatically discarded to prevent race conditions.
4. style (Declarative Reactive CSS) #
The style block defines declarative, reactive inline CSS properties and CSS Custom Properties (--*) on the custom element host tag.
style: {
// CSS Custom Property (preserved with -- prefix)
'--accent-color': (state) => state.theme === 'dark' ? '#38bdf8' : '#0284c7',
// Standard CSS property (automatically camelCase -> kebab-case)
backgroundColor: (state) => state.isActive ? '#e0f2fe' : null,
fontSize: (state) => `${state.size}px`,
// Static values
cursor: 'pointer'
}
Style Property Normalization & Removal Semantics #
- Property Name Normalization: Standard camelCase properties (e.g.,
backgroundColor) are automatically converted to kebab-case (e.g.,background-color). Custom property names starting with--are preserved as-is. - Removal Triggers: Returning
null,undefined,false, or''(empty string) removes the property from the host element's inline style (`this.style.removeProperty()` on client, omitted in SSR). - Zero Value Preservation: Returning the numeric value
0(zero) is strictly preserved as valid CSS (e.g.,opacity: 0). - Synchronous Function Enforcement: Style getter functions must be strictly synchronous. Returning a
Promisethrows aCoraliteError.
5. client (Client-Side) #
The client block is the controller for your component in the browser. This is where you add event listeners, mutate state, and dispatch custom events. Formerly known as script.
client: ({ state, signal, refs, observe, emit }) => {
// Access unique DOM elements via the 'refs' utility
const btn = refs('loadMoreBtn');
// Register an observer to react to state changes
observe('maxItems', (newVal, oldVal) => {
console.log(`maxItems updated from ${oldVal} to ${newVal}`);
});
btn.addEventListener('click', () => {
// Imperative mutation triggers DOM updates
state.maxItems += 10;
// Dispatch custom DOM event to parent components
emit('items-expanded', { count: state.maxItems });
}, { signal }); // Use the provided 'signal' for auto-cleanup
}
CoraliteScriptContext #
| Property | Type | Description |
|---|---|---|
state |
Proxy |
The Read/Write reactive state (Attributes + Data + Getters). |
signal |
AbortSignal |
Used for cleaning up event listeners and aborting fetches on unmount. |
root |
HTMLElement |
The DOM element instance of the component. |
instanceId |
string |
A unique identifier for this specific instance. |
refs |
(id: string) => HTMLElement | null |
A utility to query unique elements by their ref name. |
observe |
(key: string, callback: (newVal: any, oldVal: any) => void) => void |
Registers a callback to execute explicit side-effects on state changes. Automatically cleaned up when the component is disconnected. |
emit |
(name: string, detail?: any, options?: CustomEventInit) => boolean |
Helper function to dispatch custom DOM events from the host element. Defaults to { bubbles: true, composed: true, cancelable: false }. Returns true if event was not cancelled via preventDefault(). |
updateComplete |
Promise<boolean> |
A read-only Promise<boolean> that resolves when the element completes its current update cycle and flushes DOM changes and observers. Resolves immediately if idle; resolves to false if aborted, disconnected, or if the reactive cascade breaker trips. |
errors |
Record<string, string> |
Reactive dictionary mapping attribute names to validation error messages. |
internals |
ElementInternals | null |
The native ElementInternals instance attached when formControl: true (or legacy formAssociated: true) is configured (null otherwise). |
setFormValue |
(value: any, state?: any) => void |
Sets the custom element's form submission value and state. Automatically synchronizes with state.value. |
setValidity |
(flags?: ValidityStateFlags, message?: string, anchor?: HTMLElement) => void |
Sets the custom element's validity flags, validation message, and focus anchor element. |
checkValidity |
() => boolean |
Checks if the element satisfies constraint validation without triggering browser UI popups. |
reportValidity |
() => boolean |
Checks constraint validation and displays browser validation bubble if invalid. |
validity |
ValidityState | undefined |
Live ValidityState getter object reflecting constraint validation. |
validationMessage |
string |
Live localized validation message string getter. |
form |
HTMLFormElement | null |
Live getter resolving the associated <form> element (either ancestor form or external form via form="id"). |
onFormReset |
(callback: () => void) => () => void |
Registers a callback invoked when the enclosing form is reset. Returns a disposer function. |
onFormDisabled |
(callback: (disabled: boolean) => void) => () => void |
Registers a callback invoked when form or ancestor <fieldset disabled> state changes. Returns a disposer function. |
onFormRestore |
(callback: (state: any, mode: 'restore' | 'autocomplete') => void) => () => void |
Registers a callback invoked when the browser restores form state or autocomplete occurs. Returns a disposer function. |
6. slots #
Allows you to intercept and transform content passed into your component's slots.
type CoraliteSlotContext<state = any> = {
state: State; // reactive proxy (client) / plain merged state (SSR)
observe: (prop: string, cb: (newVal: any, oldVal?: any) => any) => () => void; // ALWAYS returns a disposer
signal: AbortSignal;
root: HTMLElement | null; // element on client, null during SSR build
refs: (name: string) => HTMLElement | null; // no-op returning null on SSR
instanceId: string;
} & Record<string, any>
type SlotTransformer<state = any> = (
nodes: Node[],
context: CoraliteSlotContext<state>
) => Node[] | Node | string | null | Promise<node[] | node string null>
</node[]></state></state></string,></state>
The Void = Bypass Paradigm #
To ensure high performance and prevent unnecessary re-rendering during client-side hydration, Coralite uses a "Void = Bypass" approach for slot transformations:
undefined(Bypass): Signals the framework to skip processing and preserve the current content. On the server, it preserves the original AST nodes; on the client, it preserves the existing DOM nodes. Use this in the browser to prevent flushing SSR-rendered content.null,"", or[](Clear): Explicitly instructs the framework to remove all content from the slot.
slots: {
default: (nodes, state) => {
// Bypass hydration in the browser to preserve SSR content
if (typeof window !== 'undefined') return undefined;
// Otherwise, perform complex transformation on the server
return nodes.map(n => transform(n));
}
}
7. formControl (Form-Associated Custom Elements) #
Coralite provides first-class, standard-aligned support for native Web Component Form-Associated Custom Elements (FACE). By exporting formControl = true (legacy: formAssociated: true in defineComponent), your custom element integrates directly with standard HTML <form> submission, FormData extraction, constraint validation, form reset cycles, and <fieldset disabled> cascading with zero third-party dependencies.
// Enables FACE lifecycle and attachInternals()
export const formControl = true
export const attributes = {
name: String,
value: {
type: String,
default: '',
validate: (val) => (!val || val.length >= 3) || 'Value must be at least 3 characters'
},
disabled: Boolean
}
export function client ({ state, setFormValue, onFormReset, onFormDisabled }) {
// 1. Form value automatically synchronizes with state.value
// Calling setFormValue(customVal) manually overrides default serialization if needed.
// 2. Form reset hook: restores initial attribute/default snapshots
onFormReset(() => {
console.log('Form was reset!')
})
// 3. Fieldset disabled cascading
onFormDisabled((disabled) => {
console.log('Fieldset disabled state changed to:', disabled)
})
}
Opt-in Policy & Zero Platform Pollution #
FACE behavior is strictly opt-in to avoid prototype pollution and runtime overhead on standard components:
- Opt-In Enforcement: When
formAssociated: trueis specified, the compiler setsstatic formAssociated = trueon the generated custom element class, and Coralite invokesthis.attachInternals()during element construction. - Clean Standalone Components: If
formAssociated: trueis omitted or false,attachInternals()is never called,internalsisnull, andel.name/el.typeremain standard element properties. CallingsetFormValue()orsetValidity()on a non-form component emits a dev-mode warning.
Automatic Value Sync & Schema-to-Validity Bridge #
Coralite eliminates boilerplate when wiring up custom form controls by automatically synchronizing component state with native form APIs:
- Automatic
setFormValueSync: Writes tostate.valueautomatically update the element's form submission value viainternals.setFormValue(value). CallingsetFormValue(customValue, customState)inclient()provides an explicit manual override. - Schema-to-Validity Bridge: Attribute schema validation on
state.valueautomatically bridges into nativeElementInternals.setValidity():- When
attributes.value.validate(val)returns an error string (orfalse), Coralite automatically callsinternals.setValidity({ customError: true }, message, anchor), pointing to the internal<input>,<textarea>, or<select>if present in the component. - When errors clear, Coralite automatically resets validity to
{}(valid). - Explicit calls to
setValidity(flags, message, anchor)inclient()latch manually until cleared or reset.
- When
- Host Element Form Properties: Form-associated components expose standard DOM properties directly on the host custom element:
el.name: Reflects to/from thenameattribute.el.type: Returns the custom element's tag name.el.form: Resolves the associated<form>element (either ancestor form or external form matched byform="id").el.validity: Returns the currentValidityState.el.validationMessage: Returns the active validation message.el.willValidate: Indicates if the element participates in constraint validation.el.checkValidity()&el.reportValidity(): Executes constraint validation.el.labels: Returns aNodeListof associated<label>elements.
Form Lifecycle Hooks (onFormReset, onFormDisabled, onFormRestore) #
Coralite provides high-level reactive hooks in client() to handle native form callbacks gracefully:
onFormReset(callback): Fires when the enclosing form is reset via<button type="reset">orform.reset(). Coralite automatically restoresstate.valueandstate.checkedto their initial attribute/default snapshots, clearsstate.errors.value, resets validity, and executes all registeredonFormResetlisteners.onFormDisabled(callback): Fires whenever the component's disabled state changes, including when an ancestor<fieldset disabled>is toggled. Coralite automatically mirrors the disabled status tostate.disabled.onFormRestore(callback): Fires when the browser restores form state after navigation or during autofill, receiving(state, mode)where mode is'restore'or'autocomplete'.
8. onError (Component Error Boundary) #
The onError handler provides component-level fault isolation for production rendering. If component script evaluation, getter computation, slot rendering, or template processing throws an error during SSR in mode: 'production', Coralite invokes onError to render fallback UI gracefully without destroying the host page.
export function onError ({ error, state, element, page, root }) {
return {
template: '<div class="component-fallback"><p></p></div>',
state: { message: 'Content temporarily unavailable' }
}
}
When an object with { template, state } is returned, the provided state properties are shallow-merged into the component state prior to parsing the fallback template string. Fallback HTML renders with noHydration: true and stripped data-cid hydration markers so browser clients do not attempt to hydrate failed SSR components. In development and testing modes (or if onError itself throws), errors bubble up to preserve immediate developer visibility and test assertion contracts.
9. listStrategy (Array Reconciliation) #
The listStrategy export controls how array state changes are reconciled with the DOM. It replaces the former reconcile and key options from defineComponent.
Modes:
'full'(default): Performs full re-rendering of the list template whenever the array mutates. Same as omitting the export.'minimal': Pattern-matches array operations (push, pop, shift, unshift, splice, swap, clear) and applies surgical, minimal DOM updates.- Object form with key extractor:
{ mode: 'minimal', key: (item) => item.uuid }. For collections where items don't have standardidorkeyproperties, specify a custom key function.
// Shorthand minimal reconciliation
export const listStrategy = 'minimal'
// Object form with custom key extractor
export const listStrategy = {
mode: 'minimal',
key: (item) => item.uuid
}