createDom function
Creates a single DOM Node from a resolved Morphic.
FragmentMorphic cannot be passed here directly — fragments produce multiple sibling nodes and have no single root. Use createDomNodes when the caller may encounter a fragment.
The optional componentOwner marks the root element as belonging to
a specific Component, registering it with the ComponentRuntime for
granular diffing. For child components, ownership is looked up via
ComponentRuntime.ownerOf.
Implementation
Node createDom(Morphic node, {Component? componentOwner}) {
if (node is FragmentMorphic) {
throw UnsupportedError(
'createDom cannot create a single node from FragmentMorphic. '
'Use createDomNodes() instead, or ensure fragments are only used '
'as children of an ElementMorphic.',
);
}
if (node is TextMorphic) {
return document.createTextNode(node.value);
}
if (node is ElementMorphic) {
final element = document.createElement(node.tag);
// ── Attributes ───────────────────────────────────────────────────────
node.attributes.forEach((key, attr) {
if (attr is StringAttribute) {
element.setAttribute(key, attr.value);
} else if (attr is BooleanAttribute) {
if (attr.value) element.setAttribute(key, '');
} else if (attr is ClassAttribute) {
element.setAttribute('class', attr.classes);
} else if (attr is StyleAttribute) {
final htmlElement = element as HTMLElement;
attr.styles.forEach((k, value) {
htmlElement.style.setProperty(_toKebabCase(k), value);
});
} else if (attr is EventAttribute) {
_registerHandler(element, key, attr);
}
});
// ── Children ─────────────────────────────────────────────────────────
// Each child may be a fragment — use createDomNodes to expand them.
final morphicChildren = node.children.cast<Morphic>();
for (final child in morphicChildren) {
Component? childOwner;
try {
childOwner = RenderContext.runtime.ownerOf(child);
} catch (_) {}
for (final domNode in createDomNodes(child, componentOwner: childOwner)) {
element.append(domNode);
}
}
// ── Component node registration ───────────────────────────────────────
if (componentOwner != null) {
try {
RenderContext.runtime.registerComponentDomNode(componentOwner, element);
} catch (_) {}
}
return element;
}
throw UnsupportedError('Unknown node type: ${node.runtimeType}');
}