134 lines
2.8 KiB
JavaScript
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
|