This commit is contained in:
2026-07-01 09:22:26 +00:00
parent 4aa1dab283
commit aa47a19e98
53 changed files with 4721 additions and 77 deletions
@@ -0,0 +1,61 @@
import React from 'react';
import { createRoot, type Root } from 'react-dom/client';
import { Dashboard } from './Dashboard';
import { PluginContext, makeClient } from './client';
// 把 build 出来的 CSS 当字符串收入,作为 ConstructableStyleSheet 注入到 shadow root
// 既能享受 shadow DOM 的样式隔离,也不需要额外的 fetch 步骤。
import css from './styles.css?inline';
const TAG = 'plugin-data-analytics';
class DataAnalyticsElement extends HTMLElement {
private root?: Root;
private mount?: HTMLDivElement;
static get observedAttributes() {
return ['token', 'api-base'];
}
connectedCallback() {
const shadow = this.attachShadow({ mode: 'open' });
// 用 <style> 注入 CSSConstructableStyleSheet 兼容性更好但 vite 注入字符串更直接)
const style = document.createElement('style');
style.textContent = css;
shadow.appendChild(style);
this.mount = document.createElement('div');
this.mount.style.cssText = 'height:100%;width:100%';
shadow.appendChild(this.mount);
this.root = createRoot(this.mount);
this.render();
}
attributeChangedCallback() {
if (this.root) this.render();
}
disconnectedCallback() {
this.root?.unmount();
this.root = undefined;
}
private render() {
const token = this.getAttribute('token') ?? '';
const apiBase = this.getAttribute('api-base') ?? '';
const client = makeClient(token, apiBase);
this.root!.render(
<React.StrictMode>
<PluginContext.Provider value={{ client, token, apiBase }}>
<Dashboard pluginName="data_analytics" />
</PluginContext.Provider>
</React.StrictMode>,
);
}
}
if (!customElements.get(TAG)) {
customElements.define(TAG, DataAnalyticsElement);
}