Skip to content

Commit

Permalink
fix: update jsx-runtime with better slot support
Browse files Browse the repository at this point in the history
  • Loading branch information
natemoo-re committed Jun 29, 2022
1 parent 787ced2 commit e2a6bc7
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
15 changes: 14 additions & 1 deletion packages/astro/src/jsx-runtime/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,20 @@ export function isVNode(vnode: any): vnode is AstroVNode {

export function transformSlots(vnode: AstroVNode) {
if (typeof vnode.type === 'string') return vnode;
if (!Array.isArray(vnode.props.children)) return;
// Handle single child with slot attribute
const slots: Record<string, any> = {};
if (isVNode(vnode.props.children)) {
const child = vnode.props.children;
if (!isVNode(child)) return;
if (!('slot' in child.props)) return;
const name = toSlotName(child.props.slot);
slots[name] = [child];
slots[name]['$$slot'] = true;
delete child.props.slot;
delete vnode.props.children;
}
if (!Array.isArray(vnode.props.children)) return;
// Handle many children with slot attributes
vnode.props.children = vnode.props.children
.map((child) => {
if (!isVNode(child)) return child;
Expand All @@ -28,6 +40,7 @@ export function transformSlots(vnode: AstroVNode) {
slots[name].push(child);
} else {
slots[name] = [child];
slots[name]['$$slot'] = true;
}
delete child.props.slot;
return Empty;
Expand Down
13 changes: 13 additions & 0 deletions packages/astro/src/runtime/server/jsx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
HTMLString,
markHTMLString,
renderComponent,
renderToString,
spreadAttributes,
voidElementNames,
} from './index.js';
Expand All @@ -23,6 +24,18 @@ export async function renderJSX(result: any, vnode: any): Promise<any> {
return markHTMLString(
(await Promise.all(vnode.map((v: any) => renderJSX(result, v)))).join('')
);
case vnode.type.isAstroComponentFactory: {
let props: Record<string, any> = {};
let slots: Record<string, any> = {};
for (const [key, value] of Object.entries(vnode.props ?? {})) {
if (key === 'children' || value && typeof value === 'object' && (value as any)['$$slot']) {
slots[key === 'children' ? 'default' : key] = () => renderJSX(result, value);
} else {
props[key] = value;
}
}
return await renderToString(result, vnode.type, props, slots)
}
}
if (vnode[AstroJSX]) {
if (!vnode.type && vnode.type !== 0) return '';
Expand Down

0 comments on commit e2a6bc7

Please sign in to comment.