defineComponent API Reference
This document details the exact API signatures, options, and types for Coralite's core defineComponent plugin.
For a conceptual guide on how to use dynamic components, see the Components Guide.
Signature #
function defineComponent(options: DefineComponentOptions): PluginDefinition
Options Object (DefineComponentOptions) #
The defineComponent function accepts a single configuration object with the following isolated blocks. Note: All components MUST have a hyphen in their name (e.g., <my-component>).
| Property | Type | Description |
|---|---|---|
attributes |
Record<string, AttributeSchema> |
Defines and coerces HTML attributes into JS primitives. |
server |
(context: CoraliteServerContext) => Promise<Record<string, any>> |
A server-side async function for fetching initial state. Stripped from the client bundle. Formerly known as data. |
getters |
Record<string, (state: ReadonlyState) => any> |
Pure functions for derived state. Receives a read-only state proxy. |
client |
(context: CoraliteScriptContext) => void |
The client-side controller. Receives a read/write state proxy. Formerly known as script. |
slots |
Record<string, CoraliteModuleSlotFunction> |
Functions for processing and transforming slot content. |
1. attributes #
The attributes block defines the inputs your component accepts from HTML. Coralite automatically coerces these values into the specified types.
attributes: {
theme: { type: String, default: 'light' },
maxItems: { type: Number, default: 10 },
expanded: { type: Boolean, default: false }
}
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:
- Client-Side: Coerced using
value === '' ? true : (value !== 'false' && value !== null). Empty attributes likedisabledevaluate totrue. - Server-Side: Coerced using
value !== 'false' && value !== null && value !== ''.
- Client-Side: Coerced using
- 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 (client) / false (server) |
0 |
"" |
null (absent) |
false (or default) |
null (or default) |
null (or default) |
"hello" |
true |
NaN |
"hello" |
Native HTML Boolean Attribute Toggling #
When reactive state tokens are bound to element attributes within templates (for example, <button disabled="{{ isDisabled }}">), Coralite handles native HTML boolean attributes with special presence logic:
-
Toggled Removal: If the bound token resolves to a falsy value (specifically
"","false","null","0", or"undefined"), Coralite completely removes the attribute from the DOM element (e.g., callingelement.removeAttribute('disabled')). This matches browser expectations, where the mere presence of a boolean attribute makes it active. -
Presence Insertion: If the value evaluates to truthy, the attribute is set as an empty string presence attribute (e.g.
element.setAttribute('disabled', '')). -
The Reserved List: This toggling behavior is restricted to standard HTML boolean attributes including:
allowfullscreen,async,autofocus,autoplay,checked,controls,default,defer,disabled,formnovalidate,hidden,inert,ismap,itemscope,loop,multiple,muted,nomodule,novalidate,open,playsinline,readonly,required,reversed,selected, andtruespeed. -
Limitation: Custom boolean attributes (like
is-active="{{ isActive }}") do not use this toggling logic; instead, their values are written directly as standard string attributes (e.g.,is-active="false").
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 pure functions used to calculate derived data. They are reactive; if an attribute or a data value changes, the getter automatically re-calculates.
getters: {
// state is a Read-Only Proxy here
visibleUsers: (state) => state.users.slice(0, state.maxItems)
}
4. client (Client-Side) #
The client block is the controller for your component in the browser. This is where you add event listeners and mutate state. Formerly known as script.
client: ({ state, signal, refs, observe }) => {
// 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;
}, { 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. |
5. slots #
Allows you to intercept and transform content passed into your component's slots.
type CoraliteModuleSlotFunction = (slotNodes: Node[], state: any) => Node[] | string | undefined | null
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));
}
}