JSFiddle - React, Tailwind, and code Playground

HTML

<x-complex></x-complex>

JavaScript

function handleSlotChanges(slots) {
	slots.forEach(currentSlot => {
    currentSlot.addEventListener('slotchange', function(e) {
      let nodes = currentSlot.assignedNodes();
      if (nodes.length > 0) console.log('Element in Slot "' + currentSlot.name + '" changed to "' + nodes[0].outerHTML + '".');
    });
  }); 
}

customElements.define('x-complex', class extends HTMLElement {
	connectedCallback() {
  	const root = this.attachShadow({ mode: 'open' });
    root.innerHTML = `
    	<x-parent>
      	<div slot="slot1">Slotted div</div>
        <span slot="slot1">Slotted span</span>
      </x-parent>
    `;
  }
});

customElements.define('x-parent', class extends HTMLElement {
	connectedCallback() {
  	const root = this.attachShadow({ mode: 'open' });
    
    root.innerHTML = `
      <style>
      	::slotted(div) {
        	color: red;
        }
      </style>
      
    	<x-child>
				<slot name="slot2" slot="slot3">
        	<slot name="slot1">
 		      </slot>
        </slot>
      </x-child>
    `;
    
    let slots = this.shadowRoot.querySelectorAll('slot');
    
    if(slots) {
      console.log('Slotting event triggered for x-parent');
      handleSlotChanges(slots);
    }
  }
});

customElements.define('x-child', class extends HTMLElement {
	connectedCallback() {
  	const root = this.attachShadow({ mode: 'open' });
    
    root.innerHTML = `
    	<style>
      	::slotted(*) {
        	color: blue;
        }
      </style>
      
			<slot name="slot3">
      </slot>
    `;
    
    let slots = this.shadowRoot.querySelectorAll('slot');
    
    if(slots) {
      console.log('Slotting event triggered for x-child');
      handleSlotChanges(slots);
    }
  }
});