You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
2.8 KiB
JavaScript

/* eslint-env browser */
const removeElement = el => el && el.parentNode && el.parentNode.removeChild(el)
const ErrorOverlay = () => {
let errors = []
let compileError = null
const errorsTitle = 'Failed to init component'
const compileErrorTitle = 'Failed to compile'
const style = {
section: `
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding: 32px;
background: rgba(0, 0, 0, .85);
font-family: Menlo, Consolas, monospace;
font-size: large;
color: rgb(232, 232, 232);
overflow: auto;
z-index: 2147483647;
`,
h1: `
margin-top: 0;
color: #E36049;
font-size: large;
font-weight: normal;
`,
h2: `
margin: 32px 0 0;
font-size: large;
font-weight: normal;
`,
pre: ``,
}
const createOverlay = () => {
const h1 = document.createElement('h1')
h1.style = style.h1
const section = document.createElement('section')
section.appendChild(h1)
section.style = style.section
const body = document.createElement('div')
section.appendChild(body)
return { h1, el: section, body }
}
const setTitle = title => {
overlay.h1.textContent = title
}
const show = () => {
const { el } = overlay
if (!el.parentNode) {
const target = document.body
target.appendChild(overlay.el)
}
}
const hide = () => {
const { el } = overlay
if (el.parentNode) {
overlay.el.remove()
}
}
const update = () => {
if (compileError) {
overlay.body.innerHTML = ''
setTitle(compileErrorTitle)
const errorEl = renderError(compileError)
overlay.body.appendChild(errorEl)
show()
} else if (errors.length > 0) {
overlay.body.innerHTML = ''
setTitle(errorsTitle)
errors.forEach(({ title, message }) => {
const errorEl = renderError(message, title)
overlay.body.appendChild(errorEl)
})
show()
} else {
hide()
}
}
const renderError = (message, title) => {
const div = document.createElement('div')
if (title) {
const h2 = document.createElement('h2')
h2.textContent = title
h2.style = style.h2
div.appendChild(h2)
}
const pre = document.createElement('pre')
pre.textContent = message
div.appendChild(pre)
return div
}
const addError = (error, title) => {
const message = (error && error.stack) || error
errors.push({ title, message })
update()
}
const clearErrors = () => {
errors.forEach(({ element }) => {
removeElement(element)
})
errors = []
update()
}
const setCompileError = message => {
compileError = message
update()
}
const overlay = createOverlay()
return {
addError,
clearErrors,
setCompileError,
}
}
export default ErrorOverlay