Skip to content

Commit 10f1ec7

Browse files
committed
feat: automatically re-render + re-evaluate slots and classes added when child node mutations are observed
1 parent 60fa53c commit 10f1ec7

File tree

1 file changed

+62
-22
lines changed

1 file changed

+62
-22
lines changed

packages/components/bolt-blockquote/src/blockquote.js

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,38 @@ class BoltBlockquote extends withLitHtml() {
3333
return self;
3434
}
3535

36+
rendered() {
37+
super.rendered && super.rendered();
38+
const self = this;
39+
40+
if (window.MutationObserver) {
41+
// Re-generate slots + re-render when mutations are observed
42+
const mutationCallback = function(mutationsList, observer) {
43+
self.slots = self._checkSlots();
44+
self.triggerUpdate();
45+
};
46+
47+
// Create an observer instance linked to the callback function
48+
self.observer = new MutationObserver(mutationCallback);
49+
50+
// Start observing the target node for configured mutations
51+
self.observer.observe(this, {
52+
attributes: false,
53+
childList: true,
54+
subtree: true,
55+
});
56+
}
57+
}
58+
59+
disconnected() {
60+
super.disconnected && super.disconnected();
61+
62+
// remove MutationObserver if supported + exists
63+
if (window.MutationObserver && this.observer) {
64+
this.observer.disconnect();
65+
}
66+
}
67+
3668
getModifiedSchema(schema) {
3769
var modifiedSchema = schema;
3870

@@ -73,6 +105,35 @@ class BoltBlockquote extends withLitHtml() {
73105
}
74106
}
75107

108+
// automatically adds classes for the first and last slotted item (in the default slot) to help with tricky ::slotted selectors
109+
addClassesToSlottedChildren() {
110+
if (this.slots) {
111+
if (this.slots.default) {
112+
const defaultSlot = [];
113+
114+
this.slots.default.forEach(item => {
115+
if (item.tagName) {
116+
item.classList.remove('is-first-child');
117+
item.classList.remove('is-last-child'); // clean up existing classes
118+
defaultSlot.push(item);
119+
}
120+
});
121+
122+
if (defaultSlot[0]) {
123+
defaultSlot[0].classList.add('is-first-child');
124+
125+
if (defaultSlot.length === 1) {
126+
defaultSlot[0].classList.add('is-last-child');
127+
}
128+
}
129+
130+
if (defaultSlot[defaultSlot.length - 1]) {
131+
defaultSlot[defaultSlot.length - 1].classList.add('is-last-child');
132+
}
133+
}
134+
}
135+
}
136+
76137
render() {
77138
// validate the original prop data passed along -- returns back the validated data w/ added default values
78139
const {
@@ -101,28 +162,7 @@ class BoltBlockquote extends withLitHtml() {
101162
let footerItems = [];
102163
footerItems.push(AuthorImage(this), AuthorName(this), AuthorTitle(this));
103164

104-
// automatically add classes for the first and last slotted item to help with tricky ::slotted selectors
105-
if (this.slots.default) {
106-
const defaultSlot = [];
107-
108-
this.slots.default.forEach(item => {
109-
if (item.tagName) {
110-
defaultSlot.push(item);
111-
}
112-
});
113-
114-
if (defaultSlot[0].attributes.length === 0) {
115-
defaultSlot[0].classList.add('is-first-child');
116-
117-
if (defaultSlot.length === 1) {
118-
defaultSlot[0].classList.add('is-last-child');
119-
}
120-
}
121-
122-
if (defaultSlot[defaultSlot.length - 1].attributes.length === 0) {
123-
defaultSlot[defaultSlot.length - 1].classList.add('is-last-child');
124-
}
125-
}
165+
this.addClassesToSlottedChildren();
126166

127167
return html`
128168
${this.addStyles([styles])}

0 commit comments

Comments
 (0)