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 #

typescript
Code copied!
  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, (context: CoraliteGetterContext) => any> Pure functions for derived state. Receives single context object parameter { state, root, refs, signal }.
style Record<string, ((state: ReadonlyState) => string | number | null | undefined | false) | string | number> Declarative, reactive CSS properties and CSS Custom Properties (--*).
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.
formAssociated boolean Opt-in flag enabling Form-Associated Custom Elements (FACE). Attaches ElementInternals and integrates with standard HTML forms.
provide Map<any, any> | Record<string | symbol, any> W3C context provider map or object providing context down the DOM tree.
consume string[] | Record<string, any> W3C context consumer declaration subscribing to context provided by an ancestor.
onError (context: { 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.

javascript
Code copied!
  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. 1. required Check: Asserts attribute presence if required: true is configured. Records "Attribute \"\" is required." on omission.
  2. 2. Type coerce: Coerces raw attribute string into specified primitive constructor (Boolean, Number, or String).
  3. 3. transform: Runs custom synchronous transform(val) function to format or sanitize value. Thrown errors are recorded in state.errors while retaining the attempted value.
  4. 4. values Check: Validates that value exists in allowed values: [...] enumeration array. Records formatted expected values error on mismatch.
  5. 5. validate: Invokes custom synchronous validate(val) predicate/function. Returning false sets default error message; returning a string records custom message; throwing records error message.
  6. 6. State Application: Applies the validated value or retains attempted input in state[key] and updates reactive state.errors and flat error_* template tokens.

Graceful Attribute Validation (state.errors & error_* Tokens) #

Coralite provides two zero-overhead mechanisms to display and handle attribute validation feedback:

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:

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:

Strict Primitive Rule

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.

javascript
Code copied!
  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.

javascript
Code copied!
  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.

javascript
Code copied!
  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 #

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.

javascript
Code copied!
  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 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.

typescript
Code copied!
  type CoraliteSlotContext<state = any> = {
    state: State;                                  // reactive proxy (client) / plain merged state (SSR)
    observe: (prop: string, cb: (newVal: any, oldVal?: any) =&gt; any) =&gt; () =&gt; void; // ALWAYS returns a disposer
    signal: AbortSignal;
    root: HTMLElement | null;                      // element on client, null during SSR build
    refs: (name: string) =&gt; HTMLElement | null;    // no-op returning null on SSR
    instanceId: string;
  } &amp; Record<string, any>
  
  type SlotTransformer<state = any> = (
    nodes: Node[],
    context: CoraliteSlotContext<state>
  ) =&gt; 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:

javascript
Code copied!
  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. formAssociated (Form-Associated Custom Elements) #

Coralite provides first-class, standard-aligned support for native Web Component Form-Associated Custom Elements (FACE). By configuring 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.

javascript
Code copied!
  import { defineComponent } from 'coralite'
  
  export default defineComponent({
    formAssociated: true, // Enables FACE lifecycle and attachInternals()
    attributes: {
      name: String,
      value: {
        type: String,
        default: '',
        validate: (val) => (!val || val.length >= 3) || 'Value must be at least 3 characters'
      },
      disabled: Boolean
    },
    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:

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:

Form Lifecycle Hooks (onFormReset, onFormDisabled, onFormRestore) #

Coralite provides high-level reactive hooks in client() to handle native form callbacks gracefully:

8. onError (Component Error Boundary) #

The onError block 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.

javascript
Code copied!
  onError({ error, state, element, page, root }) {
      return {
          template: '<div class="component-fallback"><p>{{ message }}</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.

Start Building with Coralite!

Use the scaffolding script to get jump started into your next project with Coralite

Copied commandline!