初始化
This commit is contained in:
@@ -183,6 +183,32 @@ export class BimButtonGroup implements IBimComponent {
|
||||
if (this.options.iconActiveColor) style.setProperty('--bim-icon-active-color', this.options.iconActiveColor);
|
||||
if (this.options.textColor) style.setProperty('--bim-btn-text-color', this.options.textColor);
|
||||
if (this.options.textActiveColor) style.setProperty('--bim-btn-text-active-color', this.options.textActiveColor);
|
||||
|
||||
// 同步更新所有已存在的dropdown元素的CSS变量(dropdown被添加到body,无法继承容器的CSS变量)
|
||||
const dropdowns = document.querySelectorAll('.opt-btn-dropdown');
|
||||
dropdowns.forEach(dropdown => {
|
||||
const dropdownStyle = (dropdown as HTMLElement).style;
|
||||
if (this.options.iconColor) dropdownStyle.setProperty('--bim-icon-color', this.options.iconColor);
|
||||
if (this.options.iconActiveColor) dropdownStyle.setProperty('--bim-icon-active-color', this.options.iconActiveColor);
|
||||
if (this.options.textColor) dropdownStyle.setProperty('--bim-btn-text-color', this.options.textColor);
|
||||
if (this.options.textActiveColor) dropdownStyle.setProperty('--bim-btn-text-active-color', this.options.textActiveColor);
|
||||
if (this.options.btnBackgroundColor) dropdownStyle.setProperty('--bim-btn-bg', this.options.btnBackgroundColor);
|
||||
if (this.options.btnHoverColor) dropdownStyle.setProperty('--bim-btn-hover-bg', this.options.btnHoverColor);
|
||||
if (this.options.btnActiveColor) dropdownStyle.setProperty('--bim-btn-active-bg', this.options.btnActiveColor);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置主题的primary颜色(用于边框等)
|
||||
*/
|
||||
private setPrimaryColor(color: string): void {
|
||||
this.container.style.setProperty('--bim-primary-color', color);
|
||||
|
||||
// 同步更新所有dropdown(dropdown被添加到body,无法继承容器的CSS变量)
|
||||
const dropdowns = document.querySelectorAll('.opt-btn-dropdown');
|
||||
dropdowns.forEach(dropdown => {
|
||||
(dropdown as HTMLElement).style.setProperty('--bim-primary-color', color);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,6 +236,7 @@ export class BimButtonGroup implements IBimComponent {
|
||||
});
|
||||
|
||||
this.applyStyles();
|
||||
this.setPrimaryColor(theme.primary);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -339,6 +366,10 @@ export class BimButtonGroup implements IBimComponent {
|
||||
const hasLabel = this.options.showLabel && button.label;
|
||||
if (!hasLabel) {
|
||||
btnEl.classList.add('no-label');
|
||||
// 当不显示 label 时,添加 title 属性作为 tooltip
|
||||
if (button.label) {
|
||||
btnEl.title = t(button.label);
|
||||
}
|
||||
}
|
||||
|
||||
// 应用按钮的自定义样式
|
||||
@@ -412,13 +443,64 @@ export class BimButtonGroup implements IBimComponent {
|
||||
if (button.disabled) return;
|
||||
if (!button.children || button.children.length === 0) {
|
||||
if (button.keepActive) {
|
||||
this.setBtnActive(button.id);
|
||||
// 1) 先切换自身激活状态(onClick 里通常会根据 isActive 决定“打开/关闭”逻辑)
|
||||
const wasActive = this.activeBtnIds.has(button.id);
|
||||
const newState = !wasActive;
|
||||
this.setBtnActive(button.id, newState);
|
||||
|
||||
// 2) 互斥逻辑:仅在“本次切换为激活”时触发
|
||||
// - 一级按钮:同 groupId 下其它一级按钮互斥
|
||||
// - 二级按钮:同 groupId + 同 parentId 下其它二级按钮互斥
|
||||
// - 被关闭的按钮需要触发 onClick(用于执行关闭逻辑)
|
||||
if (newState && button.exclusive && button.groupId) {
|
||||
this.deactivateExclusiveSiblings(button);
|
||||
}
|
||||
}
|
||||
this.closeDropdown();
|
||||
if (button.onClick) button.onClick(button);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 互斥关闭同范围内的其它已激活按钮,并触发它们的 onClick
|
||||
* @param button 当前被激活的按钮
|
||||
*/
|
||||
private deactivateExclusiveSiblings(button: OptButton): void {
|
||||
const group = this.groups.find(g => g.id === button.groupId);
|
||||
if (!group) return;
|
||||
|
||||
// 二级按钮:同 groupId + 同 parentId
|
||||
if (button.parentId) {
|
||||
const parent = this.findButton(group.buttons, button.parentId);
|
||||
const siblings = parent?.children || [];
|
||||
for (const sib of siblings) {
|
||||
if (!sib) continue;
|
||||
if (sib.id === button.id) continue;
|
||||
if (sib.parentId !== button.parentId) continue;
|
||||
if (sib.groupId !== button.groupId) continue;
|
||||
|
||||
if (this.activeBtnIds.has(sib.id)) {
|
||||
this.setBtnActive(sib.id, false);
|
||||
// 触发被关闭按钮的 onClick(此时 sib.isActive 已经同步为 false)
|
||||
if (sib.onClick) sib.onClick(sib);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 一级按钮:同 groupId 下其它一级按钮(不包含二级)
|
||||
for (const sib of group.buttons) {
|
||||
if (sib.id === button.id) continue;
|
||||
if (sib.groupId !== button.groupId) continue;
|
||||
if (sib.parentId) continue; // 只处理一级按钮
|
||||
|
||||
if (this.activeBtnIds.has(sib.id)) {
|
||||
this.setBtnActive(sib.id, false);
|
||||
if (sib.onClick) sib.onClick(sib);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private handleMouseEnter(button: OptButton, btnEl: HTMLElement): void {
|
||||
if (this.hoverTimeout) clearTimeout(this.hoverTimeout);
|
||||
if (button.children && button.children.length > 0) {
|
||||
@@ -440,6 +522,16 @@ export class BimButtonGroup implements IBimComponent {
|
||||
dropdown.className = 'opt-btn-dropdown';
|
||||
if (this.options.backgroundColor) dropdown.style.setProperty('--bim-toolbar-bg', this.options.backgroundColor);
|
||||
|
||||
// 将主题CSS变量复制到dropdown元素上(因为dropdown被添加到body,无法继承容器的CSS变量)
|
||||
const dropdownStyle = dropdown.style;
|
||||
if (this.options.iconColor) dropdownStyle.setProperty('--bim-icon-color', this.options.iconColor);
|
||||
if (this.options.iconActiveColor) dropdownStyle.setProperty('--bim-icon-active-color', this.options.iconActiveColor);
|
||||
if (this.options.textColor) dropdownStyle.setProperty('--bim-btn-text-color', this.options.textColor);
|
||||
if (this.options.textActiveColor) dropdownStyle.setProperty('--bim-btn-text-active-color', this.options.textActiveColor);
|
||||
if (this.options.btnBackgroundColor) dropdownStyle.setProperty('--bim-btn-bg', this.options.btnBackgroundColor);
|
||||
if (this.options.btnHoverColor) dropdownStyle.setProperty('--bim-btn-hover-bg', this.options.btnHoverColor);
|
||||
if (this.options.btnActiveColor) dropdownStyle.setProperty('--bim-btn-active-bg', this.options.btnActiveColor);
|
||||
|
||||
// 获取按钮的位置信息
|
||||
const btnRect = btnEl.getBoundingClientRect();
|
||||
const expand = this.options.expand || 'down';
|
||||
@@ -503,6 +595,14 @@ export class BimButtonGroup implements IBimComponent {
|
||||
item.classList.add('align-vertical');
|
||||
}
|
||||
|
||||
// 二级菜单项的 active 状态渲染(修复 keepActive 在二级按钮“看起来不生效”的问题)
|
||||
// 说明:
|
||||
// - keepActive 的状态会记录在 activeBtnIds / button.isActive 上
|
||||
// - 下拉菜单每次打开都会重新渲染,因此必须在这里同步一次 active 样式
|
||||
if (this.activeBtnIds.has(button.id) || button.isActive) {
|
||||
item.classList.add('active');
|
||||
}
|
||||
|
||||
// 应用按钮的自定义样式
|
||||
const iconSize = button.iconSize || 32; // 二级菜单默认图标更小
|
||||
const minWidth = button.minWidth; // 不设置默认值,让下拉菜单项保持紧凑
|
||||
@@ -523,6 +623,9 @@ export class BimButtonGroup implements IBimComponent {
|
||||
label.className = 'opt-btn-dropdown-label';
|
||||
label.textContent = t(button.label);
|
||||
item.appendChild(label);
|
||||
} else if (button.label) {
|
||||
// 当不显示 label 时,添加 title 属性作为 tooltip
|
||||
item.title = t(button.label);
|
||||
}
|
||||
|
||||
item.addEventListener('click', (e) => { e.stopPropagation(); this.handleClick(button); });
|
||||
@@ -572,11 +675,17 @@ export class BimButtonGroup implements IBimComponent {
|
||||
|
||||
const hasLabel = this.options.showLabel && button.label;
|
||||
|
||||
// 只需要更新 no-label 类,CSS 会处理显示/隐藏
|
||||
// 更新 no-label 类和 title 属性
|
||||
if (hasLabel) {
|
||||
btnEl.classList.remove('no-label');
|
||||
// 显示标签时,移除 title(避免重复显示)
|
||||
btnEl.removeAttribute('title');
|
||||
} else {
|
||||
btnEl.classList.add('no-label');
|
||||
// 隐藏标签时,添加 title 作为 tooltip
|
||||
if (button.label) {
|
||||
btnEl.title = t(button.label);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user