All files / side-notification index.js

4% Statements 1/25
0% Branches 0/4
0% Functions 0/7
4% Lines 1/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 1491x                                                                                                                                                                                                                                                                                                        
window.customElements.define('h-side-notification', class extends HTMLElement {
 
  constructor() {
    super()
    const shadowRoot = this.attachShadow({ mode: 'open' })
    shadowRoot.appendChild(this._generateTemplate().content.cloneNode(true))
    this.$list = this.shadowRoot.querySelector('div.list')
  }
 
  addNotification({ message = '', time = 10, title = '', type = 'info' }) {
    const uuid = new Date().getTime().toString(36) + performance.now().toString().replace(/[^0-9]/g, '')
    const newNotificationHTML = `
      <div id="notification-${uuid}" class="item">
        <div class="exit-icon">
          <svg height="30" width="30" viewbox="0 0 40 40">
            <path d="M 12,12 L 28,28 M 28,12 L 12,28" />
            <circle class="circle" r="18" cx="20" cy="20"></circle>
          </svg>
        </div>
        <div class="content">
          <div class="icon ${type}"></div>
          <div class="title">${title} </div>
          <div class="message">${message}</div>
        </div>
      </div>
    `
    this.$list.insertAdjacentHTML('afterbegin', newNotificationHTML)
    const $notification = this.$list.querySelector(`#notification-${uuid}`)
    const $exitIcon = $notification.querySelector('.exit-icon')
    const $circle = $notification.querySelector('.circle')
    const closeNotification = () => {
      $notification.classList.add('fade')
    }
    $exitIcon.addEventListener('click', closeNotification)
    $circle.style['animation-duration'] = `${time}s`
    $circle.addEventListener('animationend', closeNotification)
 
    $notification.addEventListener('transitionend', () => {
      $notification.remove()
    })
 
    $notification.addEventListener('mouseover', () => {
      $circle.classList.remove('circle')
    })
 
    $notification.addEventListener('mouseout', () => {
      $circle.classList.add('circle')
    })
 
  }
 
  _generateTemplate() {
    const template = document.createElement('template')
    template.innerHTML = `
    <style>
        div.list {
          display:flex;
          flex-direction:column-reverse;
          height:100vh;
          opacity:1;
          overflow-y:scroll;
          position:fixed;
          right:0;
          top:0;
          width:400px;
          z-index:9000;
        }
        .item {
          background-color: var(--surface, #f0f0f0);
          border: 1px solid rgba(32, 33, 36, .28);
          border-radius: 5px;
          box-shadow: 0 1px 6px 0 rgba(32, 33, 36, .28);
          margin: 0.3rem;
          padding: 0.4rem;
          position: relative;
        }
        .content {
          color var(--on-surface, black);
          display: grid;
          grid-template-columns: 3rem 1fr;
        }
        .icon {
          font-size: 2rem;
          align-items: center;
          display: flex;
          grid-row-start: 1;
          grid-row-end:   3;
          justify-content: center;
        }
        .icon.info::after {
          color: blue;
          content: " \u2139";
        }
        .icon.warning::after {
          color: #c1502e;
          content: " \u26A0";
        }
        .icon.error::after {
          color: red;
          content: " \u2716";
        }
        .icon.success::after {
          color: green;
          content: " \u2713";
        }
        .title {
          font-size: 1.2rem;
          font-weight: bold;
          padding-bottom: 0.1rem;
        }
        .fade {
          transition: opacity 0.25s ease-in-out;
          opacity: 0.1;
        }
        .exit-icon {
          cursor:pointer;
          float:right;
          font-size:1.4rem;
          height:30px;
          position:absolute;
          right:10px;
          top:6px;
          width:30px;
        }
        svg {
          fill: transparent;
          stroke: black;
          stroke-linecap: round;
          stroke-width: 3;
        }
        .circle {
          stroke-dasharray: 175;
          stroke-dashoffset: 0;
          animation: stroke 10s linear forwards;
        }
        @keyframes stroke {
          to {
            stroke-dashoffset: 175;
            stroke: red;
          }
        }
      </style>
      <div class="list"></div>
      `.trim()
    return template
  }
 
})