UNPKG

@applicvision/js-toolbox

Version:

A collection of tools for modern JavaScript development

125 lines (102 loc) 2.97 kB
let indicatorBall let indicatorText let paused = false function createIndicator(eventSource) { const indicator = document.createElement('div'); const shadowRoot = indicator.attachShadow({ mode: 'closed' }); indicatorBall = document.createElement('div'); indicatorBall.classList.add('indicator-ball'); indicatorText = document.createElement('div'); indicatorText.classList.add('indicator-text'); const styleElement = document.createElement('style'); shadowRoot.appendChild(styleElement); shadowRoot.appendChild(indicatorText); shadowRoot.appendChild(indicatorBall); indicatorBall.onclick = () => { paused = !paused; updateIndicator.call(eventSource) } document.body.appendChild(indicator); const style = styleElement.sheet; style.insertRule( `:host { position: fixed; display: flex; right: 0; bottom: 0; z-index: 100; border-top-left-radius: 15px; padding: 5px 5px 5px 15px; opacity: 0.5; transition: all 0.2s; }`); style.insertRule( `.indicator-text { opacity: 0; transition: opacity 0.2s; fontSize: 14px; }` ); style.insertRule( `:host(:hover)>.indicator-text { opacity: 1; }` ); style.insertRule( `:host(:hover) { opacity: 1; -webkit-backdrop-filter: blur(10px); background: rgba(200, 200, 200, 0.6); }` ); style.insertRule( `.indicator-ball { width: 20px; height: 20px; margin-left: 10px; cursor: pointer; border-radius: 10px; background: yellow; transition: background 0.3s; }` ); style.insertRule(`.indicator-ball.connected { background: #0c0; }`); style.insertRule(`.indicator-ball.connecting, .indicator-ball.closing { background: yellow; }`); style.insertRule(`.indicator-ball.closed { background: red; }`); style.insertRule(`.indicator-ball.paused { background: orange; }`); } export function pause() { paused = true; updateIndicator() } export function resume() { paused = false; updateIndicator() } function updateIndicator() { const state = paused ? 'paused' : this.readyState == 1 ? 'connected' : 'closed' indicatorText.textContent = `Autoreload: ${state}` indicatorBall.className = `indicator-ball ${state}` } export function start(handleFileChange = (message) => location.reload()) { const url = new URL('./stream', import.meta.url) const fileChangeListener = new EventSource(url) fileChangeListener.addEventListener('error', updateIndicator) createIndicator(fileChangeListener) updateIndicator.call(fileChangeListener) fileChangeListener.addEventListener('welcome', updateIndicator) fileChangeListener.addEventListener('filechange', (message) => { if (!paused) { /** @type {(message: string) => void | undefined} */ // @ts-ignore const globalFileChangeHandler = window._handleFileChange globalFileChangeHandler ? globalFileChangeHandler(message.data) : handleFileChange(message.data) } }) addEventListener('unload', () => { fileChangeListener.close() }) }