UNPKG

@starzhuimeng/formula-editor

Version:

A configurable formula editor with customizable symbols

288 lines 10.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SymbolPanel = void 0; const dom_1 = require("../utils/dom"); /** * 符号面板类 */ class SymbolPanel { constructor(options) { this.tabButtons = []; this.contentPanels = []; this.activeTabIndex = 0; this.options = options; this.container = options.container; this.panel = (0, dom_1.createElement)('div', 'formula-editor-symbol-panel'); this.initStyles(); this.renderPanel(); this.container.appendChild(this.panel); } /** * 初始化面板样式 */ initStyles() { const styles = this.options.styles || {}; (0, dom_1.setStyles)(this.panel, { backgroundColor: styles.backgroundColor || '#fff', border: `1px solid ${styles.borderColor || '#ddd'}`, borderRadius: '4px', boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)', display: 'flex', flexDirection: 'column', margin: '8px 0', overflow: 'hidden', width: '100%' }); } /** * 渲染符号面板 */ renderPanel() { var _a, _b; // 创建标签页导航 const tabNav = (0, dom_1.createElement)('div', 'formula-editor-symbol-tabs'); (0, dom_1.setStyles)(tabNav, { display: 'flex', borderBottom: `2px solid ${((_a = this.options.styles) === null || _a === void 0 ? void 0 : _a.borderColor) || '#ddd'}`, backgroundColor: '#f5f5f5', flexWrap: 'wrap', padding: '4px 4px 0 4px', position: 'relative', zIndex: '1' }); // 创建内容区域 const contentContainer = (0, dom_1.createElement)('div', 'formula-editor-symbol-content'); (0, dom_1.setStyles)(contentContainer, { padding: '12px', display: 'flex', flexWrap: 'wrap', maxHeight: '180px', overflowY: 'auto', backgroundColor: '#fff', borderTop: `1px solid ${((_b = this.options.styles) === null || _b === void 0 ? void 0 : _b.borderColor) || '#eee'}` }); // 解析组并创建标签 const groups = this.parseGroups(); groups.forEach((group, index) => { // 创建标签按钮 const tabButton = this.createTabButton(group, index); this.tabButtons.push(tabButton); tabNav.appendChild(tabButton); // 创建内容面板 const contentPanel = this.createContentPanel(group, index); this.contentPanels.push(contentPanel); contentContainer.appendChild(contentPanel); }); // 默认激活第一个标签 if (this.tabButtons.length > 0) { this.activateTab(0); } // 添加到面板 (0, dom_1.appendChildren)(this.panel, tabNav, contentContainer); } /** * 解析符号组 * 支持两种格式: * 1. 老格式: { category: symbols[] } * 2. 新格式: { category: SymbolGroup } */ parseGroups() { const result = []; const categories = Object.keys(this.options.symbols); categories.forEach(category => { const value = this.options.symbols[category]; if (value) { // 检查是否为 SymbolGroup 对象 (有 symbols 属性) if (typeof value === 'object' && 'symbols' in value) { const group = value; result.push({ name: category, displayName: group.displayName || this.formatCategoryName(category), symbols: group.symbols, style: group.style }); } // 老格式: 直接是符号数组 else if (Array.isArray(value)) { result.push({ name: category, displayName: this.formatCategoryName(category), symbols: value }); } } }); return result; } /** * 创建标签按钮 */ createTabButton(group, index) { var _a, _b; const button = (0, dom_1.createElement)('button', 'formula-editor-tab-button'); button.textContent = group.displayName; // 基本样式 const buttonStyle = { padding: '10px 15px', border: 'none', background: '#f0f0f0', cursor: 'pointer', outline: 'none', borderRight: `1px solid ${((_a = this.options.styles) === null || _a === void 0 ? void 0 : _a.borderColor) || '#ddd'}`, fontWeight: 'normal', color: ((_b = this.options.styles) === null || _b === void 0 ? void 0 : _b.tabColor) || '#333', transition: 'all 0.2s ease', margin: '0', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', minWidth: '85px', textAlign: 'center', fontSize: '14px', boxShadow: '0 1px 2px rgba(0, 0, 0, 0.05)' }; // 应用自定义样式 if (group.style) { Object.assign(buttonStyle, group.style); } (0, dom_1.setStyles)(button, buttonStyle); (0, dom_1.addEventListeners)(button, { click: () => this.activateTab(index) }); return button; } /** * 创建内容面板 */ createContentPanel(group, index) { const panel = (0, dom_1.createElement)('div', 'formula-editor-content-panel'); (0, dom_1.setStyles)(panel, { display: 'none', flexWrap: 'wrap', width: '100%', padding: '5px' }); // 为每个符号创建按钮 group.symbols.forEach(symbolItem => { var _a, _b; const symbolButton = (0, dom_1.createElement)('button', 'formula-editor-symbol-button'); // 获取符号显示值 const displayValue = typeof symbolItem === 'string' ? symbolItem : symbolItem.value; symbolButton.textContent = displayValue; // 如果有描述,添加为title属性 if (typeof symbolItem !== 'string' && symbolItem.description) { symbolButton.title = symbolItem.description; } // 基本样式 const buttonStyle = { width: '40px', height: '40px', margin: '5px', display: 'flex', justifyContent: 'center', alignItems: 'center', border: `1px solid ${((_a = this.options.styles) === null || _a === void 0 ? void 0 : _a.borderColor) || '#ddd'}`, borderRadius: '4px', background: 'white', cursor: 'pointer', color: ((_b = this.options.styles) === null || _b === void 0 ? void 0 : _b.symbolColor) || '#333', fontSize: '18px', transition: 'transform 0.1s ease, box-shadow 0.1s ease', boxShadow: '0 1px 2px rgba(0, 0, 0, 0.1)' }; // 如果有自定义样式,应用它 if (typeof symbolItem !== 'string' && symbolItem.style) { Object.assign(buttonStyle, symbolItem.style); } (0, dom_1.setStyles)(symbolButton, buttonStyle); (0, dom_1.addEventListeners)(symbolButton, { click: () => this.options.onSymbolClick(symbolItem), mousedown: (e) => { (0, dom_1.setStyles)(symbolButton, { transform: 'scale(0.95)', boxShadow: '0 0 1px rgba(0, 0, 0, 0.2)' }); }, mouseup: (e) => { (0, dom_1.setStyles)(symbolButton, { transform: 'scale(1)', boxShadow: '0 1px 2px rgba(0, 0, 0, 0.1)' }); }, mouseleave: (e) => { (0, dom_1.setStyles)(symbolButton, { transform: 'scale(1)', boxShadow: '0 1px 2px rgba(0, 0, 0, 0.1)' }); } }); panel.appendChild(symbolButton); }); return panel; } /** * 激活指定的标签 */ activateTab(index) { // 更新标签按钮样式 this.tabButtons.forEach((button, i) => { var _a, _b, _c, _d; if (i === index) { (0, dom_1.setStyles)(button, { fontWeight: 'bold', borderBottom: `3px solid ${((_a = this.options.styles) === null || _a === void 0 ? void 0 : _a.activeTabBorderColor) || '#007bff'}`, backgroundColor: ((_b = this.options.styles) === null || _b === void 0 ? void 0 : _b.activeTabColor) || '#fff', color: ((_c = this.options.styles) === null || _c === void 0 ? void 0 : _c.activeTabColor) ? undefined : '#007bff', boxShadow: '0 -2px 5px rgba(0, 0, 0, 0.05)' }); } else { (0, dom_1.setStyles)(button, { fontWeight: 'normal', borderBottom: 'none', backgroundColor: '#f0f0f0', color: ((_d = this.options.styles) === null || _d === void 0 ? void 0 : _d.tabColor) || '#555', boxShadow: '0 1px 2px rgba(0, 0, 0, 0.05)' }); } }); // 显示/隐藏内容面板 this.contentPanels.forEach((panel, i) => { panel.style.display = i === index ? 'flex' : 'none'; }); this.activeTabIndex = index; } /** * 格式化分类名称 */ formatCategoryName(category) { return category.charAt(0).toUpperCase() + category.slice(1); } /** * 显示符号面板 */ show() { this.panel.style.display = 'flex'; } /** * 隐藏符号面板 */ hide() { this.panel.style.display = 'none'; } /** * 切换显示/隐藏状态 */ toggle() { if (this.panel.style.display === 'none') { this.show(); } else { this.hide(); } } } exports.SymbolPanel = SymbolPanel; //# sourceMappingURL=SymbolPanel.js.map