@applicvision/js-toolbox
Version:
A collection of tools for modern JavaScript development
125 lines (102 loc) • 2.97 kB
JavaScript
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()
})
}