Bond VDOM & Components
Bond is Braid's Virtual DOM library (braid-lang/lib/frameworks/bond/bond.br, 1002 lines). It defines a BondElement struct and provides factory functions, element helpers, SSR, reconciliation, mounting, lifecycle scaffolding, event delegation, form management, a11y validation, security helpers, and hydration.
Core VDOM Types
BondElement Struct
struct BondElement {
kind: string, // "element" | "text" | "fragment" | "component" | "portal" | "suspense" | "error_boundary"
tag: string, // HTML tag name or SVG tag
props: object, // Attributes/properties
children: object, // Child VDOM nodes or list
key: string, // Reconciliation key
text: string, // Text content for text nodes
component_ref: object, // Reference to component function
source_span: string, // Source location for debugging
deterministic_node_id: string,
ref: object, // Ref callback
namespace: string, // SVG namespace
portal_target: string, // CSS selector for portal target
suspense_fallback: object,
error_boundary_handler: object
}Factory Functions
// Create an HTML element
fn createElement(tag: string, props: object, children: object)
// Create element with namespace (SVG)
fn createElementNS(namespace: string, tag: string, props: object, children: object)
// Create a text node
fn createText(text: string)
// Create a fragment (no wrapper DOM element)
fn createFragment(children: object)
// Create a component wrapper
fn createComponent(component_ref: object, props: object, children: object)
// Create a portal (renders children into a different DOM target)
fn createPortal(children: object, target_selector: string)
// Create a suspense boundary with a fallback
fn createSuspenseBoundary(fallback: object, children: object)
// Create an error boundary
fn createErrorBoundary(error_handler: object, children: object)Refs and Keys
fn withRef(el: object, ref_callback: object) // Attach a ref callback
fn withKey(el: object, key: string) // Attach a reconciliation keyElement Helpers (50+)
Bond provides convenience functions for every HTML element and many SVG elements. Each accepts (props, children) for container elements or (text, props) for text-containing elements:
HTML Containers
div(props, children) span(props, children) header(props, children)
footer(props, children) main(props, children) section(props, children)
article(props, children) nav(props, children) aside(props, children)
ul(props, children) ol(props, children) li(props, children)
form(props, children) select(props, children) table(props, children)
thead(props, children) tbody(props, children) tr(props, children)HTML Text Elements
h1(text, props) h2(text, props) h3(text, props) h4(text, props)
h5(text, props) h6(text, props) p(text, props) a(text, props)
strong(text, props) em(text, props) code(text, props) pre(text, props)
blockquote(text, props) label(text, props) button(text, props)
th(text, props) td(text, props) option(text, props)Void / Self-Closing
input(props) img(props) video(props) audio(props)
iframe(props) canvas(props) br(props) hr(props)
source(props) track(props) embed(props) meta(props)SVG Elements
svg(props, children) circle(props) ellipse(props)
rect(props) line(props) polyline(props)
polygon(props) path(props) text(props, content)
tspan(props, content) g(props, children) defs(props, children)
use(props) symbol(props, ch) linearGradient(props, ch)
stop(props)SSR — Server-Side Rendering
The ssr.br module provides an SSRRenderer with cache, streaming, and state injection:
fn create_ssr_renderer() -> SSRRenderer
// Render full document
renderer.render_to_string(app)
renderer.render_to_string_with_state(app, state)
// Streaming
renderer.render_streaming(app, write_chunk)
// Data injection
renderer.render_with_data(app, data_fetcher)// Core SSR render function (in bond.br)
fn render_to_html(vnode: object) -> string // Recursively renders VDOM to HTML string
fn render_children_to_html(children: object) -> stringSSR output wraps content in a <div id="app" data-braid-hydrate="true"> container and optionally includes a <script id="__BRAID_DATA__"> with serialized state for client hydration.
Hydration
The hydration.br module provides progressive hydration with mismatch recovery:
struct Hydrator {
report: HydrationReport,
event_queue: list,
observed_nodes: object,
visibility_observer: object
}
fn create_hydrator() -> Hydrator
hydrator.hydrate(vnode, dom_node) // Full tree hydration
hydrator.hydrate_progressive(runtime, sel, vnode, dom) // Progressive hydration
hydrator.hydrate_when_visible(runtime, sel, vnode, dom) // Visible-only hydation
hydrator.perform_hydration_with_fallback(runtime, sel, vnode, dom) // Fallback rerenderReconciliation (Diffing)
The core diff and diff_children functions compare old/new VDOM trees and produce patch sets:
// Compare two VDOM trees
fn diff(old_vnode: object, new_vnode: object) -> object
// Returns: null (no change) | { type: "replace", node } | { type: "remove" }
// | { type: "update_text", text } | { type: "update_element", prop_patches, child_patches }
// Compare children lists
fn diff_children(old_children: object, new_children: object) -> list
// Returns patch objects: insert, remove, patch, reorder, move, insert_all, remove_all
// Props diffing
fn diff_props(old_props: object, new_props: object) -> object
// Returns: null | { type: "set_all", props } | { type: "remove_all" }
// | { type: "patch_props", changes: [{ key, op: "set"|"remove", value }] }
// Apply patches to a VDOM node
fn apply_patches(target_node: object, patches: object) -> int
fn apply_single_patch(node: object, patch: object)Keyed Reconciliation
fn build_keyed_map(children: object) -> object
fn reconcile_keyed_children(old_children: object, new_children: object) -> listKeyed reconciliation tracks nodes by their .key property and computes minimal reorder/move operations using the last-placed-index algorithm (similar to React's list diff).
Mounting
// Mount to in-memory virtual DOM
fn mount_to_memory_dom(vnode: object, target_id: string) -> MountResult
// Render directly to HTML string
fn mount_to_html_string(vnode: object) -> string
// Mount via WASM DOM adapter
fn mount_to_wasm_dom(vnode: object, target_selector: string) -> MountResultLifecycle
The lifecycle.br module provides ComponentInstance with mount/update/unmount/error hooks, persisted state, dependency tracking, and an update loop:
struct ComponentInstance {
vnode, lifecycle: { on_mount, on_update, on_unmount, on_error },
is_mounted, state, persisted_state_key, dependencies, error
}
instance.mount(adapter, target_selector)
instance.update(adapter, target_selector, new_vnode)
instance.unmount(adapter, target_selector)Event Delegation
fn create_delegator() -> EventDelegator
delegator.add_listener(type, selector, handler)
delegator.add_passive_listener(type, selector, handler)
delegator.remove_listener(type, selector)
delegator.dispatch_custom_event(type, target, detail)
delegator.handle_composed_event(event, composed_path)
struct Event { type, target, currentTarget, defaultPrevented,
propagationStopped, composed, payload, pooled, timestamp }Forms
fn create_form_state() -> FormState
form.register_field(name, initial_value)
form.update_field(name, value)
form.touch_field(name)
form.set_field_errors(name, errors)
form.handle_submit(submit_handler)
form.get_values() -> object
form.reset()
// Validators
validate_required(value) validate_min_length(value, min)
validate_max_length(value, max) validate_email(value)
validate_number(value) validate_min(value, min)
validate_max(value, max) validate_pattern(value, pattern)
cross_validate(fields, rules) validate_password_match(values)Accessibility (a11y.br)
fn create_validator() -> A11yValidator
validator.validate_tree(vnode) // Checks images for alt, buttons for aria-label, etc.
fn create_live_region_manager() // aria-live announcements
fn create_focus_manager() // Focus trapping for modals
fn create_keyboard_nav_helper() // Arrow key navigation
fn create_screen_reader_announcer()
fn skip_nav_link(target_id, text) // Skip-to-content link
fn check_contrast(foreground, background) -> float
fn check_aa_compliance(ratio) -> bool
fn check_aaa_compliance(ratio) -> boolSecurity (security.br)
// XSS prevention
SecurityHelpers.escape_text(text) -> string
SecurityHelpers.escape_attribute(attr) -> string
SecurityHelpers.sanitize_url(url) -> string // blocks javascript: etc.
// CSP
fn create_csp_config() -> CSPConfig
csp_config.generate_csp_header() -> string
csp_config.apply_csp_meta_tag() -> vnode
// Trusted Types
fn create_trusted_types_policy(name) -> TrustedTypesPolicyComponent Composition Example
import bond;
fn UserCard(props) {
return bond.div({ class: "card" }, [
bond.h2(props.name, { class: "card-title" }),
bond.p("Email: " + props.email, { class: "card-email" }),
bond.span(props.role, { class: "badge" })
]);
}
fn UserList(props) {
return bond.div({ class: "user-list" }, [
bond.h1("Users", {}),
bond.div({}, bond.createComponent(UserCard, {
name: "Alice",
email: "alice@example.com",
role: "Admin"
})),
bond.createComponent(UserCard, {
name: "Bob",
email: "bob@example.com",
role: "Editor"
})
]);
}
let html = bond.render_to_html(bond.createComponent(UserList, {}));
// output: <div class="user-list"><h1>Users</h1><div class="card">...</div>...</div>DOM Adapter Interface
The dom.br module defines a DOMAdapter interface with 25+ methods for abstracting DOM operations, with built-in implementations: MemoryBrowserAdapter, HTMLStringAdapter, and WasmDomAdapter.
export interface DOMAdapter {
create_element(tag) -> NodeHandle
create_element_ns(ns, tag)
create_text_node(text)
create_comment_node(text)
set_attribute(node, name, value)
remove_attribute(node, name)
append_child(parent, child)
insert_before(parent, child, before)
remove_child(parent, child)
replace_child(parent, old_child, new_child)
set_text(node, text)
get_element_by_id(id)
query_selector(selector)
add_event_listener(node, event, handler, options)
remove_event_listener(node, event, handler, options)
attach_shadow(node, mode)
// ... plus parse_html, serialize_node, clone_node, etc.
}