Skip to content

Commit 2eb1e35

Browse files
committed
feat(fabric): HTML element fallback in createInstance
Expo Router DOM Components, with-html in the smoke matrix, and any example that mixes `"use dom"` directives or HTML-rendered subtrees emit lowercase HTML element names (`<div>`, `<p>`, `<span>`, `<h1>`, …) directly into the React tree. Without a host mapping for those names the reconciler hits the createInstance fallback and throws `Unknown host element: <p>` before the first frame. Map them onto the closest existing primitive: - Structural (`div`, `section`, `nav`, `article`, `header`, `footer`, `ul`, `ol`, `li`, `table`/`tr`/`td`/`th`, `button`, `a`, `video`, `audio`, `canvas`, `iframe`, `details`, `summary`, `dialog`, `form`, `fieldset`, `label`, `figure`/`figcaption`) → `View`. - Text-bearing (`p`, `span`, `strong`/`em`/`b`/`i`/`u`/`s`, `small`, `h1`–`h6`, `pre`/`code`/`kbd`/`samp`/`var`, `mark`, `sub`/`sup`/`abbr`/`cite`/`q`/`time`, `br`, `hr`) → `Paragraph`. Layout / styling fidelity isn't the goal — just "boots and renders something visible." That's enough to clear with-html's `<div className="web:px-4">` header right + similar patterns in react-flow's DOM rendering paths, and surfaces any deeper failures (like the missing SVG primitives) instead of blanking out before the first frame.
1 parent e490565 commit 2eb1e35

1 file changed

Lines changed: 100 additions & 0 deletions

File tree

apps/playground/runtime/fabricHostConfig.js

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,106 @@ const hostConfig = {
492492
return makeInstance(tag, fabricNode, 'Text', type);
493493
}
494494

495+
// HTML element fallback. Expo Router DOM Components, with-html,
496+
// and any example that mixes JSX with a `"use dom"` directive
497+
// emit lowercase HTML element names (`<div>`, `<p>`, `<span>`,
498+
// `<h1>` …) directly into the React tree. We don't have a real
499+
// WebView host, but mapping the structural elements onto View
500+
// and the text-bearing elements onto Paragraph is enough to let
501+
// these trees mount + render the visible text without throwing.
502+
// Layout / styling fidelity is not the goal here — just "boots
503+
// and renders something" so the rest of the app surface gets a
504+
// chance to run.
505+
const HTML_VIEW_TAGS = new Set([
506+
'div',
507+
'section',
508+
'nav',
509+
'main',
510+
'aside',
511+
'article',
512+
'header',
513+
'footer',
514+
'ul',
515+
'ol',
516+
'li',
517+
'figure',
518+
'figcaption',
519+
'form',
520+
'fieldset',
521+
'label',
522+
'table',
523+
'thead',
524+
'tbody',
525+
'tfoot',
526+
'tr',
527+
'td',
528+
'th',
529+
'colgroup',
530+
'col',
531+
'video',
532+
'audio',
533+
'canvas',
534+
'iframe',
535+
'details',
536+
'summary',
537+
'dialog',
538+
'button',
539+
'a',
540+
]);
541+
const HTML_TEXT_TAGS = new Set([
542+
'p',
543+
'span',
544+
'strong',
545+
'em',
546+
'b',
547+
'i',
548+
'u',
549+
's',
550+
'small',
551+
'h1',
552+
'h2',
553+
'h3',
554+
'h4',
555+
'h5',
556+
'h6',
557+
'pre',
558+
'code',
559+
'kbd',
560+
'samp',
561+
'var',
562+
'mark',
563+
'sub',
564+
'sup',
565+
'abbr',
566+
'cite',
567+
'q',
568+
'time',
569+
'br',
570+
'hr',
571+
]);
572+
if (HTML_VIEW_TAGS.has(type)) {
573+
const tag = newTag();
574+
const fabricNode = currentFabric.createNode(
575+
tag,
576+
'View',
577+
currentSurfaceId,
578+
buildFabricProps('view', props),
579+
internalInstanceHandle,
580+
);
581+
return makeInstance(tag, fabricNode, 'View', type);
582+
}
583+
if (HTML_TEXT_TAGS.has(type)) {
584+
const tag = newTag();
585+
const fabricNode = currentFabric.createNode(
586+
tag,
587+
'Paragraph',
588+
currentSurfaceId,
589+
buildFabricProps('text', props),
590+
internalInstanceHandle,
591+
);
592+
return makeInstance(tag, fabricNode, 'Paragraph', type);
593+
}
594+
495595
throw new Error('Unknown host element: <' + type + '>');
496596
},
497597

0 commit comments

Comments
 (0)