mirror of
https://github.com/hugo-fixit/FixIt.git
synced 2026-08-24 15:28:57 +00:00
95 lines
2.9 KiB
TypeScript
95 lines
2.9 KiB
TypeScript
/**
|
|
* ECharts integration for FixIt shortcode blocks.
|
|
*
|
|
* Responsibilities:
|
|
* - Initialize ECharts instances with light/dark theme support.
|
|
* - Re-render all charts on theme switch.
|
|
* - Resize charts on window resize events.
|
|
* - Re-run initialization when `fixit:content-decrypted` is emitted.
|
|
*/
|
|
import { eventBus } from '../core/event-bus'
|
|
import { getStagingDOM, isDarkMode, isObjectLiteral } from '../utils'
|
|
|
|
let echartsArr: any[] = []
|
|
|
|
function initEchartsInTarget(target: Element | Document = document) {
|
|
const echarts = window.echarts
|
|
const config = window.config.echarts
|
|
if (!echarts || !config)
|
|
return
|
|
const isDark = isDarkMode()
|
|
const stagingDOM = getStagingDOM()
|
|
target.querySelectorAll('.echarts').forEach(($echarts: Element) => {
|
|
const $dataEl = $echarts.nextElementSibling as HTMLElement
|
|
if ($dataEl.tagName !== 'TEMPLATE')
|
|
return
|
|
const chart = echarts.init($echarts as HTMLElement, isDark ? 'dark' : 'light', { renderer: 'svg' })
|
|
chart.showLoading()
|
|
stagingDOM.stage(($dataEl as HTMLTemplateElement).content.cloneNode(true))
|
|
const _setOption = (option: any) => {
|
|
if (!option) {
|
|
chart.hideLoading()
|
|
console.warn('ECharts option is missing or invalid. Chart disposed.', {
|
|
element: $echarts,
|
|
option: $dataEl,
|
|
})
|
|
chart.dispose()
|
|
;($echarts as HTMLElement).removeAttribute('style')
|
|
return
|
|
}
|
|
chart.hideLoading()
|
|
chart.setOption(option)
|
|
echartsArr.push(chart)
|
|
}
|
|
if ($dataEl.dataset.fmt === 'js') {
|
|
try {
|
|
const jsCodes = stagingDOM.contentAsText()
|
|
// eslint-disable-next-line no-new-func
|
|
const _getOption = new Function('fixit', 'chart', isObjectLiteral(jsCodes) ? `return ${jsCodes}` : jsCodes)
|
|
if ($dataEl.dataset.async === 'true') {
|
|
return Promise.resolve(_getOption(window.fixit, chart)).then((option: any) => {
|
|
_setOption(option)
|
|
})
|
|
}
|
|
return _setOption(_getOption(window.fixit, chart))
|
|
}
|
|
catch (err) {
|
|
return console.error(err)
|
|
}
|
|
}
|
|
_setOption(stagingDOM.contentAsJson())
|
|
})
|
|
stagingDOM.destroy()
|
|
}
|
|
|
|
function applyEchartsTheme() {
|
|
const echarts = window.echarts
|
|
const config = window.config.echarts
|
|
if (!echarts || !config)
|
|
return
|
|
echarts.registerTheme('light', config.lightTheme!)
|
|
echarts.registerTheme('dark', config.darkTheme!)
|
|
echartsArr.forEach(chart => chart.dispose())
|
|
echartsArr = []
|
|
initEchartsInTarget()
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
applyEchartsTheme()
|
|
eventBus.on('fixit:switch-theme', ({ detail }) => {
|
|
if (!detail.isChanged)
|
|
return
|
|
applyEchartsTheme()
|
|
})
|
|
eventBus.on('fixit:resize', () => {
|
|
echartsArr.forEach(chart => chart.resize())
|
|
})
|
|
eventBus.on('fixit:content-decrypted', ({ detail }) => {
|
|
if (detail.isPage) {
|
|
applyEchartsTheme()
|
|
return
|
|
}
|
|
initEchartsInTarget(detail.target)
|
|
})
|
|
}, false)
|