|
| 1 | +export const Slotify = Base => |
| 2 | + class extends Base { |
| 3 | + templateMap = new Map(); |
| 4 | + |
| 5 | + assignSlotToContent(child) { |
| 6 | + return child.slot || child.getAttribute |
| 7 | + ? child.getAttribute('slot') |
| 8 | + : 'default'; |
| 9 | + } |
| 10 | + |
| 11 | + isEmptyTextNode(child) { |
| 12 | + return child && (!child.textContent || !child.textContent.trim()); |
| 13 | + } |
| 14 | + |
| 15 | + // Save a reference to the pseudoSlot content before lit-element renders |
| 16 | + saveSlots() { |
| 17 | + const childNodes = []; |
| 18 | + Array.from(this.childNodes).forEach(child => { |
| 19 | + const slot = this.assignSlotToContent(child); |
| 20 | + |
| 21 | + if (!child.textContent || child.textContent.trim().length > 0) { |
| 22 | + if (!this.templateMap.has(slot)) { |
| 23 | + this.templateMap.set(slot, [child]); |
| 24 | + } else { |
| 25 | + this.templateMap.set(slot, [...this.templateMap.get(slot), child]); |
| 26 | + } |
| 27 | + } |
| 28 | + }); |
| 29 | + |
| 30 | + const shouldSlotChildren = |
| 31 | + childNodes.length > 1 || |
| 32 | + childNodes.some(child => !this.isEmptyTextNode(child)); |
| 33 | + |
| 34 | + if (shouldSlotChildren) { |
| 35 | + const fragment = document.createDocumentFragment(); |
| 36 | + |
| 37 | + childNodes.forEach(child => { |
| 38 | + fragment.appendChild(child); |
| 39 | + }); |
| 40 | + |
| 41 | + this.templateMap.set('', fragment); |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + update(changedProperties) { |
| 46 | + if (!this.hasUpdated) { |
| 47 | + this.saveSlots(); |
| 48 | + } |
| 49 | + |
| 50 | + super.update(changedProperties); |
| 51 | + } |
| 52 | + |
| 53 | + slotify(slot = '', defaultContent) { |
| 54 | + const slotContent = this.templateMap.get(slot); |
| 55 | + |
| 56 | + // render slots when using Shadow DOM |
| 57 | + if (this.shadowRoot && slotContent) { |
| 58 | + const realSlot = document.createElement('slot'); |
| 59 | + if (slot !== 'default') { |
| 60 | + realSlot.setAttribute('name', slot); |
| 61 | + } |
| 62 | + return realSlot; |
| 63 | + } |
| 64 | + |
| 65 | + if (slotContent && slotContent.content) { |
| 66 | + return slotContent.content; |
| 67 | + } else if (slotContent && slotContent.childNodes) { |
| 68 | + return Array.from(slotContent.childNodes); |
| 69 | + } else if (slotContent) { |
| 70 | + return slotContent; |
| 71 | + } else if (defaultContent) { |
| 72 | + return defaultContent; |
| 73 | + } else { |
| 74 | + return; |
| 75 | + } |
| 76 | + } |
| 77 | + }; |
0 commit comments