Import these from @grafloria/renderer.
Functions
camelToKebab
camelCase → kebab-case (strokeWidth → stroke-width).
tsfunction camelToKebab(str: string): string
createDomElement
Build a fresh detached DOM tree for vnode using the default patcher.
tsfunction createDomElement(vnode: VNode, namespace: string = SVG_NS): Element
createForeignObject
Create a foreignObject VNode
Creates a VNode representing an SVG foreignObject element, which allows embedding HTML content inside SVG. Automatically generates a container ID if not provided, and includes a default XHTML div wrapper.
tsfunction createForeignObject(options: ForeignObjectOptions): VNode
Parameters
options: Configuration options for the foreignObject
Returns A VNode of type 'foreignObject'
Example
typescriptconst vnode = createForeignObject({
nodeId: 'node-1',
x: 10,
y: 20,
width: 200,
height: 150
});
// Returns: { type: 'foreignObject', props: { x: 10, y: 20, ... }, children: [...] }
Example
With custom container ID and children
typescriptconst vnode = createForeignObject({
nodeId: 'node-1',
x: 10,
y: 20,
width: 200,
height: 150,
containerId: 'my-custom-id',
children: [
{ type: 'div', props: { className: 'custom-content' } }
]
});
getContainerId
Get the container ID from a foreignObject VNode
Extracts the container ID from a foreignObject VNode's props. Returns undefined if the VNode is not a foreignObject or doesn't have a container ID.
tsfunction getContainerId(vnode: VNode): string | undefined
Parameters
vnode: The VNode to extract the container ID from
Returns The container ID if the VNode is a foreignObject, undefined otherwise
Example
typescriptconst vnode = createForeignObject({
nodeId: 'node-1',
x: 0, y: 0, width: 100, height: 100
});
const containerId = getContainerId(vnode);
// Returns: 'fo-node-1-1'
Example
Non-foreignObject returns undefined
typescriptconst rectNode = { type: 'rect', props: { ... } };
const containerId = getContainerId(rectNode);
// Returns: undefined
isForeignObject
Check if a VNode is a foreignObject element
Type guard function that checks if the given VNode represents a foreignObject element.
tsfunction isForeignObject(vnode: VNode): boolean
Parameters
vnode: The VNode to check
Returns True if the VNode is a foreignObject, false otherwise
Example
typescriptconst foNode = createForeignObject({ ... });
const rectNode = { type: 'rect', props: { ... } };
isForeignObject(foNode); // true
isForeignObject(rectNode); // false
isOpaqueVNode
foreignObject subtrees embed live HTML (framework components, form controls, media). They are OPAQUE to the diff: props are patched, children are left exactly as they are. Diffing into them would wipe whatever was mounted there.
tsfunction isOpaqueVNode(vnode: VNode): boolean
reconcile
Reconcile vnode into container using the default patcher.
tsfunction reconcile(container: Element, vnode: VNode): Element
serializeStyle
Serialize a style prop. Accepts the object form the renderer emits
({ cursor: 'move' }) as well as a plain string. Returns '' for empty/absent styles.
tsfunction serializeStyle(style: unknown): string
Classes
ContainerIdGenerator
Generate unique container IDs for foreignObject elements
This class provides static methods to generate and validate container IDs used to link SVG foreignObject elements with their Angular component content.
tsclass ContainerIdGenerator
Methods
static generate(nodeId: string): string(static) — Generate a unique container ID for a foreignObject elementstatic isContainerId(id: string): boolean(static) — Check if a given ID is a valid container ID
Container IDs must start with 'fo-' prefix. This is a lightweight check that only validates the prefix.
static getNodeId(containerId: string): string | null(static) — Extract the node ID from a container ID
Parses a container ID and returns the original node ID. Container IDs must follow the format: fo-{nodeId}-{counter}
static reset(): void(static) — Reset the internal counter to zero
This method is primarily for testing purposes to ensure predictable ID generation in test suites.
VNodePatcher
Keyed VNode → DOM reconciler.
tsconst patcher = new VNodePatcher();
patcher.reconcile(container, vnodeTree); // first call: mount
patcher.reconcile(container, nextTree); // later calls: diff + patch in place
tsclass VNodePatcher
Methods
constructor(options: VNodePatcherOptions = {})get stats(): Readonly<PatchStats>— Work done during the most recentreconcile()call.reconcile(container: Element, vnode: VNode): Element— Diffvnodeagainst whatever this patcher last rendered intocontainerand patch the existing DOM in place. First call (or a lost root) mounts a fresh tree.hydrate(container: Element, vnode: VNode): Element— ADOPT the DOM already insidecontaineras the materialization ofvnode, without creating, moving or removing a single node.
This is the client half of SSR hydration. The server emitted the
serialization of this exact VNode tree into the HTML; re-mounting it would
mean tearing that DOM down and rebuilding it — the "hydration flash" every
flow library ships with. Instead we simply register the existing root as our
mount, so the NEXT reconcile() diffs against vnode and touches only what
genuinely changed.
The adopt is only taken when the existing root plausibly IS this tree (same
tag name); otherwise we fall back to a normal mount, which is always correct
(just not flash-free). Assert with stats: a real hydration reports
created: 0, removed: 0.
getMountedElement(container: Element): Element | undefined— The root element currently mounted incontainer, if any.unmount(container: Element): void— Remove the mounted tree and forget the container.createElement(vnode: VNode, namespace: string = SVG_NS): Element— Build a fresh detached DOM element (deep) for a VNode.patchElement(el: Element, oldVNode: VNode, newVNode: VNode): Element— Diff two VNodes onto an existing element.patchProps( el: Element, oldProps: Record<string, any>, newProps: Record<string, any> ): void— Apply a prop delta to an element (no children touched).
Constants
defaultPatcher
Process-wide default patcher — convenient for the common "one DOM, one tree"
case. Instantiate VNodePatcher directly for isolated instances.
tsconst defaultPatcher: VNodePatcher
SVG_NS
SVG namespace — everything outside a foreignObject is created here.
tsconst SVG_NS: "http://www.w3.org/2000/svg"
XHTML_NS
XHTML namespace — foreignObject children are HTML, not SVG.
tsconst XHTML_NS: "http://www.w3.org/1999/xhtml"
Interfaces
ForeignObjectOptions
Options for creating a foreignObject VNode
tsinterface ForeignObjectOptions
Properties
| Name | Type | Default | Description |
|---|---|---|---|
nodeId | string | Node ID - used to generate container ID | |
x | number | X coordinate (top-left corner) | |
y | number | Y coordinate (top-left corner) | |
width | number | Width in pixels | |
height | number | Height in pixels | |
containerId? | string | Optional custom container ID If not provided, will be auto-generated using ContainerIdGenerator | |
children? | VNode[] | Optional children VNodes If not provided, creates a default XHTML div wrapper | |
key? | string | Optional key for React/Angular diffing optimization |
PatchStats
Per-reconcile work counters. Reset at the top of every reconcile() call. Useful as a cheap regression guard: a steady-state frame should create ~0
elements ("no teardown-and-rebuild").
tsinterface PatchStats
Properties
| Name | Type | Default | Description |
|---|---|---|---|
created | number | DOM nodes created from scratch. | |
reused | number | DOM nodes reused in place (patched, not recreated). | |
moved | number | Reused DOM nodes that had to move to a new sibling index. | |
removed | number | DOM nodes removed because their VNode disappeared. | |
skipped | number | Subtrees skipped entirely because the VNode object was identical. |
VNodePatcherOptions
Options for a patcher instance.
tsinterface VNodePatcherOptions
Properties
| Name | Type | Default | Description |
|---|---|---|---|
document? | Document | Document used to create nodes. Defaults to the ambient globalThis.document. Pass one explicitly for headless / SSR / multi-document use. |
Types
VNodeChild
A child slot in a VNode tree. Strings/numbers materialise as text nodes.
tstype VNodeChild = VNode | string | number | null | undefined;
Members
toString(): string— Returns a string representation of a string.valueOf(): string— Returns the primitive value of the specified object.toLocaleString(): string— Returns a date converted to a string using the current locale.
Was this page helpful?