class ExampleElement extends HTMLElement {
  // The constructor runs whenever an element is created, but before the element is attached to the document.
  // We'll use the constructor for setting some initial state, event listeners, and creating the shadow DOM.
  constructor() {
    // always call super() first

    // NOTE
    // do not perform dom manipulations here if planning to use this component with react,
    // instead do with in the render call

  // The connectedCallback is called when the element is inserted to the DOM.
  // It's a good place to run setup code, like fetching data, or setting default attributes.
  connectedCallback() {

  // called whenever the element is removed from the DOM. Clean up time!
  // We can use the disconnectedCallback to remove any event listeners, or cancel intervals
  disconnectedCallback() {

  // Only attributes listed in the observedAttributes getter are affected in the attributeChangedCallback.
  static get observedAttributes() {
    return ['my-attr'];

  attributeChangedCallback(name, oldVal, newVal) {
    console.log(`Attribute: ${name} changed!`);

  // The adoptedCallback is called each time the custom element is moved to a new document.
  // You'll only run into this use case when you have <iframe> elements in your page.
  adoptedCallback() {

// we register our element to the CustomElementRegistry
window.customElements.define('example-element', ExampleElement);