@meshmakers / octo-ui
为OctoMesh应用程序提供可重用UI组件的Angular库。
功能
- 数据源 -列表视图和层次结构的基于graphql的数据源抽象
- 属性网格 -具有类型感知值显示的动态属性编辑器
- 浏览器运行时 -树形/详细视图,为运行时实体创建和更新编辑器
- 选择器对话框 -属性和CK类型选择对话框
- 筛选编辑器 —可视化查询过滤器配置
- 独立的主题 -适用于任何剑道UI主题
文档
- 开发人员文档 -完整的API参考和使用示例
快速入门
1. 导入组件
import {
PropertyGridComponent,
CkTypeSelectorInputComponent,
AttributeSelectorDialogService
} from '@meshmakers/octo-ui';
@Component({
imports: [PropertyGridComponent, CkTypeSelectorInputComponent],
// ...
})
export class MyComponent {}
2. 使用属性网格
import { PropertyGridComponent, PropertyGridItem, AttributeValueTypeDto } from '@meshmakers/octo-ui';
@Component({
template: `
<mm-property-grid
[properties]="properties"
[readOnlyMode]="false"
(propertyChange)="onPropertyChange($event)">
</mm-property-grid>
`
})
export class EntityDetailComponent {
properties: PropertyGridItem[] = [
{
id: 'name',
name: 'name',
displayName: 'Customer Name',
value: 'Acme Corp',
type: AttributeValueTypeDto.StringDto,
readOnly: false,
category: 'General'
}
];
onPropertyChange(event: PropertyChangeEvent) {
console.log('Property changed:', event.propertyId, event.newValue);
}
}
3. 使用CK类型选择器
import { CkTypeSelectorInputComponent, CkTypeSelectorItem } from '@meshmakers/octo-ui';
@Component({
template: `
<mm-ck-type-selector-input
[(ngModel)]="selectedType"
[ckModelIds]="['OctoSdkDemo']"
(ckTypeSelected)="onTypeSelected($event)">
</mm-ck-type-selector-input>
`
})
export class TypeSelectorComponent {
selectedType: CkTypeSelectorItem | null = null;
onTypeSelected(type: CkTypeSelectorItem) {
// Use type.rtCkTypeId for runtime queries
console.log('Selected:', type.rtCkTypeId);
}
}
4. 与列表视图一起使用数据源
import { OctoGraphQlDataSource, FetchDataOptions, FetchResultTyped } from '@meshmakers/octo-ui';
import { DataSourceBase, ListViewComponent } from '@meshmakers/shared-ui';
@Directive({
selector: '[appCustomerDataSource]',
exportAs: 'appCustomerDataSource',
providers: [{ provide: DataSourceBase, useExisting: forwardRef(() => CustomerDataSourceDirective) }]
})
export class CustomerDataSourceDirective extends OctoGraphQlDataSource<CustomerDto> {
private readonly getCustomersGQL = inject(GetCustomersDtoGQL);
constructor() {
super(inject(ListViewComponent));
this.searchFilterAttributePaths = ['name', 'email'];
}
fetchData(options: FetchDataOptions): Observable<FetchResultTyped<CustomerDto>> {
return this.getCustomersGQL.fetch({
variables: {
first: options.state.take,
after: GraphQL.offsetToCursor(options.state.skip ?? 0),
sortOrder: this.getSortDefinitions(options.state),
fieldFilter: this.getFieldFilterDefinitions(options.state),
searchFilter: this.getSearchFilterDefinitions(options.textSearch)
},
fetchPolicy: 'network-only'
}).pipe(map(result => new FetchResultTyped<CustomerDto>(
result.data?.runtime?.customers?.items ?? [],
result.data?.runtime?.customers?.totalCount ?? 0
)));
}
}
可用的组件
| 组件 | 描述 |
|---|---|
PropertyGridComponent | 具有类型感知编辑功能的动态属性网格 |
PropertyValueDisplayComponent | 具有类型格式的只读值显示 |
CkTypeSelectorInputComponent | 自动完成输入的CK类型选择 |
FieldFilterEditorComponent | 用于查询的可视化过滤器编辑器 |
EntityIdInfoComponent | 实体ID显示与复制到剪贴板下拉 |
OctoLoaderComponent | 动画OctoMesh标志加载指示器 |
PageComponent (MM_PAGE) | <mm-page> 页面布局:可选的页眉(标题,副标题,动作)+滚动内容,没有页脚 |
可用的服务
| 服务 | 描述 |
|---|---|
PropertyConverterService | 将实体转换为属性网格项 |
AttributeSelectorDialogService | 打开属性选择对话框 |
AttributeSortSelectorDialogService | 使用排序顺序打开属性选择 |
CkTypeSelectorDialogService | 打开CK类型选择对话框 |
数据源类
| 类 | 描述 |
|---|---|
OctoGraphQlDataSource | GraphQL列表数据源的基类 |
OctoGraphQlHierarchyDataSource | 树/层次数据源的基类 |
FetchResultTyped | 带有项目和totalCount的键入结果包装器 |
品牌
每个租户的品牌(标识、标题、调色板)具有亮/暗模式和可配置的
设置页面。看到 src/lib/branding/BRANDING_USAGE.md.
// app.config.ts
import { provideOctoBranding } from '@meshmakers/octo-ui';
providers: [
provideOctoBranding({
defaults: { appName: 'MyApp', appTitle: 'MyApp' },
fallbackAssets: { headerLogo: '/logo.svg', favicon: '/favicon.ico' },
}),
];
线 /settings 路线:
// app.routes.ts
import { BRANDING_ROUTES } from '@meshmakers/octo-ui';
{ path: 'settings', canActivate: [adminGuard], children: BRANDING_ROUTES }
将独立组件放到它们所属的shell中,然后 绑定你的页眉/页脚chrome到CSS变量库写入:
<header class="my-header">
<mm-theme-switcher />
<!-- Render the logo inline; inject BrandingDataSource and bind .branding().headerLogoUrl -->
<img [src]="logoUrl()" alt="" class="my-header-logo" />
</header>
.my-header {
background: linear-gradient(
to right,
var(--app-header-gradient-start),
var(--app-header-gradient-end)
);
color: var(--app-header-text);
}
看到 src/lib/branding/BRANDING_USAGE.md
获取库更新的CSS变量的完整列表和host-app
地面梯架合同。
页面布局(mm-page)
<mm-page> (PageComponent)是基于令牌的页面框架,它取代
LCARS header / content panel / footer三元组:一个可选的header (title,
副标题, [mmPageActions])和滚动内容区,没有页脚。进口
MM_PAGE (组件+插槽指令);标题默认为标题级别2
标题是一个plain <div>. 看到
src/lib/page/README.md.
<mm-page pageTitle="Adapters" pageSubtitle="12 registered">
<div mmPageActions><button kendoButton themeColor="primary">New adapter</button></div>
<mm-list-view …></mm-list-view>
</mm-page>
主题标记(可重写的CSS变量)
@include octo.theme() 发出“Deep Sea”令牌 :root (黑
默认为light via prefers-color-scheme 或者 data-theme="light");来源:
src/lib/runtime-browser/styles/_theme.scss. 主机可以覆盖其中的任何一个
包含后的自定义属性。所有 --theme-* 前者的名字
主题保持不变;令牌标志 新 添加到ab# 5519中。
| 集团 | 令牌 |
|---|---|
| 表面 | --theme-bg-app, --theme-bg-app-end, --theme-bg-surface, --theme-bg-elevated, --theme-bg-overlay, --theme-bg-input, 新: --theme-bg-sunken, --theme-bg-selected, --theme-bg-hover |
| 文本 | --theme-text-primary, --theme-text-secondary, --theme-text-muted, --theme-text-on-accent, --theme-text-accent, 新: --theme-text-code |
| 边界 | --theme-border-subtle, --theme-border-strong, --theme-border-divider (=微妙的), 新: --theme-border-default, --theme-focus-ring (一个 box-shadow 值) |
| 口音/ AI (新) | --theme-accent, --theme-accent-hover, --theme-accent-subtle, --theme-accent-2, --theme-ai, --theme-ai-subtle |
| 状态 | --theme-status-success, -warning, -error, -info, 新: --theme-status-neutral, --theme-status-{success,warning,error,info,neutral}-subtle |
| 影响 | --theme-shadow-panel, --theme-shadow-popup; --theme-glow-primary, --theme-glow-accent (包括 none); --theme-gradient-page, --theme-gradient-header, --theme-accent-bar, --theme-accent-line, --theme-panel-rule (现为平面色) |
| 图表 | --theme-chart-1 … --theme-chart-8 |
| 油墨覆盖 | --theme-ink-02 … --theme-ink-70 (文字颜色为n % -随主题变化) |
| 排版(新theme-invariant) | --theme-font-display (蒙特塞拉特岛), --theme-font-ui (Roboto), --theme-font-mono (Roboto Mono) |
| 间距(新) | --theme-space-1 … --theme-space-8 (4像素网格:4,8,12,16,20,24,28,32像素) |
| 半径(新) | --theme-radius-xs 2像素(芯片), -sm 4px(按钮,输入), -md 6px(卡片,面板), -lg 8px(对话框,弹出窗口) |
| 运动(新) | --theme-motion-fast 120毫秒, --theme-motion-base 200毫秒, --theme-motion-easing;两个持续时间都变成 0ms 下 prefers-reduced-motion: reduce |
遗留别名(AB#5526阶段2):仅限 --lcars-font-primary →
--theme-font-display, --lcars-font-mono → --theme-font-mono 和
--lcars-transition-fast → --theme-motion-fast +宽松的保留,保留为该
Meshmakers App,直到它迁移。所有其他的 --lcars-* 变量(发光,
按键基础,输入焦点,半径,面板标记, --lcars-transition-normal)
被删除-使用 --theme-* 令牌。
正文: octo.styles() 集合 body { font-family: var(--theme-font-ui) }
(Roboto)自AB#5526; h1–h3、页面和对话标题; mm-page 标题和
KPI数字使用 --theme-font-display (600年蒙特塞拉特岛)。
组件样式 octo.styles() (深海,AB#5526)
- 按钮是平的: primary =
--theme-accent与--theme-text-on-accent(悬停--theme-accent-hover), base =--theme-bg-elevated与一个--theme-border-default发际线(悬停--theme-bg-hover+--theme-border-strong),轮廓/平面变体透明;错误=--theme-status-error. 句子的情况下,--theme-font-ui,--theme-radius-sm, 键盘焦点--theme-focus-ring. 两个主题使用相同的规则,所以 以前的仅亮按钮覆盖是无操作的。 - 没有装饰:没有渐变(包括滑块),发光,脉冲,扫描线
或text-shadows;网格标题,选项卡(Kendo和dockview),进程设计器
调色板/检查器标题、对话框标题和上下文菜单都是句子大小写
在
--theme-font-ui(唯一的左大写字母是头像的首字母);弹出窗口, 对话框和菜单的使用--theme-bg-overlay+--theme-border-default+--theme-shadow-popup;抽屉是平的--theme-bg-elevated. theme-overrides():light-theme-surface-overrides被降到什么程度 代币不能表达(旧的轻卡,#d7ebe5桌带、抽屉 应用程序栏的治疗方法也消失了——这两个主题现在一致)。它也会发出 句格规则(html:root .k-label, kendo-label, .section-title), 在两个主题中都超过宿主组件样式。- 遗留的LCARS页面类-仅为Meshmakers App保留 (AB # 5526
第二阶段;精炼厂工作室不再使用它们):
.lcars-page-header,.page-title/.title-prefix/.title-main,.header-content和.lcars-content-panel面卡,带其.k-grid规则)保持中立 深海定义;.lcars-header-accent,.lcars-header-line,.panel-accent-top/-bottom,.lcars-footer和.footer-*使什么 (display: none). 其他的都被删除了:.header-stats,.stat-badge,.lcars-panel,.lcars-panel-asymmetric,.lcars-header-bar,.lcars-divider,.lcars-text-*,.lcars-bg-*,.lcars-border-mint, 辉光/扫描线/脉冲实用程序,以及_lcars-button.scss,_lcars-flat-btn.scss和_lcars-input.scssMixin文件(现在是内部的_button.scss/octo-button,_flat-button.scss/flat-button和_field-input.scss/field-input). 新页面使用<mm-page>.
偏离概念§6.2(对比驱动):光 --theme-text-accent /
--theme-accent #2c7d6d (概念 #2e8473, 4.16:1轻帆布→
4.55: 1),光 --theme-accent-hover #24685a (概念 #266f61),
--theme-text-muted 黑暗 #77869c (概念 #687890)和灯光 #657189
(概念 #75829a),均≥4.5:1 on --theme-bg-input. 剑道桥指向 --kendo-color-primary,
--kendo-color-surface(-alt), --kendo-color-border, --kendo-color-base*,
--kendo-border-radius-* 和 --kendo-font-family 看这些记号。
字体没有捆绑:主机加载Montserrat, Roboto和Roboto Mono
(炼油厂工作室通过谷歌字体在 index.html)。
次级入境点
繁重的管理编辑器驻留在它们自己的入口点,所以不使用它们的应用程序可以保留它们
主束小。的公共API @meshmakers/octo-ui.
| 入口点 | 目录 |
|---|---|
@meshmakers/octo-ui/branding | 品牌服务, provideOctoBranding,主题切换器 |
@meshmakers/octo-ui/branding-settings | 品牌设置页面(BRANDING_ROUTES) |
@meshmakers/octo-ui/tree-navigation-settings | 编辑 System.UI/TreeNavigationConfiguration |
@meshmakers/octo-ui/entity-forms | 表单驱动的实体列表/创建/编辑页面(<mm-entity-page>, <mm-entity-list>, <mm-entity-form>, entityFormRoutes()),由 System.UI/EntityForm ——看 entity-forms/README.md |
构建
# From frontend-libraries directory
npm run build:octo-ui
测试
npm run test:octo-ui
线头
npm run lint:octo-ui