if the contents are simply getting slotted using the slotchange
event is easiest, it doesn't fire on deeper changes, just the slotting (unlike a mutation observer watching a subtree and childList); it's like an observer of childList on the slot and the best way to separate concerns between a component and slotted content; when observing changes in a component's own respective shadowRoot
or deeper in a tree for some reason, use the mutation observer in @Supersharp's answer except adding subtree
to the config (or possibly setup children with their respective shadowRoots to dispatch an event with {composed: true, cancelable: true, bubbles: true}
notifying ancestors up to your component of the change;
there'd need to be a slot added to the shadowRoot and the event listener added to it like shadowRoot.innerHTML = <slot onslotchange=...>empty slot</slot>
adapted to work in-context
https://developer.mozilla.org/docs/Web/API/HTMLSlotElement/slotchange_event