Skip to content

Commit e506dcb

Browse files
Merge pull request #36 from preactjs/slots
Add support for slot as props
2 parents 63e2903 + eda464b commit e506dcb

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

src/index.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,21 @@ function toVdom(element, nodeName) {
5353
a = element.attributes,
5454
cn = element.childNodes;
5555
for (i = a.length; i--; ) {
56-
props[a[i].name] = a[i].value;
57-
props[toCamelCase(a[i].name)] = a[i].value;
58-
}
59-
for (i = cn.length; i--; ) children[i] = toVdom(cn[i]);
56+
if (a[i].name !== 'slot') {
57+
props[a[i].name] = a[i].value;
58+
props[toCamelCase(a[i].name)] = a[i].value;
59+
}
60+
}
61+
62+
for (i = cn.length; i--; ) {
63+
const vnode = toVdom(cn[i]);
64+
// Move slots correctly
65+
const name = cn[i].slot;
66+
if (name) {
67+
props[name] = h('slot', { name }, vnode);
68+
} else {
69+
children[i] = vnode;
70+
}
71+
}
6072
return h(nodeName || element.nodeName.toLowerCase(), props, children);
6173
}

src/index.test.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,44 @@ it('renders ok, updates on attr change', () => {
3131
document.body.removeChild(root);
3232
});
3333

34+
function Foo({ text, children }) {
35+
return (
36+
<span class="wrapper">
37+
<div class="children">{children}</div>
38+
<div class="slotted">{text}</div>
39+
</span>
40+
);
41+
}
42+
43+
registerElement(Foo, 'x-foo', [], { shadow: true });
44+
45+
it('renders slots as props with shadow DOM', () => {
46+
const root = document.createElement('div');
47+
const el = document.createElement('x-foo');
48+
49+
// <span slot="text">here is a slot</span>
50+
const slot = document.createElement('span');
51+
slot.textContent = 'here is a slot';
52+
slot.slot = 'text';
53+
el.appendChild(slot);
54+
55+
// <div>no slot</div>
56+
const noSlot = document.createElement('div');
57+
noSlot.textContent = 'no slot';
58+
el.appendChild(noSlot);
59+
el.appendChild(slot);
60+
61+
root.appendChild(el);
62+
document.body.appendChild(root);
63+
64+
assert.equal(root.innerHTML, '<x-foo><div>no slot</div><span slot="text">here is a slot</span></x-foo>');
65+
66+
const shadowHTML = document.querySelector('x-foo').shadowRoot.innerHTML;
67+
assert.equal(shadowHTML, '<span class="wrapper"><div class="children"><div>no slot</div></div><div class="slotted"><slot name="text"><span>here is a slot</span></slot></div></span>');
68+
69+
document.body.removeChild(root);
70+
});
71+
3472
const kebabName = 'custom-date-long-name';
3573
const camelName = 'customDateLongName';
3674
const lowerName = camelName.toLowerCase();

0 commit comments

Comments
 (0)