refactor: 重命名SDK为iflow-engine,使用npm包引入第三方引擎
- 将包名从 @fishdingding/bim-engine-sdk 改为 iflow-engine - 将构建输出文件从 bim-engine-sdk.*.js 改为 iflow-engine.*.js - 将全局变量从 LyzBimEngineSDK 改为 IflowEngine - 将第三方引擎SDK从本地引入改为npm包引入 (iflow-engine-base) - 移除本地 src/engine_base 目录,移至回收站 - 更新所有文档和demo中的引用
309
.recycle/2026-01-21/src/components/button-group/index.css
Normal file
@@ -0,0 +1,309 @@
|
||||
/* 根容器 */
|
||||
.bim-btn-group-root {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
z-index: 1000;
|
||||
position: absolute;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.bim-btn-group-root.static {
|
||||
position: relative;
|
||||
top: auto;
|
||||
left: auto;
|
||||
bottom: auto;
|
||||
right: auto;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.bim-btn-group-root.dir-row {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bim-btn-group-root.dir-column {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
/* 分组区域 */
|
||||
.bim-btn-group-section {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
background-color: var(--bim-btn-group-section-bg, rgba(17, 17, 17, 0.88));
|
||||
border-radius: 6px;
|
||||
padding: 4px;
|
||||
/* 添加阴影效果,增强视觉层次感 */
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3), 0 1px 3px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.bim-btn-group-root.dir-row .bim-btn-group-section {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bim-btn-group-root.dir-column .bim-btn-group-section {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 按钮外层 */
|
||||
.opt-btn-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 按钮本体 */
|
||||
.opt-btn {
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.2s, color 0.2s, border-color 0.2s;
|
||||
color: var(--bim-btn-text-color, #ccc);
|
||||
background-color: var(--bim-btn-bg, transparent);
|
||||
padding: 6px;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
/* 为绝对定位提供锚点 */
|
||||
justify-content: center;
|
||||
border: 1px solid transparent;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.opt-btn:hover {
|
||||
background-color: var(--bim-btn-hover-bg, #444);
|
||||
}
|
||||
|
||||
.opt-btn.active {
|
||||
background-color: var(--bim-btn-active-bg, rgba(255, 255, 255, 0.15));
|
||||
color: var(--bim-btn-text-active-color, #fff);
|
||||
/* 开关按钮激活时不显示边框,只改变背景 */
|
||||
}
|
||||
|
||||
/* 开关按钮激活时图标颜色保持不变,继承默认颜色 */
|
||||
|
||||
.opt-btn.disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* --- 图标 --- */
|
||||
.opt-btn-icon {
|
||||
width: var(--bim-icon-size, 24px);
|
||||
height: var(--bim-icon-size, 24px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--bim-icon-color, #ccc);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.opt-btn-icon svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
/* --- 箭头 --- */
|
||||
.opt-btn-arrow {
|
||||
font-size: 10px;
|
||||
opacity: 0.6;
|
||||
transition: transform 0.2s;
|
||||
display: inline-block;
|
||||
/* 默认情况 (有Label) */
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.opt-btn-arrow.rotated {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
/* --- 文字容器 --- */
|
||||
.opt-btn-text-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* --- Label 显示控制 --- */
|
||||
.opt-btn-label {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.opt-btn.no-label .opt-btn-label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* --- 场景 A: 有 Label (常规布局) --- */
|
||||
|
||||
.opt-btn.align-vertical:not(.no-label) {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.opt-btn.align-vertical:not(.no-label) .opt-btn-text-wrapper {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.opt-btn.align-vertical:not(.no-label) .opt-btn-label {
|
||||
font-size: 12px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.opt-btn.align-horizontal:not(.no-label) {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.opt-btn.align-horizontal:not(.no-label) .opt-btn-text-wrapper {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.opt-btn.align-horizontal:not(.no-label) .opt-btn-label {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* --- 场景 B: 无 Label (强制绝对定位) --- */
|
||||
|
||||
/* 当没有 label 时,text-wrapper 其实只包裹了 arrow */
|
||||
/* 我们需要让 wrapper 失去布局影响,直接定位内部的 arrow */
|
||||
|
||||
.opt-btn.no-label .opt-btn-text-wrapper {
|
||||
/* 让 wrapper 变为 0 尺寸,不影响 flex 布局 */
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
/* 关键:允许子元素溢出 */
|
||||
position: absolute;
|
||||
/* 脱离文档流,相对于 .opt-btn */
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.opt-btn.no-label .opt-btn-arrow {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
margin: 0;
|
||||
/* 清除之前的 margin */
|
||||
font-size: 8px;
|
||||
/*
|
||||
如果父级 wrapper 已经是 top:0, right:0
|
||||
那么 arrow 相对 wrapper 定位即可
|
||||
*/
|
||||
}
|
||||
|
||||
/* --- 下拉菜单 & 动画 --- */
|
||||
.opt-btn-dropdown {
|
||||
position: absolute;
|
||||
background-color: var(--bim-toolbar-bg, rgba(17, 17, 17, 0.95));
|
||||
border-radius: 4px;
|
||||
padding: 4px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
||||
z-index: 1001;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
|
||||
/* 动画起始状态 */
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translateY(-10px);
|
||||
/* 默认向上偏移一点 */
|
||||
transition: opacity 0.2s ease, transform 0.2s cubic-bezier(0.2, 0, 0.2, 1), visibility 0.2s;
|
||||
}
|
||||
|
||||
/* 动画激活状态 (需要 JS 添加 .show 类,或者直接在 display:flex 时生效?) */
|
||||
/* 这里的实现有点 tricky,因为 JS 里直接 appendChild */
|
||||
/* 我们可以利用 CSS 动画关键帧,或者简单的 transition */
|
||||
/* 由于 DOM 是动态插入的,插入瞬间是 opacity: 0 -> requestAnimationFrame -> opacity: 1 */
|
||||
/* 简单的办法:添加动画 keyframes */
|
||||
|
||||
@keyframes dropdown-fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-8px) scale(0.98);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.opt-btn-dropdown {
|
||||
/* 覆盖上面的 transition,直接用 animation */
|
||||
animation: dropdown-fade-in 0.2s cubic-bezier(0.2, 0, 0.2, 1) forwards;
|
||||
/* 初始可见性由 JS 控制(append 即显示) */
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.opt-btn-dropdown-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
color: var(--bim-btn-text-color, #ccc);
|
||||
transition: background 0.2s, border-color 0.2s, color 0.2s;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid transparent;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* 二级菜单项的图标默认颜色 */
|
||||
.opt-btn-dropdown-item .opt-btn-icon {
|
||||
color: var(--bim-icon-color, #ccc);
|
||||
}
|
||||
|
||||
.opt-btn-dropdown-item:hover {
|
||||
background-color: var(--bim-btn-hover-bg, #444);
|
||||
}
|
||||
|
||||
/* 二级菜单项激活态(支持 keepActive 的可视化) */
|
||||
.opt-btn-dropdown-item.active {
|
||||
background-color: var(--bim-btn-active-bg, rgba(255, 255, 255, 0.15));
|
||||
color: var(--bim-btn-text-active-color, #fff);
|
||||
/* 开关按钮激活时不显示边框,只改变背景 */
|
||||
}
|
||||
|
||||
/* 开关按钮激活时图标颜色保持不变,继承默认颜色 */
|
||||
|
||||
/* 下拉菜单项 - 横向布局(图标在左,默认) */
|
||||
.opt-btn-dropdown-item.align-horizontal {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.opt-btn-dropdown-item.align-horizontal .opt-btn-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
/* 下拉菜单项 - 纵向布局(图标在上) */
|
||||
.opt-btn-dropdown-item.align-vertical {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.opt-btn-dropdown-item.align-vertical .opt-btn-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.opt-btn-dropdown-item.align-vertical .opt-btn-dropdown-label {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* --- 特定样式覆盖:底部工具栏 --- */
|
||||
.bim-btn-group-root.is-bottom-toolbar .opt-btn-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.bim-btn-group-root.is-bottom-toolbar .opt-btn {
|
||||
padding: 8px;
|
||||
}
|
||||
717
.recycle/2026-01-21/src/components/button-group/index.ts
Normal file
@@ -0,0 +1,717 @@
|
||||
import './index.css';
|
||||
import type {
|
||||
OptButton,
|
||||
ButtonGroup,
|
||||
ButtonGroupOptions,
|
||||
ButtonConfig,
|
||||
ButtonGroupColors
|
||||
} from './index.type';
|
||||
import { t, localeManager } from '../../services/locale';
|
||||
import { themeManager } from '../../services/theme';
|
||||
import type { ThemeConfig } from '../../themes/types';
|
||||
import { IBimComponent } from '../../types/component';
|
||||
import type { BimEngine } from '../../bim-engine';
|
||||
import { EngineEvents } from '../../types/events';
|
||||
|
||||
/**
|
||||
* 通用按钮组组件 (BimButtonGroup)
|
||||
*/
|
||||
export class BimButtonGroup implements IBimComponent {
|
||||
private container: HTMLElement;
|
||||
private options: ButtonGroupOptions;
|
||||
private groups: ButtonGroup[] = [];
|
||||
private activeBtnIds: Set<string> = new Set();
|
||||
private btnRefs: Map<string, HTMLElement> = new Map();
|
||||
private dropdownElement: HTMLElement | null = null;
|
||||
private hoverTimeout: number | null = null;
|
||||
private customColors: Set<keyof ButtonGroupColors> = new Set(); // 记录用户自定义的颜色属性
|
||||
private unsubscribeLocale: (() => void) | null = null;
|
||||
private unsubscribeTheme: (() => void) | null = null;
|
||||
|
||||
protected engine: BimEngine | null = null;
|
||||
|
||||
private readonly DEFAULT_ICON = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect></svg>';
|
||||
|
||||
constructor(options: ButtonGroupOptions) {
|
||||
const el = typeof options.container === 'string'
|
||||
? document.getElementById(options.container)
|
||||
: options.container;
|
||||
|
||||
if (!el) throw new Error('Container not found');
|
||||
|
||||
this.container = el;
|
||||
// 合并默认配置
|
||||
this.options = {
|
||||
showLabel: true,
|
||||
visibility: {},
|
||||
direction: 'row', // 默认横向
|
||||
position: 'static', // 默认静态定位
|
||||
align: 'vertical', // 默认图标在上
|
||||
expand: 'down', // 默认向下展开
|
||||
...options
|
||||
};
|
||||
|
||||
// 记录初始传入的自定义颜色
|
||||
const colorKeys: (keyof ButtonGroupColors)[] = [
|
||||
'backgroundColor', 'btnBackgroundColor', 'btnHoverColor',
|
||||
'btnActiveColor', 'iconColor', 'iconActiveColor',
|
||||
'textColor', 'textActiveColor'
|
||||
];
|
||||
colorKeys.forEach(key => {
|
||||
if (options[key]) {
|
||||
this.customColors.add(key);
|
||||
}
|
||||
});
|
||||
|
||||
this.initContainer();
|
||||
this.applyStyles();
|
||||
}
|
||||
|
||||
public setEngine(engine: BimEngine) {
|
||||
this.engine = engine;
|
||||
}
|
||||
|
||||
protected emit<K extends keyof EngineEvents>(event: K, payload: EngineEvents[K]) {
|
||||
if (this.engine) {
|
||||
this.engine.emit(event, payload);
|
||||
} else {
|
||||
console.warn('[BimButtonGroup] Engine not set, cannot emit event:', event);
|
||||
}
|
||||
}
|
||||
|
||||
private initContainer(): void {
|
||||
this.container.innerHTML = '';
|
||||
this.container.classList.add('bim-btn-group-root');
|
||||
|
||||
if (this.options.direction === 'column') {
|
||||
this.container.classList.add('dir-column');
|
||||
} else {
|
||||
this.container.classList.add('dir-row');
|
||||
}
|
||||
|
||||
if (this.options.className) {
|
||||
this.container.classList.add(this.options.className);
|
||||
}
|
||||
|
||||
this.updatePosition();
|
||||
|
||||
// 添加事件拦截,防止点击穿透到 3D 引擎
|
||||
this.setupEventInterception(this.container);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置事件拦截,防止事件冒泡到下层元素(如 3D 引擎)
|
||||
*/
|
||||
private setupEventInterception(el: HTMLElement): void {
|
||||
const stopPropagation = (e: Event) => {
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const events = [
|
||||
'click', 'dblclick', 'contextmenu', 'wheel',
|
||||
'mousedown', 'mouseup', 'mousemove',
|
||||
'touchstart', 'touchend', 'touchmove',
|
||||
'pointerdown', 'pointerup', 'pointermove', 'pointerenter', 'pointerleave', 'pointerover', 'pointerout'
|
||||
];
|
||||
|
||||
events.forEach(eventType => {
|
||||
el.addEventListener(eventType, stopPropagation, { passive: false });
|
||||
});
|
||||
}
|
||||
|
||||
private updatePosition() {
|
||||
const pos = this.options.position;
|
||||
const style = this.container.style;
|
||||
|
||||
style.top = ''; style.bottom = ''; style.left = ''; style.right = ''; style.transform = '';
|
||||
|
||||
if (pos === 'static') {
|
||||
this.container.classList.add('static');
|
||||
return;
|
||||
}
|
||||
|
||||
this.container.classList.remove('static');
|
||||
this.container.style.position = 'absolute';
|
||||
|
||||
if (typeof pos === 'object' && 'x' in pos) {
|
||||
style.left = `${pos.x}px`;
|
||||
style.top = `${pos.y}px`;
|
||||
} else {
|
||||
const margin = '20px';
|
||||
switch (pos) {
|
||||
case 'top-left':
|
||||
style.top = margin; style.left = margin;
|
||||
break;
|
||||
case 'top-center':
|
||||
style.top = margin; style.left = '50%'; style.transform = 'translateX(-50%)';
|
||||
break;
|
||||
case 'top-right':
|
||||
style.top = margin; style.right = margin;
|
||||
break;
|
||||
case 'bottom-left':
|
||||
style.bottom = margin; style.left = margin;
|
||||
break;
|
||||
case 'bottom-center':
|
||||
style.bottom = margin; style.left = '50%'; style.transform = 'translateX(-50%)';
|
||||
break;
|
||||
case 'bottom-right':
|
||||
style.bottom = margin; style.right = margin;
|
||||
break;
|
||||
case 'left-center':
|
||||
style.left = margin; style.top = '50%'; style.transform = 'translateY(-50%)';
|
||||
break;
|
||||
case 'right-center':
|
||||
style.right = margin; style.top = '50%'; style.transform = 'translateY(-50%)';
|
||||
break;
|
||||
case 'center':
|
||||
style.top = '50%'; style.left = '50%'; style.transform = 'translate(-50%, -50%)';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用样式到容器
|
||||
*/
|
||||
private applyStyles(): void {
|
||||
const style = this.container.style;
|
||||
if (this.options.backgroundColor) style.setProperty('--bim-btn-group-section-bg', this.options.backgroundColor);
|
||||
if (this.options.btnBackgroundColor) style.setProperty('--bim-btn-bg', this.options.btnBackgroundColor);
|
||||
if (this.options.btnHoverColor) style.setProperty('--bim-btn-hover-bg', this.options.btnHoverColor);
|
||||
if (this.options.btnActiveColor) style.setProperty('--bim-btn-active-bg', this.options.btnActiveColor);
|
||||
if (this.options.iconColor) style.setProperty('--bim-icon-color', this.options.iconColor);
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置主题颜色
|
||||
* 只会应用到没有被用户自定义的颜色属性上
|
||||
*/
|
||||
public setTheme(theme: ThemeConfig): void {
|
||||
const themeColors: ButtonGroupColors = {
|
||||
backgroundColor: theme.panelBackground,
|
||||
btnBackgroundColor: theme.componentBackground,
|
||||
btnHoverColor: theme.componentHover,
|
||||
btnActiveColor: theme.componentActive,
|
||||
iconColor: theme.icon,
|
||||
iconActiveColor: theme.iconActive,
|
||||
textColor: theme.textSecondary,
|
||||
textActiveColor: theme.textPrimary
|
||||
};
|
||||
|
||||
// 只应用没有被自定义的颜色
|
||||
Object.entries(themeColors).forEach(([key, value]) => {
|
||||
const colorKey = key as keyof ButtonGroupColors;
|
||||
if (!this.customColors.has(colorKey)) {
|
||||
this.options[colorKey] = value;
|
||||
}
|
||||
});
|
||||
|
||||
this.applyStyles();
|
||||
this.setPrimaryColor(theme.primary);
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接设置颜色(强制覆盖)
|
||||
* 设置的颜色会被标记为自定义,后续的 setTheme 不会覆盖它们
|
||||
*/
|
||||
public setColors(colors: ButtonGroupColors): void {
|
||||
// 更新 options
|
||||
this.options = { ...this.options, ...colors };
|
||||
|
||||
// 标记这些颜色为自定义
|
||||
Object.keys(colors).forEach(key => {
|
||||
this.customColors.add(key as keyof ButtonGroupColors);
|
||||
});
|
||||
|
||||
this.applyStyles();
|
||||
}
|
||||
|
||||
public async init(): Promise<void> {
|
||||
this.render();
|
||||
|
||||
// 自动订阅语言变更
|
||||
this.unsubscribeLocale = localeManager.subscribe(() => {
|
||||
this.setLocales();
|
||||
});
|
||||
|
||||
// 自动订阅主题变更
|
||||
this.unsubscribeTheme = themeManager.subscribe((theme) => {
|
||||
this.setTheme(theme);
|
||||
});
|
||||
}
|
||||
|
||||
public setLocales(): void {
|
||||
this.render();
|
||||
}
|
||||
|
||||
public addGroup(groupId: string, beforeGroupId?: string): void {
|
||||
if (this.groups.some(g => g.id === groupId)) return;
|
||||
const newGroup: ButtonGroup = { id: groupId, buttons: [] };
|
||||
if (beforeGroupId) {
|
||||
const index = this.groups.findIndex(g => g.id === beforeGroupId);
|
||||
index !== -1 ? this.groups.splice(index, 0, newGroup) : this.groups.push(newGroup);
|
||||
} else {
|
||||
this.groups.push(newGroup);
|
||||
}
|
||||
}
|
||||
|
||||
public addButton(config: ButtonConfig): void {
|
||||
const { groupId, parentId } = config;
|
||||
const group = this.groups.find(g => g.id === groupId);
|
||||
if (!group) return;
|
||||
|
||||
const button: OptButton = { ...config, children: config.children || [] };
|
||||
if (parentId) {
|
||||
const parentBtn = this.findButton(group.buttons, parentId);
|
||||
if (parentBtn) {
|
||||
if (!parentBtn.children) parentBtn.children = [];
|
||||
parentBtn.children.push(button);
|
||||
}
|
||||
} else {
|
||||
group.buttons.push(button);
|
||||
}
|
||||
}
|
||||
|
||||
private findButton(buttons: OptButton[], id: string): OptButton | undefined {
|
||||
for (const btn of buttons) {
|
||||
if (btn.id === id) return btn;
|
||||
if (btn.children) {
|
||||
const found = this.findButton(btn.children, id);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public render(): void {
|
||||
this.container.innerHTML = '';
|
||||
this.btnRefs.clear();
|
||||
|
||||
this.groups.forEach((group, index) => {
|
||||
const groupElement = this.renderGroup(group, index, this.groups.length);
|
||||
this.container.appendChild(groupElement);
|
||||
});
|
||||
}
|
||||
|
||||
private renderGroup(group: ButtonGroup, index: number, total: number): HTMLElement {
|
||||
const groupEl = document.createElement('div');
|
||||
groupEl.className = 'bim-btn-group-section';
|
||||
|
||||
if (index < total - 1) {
|
||||
groupEl.classList.add('has-divider');
|
||||
}
|
||||
|
||||
group.buttons.forEach(button => {
|
||||
if (this.isVisible(button.id)) {
|
||||
const btnWrapper = this.renderButton(button);
|
||||
groupEl.appendChild(btnWrapper);
|
||||
}
|
||||
});
|
||||
return groupEl;
|
||||
}
|
||||
|
||||
private renderButton(button: OptButton): HTMLElement {
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.className = 'opt-btn-wrapper';
|
||||
|
||||
const btnEl = document.createElement('div');
|
||||
btnEl.className = 'opt-btn';
|
||||
|
||||
// 初始化时根据 button 自身的属性同步 active 状态
|
||||
if (button.isActive) {
|
||||
this.activeBtnIds.add(button.id);
|
||||
}
|
||||
|
||||
// 按钮优先使用自己的 align,否则使用全局配置,默认为 vertical
|
||||
const align = button.align || this.options.align || 'vertical';
|
||||
if (align === 'horizontal') {
|
||||
btnEl.classList.add('align-horizontal');
|
||||
} else {
|
||||
btnEl.classList.add('align-vertical');
|
||||
}
|
||||
|
||||
if (this.activeBtnIds.has(button.id)) btnEl.classList.add('active');
|
||||
if (button.disabled) btnEl.classList.add('disabled');
|
||||
|
||||
// 判断是否显示 label
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// 应用按钮的自定义样式
|
||||
const iconSize = button.iconSize || 32;
|
||||
const minWidth = button.minWidth || 50;
|
||||
btnEl.style.minWidth = `${minWidth}px`;
|
||||
|
||||
const icon = document.createElement('div');
|
||||
icon.className = 'opt-btn-icon';
|
||||
icon.style.width = `${iconSize}px`;
|
||||
icon.style.height = `${iconSize}px`;
|
||||
icon.innerHTML = this.getIcon(button.icon);
|
||||
btnEl.appendChild(icon);
|
||||
|
||||
// 创建文字和箭头的容器,确保它们始终在一起(无论主轴是横是竖)
|
||||
const textWrapper = document.createElement('div');
|
||||
textWrapper.className = 'opt-btn-text-wrapper';
|
||||
|
||||
if (this.options.showLabel && button.label) {
|
||||
const label = document.createElement('span');
|
||||
label.className = 'opt-btn-label';
|
||||
label.textContent = t(button.label);
|
||||
textWrapper.appendChild(label);
|
||||
}
|
||||
|
||||
if (button.children && button.children.length > 0) {
|
||||
const arrow = document.createElement('span');
|
||||
arrow.className = 'opt-btn-arrow';
|
||||
arrow.textContent = '▼';
|
||||
textWrapper.appendChild(arrow);
|
||||
}
|
||||
|
||||
// 只有当有内容时才添加 wrapper
|
||||
if (textWrapper.hasChildNodes()) {
|
||||
btnEl.appendChild(textWrapper);
|
||||
}
|
||||
|
||||
btnEl.addEventListener('click', () => this.handleClick(button));
|
||||
btnEl.addEventListener('mouseenter', () => this.handleMouseEnter(button, btnEl));
|
||||
btnEl.addEventListener('mouseleave', () => this.handleMouseLeave());
|
||||
|
||||
this.btnRefs.set(button.id, btnEl);
|
||||
wrapper.appendChild(btnEl);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置按钮的激活状态
|
||||
* @param id 按钮 ID
|
||||
* @param active 可选,如果不传则切换(toggle)当前状态
|
||||
*/
|
||||
public setBtnActive(id: string, active?: boolean): void {
|
||||
const button = this.findButtonById(id);
|
||||
if (!button) return;
|
||||
|
||||
// 确定最终状态
|
||||
const newState = active !== undefined ? active : !this.activeBtnIds.has(id);
|
||||
|
||||
if (newState) {
|
||||
this.activeBtnIds.add(id);
|
||||
} else {
|
||||
this.activeBtnIds.delete(id);
|
||||
}
|
||||
|
||||
// 同步对象状态并更新 DOM
|
||||
button.isActive = newState;
|
||||
this.updateButtonState(id);
|
||||
}
|
||||
|
||||
private handleClick(button: OptButton): void {
|
||||
if (button.disabled) return;
|
||||
if (!button.children || button.children.length === 0) {
|
||||
if (button.keepActive) {
|
||||
// 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) {
|
||||
this.showDropdown(button, btnEl);
|
||||
} else {
|
||||
this.closeDropdown();
|
||||
}
|
||||
}
|
||||
|
||||
private handleMouseLeave(): void {
|
||||
this.hoverTimeout = window.setTimeout(() => this.closeDropdown(), 200);
|
||||
}
|
||||
|
||||
private showDropdown(button: OptButton, btnEl: HTMLElement): void {
|
||||
this.closeDropdown();
|
||||
if (!button.children) return;
|
||||
|
||||
const dropdown = document.createElement('div');
|
||||
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';
|
||||
|
||||
// 根据主按钮组的方向设置下拉菜单的布局方向
|
||||
if (this.options.direction === 'row') {
|
||||
dropdown.style.flexDirection = 'column'; // 横向按钮组,菜单纵向排列
|
||||
} else {
|
||||
dropdown.style.flexDirection = 'row'; // 纵向按钮组,菜单横向排列
|
||||
}
|
||||
|
||||
// 先添加到 DOM 以便计算尺寸
|
||||
document.body.appendChild(dropdown);
|
||||
|
||||
// 添加事件拦截
|
||||
this.setupEventInterception(dropdown);
|
||||
|
||||
// 添加菜单项
|
||||
button.children.forEach(subBtn => {
|
||||
if (this.isVisible(subBtn.id)) {
|
||||
const item = this.renderDropdownItem(subBtn);
|
||||
dropdown.appendChild(item);
|
||||
}
|
||||
});
|
||||
|
||||
// 获取下拉菜单的实际尺寸
|
||||
const dropdownRect = dropdown.getBoundingClientRect();
|
||||
|
||||
if (expand === 'up') {
|
||||
// 向上展开,与按钮水平居中对齐
|
||||
dropdown.style.bottom = (window.innerHeight - btnRect.top + 8) + 'px';
|
||||
dropdown.style.left = (btnRect.left + (btnRect.width - dropdownRect.width) / 2) + 'px';
|
||||
} else if (expand === 'down') {
|
||||
// 向下展开,与按钮水平居中对齐
|
||||
dropdown.style.top = (btnRect.bottom + 8) + 'px';
|
||||
dropdown.style.left = (btnRect.left + (btnRect.width - dropdownRect.width) / 2) + 'px';
|
||||
} else if (expand === 'right') {
|
||||
// 向右展开,与按钮垂直居中对齐
|
||||
dropdown.style.top = (btnRect.top + (btnRect.height - dropdownRect.height) / 2) + 'px';
|
||||
dropdown.style.left = (btnRect.right + 8) + 'px';
|
||||
} else if (expand === 'left') {
|
||||
// 向左展开,与按钮垂直居中对齐
|
||||
dropdown.style.top = (btnRect.top + (btnRect.height - dropdownRect.height) / 2) + 'px';
|
||||
dropdown.style.right = (window.innerWidth - btnRect.left + 8) + 'px';
|
||||
}
|
||||
|
||||
dropdown.addEventListener('mouseenter', () => { if (this.hoverTimeout) clearTimeout(this.hoverTimeout); });
|
||||
dropdown.addEventListener('mouseleave', () => this.handleMouseLeave());
|
||||
this.dropdownElement = dropdown;
|
||||
}
|
||||
|
||||
private renderDropdownItem(button: OptButton): HTMLElement {
|
||||
const item = document.createElement('div');
|
||||
item.className = 'opt-btn-dropdown-item';
|
||||
|
||||
// 应用按钮的 align 设置,默认为 horizontal(图标在左)
|
||||
const align = button.align || 'horizontal';
|
||||
if (align === 'horizontal') {
|
||||
item.classList.add('align-horizontal');
|
||||
} else {
|
||||
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; // 不设置默认值,让下拉菜单项保持紧凑
|
||||
if (minWidth) {
|
||||
item.style.minWidth = `${minWidth}px`;
|
||||
}
|
||||
|
||||
const icon = document.createElement('div');
|
||||
icon.className = 'opt-btn-icon';
|
||||
icon.style.width = `${iconSize}px`;
|
||||
icon.style.height = `${iconSize}px`;
|
||||
icon.innerHTML = this.getIcon(button.icon);
|
||||
item.appendChild(icon);
|
||||
|
||||
// 只有在 showLabel 为 true 时才显示 label
|
||||
if (this.options.showLabel && button.label) {
|
||||
const label = document.createElement('span');
|
||||
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); });
|
||||
return item;
|
||||
}
|
||||
|
||||
private closeDropdown(): void {
|
||||
if (this.dropdownElement) {
|
||||
this.dropdownElement.remove();
|
||||
this.dropdownElement = null;
|
||||
}
|
||||
this.btnRefs.forEach(btnEl => {
|
||||
const arrow = btnEl.querySelector('.opt-btn-arrow');
|
||||
if (arrow) arrow.classList.remove('rotated');
|
||||
});
|
||||
}
|
||||
|
||||
private updateButtonState(buttonId: string): void {
|
||||
const btnEl = this.btnRefs.get(buttonId);
|
||||
if (btnEl) {
|
||||
if (this.activeBtnIds.has(buttonId)) {
|
||||
btnEl.classList.add('active');
|
||||
} else {
|
||||
btnEl.classList.remove('active');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private getIcon(icon?: string): string { return icon || this.DEFAULT_ICON; }
|
||||
|
||||
public updateButtonVisibility(id: string, visible: boolean): void {
|
||||
if (!this.options.visibility) this.options.visibility = {};
|
||||
this.options.visibility[id] = visible;
|
||||
this.render();
|
||||
}
|
||||
|
||||
public setShowLabel(show: boolean): void {
|
||||
this.options.showLabel = show;
|
||||
this.updateLabelsVisibility();
|
||||
}
|
||||
|
||||
private updateLabelsVisibility(): void {
|
||||
this.btnRefs.forEach((btnEl, buttonId) => {
|
||||
// 查找按钮配置
|
||||
const button = this.findButtonById(buttonId);
|
||||
if (!button) return;
|
||||
|
||||
const hasLabel = this.options.showLabel && button.label;
|
||||
|
||||
// 更新 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);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private findButtonById(id: string): OptButton | undefined {
|
||||
for (const group of this.groups) {
|
||||
const found = this.findButton(group.buttons, id);
|
||||
if (found) return found;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public setBackgroundColor(color: string): void { this.setColors({ backgroundColor: color }); }
|
||||
private isVisible(id: string): boolean { return this.options.visibility?.[id] !== false; }
|
||||
|
||||
public destroy(): void {
|
||||
if (this.unsubscribeLocale) {
|
||||
this.unsubscribeLocale();
|
||||
this.unsubscribeLocale = null;
|
||||
}
|
||||
if (this.unsubscribeTheme) {
|
||||
this.unsubscribeTheme();
|
||||
this.unsubscribeTheme = null;
|
||||
}
|
||||
this.closeDropdown();
|
||||
this.container.innerHTML = '';
|
||||
this.btnRefs.clear();
|
||||
}
|
||||
}
|
||||
100
.recycle/2026-01-21/src/components/button-group/index.type.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
export type ButtonType = 'button' | 'menu';
|
||||
|
||||
/** 按钮配置 */
|
||||
export interface ButtonConfig {
|
||||
id: string;
|
||||
type: ButtonType;
|
||||
label: string;
|
||||
icon?: string;
|
||||
keepActive?: boolean;
|
||||
/**
|
||||
* 是否互斥(开关互斥)
|
||||
*
|
||||
* 行为说明:
|
||||
* - 当按钮从“未激活”切换到“激活”时,如果该按钮开启了 exclusive,
|
||||
* 会自动关闭同互斥范围内的其它已激活按钮,并触发它们的 onClick(用于执行关闭逻辑)。
|
||||
* - 一级按钮:互斥范围 = 同 groupId 下的一级按钮
|
||||
* - 二级按钮:互斥范围 = 同 groupId 且同 parentId 下的二级按钮
|
||||
*
|
||||
* 注意:该能力通常与 keepActive 搭配使用。
|
||||
*/
|
||||
exclusive?: boolean;
|
||||
isActive?:boolean;
|
||||
disabled?: boolean;
|
||||
onClick?: (button: OptButton) => void;
|
||||
children?: ButtonConfig[];
|
||||
groupId?: string;
|
||||
parentId?: string;
|
||||
/** 按钮内部图标文字排列 (默认 vertical,即图标在上) */
|
||||
align?: ButtonAlign;
|
||||
/** 图标大小 (正方形,单位 px,默认 32) */
|
||||
iconSize?: number;
|
||||
/** 按钮最小宽度 (单位 px,默认 50) */
|
||||
minWidth?: number;
|
||||
}
|
||||
|
||||
export interface OptButton extends ButtonConfig {
|
||||
children?: OptButton[];
|
||||
}
|
||||
|
||||
export interface ButtonGroup {
|
||||
id: string;
|
||||
buttons: OptButton[];
|
||||
}
|
||||
|
||||
export interface ButtonGroupColors {
|
||||
backgroundColor?: string;
|
||||
btnBackgroundColor?: string;
|
||||
btnHoverColor?: string;
|
||||
btnActiveColor?: string;
|
||||
iconColor?: string;
|
||||
iconActiveColor?: string;
|
||||
textColor?: string;
|
||||
textActiveColor?: string;
|
||||
}
|
||||
|
||||
// --- 新增布局类型 ---
|
||||
|
||||
/** 弹窗/按钮组位置 */
|
||||
export type GroupPosition =
|
||||
| 'center'
|
||||
| 'top-left' | 'top-center' | 'top-right'
|
||||
| 'left-center' | 'right-center'
|
||||
| 'bottom-left' | 'bottom-center' | 'bottom-right'
|
||||
| { x: number; y: number }
|
||||
| 'static'; // static 表示不绝对定位,随文档流
|
||||
|
||||
/** 按钮组排列方向 (Flex-direction) */
|
||||
export type GroupDirection = 'row' | 'column';
|
||||
|
||||
/** 按钮内部文字图标排列 */
|
||||
export type ButtonAlign = 'vertical' /* 图标在上 */ | 'horizontal' /* 图标在左 */;
|
||||
|
||||
/** 二级菜单展开方向 */
|
||||
export type ExpandDirection = 'up' | 'down' | 'left' | 'right';
|
||||
|
||||
export interface ButtonGroupOptions extends ButtonGroupColors {
|
||||
container: HTMLElement | string;
|
||||
|
||||
/** 屏幕位置 (如 top-left) */
|
||||
position?: GroupPosition;
|
||||
|
||||
/** 按钮组排列方向 (默认 row) */
|
||||
direction?: GroupDirection;
|
||||
|
||||
/** 按钮内部图标文字排列 (默认 vertical) */
|
||||
align?: ButtonAlign;
|
||||
|
||||
/** 菜单展开方向 */
|
||||
expand?: ExpandDirection;
|
||||
|
||||
showLabel?: boolean;
|
||||
visibility?: Record<string, boolean>;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export interface ClickPayload {
|
||||
button: OptButton;
|
||||
action: 'activate' | 'deactivate' | 'trigger';
|
||||
isActive?: boolean;
|
||||
}
|
||||
96
.recycle/2026-01-21/src/managers/toolbar-manager.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import type { ButtonGroupColors, ButtonConfig } from '../components/button-group/index.type';
|
||||
import { Toolbar } from '../components/button-group/toolbar';
|
||||
import type { ThemeConfig } from '../themes/types';
|
||||
import { BimComponent } from '../core/component';
|
||||
import type { BimEngine } from '../bim-engine';
|
||||
|
||||
/**
|
||||
* 底部工具栏管理器 (ToolbarManager)
|
||||
* 仅负责管理底部工具栏实例。
|
||||
*/
|
||||
export class ToolbarManager extends BimComponent {
|
||||
private toolbar: Toolbar | null = null;
|
||||
private toolbarContainer: HTMLElement | null = null;
|
||||
private container: HTMLElement;
|
||||
|
||||
constructor(engine: BimEngine, container: HTMLElement) {
|
||||
super(engine);
|
||||
this.container = container;
|
||||
this.init();
|
||||
}
|
||||
|
||||
private init() {
|
||||
// 创建底部工具栏专用容器
|
||||
this.toolbarContainer = document.createElement('div');
|
||||
this.toolbarContainer.id = 'opt-btn-groups';
|
||||
this.toolbarContainer.className = 'bim-engine-opt-btn-container is-bottom-toolbar';
|
||||
this.container.appendChild(this.toolbarContainer);
|
||||
|
||||
this.toolbar = new Toolbar({
|
||||
container: this.toolbarContainer,
|
||||
showLabel: true,
|
||||
direction: 'row',
|
||||
position: 'bottom-center', // 底部居中
|
||||
align: 'vertical', // 图标在上
|
||||
expand: 'up' // 向上展开
|
||||
});
|
||||
|
||||
// 注入 engine 到 Toolbar
|
||||
// @ts-ignore - Toolbar 还没更新类型,暂时忽略
|
||||
this.toolbar.setEngine(this.engine);
|
||||
|
||||
this.toolbar.init();
|
||||
}
|
||||
|
||||
public updateTheme(theme: ThemeConfig) {
|
||||
this.toolbar?.setTheme(theme);
|
||||
}
|
||||
|
||||
public refresh() {
|
||||
this.toolbar?.render();
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
this.toolbar?.destroy();
|
||||
this.toolbar = null;
|
||||
}
|
||||
|
||||
// --- 转发 API ---
|
||||
public addGroup(groupId: string, beforeGroupId?: string) { this.toolbar?.addGroup(groupId, beforeGroupId); this.toolbar?.render(); }
|
||||
public addButton(config: ButtonConfig) { this.toolbar?.addButton(config); this.toolbar?.render(); }
|
||||
public setButtonVisibility(id: string, v: boolean) { this.toolbar?.updateButtonVisibility(id, v); }
|
||||
public setShowLabel(show: boolean) { this.toolbar?.setShowLabel(show); }
|
||||
public setBtnActive(id: string, active?: boolean) { this.toolbar?.setBtnActive(id, active); }
|
||||
public setVisible(visible: boolean) {
|
||||
if (this.toolbarContainer) {
|
||||
this.toolbarContainer.style.visibility = visible ? 'visible' : 'hidden';
|
||||
}
|
||||
}
|
||||
public setBackgroundColor(color: string) { this.toolbar?.setBackgroundColor(color); }
|
||||
public setColors(colors: ButtonGroupColors) { this.toolbar?.setColors(colors); }
|
||||
|
||||
/**
|
||||
* 隐藏工具栏
|
||||
*/
|
||||
public hide(): void {
|
||||
if (this.toolbarContainer) {
|
||||
this.toolbarContainer.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示工具栏
|
||||
*/
|
||||
public show(): void {
|
||||
if (this.toolbarContainer) {
|
||||
this.toolbarContainer.style.display = '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取工具栏容器
|
||||
*/
|
||||
public getContainer(): HTMLElement | null {
|
||||
return this.toolbarContainer;
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 528 B After Width: | Height: | Size: 528 B |
@@ -1,4 +1,4 @@
|
||||
# BIM Engine SDK - AI 协作文档
|
||||
# iFlow Engine - AI 协作文档
|
||||
|
||||
> 本文档用于向 AI 助手传递项目信息,帮助 AI 更好地理解和维护本项目。**每次代码改动后,请务必更新本文档的相关部分。**
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
### 1.1 项目描述
|
||||
|
||||
**BIM Engine SDK** 是一个通用的 3D BIM 引擎 SDK 开发框架,旨在通过一次编码,同时支持 Vue 2、Vue 3、React 和纯 HTML 环境。
|
||||
**iFlow Engine** 是一个通用的 3D BIM 引擎 SDK 开发框架,旨在通过一次编码,同时支持 Vue 2、Vue 3、React 和纯 HTML 环境。
|
||||
|
||||
### 1.2 技术栈
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
- **构建工具**: Vite (Library Mode)
|
||||
- **类型生成**: vite-plugin-dts
|
||||
- **CSS 注入**: vite-plugin-css-injected-by-js
|
||||
- **3D 引擎**: 基于第三方 SDK (bim-engine-sdk.es.js)
|
||||
- **3D 引擎**: 基于第三方 SDK (iflow-engine-base)
|
||||
|
||||
### 1.3 项目结构
|
||||
|
||||
@@ -59,8 +59,8 @@ engine/
|
||||
```bash
|
||||
npm run build
|
||||
# 生成 dist/ 目录,包含:
|
||||
# - bim-engine-sdk.es.js (ESM 格式)
|
||||
# - bim-engine-sdk.umd.js (UMD 格式)
|
||||
# - iflow-engine.es.js (ESM 格式)
|
||||
# - iflow-engine.umd.js (UMD 格式)
|
||||
# - index.d.ts (TypeScript 类型定义)
|
||||
# - *.map (Source Map 文件)
|
||||
```
|
||||
@@ -101,8 +101,8 @@ npm run dev:all
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/bim-engine-sdk.es.js",
|
||||
"require": "./dist/bim-engine-sdk.umd.js"
|
||||
"import": "./dist/iflow-engine.es.js",
|
||||
"require": "./dist/iflow-engine.umd.js"
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -489,14 +489,14 @@ interface IBimComponent {
|
||||
**❌ 错误方式 - 尝试直接导入组件:**
|
||||
```typescript
|
||||
// 错误:BimDialog 类未导出,会导致编译错误
|
||||
import { BimDialog } from 'bim-engine-sdk';
|
||||
// Error: Module 'bim-engine-sdk' has no exported member 'BimDialog'.
|
||||
import { BimDialog } from 'iflow-engine';
|
||||
// Error: Module 'iflow-engine' has no exported member 'BimDialog'.
|
||||
```
|
||||
|
||||
**✅ 正确方式 - 通过 Manager 使用:**
|
||||
```typescript
|
||||
// 正确:通过 BimEngine 的 Manager 使用组件
|
||||
import { BimEngine } from 'bim-engine-sdk';
|
||||
import { BimEngine } from 'iflow-engine';
|
||||
|
||||
const engine = new BimEngine('container', {
|
||||
locale: 'zh-CN',
|
||||
|
||||
36
README.md
@@ -1,4 +1,4 @@
|
||||
# BIM Engine SDK
|
||||
# iFlow Engine
|
||||
|
||||
> 一个功能强大的 BIM(建筑信息模型)引擎 SDK,提供 3D 可视化、构件管理、测量工具、剖切功能和漫游控制等完整功能。支持 Vue 2、Vue 3、React 和原生 HTML 等多种前端框架。
|
||||
|
||||
@@ -21,14 +21,14 @@
|
||||
## 📦 安装
|
||||
|
||||
```bash
|
||||
npm install bim-engine-sdk
|
||||
npm install iflow-engine
|
||||
```
|
||||
|
||||
或使用 yarn/pnpm:
|
||||
|
||||
```bash
|
||||
yarn add bim-engine-sdk
|
||||
pnpm add bim-engine-sdk
|
||||
yarn add iflow-engine
|
||||
pnpm add iflow-engine
|
||||
```
|
||||
|
||||
## 🚀 快速开始
|
||||
@@ -42,7 +42,7 @@ pnpm add bim-engine-sdk
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import { BimEngine } from 'bim-engine-sdk';
|
||||
import { BimEngine } from 'iflow-engine';
|
||||
|
||||
const containerRef = ref<HTMLElement>();
|
||||
let bimEngine: BimEngine | null = null;
|
||||
@@ -93,7 +93,7 @@ onUnmounted(() => {
|
||||
|
||||
```tsx
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { BimEngine } from 'bim-engine-sdk';
|
||||
import { BimEngine } from 'iflow-engine';
|
||||
|
||||
function App() {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
@@ -150,10 +150,10 @@ export default App;
|
||||
<div id="container"></div>
|
||||
|
||||
<!-- 使用 UMD 版本 -->
|
||||
<script src="./node_modules/bim-engine-sdk/dist/bim-engine-sdk.umd.js"></script>
|
||||
<script src="./node_modules/iflow-engine/dist/iflow-engine.umd.js"></script>
|
||||
<script>
|
||||
const container = document.getElementById('container');
|
||||
const bimEngine = new BimEngineSdk.BimEngine(container, {
|
||||
const bimEngine = new IflowEngine.BimEngine(container, {
|
||||
locale: 'zh-CN',
|
||||
theme: 'dark'
|
||||
});
|
||||
@@ -229,7 +229,7 @@ BIM Engine SDK 采用 **管理器模式 (Manager Pattern)** 作为核心架构,
|
||||
## 📁 项目结构
|
||||
|
||||
```
|
||||
bim-engine-sdk/
|
||||
iflow-engine/
|
||||
├── src/ # 源代码
|
||||
│ ├── bim-engine.ts # 主引擎类
|
||||
│ ├── index.ts # 入口文件
|
||||
@@ -271,8 +271,8 @@ bim-engine-sdk/
|
||||
│ │ └── icon-manager.ts # 图标管理器
|
||||
│ └── assets/ # 静态资源
|
||||
├── dist/ # 构建产物
|
||||
│ ├── bim-engine-sdk.es.js # ESM 格式
|
||||
│ ├── bim-engine-sdk.umd.js # UMD 格式
|
||||
│ ├── iflow-engine.es.js # ESM 格式
|
||||
│ ├── iflow-engine.umd.js # UMD 格式
|
||||
│ └── index.d.ts # TypeScript 类型定义
|
||||
├── demo/ # HTML Demo
|
||||
├── demo-vue/ # Vue Demo
|
||||
@@ -437,8 +437,8 @@ npm run dev:demo-vue
|
||||
|
||||
运行 `npm run build` 后,会在 `dist/` 目录生成:
|
||||
|
||||
- `bim-engine-sdk.es.js` - ESM 格式 (用于现代打包工具)
|
||||
- `bim-engine-sdk.umd.js` - UMD 格式 (用于浏览器直接引入)
|
||||
- `iflow-engine.es.js` - ESM 格式 (用于现代打包工具)
|
||||
- `iflow-engine.umd.js` - UMD 格式 (用于浏览器直接引入)
|
||||
- `index.d.ts` - TypeScript 类型定义
|
||||
- `*.css` - 样式文件 (已内联注入到 JS 中)
|
||||
|
||||
@@ -446,14 +446,14 @@ npm run dev:demo-vue
|
||||
|
||||
```json
|
||||
{
|
||||
"main": "./dist/bim-engine-sdk.umd.js",
|
||||
"module": "./dist/bim-engine-sdk.es.js",
|
||||
"main": "./dist/iflow-engine.umd.js",
|
||||
"module": "./dist/iflow-engine.es.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/bim-engine-sdk.es.js",
|
||||
"require": "./dist/bim-engine-sdk.umd.js"
|
||||
"import": "./dist/iflow-engine.es.js",
|
||||
"require": "./dist/iflow-engine.umd.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -544,7 +544,7 @@ ISC License
|
||||
|
||||
如有问题或建议,请通过以下方式联系:
|
||||
|
||||
- 提交 [Issue](https://github.com/your-repo/bim-engine-sdk/issues)
|
||||
- 提交 [Issue](https://github.com/your-repo/iflow-engine/issues)
|
||||
- 发送邮件至 your-email@example.com
|
||||
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# BIM Engine SDK Vue3 Demo
|
||||
# iFlow Engine Vue3 Demo
|
||||
|
||||
这是一个使用 Vue3 + TypeScript 的演示项目,用于验证 BIM Engine SDK 在 Vue 环境下的兼容性。
|
||||
这是一个使用 Vue3 + TypeScript 的演示项目,用于验证 iFlow Engine 在 Vue 环境下的兼容性。
|
||||
|
||||
## 前置要求
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
或者手动复制:
|
||||
```bash
|
||||
mkdir -p public/lib
|
||||
cp ../dist/bim-engine-sdk.umd.js public/lib/
|
||||
cp ../dist/bim-engine-sdk.umd.js.map public/lib/
|
||||
cp ../dist/iflow-engine.umd.js public/lib/
|
||||
cp ../dist/iflow-engine.umd.js.map public/lib/
|
||||
```
|
||||
|
||||
## 运行
|
||||
@@ -61,7 +61,7 @@ demo-vue/
|
||||
│ └── vite-env.d.ts # TypeScript 类型声明
|
||||
├── public/
|
||||
│ ├── lib/ # SDK 文件目录
|
||||
│ │ └── bim-engine-sdk.umd.js
|
||||
│ │ └── iflow-engine.umd.js
|
||||
│ └── model/ # 3D 模型文件
|
||||
│ └── gujianzhu.glb
|
||||
├── index.html # HTML 入口
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BIM Engine SDK Vue3 Demo</title>
|
||||
<title>iFlow Engine Vue3 Demo</title>
|
||||
<!-- 从 public/lib 目录加载 SDK 文件 -->
|
||||
<script src="/lib/bim-engine-sdk.umd.js"></script>
|
||||
<script src="/lib/iflow-engine.umd.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "bim-engine-demo-vue",
|
||||
"name": "iflow-engine-demo-vue",
|
||||
"version": "1.0.0",
|
||||
"description": "BIM Engine SDK Vue3 Demo",
|
||||
"description": "iFlow Engine SDK Vue3 Demo",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc && vite build",
|
||||
"preview": "vite preview",
|
||||
"copy-sdk": "mkdir -p public/lib && cp ../dist/bim-engine-sdk.umd.js public/lib/ && cp ../dist/bim-engine-sdk.umd.js.map public/lib/ 2>/dev/null || true"
|
||||
"copy-sdk": "mkdir -p public/lib && cp ../dist/iflow-engine.umd.js public/lib/ && cp ../dist/iflow-engine.umd.js.map public/lib/ 2>/dev/null || true"
|
||||
},
|
||||
"dependencies": {
|
||||
"vue": "^3.4.21"
|
||||
|
||||
4808
demo-vue/public/lib/iflow-engine.umd.js
Normal file
1
demo-vue/public/lib/iflow-engine.umd.js.map
Normal file
@@ -2,7 +2,7 @@
|
||||
<div class="app-container">
|
||||
<!-- 左侧控制面板 -->
|
||||
<aside class="sidebar">
|
||||
<h1>BIM SDK Demo (Vue3)</h1>
|
||||
<h1>iFlow Engine Demo (Vue3)</h1>
|
||||
|
||||
<!-- 1. 语言设置 -->
|
||||
<div class="control-group">
|
||||
@@ -84,8 +84,8 @@ const engineStatusColor = ref('#666');
|
||||
|
||||
// 初始化引擎
|
||||
onMounted(() => {
|
||||
if (window.LyzBimEngineSDK) {
|
||||
const Engine = window.LyzBimEngineSDK.BimEngine;
|
||||
if (window.IflowEngine) {
|
||||
const Engine = window.IflowEngine.BimEngine;
|
||||
try {
|
||||
if (appContainer.value) {
|
||||
engine.value = new Engine(appContainer.value, { locale: 'zh-CN' });
|
||||
|
||||
2
demo-vue/src/vite-env.d.ts
vendored
@@ -9,7 +9,7 @@ declare module '*.vue' {
|
||||
// 声明全局 SDK 类型
|
||||
declare global {
|
||||
interface Window {
|
||||
LyzBimEngineSDK: {
|
||||
IflowEngine: {
|
||||
BimEngine: any;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# BIM Engine SDK Demo
|
||||
# iFlow Engine Demo
|
||||
|
||||
这是一个独立的演示项目,展示如何使用 BIM Engine SDK。
|
||||
这是一个独立的演示项目,展示如何使用 iFlow Engine。
|
||||
|
||||
## 前置要求
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
或者手动复制:
|
||||
```bash
|
||||
mkdir -p lib
|
||||
cp ../dist/bim-engine-sdk.umd.js lib/
|
||||
cp ../dist/iflow-engine.umd.js lib/
|
||||
```
|
||||
|
||||
## 运行
|
||||
@@ -57,7 +57,7 @@ demo/
|
||||
├── model/ # 3D 模型文件
|
||||
│ └── gujianzhu.glb
|
||||
├── lib/ # SDK 文件目录
|
||||
│ └── bim-engine-sdk.umd.js
|
||||
│ └── iflow-engine.umd.js
|
||||
├── package.json # 项目配置
|
||||
├── vite.config.js # Vite 配置
|
||||
└── README.md # 说明文档
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BIM Engine SDK Demo</title>
|
||||
<title>iFlow Engine Demo</title>
|
||||
<!-- 从本地 lib 目录加载 SDK 文件 -->
|
||||
<script src="./lib/bim-engine-sdk.umd.js"></script>
|
||||
<script src="./lib/iflow-engine.umd.js"></script>
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
@@ -195,8 +195,8 @@
|
||||
|
||||
// 初始化引擎
|
||||
window.onload = () => {
|
||||
if (window.LyzBimEngineSDK) {
|
||||
const Engine = window.LyzBimEngineSDK.BimEngine;
|
||||
if (window.IflowEngine) {
|
||||
const Engine = window.IflowEngine.BimEngine;
|
||||
try {
|
||||
engine = new Engine('app', { locale: 'zh-CN' });
|
||||
initEngine3D();
|
||||
|
||||
4808
demo/lib/iflow-engine.umd.js
Normal file
1
demo/lib/iflow-engine.umd.js.map
Normal file
@@ -7,8 +7,8 @@
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"copy-sdk": "mkdir -p lib && cp ../dist/bim-engine-sdk.umd.js lib/ && cp ../dist/bim-engine-sdk.umd.js.map lib/ 2>/dev/null || true",
|
||||
"copy-draco": "mkdir -p static/js/draco && cp ../src/engine_base/draco/*.js ../src/engine_base/draco/*.wasm static/js/draco/ 2>/dev/null || true",
|
||||
"copy-sdk": "mkdir -p lib && cp ../dist/iflow-engine.umd.js lib/ && cp ../dist/iflow-engine.umd.js.map lib/ 2>/dev/null || true",
|
||||
"copy-draco": "mkdir -p static/js/draco && cp ../node_modules/iflow-engine-base/dist/draco/*.js ../node_modules/iflow-engine-base/dist/draco/*.wasm static/js/draco/ 2>/dev/null || true",
|
||||
"copy-all": "npm run copy-sdk && npm run copy-draco"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BIM Engine Viewer</title>
|
||||
<title>iFlow Engine Viewer</title>
|
||||
<!-- 从本地 lib 目录加载 SDK 文件 -->
|
||||
<script src="./lib/bim-engine-sdk.umd.js"></script>
|
||||
<script src="./lib/iflow-engine.umd.js"></script>
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
@@ -148,12 +148,12 @@
|
||||
async function initializeViewer() {
|
||||
try {
|
||||
// 检查 SDK 是否加载
|
||||
if (!window.LyzBimEngineSDK) {
|
||||
if (!window.IflowEngine) {
|
||||
throw new Error('SDK not loaded');
|
||||
}
|
||||
|
||||
// 创建引擎实例
|
||||
const Engine = window.LyzBimEngineSDK.BimEngine;
|
||||
const Engine = window.IflowEngine.BimEngine;
|
||||
engine = new Engine('app', {
|
||||
locale: 'zh-CN'
|
||||
});
|
||||
|
||||
1
dist/bim-engine-sdk.es.js.map
vendored
4872
dist/bim-engine-sdk.umd.js
vendored
1
dist/bim-engine-sdk.umd.js.map
vendored
51
dist/index.d.ts
vendored
@@ -1328,6 +1328,44 @@ export declare interface ThemeConfig {
|
||||
scrollbarThumb: ColorToken;
|
||||
/** Scrollbar thumb on hover */
|
||||
scrollbarThumbHover: ColorToken;
|
||||
/** 浮动容器背景 (支持 rgba 实现毛玻璃效果) */
|
||||
floatingBg: ColorToken;
|
||||
/** 浮动容器边框 */
|
||||
floatingBorder: ColorToken;
|
||||
/** 浮动容器阴影 */
|
||||
floatingShadow: ShadowToken;
|
||||
/** 浮动按钮背景 */
|
||||
floatingBtnBg: ColorToken;
|
||||
/** 浮动按钮边框 */
|
||||
floatingBtnBorder: ColorToken;
|
||||
/** 浮动按钮阴影 */
|
||||
floatingBtnShadow: ShadowToken;
|
||||
/** 浮动按钮悬停背景 */
|
||||
floatingBtnBgHover: ColorToken;
|
||||
/** 浮动按钮悬停阴影 */
|
||||
floatingBtnShadowHover: ShadowToken;
|
||||
/** 浮动组件图标颜色 */
|
||||
floatingIconColor: ColorToken;
|
||||
/** 浮动组件图标悬停颜色 */
|
||||
floatingIconColorHover: ColorToken;
|
||||
/** 面板背景 (支持毛玻璃) */
|
||||
panelBg: ColorToken;
|
||||
/** 面板边框 */
|
||||
panelBorder: ColorToken;
|
||||
/** 面板 Header 背景 */
|
||||
panelHeaderBg: ColorToken;
|
||||
/** 面板圆角 */
|
||||
panelRadius: string;
|
||||
/** Tab 容器背景 */
|
||||
tabBg: ColorToken;
|
||||
/** Tab 项背景 */
|
||||
tabItemBg: ColorToken;
|
||||
/** Tab 项悬停背景 */
|
||||
tabItemBgHover: ColorToken;
|
||||
/** Tab 激活项背景 */
|
||||
tabItemBgActive: ColorToken;
|
||||
/** Tab 激活项文字颜色 */
|
||||
tabItemTextActive: ColorToken;
|
||||
/**
|
||||
* Component-specific overrides
|
||||
* Only define these when absolutely necessary
|
||||
@@ -1351,19 +1389,6 @@ export declare interface ThemeConfig {
|
||||
bgFocus?: ColorToken;
|
||||
placeholder?: ColorToken;
|
||||
};
|
||||
/** Glass-pill button group specific colors */
|
||||
glassPill?: {
|
||||
sectionBg?: ColorToken;
|
||||
sectionBorder?: ColorToken;
|
||||
sectionShadow?: ShadowToken;
|
||||
btnBg?: ColorToken;
|
||||
btnBorder?: ColorToken;
|
||||
btnShadow?: ShadowToken;
|
||||
btnBgHover?: ColorToken;
|
||||
btnShadowHover?: ShadowToken;
|
||||
iconColor?: ColorToken;
|
||||
iconColorHover?: ColorToken;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# BIM Engine SDK 使用文档
|
||||
# iFlow Engine 使用文档
|
||||
|
||||
BIM Engine SDK 是一个用于 3D BIM 模型展示的 JavaScript SDK,支持原生 HTML、Vue 2/3 和 React 框架。
|
||||
iFlow Engine 是一个用于 3D BIM 模型展示的 JavaScript SDK,支持原生 HTML、Vue 2/3 和 React 框架。
|
||||
|
||||
## 目录
|
||||
|
||||
@@ -19,19 +19,19 @@ BIM Engine SDK 是一个用于 3D BIM 模型展示的 JavaScript SDK,支持原
|
||||
### NPM 安装(推荐)
|
||||
|
||||
```bash
|
||||
npm install @fishdingding/bim-engine-sdk
|
||||
npm install iflow-engine
|
||||
```
|
||||
|
||||
### Yarn 安装
|
||||
|
||||
```bash
|
||||
yarn add @fishdingding/bim-engine-sdk
|
||||
yarn add iflow-engine
|
||||
```
|
||||
|
||||
### PNPM 安装
|
||||
|
||||
```bash
|
||||
pnpm add @fishdingding/bim-engine-sdk
|
||||
pnpm add iflow-engine
|
||||
```
|
||||
|
||||
### CDN / 本地文件引入
|
||||
@@ -39,7 +39,7 @@ pnpm add @fishdingding/bim-engine-sdk
|
||||
如果不使用包管理器,可以直接下载 JS 文件引入:
|
||||
|
||||
```html
|
||||
<script src="./lib/bim-engine-sdk.umd.js"></script>
|
||||
<script src="./lib/iflow-engine.umd.js"></script>
|
||||
```
|
||||
|
||||
---
|
||||
@@ -64,7 +64,7 @@ pnpm add @fishdingding/bim-engine-sdk
|
||||
<div id="app"></div>
|
||||
|
||||
<script type="module">
|
||||
import { BimEngine } from '@fishdingding/bim-engine-sdk';
|
||||
import { BimEngine } from 'iflow-engine';
|
||||
|
||||
// 1. 创建引擎实例
|
||||
const engine = new BimEngine('app', {
|
||||
@@ -101,7 +101,7 @@ pnpm add @fishdingding/bim-engine-sdk
|
||||
<meta charset="UTF-8">
|
||||
<title>BIM Engine Demo</title>
|
||||
<!-- 引入 UMD 版本 -->
|
||||
<script src="https://unpkg.com/@fishdingding/bim-engine-sdk/dist/bim-engine-sdk.umd.js"></script>
|
||||
<script src="https://unpkg.com/iflow-engine/dist/iflow-engine.umd.js"></script>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
html, body { width: 100%; height: 100%; overflow: hidden; }
|
||||
@@ -200,7 +200,7 @@ window.onload = init;
|
||||
### 1. 安装
|
||||
|
||||
```bash
|
||||
npm install @fishdingding/bim-engine-sdk
|
||||
npm install iflow-engine
|
||||
```
|
||||
|
||||
### 2. 组件封装
|
||||
@@ -213,7 +213,7 @@ npm install @fishdingding/bim-engine-sdk
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
||||
import { BimEngine } from '@fishdingding/bim-engine-sdk';
|
||||
import { BimEngine } from 'iflow-engine';
|
||||
|
||||
// Props
|
||||
const props = defineProps({
|
||||
@@ -352,7 +352,7 @@ const stopMeasure = () => viewerRef.value?.deactivateMeasure();
|
||||
### 1. 安装
|
||||
|
||||
```bash
|
||||
npm install @fishdingding/bim-engine-sdk
|
||||
npm install iflow-engine
|
||||
```
|
||||
|
||||
### 2. 组件封装
|
||||
@@ -364,7 +364,7 @@ npm install @fishdingding/bim-engine-sdk
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { BimEngine } from '@fishdingding/bim-engine-sdk';
|
||||
import { BimEngine } from 'iflow-engine';
|
||||
|
||||
export default {
|
||||
name: 'BimViewer',
|
||||
@@ -500,7 +500,7 @@ export default {
|
||||
### 1. 安装
|
||||
|
||||
```bash
|
||||
npm install @fishdingding/bim-engine-sdk
|
||||
npm install iflow-engine
|
||||
```
|
||||
|
||||
### 2. Hook 封装
|
||||
@@ -508,7 +508,7 @@ npm install @fishdingding/bim-engine-sdk
|
||||
```jsx
|
||||
// hooks/useBimEngine.js
|
||||
import { useEffect, useRef, useState, useCallback } from 'react';
|
||||
import { BimEngine } from '@fishdingding/bim-engine-sdk';
|
||||
import { BimEngine } from 'iflow-engine';
|
||||
|
||||
export function useBimEngine(options = {}) {
|
||||
const containerRef = useRef(null);
|
||||
@@ -697,7 +697,7 @@ export default App;
|
||||
#### 构造函数
|
||||
|
||||
```javascript
|
||||
import { BimEngine } from '@fishdingding/bim-engine-sdk';
|
||||
import { BimEngine } from 'iflow-engine';
|
||||
|
||||
new BimEngine(container, options)
|
||||
```
|
||||
@@ -818,5 +818,5 @@ engine.on('modelLoaded', (data) => {
|
||||
|
||||
## 技术支持
|
||||
|
||||
- NPM 包地址:https://www.npmjs.com/package/@fishdingding/bim-engine-sdk
|
||||
- NPM 包地址:https://www.npmjs.com/package/iflow-engine
|
||||
- 如有问题,请联系技术支持
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
- 采用延迟初始化模式,需要用户主动调用 `init()` 方法
|
||||
|
||||
### 1.3 第三方 SDK 依赖
|
||||
- 依赖 `src/bim-engine-sdk.es.js` 中的 `createEngine` 函数
|
||||
- 依赖 `iflow-engine-base` npm 包中的 `createEngine` 函数
|
||||
- 通过依赖注入方式使用,不直接导入
|
||||
|
||||
---
|
||||
@@ -396,7 +396,7 @@ public setTheme(theme: ThemeConfig): void {
|
||||
### 9.1 基本使用(通过 EngineManager)
|
||||
|
||||
```typescript
|
||||
import { BimEngine } from 'bim-engine-sdk';
|
||||
import { BimEngine } from 'iflow-engine';
|
||||
|
||||
const engine = new BimEngine('container');
|
||||
|
||||
@@ -539,9 +539,9 @@ function updateEngineBackground(engine: any, color: number): void {
|
||||
- 不抛出未捕获的异常
|
||||
|
||||
7. **第三方 SDK 依赖**:
|
||||
- 依赖 `bim-engine-sdk.es.js` 文件
|
||||
- 通过动态导入或全局变量访问
|
||||
- 需要确保 SDK 文件已加载
|
||||
- 依赖 `iflow-engine-base` npm 包
|
||||
- 通过 npm 包导入
|
||||
- 需要确保依赖已安装
|
||||
|
||||
---
|
||||
|
||||
@@ -579,7 +579,7 @@ interface ModelLoadOptions {
|
||||
- `src/components/engine/index.ts` - 主组件类
|
||||
- `src/components/engine/types.ts` - 类型定义
|
||||
- `src/managers/engine-manager.ts` - 管理器类
|
||||
- `src/bim-engine-sdk.es.js` - 第三方 SDK(依赖)
|
||||
- `iflow-engine-base` - 第三方 SDK(npm 依赖)
|
||||
|
||||
### 12.2 依赖文件
|
||||
|
||||
|
||||
@@ -640,7 +640,7 @@ public setTheme(theme: ThemeConfig) {
|
||||
### 9.1 基本使用(通过 Manager)
|
||||
|
||||
```typescript
|
||||
import { BimEngine } from 'bim-engine-sdk';
|
||||
import { BimEngine } from 'iflow-engine';
|
||||
|
||||
const engine = new BimEngine('container');
|
||||
|
||||
|
||||
@@ -921,7 +921,7 @@ label.textContent = t(button.label);
|
||||
### 9.1 基本使用(通过 ButtonGroupManager)
|
||||
|
||||
```typescript
|
||||
import { BimEngine } from 'bim-engine-sdk';
|
||||
import { BimEngine } from 'iflow-engine';
|
||||
|
||||
const engine = new BimEngine('container');
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ new BimDescription({
|
||||
**组件内部不进行翻译**。调用者应在传入 `label` 之前使用 `t()` 函数进行翻译。
|
||||
|
||||
```typescript
|
||||
import { t } from 'bim-engine-sdk/services/locale';
|
||||
import { t } from 'iflow-engine/services/locale';
|
||||
|
||||
new BimDescription({
|
||||
// ...
|
||||
|
||||
473
package-lock.json
generated
@@ -1,14 +1,15 @@
|
||||
{
|
||||
"name": "bim-engine-sdk",
|
||||
"version": "1.0.0",
|
||||
"name": "@fishdingding/bim-engine-sdk",
|
||||
"version": "1.0.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "bim-engine-sdk",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"name": "@fishdingding/bim-engine-sdk",
|
||||
"version": "1.0.3",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"iflow-engine-base": "^1.0.1",
|
||||
"three": "^0.182.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -69,6 +70,12 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dimforge/rapier3d-compat": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz",
|
||||
"integrity": "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
|
||||
@@ -1045,6 +1052,12 @@
|
||||
"string-argv": "~0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@tweenjs/tween.js": {
|
||||
"version": "23.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz",
|
||||
"integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/argparse": {
|
||||
"version": "1.0.38",
|
||||
"resolved": "https://registry.npmmirror.com/@types/argparse/-/argparse-1.0.38.tgz",
|
||||
@@ -1069,6 +1082,33 @@
|
||||
"undici-types": "~7.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/stats.js": {
|
||||
"version": "0.17.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.4.tgz",
|
||||
"integrity": "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/three": {
|
||||
"version": "0.181.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/three/-/three-0.181.0.tgz",
|
||||
"integrity": "sha512-MLF1ks8yRM2k71D7RprFpDb9DOX0p22DbdPqT/uAkc6AtQXjxWCVDjCy23G9t1o8HcQPk7woD2NIyiaWcWPYmA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@dimforge/rapier3d-compat": "~0.12.0",
|
||||
"@tweenjs/tween.js": "~23.1.3",
|
||||
"@types/stats.js": "*",
|
||||
"@types/webxr": "*",
|
||||
"@webgpu/types": "*",
|
||||
"fflate": "~0.8.2",
|
||||
"meshoptimizer": "~0.22.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/webxr": {
|
||||
"version": "0.5.24",
|
||||
"resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.24.tgz",
|
||||
"integrity": "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@volar/language-core": {
|
||||
"version": "2.4.26",
|
||||
"resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.26.tgz",
|
||||
@@ -1182,6 +1222,12 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@webgpu/types": {
|
||||
"version": "0.1.69",
|
||||
"resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.69.tgz",
|
||||
"integrity": "sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.15.0",
|
||||
"resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.15.0.tgz",
|
||||
@@ -1262,6 +1308,23 @@
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
|
||||
"integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.4",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
@@ -1279,6 +1342,31 @@
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind-apply-helpers": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/compare-versions": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/compare-versions/-/compare-versions-6.1.1.tgz",
|
||||
@@ -1293,6 +1381,12 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/core-util-is": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/de-indent": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz",
|
||||
@@ -1318,6 +1412,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/diff/-/diff-8.0.2.tgz",
|
||||
@@ -1328,6 +1431,20 @@
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz",
|
||||
@@ -1341,6 +1458,51 @@
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-errors": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-object-atoms": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-set-tostringtag": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"get-intrinsic": "^1.2.6",
|
||||
"has-tostringtag": "^1.0.2",
|
||||
"hasown": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.12.tgz",
|
||||
@@ -1422,6 +1584,48 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/fflate": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
|
||||
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.11",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
||||
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
|
||||
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-extra": {
|
||||
"version": "11.3.2",
|
||||
"resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.2.tgz",
|
||||
@@ -1456,12 +1660,60 @@
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"es-define-property": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"es-object-atoms": "^1.1.1",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-proto": "^1.0.1",
|
||||
"gopd": "^1.2.0",
|
||||
"has-symbols": "^1.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"math-intrinsics": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dunder-proto": "^1.0.1",
|
||||
"es-object-atoms": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/gopd": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
@@ -1479,11 +1731,37 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/has-symbols": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-tostringtag": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-symbols": "^1.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
|
||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
@@ -1502,6 +1780,32 @@
|
||||
"he": "bin/he"
|
||||
}
|
||||
},
|
||||
"node_modules/iflow-engine-base": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/iflow-engine-base/-/iflow-engine-base-1.0.1.tgz",
|
||||
"integrity": "sha512-jrFn1bvisBA6jCn0+9gx9ZAkd1UHUoXo6bVkMsaM5tXIdABog/XYkJNADhdSrWzdB0u58M5ySZq3nqIpGq9LLQ==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@types/three": "^0.181.0",
|
||||
"axios": "^1.13.2",
|
||||
"jszip": "^3.10.1",
|
||||
"stats.js": "^0.17.0",
|
||||
"three": "^0.181.2",
|
||||
"three-bvh-csg": "^0.0.17"
|
||||
}
|
||||
},
|
||||
"node_modules/iflow-engine-base/node_modules/three": {
|
||||
"version": "0.181.2",
|
||||
"resolved": "https://registry.npmjs.org/three/-/three-0.181.2.tgz",
|
||||
"integrity": "sha512-k/CjiZ80bYss6Qs7/ex1TBlPD11whT9oKfT8oTGiHa34W4JRd1NiH/Tr1DbHWQ2/vMUypxksLnF2CfmlmM5XFQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/immediate": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/import-lazy": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/import-lazy/-/import-lazy-4.0.0.tgz",
|
||||
@@ -1512,6 +1816,12 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/is-core-module": {
|
||||
"version": "2.16.1",
|
||||
"resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.16.1.tgz",
|
||||
@@ -1528,6 +1838,12 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/jju": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/jju/-/jju-1.4.0.tgz",
|
||||
@@ -1555,6 +1871,18 @@
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/jszip": {
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
|
||||
"integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
|
||||
"license": "(MIT OR GPL-3.0-or-later)",
|
||||
"dependencies": {
|
||||
"lie": "~3.3.0",
|
||||
"pako": "~1.0.2",
|
||||
"readable-stream": "~2.3.6",
|
||||
"setimmediate": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/kolorist": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmmirror.com/kolorist/-/kolorist-1.8.0.tgz",
|
||||
@@ -1562,6 +1890,15 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lie": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
|
||||
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"immediate": "~3.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/local-pkg": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-1.1.2.tgz",
|
||||
@@ -1610,6 +1947,42 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||
}
|
||||
},
|
||||
"node_modules/math-intrinsics": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/meshoptimizer": {
|
||||
"version": "0.22.0",
|
||||
"resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.22.0.tgz",
|
||||
"integrity": "sha512-IebiK79sqIy+E4EgOr+CAw+Ke8hAspXKzBd0JdgEmPHiAwmvEj2S4h1rfvo+o/BnfEYd/jAOg5IeeIjzlzSnDg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "10.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-10.0.3.tgz",
|
||||
@@ -1691,6 +2064,12 @@
|
||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/pako": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
||||
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
|
||||
"license": "(MIT AND Zlib)"
|
||||
},
|
||||
"node_modules/path-browserify": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz",
|
||||
@@ -1773,6 +2152,18 @@
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz",
|
||||
@@ -1800,6 +2191,21 @@
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
||||
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/require-from-string": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz",
|
||||
@@ -1873,6 +2279,12 @@
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmmirror.com/semver/-/semver-7.5.4.tgz",
|
||||
@@ -1889,6 +2301,12 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/setimmediate": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
|
||||
@@ -1916,6 +2334,21 @@
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/stats.js": {
|
||||
"version": "0.17.0",
|
||||
"resolved": "https://registry.npmjs.org/stats.js/-/stats.js-0.17.0.tgz",
|
||||
"integrity": "sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string-argv": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.2.tgz",
|
||||
@@ -1974,6 +2407,26 @@
|
||||
"integrity": "sha512-GbHabT+Irv+ihI1/f5kIIsZ+Ef9Sl5A1Y7imvS5RQjWgtTPfPnZ43JmlYI7NtCRDK9zir20lQpfg8/9Yd02OvQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/three-bvh-csg": {
|
||||
"version": "0.0.17",
|
||||
"resolved": "https://registry.npmjs.org/three-bvh-csg/-/three-bvh-csg-0.0.17.tgz",
|
||||
"integrity": "sha512-iEkHDF8GRfGM6593Cuw8SnF1vfENCp46gIAtRzuL4nGXGWPcR1sbTBwM9ptDONb5twqlZp5WkAKya5aBKe2qcA==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"three": ">=0.151.0",
|
||||
"three-mesh-bvh": ">=0.6.6"
|
||||
}
|
||||
},
|
||||
"node_modules/three-mesh-bvh": {
|
||||
"version": "0.9.7",
|
||||
"resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.9.7.tgz",
|
||||
"integrity": "sha512-EYSJbykeAjhVxwZjuUYq/kelIbqBoV9sbAgvZ+j1xCgZyNYSkr51WDJWS4WIfK2OX6YcjBGoTicX4RoOVQzx0g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"three": ">= 0.159.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tinyglobby": {
|
||||
"version": "0.2.15",
|
||||
"resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||
@@ -2039,6 +2492,12 @@
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "7.2.6",
|
||||
"resolved": "https://registry.npmmirror.com/vite/-/vite-7.2.6.tgz",
|
||||
|
||||
21
package.json
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@fishdingding/bim-engine-sdk",
|
||||
"version": "1.0.3",
|
||||
"description": "BIM Engine SDK for Vue2, Vue3, React and HTML",
|
||||
"main": "./dist/bim-engine-sdk.umd.js",
|
||||
"module": "./dist/bim-engine-sdk.es.js",
|
||||
"name": "iflow-engine",
|
||||
"version": "1.0.0",
|
||||
"description": "iFlow Engine SDK for Vue2, Vue3, React and HTML",
|
||||
"main": "./dist/iflow-engine.umd.js",
|
||||
"module": "./dist/iflow-engine.es.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/bim-engine-sdk.es.js",
|
||||
"require": "./dist/bim-engine-sdk.umd.js"
|
||||
"import": "./dist/iflow-engine.es.js",
|
||||
"require": "./dist/iflow-engine.umd.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
@@ -18,10 +18,10 @@
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"copy:demo": "mkdir -p demo/lib && cp dist/bim-engine-sdk.es.js dist/bim-engine-sdk.umd.js dist/bim-engine-sdk.umd.js.map demo/lib/",
|
||||
"copy:demo-draco": "mkdir -p demo/static/js/draco && cp src/engine_base/draco/*.js src/engine_base/draco/*.wasm demo/static/js/draco/",
|
||||
"copy:demo": "mkdir -p demo/lib && cp dist/iflow-engine.es.js dist/iflow-engine.umd.js dist/iflow-engine.umd.js.map demo/lib/",
|
||||
"copy:demo-draco": "mkdir -p demo/static/js/draco && cp node_modules/iflow-engine-base/dist/draco/*.js node_modules/iflow-engine-base/dist/draco/*.wasm demo/static/js/draco/",
|
||||
"copy:demo-all": "npm run copy:demo && npm run copy:demo-draco",
|
||||
"copy:demo-vue": "mkdir -p demo-vue/public/lib && cp dist/bim-engine-sdk.es.js dist/bim-engine-sdk.umd.js dist/bim-engine-sdk.umd.js.map demo-vue/public/lib/",
|
||||
"copy:demo-vue": "mkdir -p demo-vue/public/lib && cp dist/iflow-engine.es.js dist/iflow-engine.umd.js dist/iflow-engine.umd.js.map demo-vue/public/lib/",
|
||||
"dev:demo": "npm run build && npm run copy:demo-all && cd demo && npm run dev",
|
||||
"dev:demo-vue": "npm run build && npm run copy:demo-vue && cd demo-vue && npm run dev",
|
||||
"dev:all": "npm run dev:demo & npm run dev:demo-vue",
|
||||
@@ -59,6 +59,7 @@
|
||||
"vite-plugin-dts": "^4.5.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"iflow-engine-base": "^1.0.1",
|
||||
"three": "^0.182.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/* Root Container */
|
||||
.bim-collapse {
|
||||
background-color: var(--bim-bg-color, #ffffff);
|
||||
border: 1px solid var(--bim-border-color, #d9d9d9);
|
||||
border-radius: 4px;
|
||||
background-color: var(--bim-bg-elevated);
|
||||
border: 1px solid var(--bim-border-default);
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
color: var(--bim-text-color, rgba(0, 0, 0, 0.88));
|
||||
color: var(--bim-text-primary);
|
||||
}
|
||||
|
||||
.bim-collapse.is-ghost {
|
||||
@@ -27,9 +26,8 @@
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
/* Item */
|
||||
.bim-collapse-item {
|
||||
border-bottom: 1px solid var(--bim-border-color, #d9d9d9);
|
||||
border-bottom: 1px solid var(--bim-border-subtle);
|
||||
}
|
||||
|
||||
.bim-collapse-item:last-child {
|
||||
@@ -37,23 +35,22 @@
|
||||
}
|
||||
|
||||
.bim-collapse-item.is-disabled .bim-collapse-header {
|
||||
color: var(--bim-disabled-color, rgba(0, 0, 0, 0.25));
|
||||
color: var(--bim-text-disabled);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.bim-collapse-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
background-color: var(--bim-header-bg-color, rgba(0, 0, 0, 0.02));
|
||||
background-color: var(--bim-component-bg);
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.bim-collapse-header:hover {
|
||||
background-color: var(--bim-header-hover-bg-color, rgba(0, 0, 0, 0.05));
|
||||
background-color: var(--bim-component-bg-hover);
|
||||
}
|
||||
|
||||
/* Arrow Icon */
|
||||
@@ -104,11 +101,10 @@
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
.bim-collapse-content {
|
||||
overflow: hidden;
|
||||
background-color: var(--bim-content-bg-color, #ffffff);
|
||||
border-top: 1px solid var(--bim-border-color, #d9d9d9);
|
||||
background-color: var(--bim-bg-elevated);
|
||||
border-top: 1px solid var(--bim-border-subtle);
|
||||
transition: height 0.2s ease-in-out, opacity 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
/* 默认字体大小和颜色 */
|
||||
font-size: var(--bim-desc-font-size, 14px);
|
||||
color: var(--bim-text-color, #333);
|
||||
/* 严格移除容器本身的 padding */
|
||||
font-size: 14px;
|
||||
color: var(--bim-text-primary);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@@ -23,31 +21,26 @@
|
||||
}
|
||||
|
||||
.bim-description.is-bordered .bim-description-item {
|
||||
border-bottom: 1px solid var(--bim-border-color, #eee);
|
||||
border-bottom: 1px solid var(--bim-border-subtle);
|
||||
}
|
||||
|
||||
/* 标签样式 */
|
||||
.bim-description-label {
|
||||
color: var(--bim-desc-label-color, var(--bim-label-color, #666));
|
||||
color: var(--bim-text-secondary);
|
||||
flex-shrink: 0;
|
||||
/* 默认 padding: 0 4px */
|
||||
padding: var(--bim-desc-label-padding, 4px 4px);
|
||||
display: flex;
|
||||
align-items: center; /* 垂直居中 */
|
||||
}
|
||||
|
||||
/* 边框模式下的标签样式 */
|
||||
.bim-description.is-bordered .bim-description-label {
|
||||
border-right: 1px solid var(--bim-border-color, #eee);
|
||||
}
|
||||
|
||||
/* 内容样式 */
|
||||
.bim-description-value {
|
||||
color: var(--bim-desc-value-color, var(--bim-value-color, #333));
|
||||
flex: 1;
|
||||
word-break: break-all;
|
||||
/* 默认 padding: 0 4px */
|
||||
padding: var(--bim-desc-value-padding, 4px 4px);
|
||||
padding: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bim-description.is-bordered .bim-description-label {
|
||||
border-right: 1px solid var(--bim-border-subtle);
|
||||
}
|
||||
|
||||
.bim-description-value {
|
||||
color: var(--bim-text-primary);
|
||||
flex: 1;
|
||||
word-break: break-all;
|
||||
padding: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
.bim-dialog {
|
||||
position: absolute;
|
||||
background-color: var(--bim-dialog-bg, var(--bim-bg-elevated));
|
||||
border: 1px solid var(--bim-dialog-border-color, var(--bim-border-default));
|
||||
border-radius: 6px;
|
||||
background-color: var(--bim-bg-elevated);
|
||||
border: 1px solid var(--bim-border-default);
|
||||
border-radius: var(--bim-panel-radius, 12px);
|
||||
box-shadow: var(--bim-shadow-lg);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -15,15 +15,15 @@
|
||||
}
|
||||
|
||||
.bim-dialog-header {
|
||||
height: 32px;
|
||||
background-color: var(--bim-dialog-header-bg, var(--bim-bg-inset));
|
||||
height: 40px;
|
||||
background-color: var(--bim-bg-inset);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 10px;
|
||||
padding: 0 12px;
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
border-bottom: 1px solid var(--bim-dialog-border-color, var(--bim-border-default));
|
||||
border-bottom: 1px solid var(--bim-border-default);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ import { IBimComponent } from '../../types/component';
|
||||
import { themeManager } from '../../services/theme';
|
||||
import type { EngineOptions, ModelLoadOptions } from './types';
|
||||
import type { MeasureMode } from '../../types/measure';
|
||||
// 导入第三方 SDK 的 createEngine 函数
|
||||
import { createEngine as createEngineSDK } from '../../engine_base/bim-engine-sdk.es.js';
|
||||
// 导入第三方 SDK 的 createEngine 函数(从 npm 包引入)
|
||||
import { createEngine as createEngineSDK } from 'iflow-engine-base';
|
||||
|
||||
// 重新导出类型,方便外部引用
|
||||
export type { EngineOptions, ModelLoadOptions };
|
||||
|
||||
@@ -11,15 +11,13 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
|
||||
/* 面板内部颜色尽量复用 Dialog 的变量,保证整体一致 */
|
||||
color: var(--bim-dialog-text-color, #ccc);
|
||||
color: var(--bim-text-secondary);
|
||||
}
|
||||
|
||||
.bim-measure-settings {
|
||||
display: none;
|
||||
box-sizing: border-box;
|
||||
color: var(--bim-dialog-text-color, #ccc);
|
||||
color: var(--bim-text-secondary);
|
||||
}
|
||||
|
||||
.bim-measure-settings-title {
|
||||
@@ -37,7 +35,7 @@
|
||||
}
|
||||
|
||||
.bim-measure-settings-row .label {
|
||||
color: var(--bim-measure-label-color, rgba(255, 255, 255, 0.70));
|
||||
color: var(--bim-text-secondary);
|
||||
font-size: 13px;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
@@ -46,10 +44,10 @@
|
||||
flex: 0 0 auto;
|
||||
width: 120px;
|
||||
height: 28px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--bim-measure-border, rgba(255, 255, 255, 0.12));
|
||||
background: rgba(0, 0, 0, 0.12);
|
||||
color: var(--bim-dialog-text-color, #ccc);
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--bim-border-default);
|
||||
background: var(--bim-bg-inset);
|
||||
color: var(--bim-text-primary);
|
||||
padding: 0 8px;
|
||||
box-sizing: border-box;
|
||||
outline: none;
|
||||
@@ -58,7 +56,7 @@
|
||||
.bim-measure-settings-hint {
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
color: var(--bim-measure-label-color, rgba(255, 255, 255, 0.70));
|
||||
color: var(--bim-text-tertiary);
|
||||
margin-top: -4px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
@@ -85,14 +83,14 @@
|
||||
|
||||
.bim-measure-settings-save {
|
||||
border: none;
|
||||
background: var(--bim-measure-primary, #0078d4);
|
||||
color: #fff;
|
||||
background: var(--bim-primary);
|
||||
color: var(--bim-text-inverse);
|
||||
}
|
||||
|
||||
.bim-measure-settings-cancel {
|
||||
border: 1px solid var(--bim-measure-border, rgba(255, 255, 255, 0.12));
|
||||
border: 1px solid var(--bim-border-default);
|
||||
background: transparent;
|
||||
color: var(--bim-dialog-text-color, #ccc);
|
||||
color: var(--bim-text-secondary);
|
||||
}
|
||||
|
||||
.bim-measure-settings-save:hover,
|
||||
@@ -105,9 +103,8 @@
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* 保存按钮 hover 用主题 hover 色(轻微反馈,不改变布局) */
|
||||
.bim-measure-settings-save:hover {
|
||||
background: var(--bim-measure-primary-hover, #0063b1);
|
||||
background: var(--bim-primary-hover);
|
||||
}
|
||||
|
||||
/* 顶部:测量方式按钮区 */
|
||||
@@ -127,24 +124,29 @@
|
||||
width: 100%;
|
||||
height: 42px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--bim-measure-border, rgba(255, 255, 255, 0.12));
|
||||
background: var(--bim-measure-btn-bg, rgba(255, 255, 255, 0.06));
|
||||
border: 1px solid var(--bim-border-default);
|
||||
background: var(--bim-bg-inset);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background-color 0.15s ease, border-color 0.15s ease;
|
||||
transition: all 0.2s ease;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.bim-measure-tool-btn:hover {
|
||||
background: var(--bim-measure-btn-hover-bg, rgba(255, 255, 255, 0.10));
|
||||
background: var(--bim-component-bg-hover);
|
||||
border-color: var(--bim-border-strong);
|
||||
}
|
||||
|
||||
.bim-measure-tool-btn.is-active {
|
||||
border-color: var(--bim-measure-active-border, rgba(255, 255, 255, 0.30));
|
||||
background: var(--bim-measure-btn-active-bg, rgba(255, 255, 255, 0.14));
|
||||
border-color: var(--bim-primary);
|
||||
background: var(--bim-primary-subtle);
|
||||
}
|
||||
|
||||
.bim-measure-tool-btn.is-active .bim-measure-tool-icon {
|
||||
color: var(--bim-primary);
|
||||
}
|
||||
|
||||
.bim-measure-tool-icon {
|
||||
@@ -153,7 +155,7 @@
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--bim-measure-icon-color, #ddd);
|
||||
color: var(--bim-icon-default);
|
||||
}
|
||||
|
||||
.bim-measure-tool-icon svg {
|
||||
@@ -170,16 +172,15 @@
|
||||
}
|
||||
|
||||
.bim-measure-toggle-btn {
|
||||
/* 你要求:更小,并带文字提示 */
|
||||
height: 22px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--bim-measure-border, rgba(255, 255, 255, 0.12));
|
||||
background: var(--bim-measure-btn-bg, rgba(255, 255, 255, 0.06));
|
||||
border: 1px solid var(--bim-border-default);
|
||||
background: var(--bim-bg-inset);
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background-color 0.15s ease;
|
||||
transition: all 0.2s ease;
|
||||
padding: 0 6px;
|
||||
gap: 4px;
|
||||
font-size: 12px;
|
||||
@@ -187,18 +188,19 @@
|
||||
}
|
||||
|
||||
.bim-measure-toggle-btn:hover {
|
||||
background: var(--bim-measure-btn-hover-bg, rgba(255, 255, 255, 0.10));
|
||||
background: var(--bim-component-bg-hover);
|
||||
border-color: var(--bim-border-strong);
|
||||
}
|
||||
|
||||
.bim-measure-toggle-text {
|
||||
color: var(--bim-measure-label-color, rgba(255, 255, 255, 0.70));
|
||||
color: var(--bim-text-secondary);
|
||||
}
|
||||
|
||||
.bim-measure-toggle-icon svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
fill: currentColor;
|
||||
color: var(--bim-measure-icon-color, #ddd);
|
||||
color: var(--bim-icon-default);
|
||||
transition: transform 0.15s ease;
|
||||
}
|
||||
|
||||
@@ -206,11 +208,10 @@
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
/* 中部:结果展示区 */
|
||||
.bim-measure-result {
|
||||
margin-top: 12px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid var(--bim-measure-divider, rgba(255, 255, 255, 0.10));
|
||||
border-top: 1px solid var(--bim-divider);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
@@ -225,12 +226,12 @@
|
||||
}
|
||||
|
||||
.bim-measure-row .label {
|
||||
color: var(--bim-measure-label-color, rgba(255, 255, 255, 0.70));
|
||||
color: var(--bim-text-secondary);
|
||||
min-width: 84px;
|
||||
}
|
||||
|
||||
.bim-measure-row .value {
|
||||
color: var(--bim-measure-value-color, rgba(255, 255, 255, 0.90));
|
||||
color: var(--bim-text-primary);
|
||||
flex: 1;
|
||||
word-break: break-word;
|
||||
}
|
||||
@@ -241,12 +242,11 @@
|
||||
}
|
||||
|
||||
.bim-measure-main-number.is-laser-text {
|
||||
/* 激光测距:不使用黄色,回到默认文字颜色 */
|
||||
color: var(--bim-measure-value-color, rgba(255, 255, 255, 0.90));
|
||||
color: var(--bim-text-primary);
|
||||
}
|
||||
|
||||
.bim-measure-main-unit {
|
||||
color: var(--bim-measure-value-color, rgba(255, 255, 255, 0.90));
|
||||
color: var(--bim-text-primary);
|
||||
}
|
||||
|
||||
.bim-measure-xyz {
|
||||
@@ -272,18 +272,37 @@
|
||||
color: #1677ff !important;
|
||||
}
|
||||
|
||||
/* 底部:操作区(删除全部 / 设置) */
|
||||
.bim-measure-footer {
|
||||
margin-top: 12px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid var(--bim-measure-divider, rgba(255, 255, 255, 0.10));
|
||||
border-top: 1px solid var(--bim-divider);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/* 你要求:底部不要“占满”交互区域,按钮按自身尺寸布局 */
|
||||
justify-content: flex-start;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.bim-measure-clear-btn {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: var(--bim-danger);
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
font-size: 13px;
|
||||
flex: 0 0 auto !important;
|
||||
width: auto;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.bim-measure-clear-btn:hover,
|
||||
.bim-measure-clear-btn:active,
|
||||
.bim-measure-clear-btn:focus {
|
||||
background: transparent;
|
||||
border: none;
|
||||
outline: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.bim-measure-clear-btn {
|
||||
background: transparent;
|
||||
border: none;
|
||||
@@ -339,7 +358,7 @@
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
fill: currentColor;
|
||||
color: var(--bim-measure-icon-color, #ddd);
|
||||
color: var(--bim-icon-default);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -146,24 +146,27 @@ export class MeasurePanel implements IBimComponent {
|
||||
* @param theme 主题配置
|
||||
*/
|
||||
public setTheme(theme: ThemeConfig): void {
|
||||
// 为了可读性:这里显式写出映射,不做过度抽象
|
||||
const style = this.element.style;
|
||||
|
||||
// 这些变量不会强制覆盖外部(Dialog)已有变量,只做兜底
|
||||
style.setProperty('--bim-measure-border', theme.borderDefault ?? 'rgba(255, 255, 255, 0.12)');
|
||||
style.setProperty('--bim-measure-divider', theme.borderDefault ?? 'rgba(255, 255, 255, 0.10)');
|
||||
style.setProperty('--bim-measure-icon-color', theme.iconDefault ?? '#ddd');
|
||||
style.setProperty('--bim-measure-label-color', theme.textSecondary ?? 'rgba(255, 255, 255, 0.70)');
|
||||
style.setProperty('--bim-measure-value-color', theme.textPrimary ?? 'rgba(255, 255, 255, 0.90)');
|
||||
style.setProperty('--bim-bg-inset', theme.bgInset ?? '#152232');
|
||||
style.setProperty('--bim-bg-elevated', theme.bgElevated ?? '#1f2d3e');
|
||||
style.setProperty('--bim-border-default', theme.borderDefault ?? '#334155');
|
||||
style.setProperty('--bim-border-strong', theme.borderStrong ?? '#475569');
|
||||
style.setProperty('--bim-divider', theme.divider ?? '#334155');
|
||||
|
||||
// “删除全部”颜色:截图中偏绿色,这里用 primary 做一个合理映射
|
||||
style.setProperty('--bim-measure-danger', theme.primary ?? '#46d369');
|
||||
// 设置面板“保存设置”按钮用主题色
|
||||
style.setProperty('--bim-measure-primary', theme.primary ?? '#0078d4');
|
||||
style.setProperty('--bim-measure-primary-hover', theme.primaryHover ?? '#0063b1');
|
||||
style.setProperty('--bim-measure-btn-bg', theme.componentBg ?? 'rgba(255, 255, 255, 0.06)');
|
||||
style.setProperty('--bim-measure-btn-hover-bg', theme.componentBgHover ?? 'rgba(255, 255, 255, 0.10)');
|
||||
style.setProperty('--bim-measure-btn-active-bg', theme.componentBgActive ?? 'rgba(255, 255, 255, 0.14)');
|
||||
style.setProperty('--bim-primary', theme.primary ?? '#3b82f6');
|
||||
style.setProperty('--bim-primary-hover', theme.primaryHover ?? '#60a5fa');
|
||||
style.setProperty('--bim-primary-subtle', theme.primarySubtle ?? 'rgba(59, 130, 246, 0.15)');
|
||||
style.setProperty('--bim-danger', theme.danger ?? '#ef4444');
|
||||
|
||||
style.setProperty('--bim-text-primary', theme.textPrimary ?? '#ffffff');
|
||||
style.setProperty('--bim-text-secondary', theme.textSecondary ?? '#94a3b8');
|
||||
style.setProperty('--bim-text-tertiary', theme.textTertiary ?? '#64748b');
|
||||
style.setProperty('--bim-text-inverse', theme.textInverse ?? '#152232');
|
||||
|
||||
style.setProperty('--bim-icon-default', theme.iconDefault ?? '#ffffff');
|
||||
|
||||
style.setProperty('--bim-component-bg-hover', theme.componentBgHover ?? 'rgba(248, 250, 252, 0.06)');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--bim-bg-elevated);
|
||||
border-radius: 4px;
|
||||
padding: 4px 0;
|
||||
border: 1px solid var(--bim-border-default);
|
||||
border-radius: 8px;
|
||||
padding: 6px;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
min-width: 160px;
|
||||
@@ -27,16 +28,18 @@
|
||||
.bim-menu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 6px 12px;
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
transition: all 0.2s ease;
|
||||
font-size: 13px;
|
||||
position: relative;
|
||||
color: var(--bim-text-primary);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.bim-menu-item:hover {
|
||||
background-color: var(--bim-component-bg-hover);
|
||||
background-color: var(--bim-floating-btn-bg);
|
||||
transform: translateX(2px);
|
||||
}
|
||||
|
||||
.bim-menu-item.disabled {
|
||||
|
||||
@@ -10,12 +10,11 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 第一行:隐藏、反向 */
|
||||
.section-axis-row-1 {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-bottom: 1px solid var(--bim-divider);
|
||||
}
|
||||
|
||||
/* 第二行:X、Y、Z */
|
||||
@@ -25,7 +24,6 @@
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
/* 按钮基础样式 */
|
||||
.section-axis-btn {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
@@ -34,35 +32,38 @@
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
padding: 8px;
|
||||
background: var(--bim-section-axis-btn-bg, rgba(255, 255, 255, 0.06));
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
background: var(--bim-bg-inset);
|
||||
border: 1px solid var(--bim-border-default);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
transition: all 0.2s ease;
|
||||
outline: none;
|
||||
color: var(--bim-text-color, rgba(255, 255, 255, 0.90));
|
||||
color: var(--bim-text-primary);
|
||||
min-height: 48px;
|
||||
}
|
||||
|
||||
.section-axis-btn:hover {
|
||||
background: var(--bim-section-axis-btn-hover, rgba(255, 255, 255, 0.10));
|
||||
background: var(--bim-component-bg-hover);
|
||||
border-color: var(--bim-border-strong);
|
||||
}
|
||||
|
||||
/* 激活状态 */
|
||||
.section-axis-btn.active {
|
||||
background: var(--bim-section-axis-btn-active, rgba(255, 255, 255, 0.14));
|
||||
border-color: var(--bim-text-active-color, #fff);
|
||||
color: var(--bim-text-active-color, #fff);
|
||||
background: var(--bim-primary-subtle);
|
||||
border-color: var(--bim-primary);
|
||||
color: var(--bim-primary);
|
||||
}
|
||||
|
||||
.section-axis-btn.active .section-axis-btn-icon {
|
||||
color: var(--bim-primary);
|
||||
}
|
||||
|
||||
/* 图标样式 */
|
||||
.section-axis-btn-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--bim-icon-color, #ccc);
|
||||
color: var(--bim-icon-default);
|
||||
}
|
||||
|
||||
.section-axis-btn-icon svg {
|
||||
|
||||
@@ -69,13 +69,15 @@ export class SectionAxisPanel implements IBimComponent {
|
||||
*/
|
||||
public setTheme(theme: ThemeConfig): void {
|
||||
const style = this.element.style;
|
||||
style.setProperty('--bim-section-axis-btn-bg', theme.componentBg ?? 'rgba(255, 255, 255, 0.06)');
|
||||
style.setProperty('--bim-section-axis-btn-hover', theme.componentBgHover ?? 'rgba(255, 255, 255, 0.10)');
|
||||
style.setProperty('--bim-section-axis-btn-active', theme.componentBgActive ?? 'rgba(255, 255, 255, 0.14)');
|
||||
style.setProperty('--bim-primary-color', theme.primary ?? '#1890ff');
|
||||
style.setProperty('--bim-icon-color', theme.iconDefault ?? '#ccc');
|
||||
style.setProperty('--bim-text-color', theme.textSecondary ?? 'rgba(255, 255, 255, 0.90)');
|
||||
style.setProperty('--bim-text-active-color', theme.textPrimary ?? '#fff');
|
||||
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-divider', theme.divider ?? '#334155');
|
||||
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)');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-bottom: 1px solid var(--bim-divider);
|
||||
}
|
||||
|
||||
.section-box-btn {
|
||||
@@ -21,29 +21,34 @@
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
padding: 6px;
|
||||
background: var(--bim-section-box-btn-bg);
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
background: var(--bim-bg-inset);
|
||||
border: 1px solid var(--bim-border-default);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
color: var(--bim-text-color);
|
||||
color: var(--bim-text-primary);
|
||||
min-height: 44px;
|
||||
transition: all 0.2s;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.section-box-btn:hover {
|
||||
background: var(--bim-section-box-btn-hover);
|
||||
background: var(--bim-component-bg-hover);
|
||||
border-color: var(--bim-border-strong);
|
||||
}
|
||||
|
||||
.section-box-btn.active {
|
||||
background: var(--bim-section-box-btn-active);
|
||||
border-color: var(--bim-text-active-color);
|
||||
color: var(--bim-text-active-color);
|
||||
background: var(--bim-primary-subtle);
|
||||
border-color: var(--bim-primary);
|
||||
color: var(--bim-primary);
|
||||
}
|
||||
|
||||
.section-box-btn.active .section-box-btn-icon {
|
||||
color: var(--bim-primary);
|
||||
}
|
||||
|
||||
.section-box-btn-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
color: var(--bim-icon-color);
|
||||
color: var(--bim-icon-default);
|
||||
}
|
||||
|
||||
.section-box-btn-icon svg {
|
||||
@@ -81,7 +86,7 @@
|
||||
.section-box-slider-label {
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
color: var(--bim-text-color);
|
||||
color: var(--bim-text-primary);
|
||||
min-width: 14px;
|
||||
}
|
||||
|
||||
@@ -89,8 +94,7 @@
|
||||
position: relative;
|
||||
flex: 1;
|
||||
height: 4px;
|
||||
/* 轨道变细 */
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
background: var(--bim-border-default);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
@@ -98,20 +102,18 @@
|
||||
position: absolute;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
background: var(--bim-primary-color);
|
||||
background: var(--bim-primary);
|
||||
border-radius: 2px;
|
||||
pointer-events: none;
|
||||
/* 防止遮挡手柄点击 */
|
||||
}
|
||||
|
||||
.section-box-slider-handle {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 14px;
|
||||
/* 手柄变小 */
|
||||
height: 14px;
|
||||
background: #fff;
|
||||
border: 2px solid var(--bim-primary-color);
|
||||
background: var(--bim-bg-elevated);
|
||||
border: 2px solid var(--bim-primary);
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
cursor: grab;
|
||||
@@ -122,12 +124,12 @@
|
||||
|
||||
.section-box-slider-handle:hover {
|
||||
transform: translate(-50%, -50%) scale(1.2);
|
||||
box-shadow: 0 0 0 4px rgba(24, 144, 255, 0.2);
|
||||
box-shadow: 0 0 0 4px var(--bim-primary-subtle);
|
||||
}
|
||||
|
||||
.section-box-slider-handle.dragging {
|
||||
cursor: grabbing;
|
||||
transform: translate(-50%, -50%) scale(1.2);
|
||||
background: var(--bim-primary-color);
|
||||
background: var(--bim-primary);
|
||||
}
|
||||
|
||||
|
||||
@@ -339,13 +339,16 @@ export class SectionBoxPanel implements IBimComponent {
|
||||
public setTheme(theme: ThemeConfig): void {
|
||||
if (!this.element) return;
|
||||
const style = this.element.style;
|
||||
style.setProperty('--bim-section-box-btn-bg', theme.componentBg ?? 'rgba(255, 255, 255, 0.06)');
|
||||
style.setProperty('--bim-section-box-btn-hover', theme.componentBgHover ?? 'rgba(255, 255, 255, 0.10)');
|
||||
style.setProperty('--bim-section-box-btn-active', theme.componentBgActive ?? 'rgba(255, 255, 255, 0.14)');
|
||||
style.setProperty('--bim-primary-color', theme.primary ?? '#1890ff');
|
||||
style.setProperty('--bim-icon-color', theme.iconDefault ?? '#ccc');
|
||||
style.setProperty('--bim-text-color', theme.textSecondary ?? 'rgba(255, 255, 255, 0.90)');
|
||||
style.setProperty('--bim-text-active-color', theme.textPrimary ?? '#fff');
|
||||
style.setProperty('--bim-bg-inset', theme.bgInset ?? '#152232');
|
||||
style.setProperty('--bim-bg-elevated', theme.bgElevated ?? '#1f2d3e');
|
||||
style.setProperty('--bim-border-default', theme.borderDefault ?? '#334155');
|
||||
style.setProperty('--bim-border-strong', theme.borderStrong ?? '#475569');
|
||||
style.setProperty('--bim-divider', theme.divider ?? '#334155');
|
||||
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 destroy(): void {
|
||||
|
||||
@@ -16,25 +16,35 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
padding: 8px;
|
||||
border: 1px solid transparent;
|
||||
background: var(--bim-section-btn-bg, rgba(255, 255, 255, 0.06));
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
border: 1px solid var(--bim-border-default);
|
||||
background: var(--bim-bg-inset);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
|
||||
transition: all 0.2s ease;
|
||||
min-width: 60px;
|
||||
outline: none;
|
||||
color: var(--bim-text-color, rgba(255, 255, 255, 0.90));
|
||||
color: var(--bim-text-primary);
|
||||
}
|
||||
|
||||
.section-plane-btn:hover {
|
||||
background: var(--bim-section-btn-hover, rgba(255, 255, 255, 0.10));
|
||||
background: var(--bim-component-bg-hover);
|
||||
border-color: var(--bim-border-strong);
|
||||
}
|
||||
|
||||
.section-plane-btn:active {
|
||||
background: var(--bim-section-btn-active, rgba(255, 255, 255, 0.14));
|
||||
border-color: var(--bim-text-active-color, #fff);
|
||||
color: var(--bim-text-active-color, #fff);
|
||||
background: var(--bim-primary-subtle);
|
||||
border-color: var(--bim-primary);
|
||||
}
|
||||
|
||||
.section-plane-btn.is-active {
|
||||
background: var(--bim-primary-subtle);
|
||||
border-color: var(--bim-primary);
|
||||
color: var(--bim-primary);
|
||||
}
|
||||
|
||||
.section-plane-btn.is-active .section-plane-btn-icon {
|
||||
color: var(--bim-primary);
|
||||
}
|
||||
|
||||
.section-plane-btn-icon {
|
||||
@@ -43,7 +53,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--bim-icon-color, #ccc);
|
||||
color: var(--bim-icon-default);
|
||||
}
|
||||
|
||||
.section-plane-btn-icon svg {
|
||||
|
||||
@@ -55,13 +55,14 @@ export class SectionPlanePanel implements IBimComponent {
|
||||
*/
|
||||
public setTheme(theme: ThemeConfig): void {
|
||||
const style = this.element.style;
|
||||
style.setProperty('--bim-section-btn-bg', theme.componentBg ?? 'rgba(255, 255, 255, 0.06)');
|
||||
style.setProperty('--bim-section-btn-hover', theme.componentBgHover ?? 'rgba(255, 255, 255, 0.10)');
|
||||
style.setProperty('--bim-section-btn-active', theme.componentBgActive ?? 'rgba(255, 255, 255, 0.14)');
|
||||
style.setProperty('--bim-primary-color', theme.primary ?? '#1890ff');
|
||||
style.setProperty('--bim-icon-color', theme.iconDefault ?? '#ccc');
|
||||
style.setProperty('--bim-text-color', theme.textSecondary ?? 'rgba(255, 255, 255, 0.90)');
|
||||
style.setProperty('--bim-text-active-color', theme.textPrimary ?? '#fff');
|
||||
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)');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,14 +4,18 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: transparent;
|
||||
color: var(--bim-tab-text, #e6e6e6);
|
||||
color: var(--bim-text-secondary);
|
||||
}
|
||||
|
||||
.bim-tab__nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
background: transparent;
|
||||
gap: 4px;
|
||||
padding: 4px;
|
||||
margin: 8px 12px;
|
||||
background: var(--bim-bg-inset);
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--bim-border-subtle);
|
||||
}
|
||||
|
||||
.bim-tab__item {
|
||||
@@ -20,28 +24,26 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
/* 恢复原样式:上下4px,左右0 */
|
||||
padding: 4px 0;
|
||||
padding: 8px 12px;
|
||||
border: none;
|
||||
border-radius: 0; /* 恢复直角 */
|
||||
border-radius: 6px;
|
||||
background: transparent;
|
||||
color: var(--bim-tab-text, #e6e6e6);
|
||||
color: var(--bim-text-secondary);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
font-size: 14px;
|
||||
border-bottom: 4px solid transparent;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.bim-tab__item:hover {
|
||||
color: var(--bim-tab-text, #e6e6e6);
|
||||
background-color: var(--bim-tab-hover-bg, rgba(255, 255, 255, 0.05));
|
||||
border-bottom-color: var(--bim-tab-hover-bg, rgba(255, 255, 255, 0.15));
|
||||
color: var(--bim-text-primary);
|
||||
background-color: var(--bim-component-bg-hover);
|
||||
}
|
||||
|
||||
/* Active 状态 */
|
||||
.bim-tab__item.is-active {
|
||||
color: var(--bim-tab-text-active, #4da3ff);
|
||||
border-bottom-color: var(--bim-tab-text-active, #4da3ff);
|
||||
color: var(--bim-primary);
|
||||
background-color: var(--bim-bg-elevated);
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.bim-tab__item.is-disabled {
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/* 漫游控制面板 */
|
||||
.walk-control-panel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
padding: 8px 16px;
|
||||
background: var(--bim-walk-control-bg, rgba(0, 0, 0, 0.8));
|
||||
border-radius: 8px;
|
||||
padding: 12px 20px;
|
||||
background-color: var(--bim-bg-base, #152232);
|
||||
border: 1px solid var(--bim-border-strong, #475569);
|
||||
border-radius: 12px;
|
||||
box-shadow: var(--bim-shadow-xl, 0 20px 40px rgba(0, 0, 0, 0.3));
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* 分割线 */
|
||||
.walk-divider {
|
||||
width: 1px;
|
||||
height: 40px;
|
||||
background: var(--bim-divider-color, rgba(255, 255, 255, 0.2));
|
||||
background: var(--bim-divider);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@@ -29,21 +29,28 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: transparent;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 6px;
|
||||
background: var(--bim-bg-inset);
|
||||
border: 1px solid var(--bim-border-default);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
color: var(--bim-icon-color, #ccc);
|
||||
transition: all 0.2s ease;
|
||||
color: var(--bim-icon-default);
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.walk-icon-btn:hover {
|
||||
background: var(--bim-walk-btn-hover, rgba(255, 255, 255, 0.15));
|
||||
background: var(--bim-component-bg-hover);
|
||||
border-color: var(--bim-border-strong);
|
||||
}
|
||||
|
||||
.walk-icon-btn.active {
|
||||
background: var(--bim-walk-btn-active, rgba(255, 255, 255, 0.3));
|
||||
background: var(--bim-primary-subtle);
|
||||
border-color: var(--bim-primary);
|
||||
color: var(--bim-primary);
|
||||
}
|
||||
|
||||
.walk-icon-btn.active svg {
|
||||
fill: var(--bim-primary);
|
||||
}
|
||||
|
||||
.walk-icon-btn svg {
|
||||
@@ -67,7 +74,7 @@
|
||||
}
|
||||
|
||||
.walk-speed-label {
|
||||
color: var(--bim-text-color, #fff);
|
||||
color: var(--bim-text-primary);
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -76,25 +83,27 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background: var(--bim-speed-group-bg, rgba(255, 255, 255, 0.1));
|
||||
border-radius: 4px;
|
||||
background: var(--bim-bg-inset);
|
||||
border: 1px solid var(--bim-border-subtle);
|
||||
border-radius: 6px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.walk-speed-btn {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: var(--bim-speed-btn-bg, rgba(255, 255, 255, 0.1));
|
||||
border: none;
|
||||
background: var(--bim-bg-elevated);
|
||||
border: 1px solid var(--bim-border-subtle);
|
||||
border-radius: 4px;
|
||||
color: var(--bim-text-color, #fff);
|
||||
color: var(--bim-text-primary);
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.walk-speed-btn:hover {
|
||||
background: var(--bim-speed-btn-hover, rgba(255, 255, 255, 0.2));
|
||||
background: var(--bim-component-bg-hover);
|
||||
border-color: var(--bim-border-strong);
|
||||
}
|
||||
|
||||
.walk-speed-btn:disabled {
|
||||
@@ -105,7 +114,7 @@
|
||||
.walk-speed-display {
|
||||
min-width: 40px;
|
||||
text-align: center;
|
||||
color: var(--bim-text-color, #fff);
|
||||
color: var(--bim-text-primary);
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -130,7 +139,7 @@
|
||||
}
|
||||
|
||||
.walk-checkbox-label {
|
||||
color: var(--bim-text-color, #fff);
|
||||
color: var(--bim-text-primary);
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -147,41 +156,41 @@
|
||||
}
|
||||
|
||||
.walk-select-label {
|
||||
color: var(--bim-text-color, #fff);
|
||||
color: var(--bim-text-primary);
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.walk-select {
|
||||
padding: 6px 12px;
|
||||
background: var(--bim-select-bg, rgba(255, 255, 255, 0.1));
|
||||
border: 1px solid var(--bim-select-border, rgba(255, 255, 255, 0.2));
|
||||
border-radius: 4px;
|
||||
color: var(--bim-text-color, #fff);
|
||||
background: var(--bim-bg-inset);
|
||||
border: 1px solid var(--bim-border-default);
|
||||
border-radius: 6px;
|
||||
color: var(--bim-text-primary);
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.walk-select option {
|
||||
background: var(--bim-select-option-bg, #333);
|
||||
color: var(--bim-text-color, #fff);
|
||||
background: var(--bim-bg-elevated);
|
||||
color: var(--bim-text-primary);
|
||||
}
|
||||
|
||||
/* 退出按钮 */
|
||||
.walk-exit-btn {
|
||||
padding: 10px 24px;
|
||||
background: var(--bim-primary-color, #1890ff);
|
||||
background: var(--bim-primary);
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
color: #fff;
|
||||
border-radius: 8px;
|
||||
color: var(--bim-text-inverse);
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
transition: all 0.2s ease;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.walk-exit-btn:hover {
|
||||
background: var(--bim-primary-hover, #40a9ff);
|
||||
background: var(--bim-primary-hover);
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
@@ -434,20 +434,27 @@ export class WalkControlPanel implements IBimComponent {
|
||||
public setTheme(theme: ThemeConfig): void {
|
||||
if (!this.element) return;
|
||||
const style = this.element.style;
|
||||
style.setProperty('--bim-walk-control-bg', theme.bgElevated ?? 'rgba(0, 0, 0, 0.8)');
|
||||
style.setProperty('--bim-walk-btn-hover', theme.componentBgHover ?? 'rgba(255, 255, 255, 0.15)');
|
||||
style.setProperty('--bim-walk-btn-active', theme.componentBgActive ?? 'rgba(255, 255, 255, 0.3)');
|
||||
style.setProperty('--bim-primary-color', theme.primary ?? '#1890ff');
|
||||
style.setProperty('--bim-primary-hover', theme.primaryHover ?? '#40a9ff');
|
||||
style.setProperty('--bim-icon-color', theme.iconDefault ?? '#ccc');
|
||||
style.setProperty('--bim-text-color', theme.textPrimary ?? '#fff');
|
||||
style.setProperty('--bim-divider-color', theme.borderDefault ?? 'rgba(255, 255, 255, 0.2)');
|
||||
style.setProperty('--bim-speed-group-bg', theme.componentBgHover ?? 'rgba(255, 255, 255, 0.1)');
|
||||
style.setProperty('--bim-speed-btn-bg', theme.componentBgHover ?? 'rgba(255, 255, 255, 0.1)');
|
||||
style.setProperty('--bim-speed-btn-hover', theme.componentBgActive ?? 'rgba(255, 255, 255, 0.2)');
|
||||
style.setProperty('--bim-select-bg', theme.componentBgHover ?? 'rgba(255, 255, 255, 0.1)');
|
||||
style.setProperty('--bim-select-border', theme.borderDefault ?? 'rgba(255, 255, 255, 0.2)');
|
||||
style.setProperty('--bim-select-option-bg', theme.bgElevated ?? '#333');
|
||||
|
||||
style.setProperty('--bim-bg-base', theme.bgBase ?? '#152232');
|
||||
style.setProperty('--bim-bg-elevated', theme.bgElevated ?? '#1f2d3e');
|
||||
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-border-subtle', theme.borderSubtle ?? '#1e293b');
|
||||
style.setProperty('--bim-divider', theme.divider ?? '#334155');
|
||||
style.setProperty('--bim-shadow-xl', theme.shadowXl ?? '0 20px 40px rgba(0, 0, 0, 0.3)');
|
||||
|
||||
style.setProperty('--bim-primary', theme.primary ?? '#3b82f6');
|
||||
style.setProperty('--bim-primary-hover', theme.primaryHover ?? '#60a5fa');
|
||||
style.setProperty('--bim-primary-subtle', theme.primarySubtle ?? 'rgba(59, 130, 246, 0.15)');
|
||||
|
||||
style.setProperty('--bim-text-primary', theme.textPrimary ?? '#ffffff');
|
||||
style.setProperty('--bim-text-inverse', theme.textInverse ?? '#152232');
|
||||
|
||||
style.setProperty('--bim-icon-default', theme.iconDefault ?? '#ffffff');
|
||||
|
||||
style.setProperty('--bim-component-bg-hover', theme.componentBgHover ?? 'rgba(248, 250, 252, 0.06)');
|
||||
style.setProperty('--bim-component-bg-active', theme.componentBgActive ?? 'rgba(248, 250, 252, 0.1)');
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
|
||||