|
|
|
|
|
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 |
|
|