adapter

The DOM render adapter implementing the RenderAdapter interface for browser environments.

Syntax

const adapter: Partial<RenderAdapter<Node, string, Node>>

Description

The adapter object contains the implementation details for how Crank elements are converted to DOM nodes. It implements the RenderAdapter interface with DOM-specific behavior.

This is primarily an internal implementation detail, but it's exported for:

Implemented methods

scope()

Handles XML namespace propagation for SVG and MathML elements.

scope({scope: xmlns, tag, props}): string | undefined

create()

Creates DOM elements with proper namespace handling.

create({tag, tagName, scope: xmlns, root}): Node

adopt()

Adopts existing DOM nodes during hydration.

adopt({tag, tagName, node, root}): Array<Node> | undefined

Returns child nodes if the node matches, or undefined for hydration mismatch.

patch()

Updates DOM element attributes and properties.

patch({tagName, node, props, oldProps, scope: xmlns, ...}): void

Handles:

arrange()

Arranges child nodes within their parent.

arrange({tag, node, props, children}): void

Efficiently moves, inserts, and removes nodes to match the children array.

remove()

Removes a node from its parent.

remove({node, parentNode, isNested}): void

text()

Creates or updates text nodes.

text({value, oldNode, hydrationNodes, root}): Node

raw()

Handles Raw element values.

raw({value, scope: xmlns, hydrationNodes, root}): ElementValue<Node>

Parses HTML strings or returns node arrays directly.

Examples

Understanding prop handling

// These all work thanks to the adapter's patch() method:

// String class
<div class="container" />

// Object class (conditional classes)
<div class={{"active": isActive, "disabled": isDisabled}} />

// Style string
<div style="color: red; font-size: 16px;" />

// Style object
<div style={{color: "red", fontSize: "16px"}} />

// Event handlers (React-style naming works)
<button onClick={handleClick} />

// Boolean attributes
<input disabled={true} />
<input disabled />

// Force attribute vs property
<input attr:value="forced attribute" />
<input prop:value="forced property" />

Custom renderer extending DOM

import {Renderer} from "@b9g/crank";
import {adapter as domAdapter} from "@b9g/crank/dom";

const customAdapter = {
...domAdapter,
patch(data) {
// Custom patching logic
console.log("Patching:", data.tagName);
domAdapter.patch?.(data);
},
};

class CustomDOMRenderer extends Renderer<Node, string, Element> {
constructor() {
super(customAdapter);
}
}

See also

Edit on GitHub