import './index.css'; import type { ThemeConfig } from '../../themes/types'; import { IBimComponent } from '../../types/component'; import { localeManager, t } from '../../services/locale'; import { themeManager } from '../../services/theme'; import type { SectionPlanePanelOptions } from './types'; import { getIcon } from '../../utils/icon-manager'; /** * 拾取面剖切面板组件 * 包含三个操作按钮:隐藏、反向、重置 */ export class SectionPlanePanel implements IBimComponent { public element: HTMLElement; private options: SectionPlanePanelOptions; private isHidden: boolean = false; // DOM 引用 private hideBtn!: HTMLButtonElement; private reverseBtn!: HTMLButtonElement; private resetBtn!: HTMLButtonElement; private hideLabelEl!: HTMLElement; private reverseLabelEl!: HTMLElement; private resetLabelEl!: HTMLElement; // 订阅清理 private unsubscribeLocale: (() => void) | null = null; private unsubscribeTheme: (() => void) | null = null; constructor(options: SectionPlanePanelOptions = {}) { this.options = options; this.isHidden = options.defaultHidden ?? false; this.element = this.createDom(); } public setHiddenState(isHidden: boolean): void { this.isHidden = isHidden; this.updateButtonStates(); } public getHiddenState(): boolean { return this.isHidden; } private updateButtonStates(): void { this.hideBtn?.classList.toggle('active', this.isHidden); } /** * 初始化组件 */ public init(): void { // 订阅语言变更 this.unsubscribeLocale = localeManager.subscribe(() => { this.setLocales(); }); // 订阅主题变更 this.unsubscribeTheme = themeManager.subscribe((theme) => { this.setTheme(theme); }); // 初始应用 this.setLocales(); this.setTheme(themeManager.getTheme()); } /** * 设置主题 */ public setTheme(theme: ThemeConfig): void { const style = this.element.style; style.setProperty('--bim-bg-inset', theme.bgInset ?? '#152232'); style.setProperty('--bim-border-default', theme.borderDefault ?? '#334155'); style.setProperty('--bim-border-strong', theme.borderStrong ?? '#475569'); style.setProperty('--bim-primary', theme.primary ?? '#3b82f6'); style.setProperty('--bim-primary-subtle', theme.primarySubtle ?? 'rgba(59, 130, 246, 0.15)'); style.setProperty('--bim-icon-default', theme.iconDefault ?? '#ffffff'); style.setProperty('--bim-text-primary', theme.textPrimary ?? '#ffffff'); style.setProperty('--bim-component-bg-hover', theme.componentBgHover ?? 'rgba(248, 250, 252, 0.06)'); } /** * 设置语言 */ public setLocales(): void { this.hideLabelEl.textContent = t('sectionPlane.actions.hide'); this.reverseLabelEl.textContent = t('sectionPlane.actions.reverse'); this.resetLabelEl.textContent = t('sectionPlane.actions.reset'); this.hideBtn.title = t('sectionPlane.actions.hide'); this.reverseBtn.title = t('sectionPlane.actions.reverse'); this.resetBtn.title = t('sectionPlane.actions.reset'); } /** * 销毁组件 */ public destroy(): void { if (this.unsubscribeLocale) { this.unsubscribeLocale(); this.unsubscribeLocale = null; } if (this.unsubscribeTheme) { this.unsubscribeTheme(); this.unsubscribeTheme = null; } this.element.remove(); } /** * 创建 DOM */ private createDom(): HTMLElement { const root = document.createElement('div'); root.className = 'section-plane-panel'; // 隐藏按钮 this.hideBtn = this.createButton( 'hide', getIcon('隐藏'), () => { this.isHidden = !this.isHidden; this.updateButtonStates(); this.options.onHideToggle?.(this.isHidden); } ); // 反向按钮 this.reverseBtn = this.createButton( 'reverse', getIcon('反向'), () => { if (this.options.onReverse) { this.options.onReverse(); } } ); // 重置按钮 this.resetBtn = this.createButton( 'reset', getIcon('重置'), () => { if (this.options.onReset) { this.options.onReset(); } } ); root.appendChild(this.hideBtn); root.appendChild(this.reverseBtn); root.appendChild(this.resetBtn); return root; } /** * 创建按钮 */ private createButton(type: 'hide' | 'reverse' | 'reset', iconSvg: string, onClick: () => void): HTMLButtonElement { const btn = document.createElement('button'); btn.type = 'button'; btn.className = 'section-plane-btn'; // 图标 const icon = document.createElement('div'); icon.className = 'section-plane-btn-icon'; icon.innerHTML = iconSvg; btn.appendChild(icon); // 标签 const label = document.createElement('div'); label.className = 'section-plane-btn-label'; btn.appendChild(label); // 保存 label 引用 if (type === 'hide') { this.hideLabelEl = label; } else if (type === 'reverse') { this.reverseLabelEl = label; } else { this.resetLabelEl = label; } // 点击事件 btn.addEventListener('click', onClick); return btn; } }