@mica-js/editor 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +172 -2
- package/dist/index.d.ts +411 -0
- package/dist/index.js +7348 -0
- package/dist/index.js.map +1 -0
- package/dist/style.css +104 -0
- package/package.json +44 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DigitalEcho
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,173 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @mica-js/editor
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
独立组合根的编辑器。原理图工厂提供 URI 加载、器件解析、Canvas 渲染、编辑、撤销与重做;画布工厂提供 widget 合成、布局编辑和仿真会话。两个工厂分别拥有服务容器和内部实现。
|
|
4
|
+
|
|
5
|
+
## 使用
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import '@mica-js/editor/style.css';
|
|
9
|
+
import {
|
|
10
|
+
createSchematicEditor,
|
|
11
|
+
type IDeviceLibrary,
|
|
12
|
+
type IFileSystemProvider,
|
|
13
|
+
} from '@mica-js/editor';
|
|
14
|
+
|
|
15
|
+
export async function mount(
|
|
16
|
+
container: HTMLElement,
|
|
17
|
+
uri: string,
|
|
18
|
+
fileSystem: IFileSystemProvider,
|
|
19
|
+
deviceLibrary: IDeviceLibrary,
|
|
20
|
+
) {
|
|
21
|
+
const editor = await createSchematicEditor({ container, uri, fileSystem, deviceLibrary });
|
|
22
|
+
const subscription = editor.onDidChangeContent((document) => {
|
|
23
|
+
// Integrators decide how and when to persist each committed snapshot.
|
|
24
|
+
console.log(document);
|
|
25
|
+
});
|
|
26
|
+
return async () => {
|
|
27
|
+
subscription.dispose();
|
|
28
|
+
await editor.dispose();
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`uri` 必须为绝对 URI。工厂读取并解析文档、准备其中引用的器件、挂载视图后返回;首次加载缺失器件会拒绝创建。内置符号不请求 library。初始化失败会释放已构造的服务。可选 `readOnly` 禁止交互和命令修改,可选 `theme` 配置颜色。
|
|
34
|
+
|
|
35
|
+
内容事件在编辑、撤销、重做提交后发送快照,首次加载不发送;订阅返回 Disposable。文件系统只读,保存、序列化和修改状态由集成方维护。
|
|
36
|
+
|
|
37
|
+
命令通过类型映射约束名称、参数及返回值。修改命令使用一个参数对象,无参数命令省略第二个参数;底层文档命令保留为内部实现。
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
await editor.executeCommand('schematic.setProperty', {
|
|
41
|
+
symbolId,
|
|
42
|
+
key: 'resistance',
|
|
43
|
+
value: 1000,
|
|
44
|
+
});
|
|
45
|
+
await editor.executeCommand('schematic.setProperties', {
|
|
46
|
+
symbolId,
|
|
47
|
+
values: { resistance: 2200 },
|
|
48
|
+
remove: ['tolerance'],
|
|
49
|
+
});
|
|
50
|
+
await editor.executeCommand('schematic.placeDevice', { deviceId: 'demo:resistor' });
|
|
51
|
+
await editor.executeCommand('schematic.undo');
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`setProperties` 将整组设置及重置作为一步撤销;重置使用 `remove`,保留属性值 `null` 自身的含义。器件、导线、选择、工具及视图操作见导出的 `ISchematicCommandMap`。
|
|
55
|
+
|
|
56
|
+
文档命令按调用顺序执行。命令失败拒绝 Promise,队列继续接受后续命令。关闭后禁止执行命令,正在等待器件解析的编辑不会再提交;重复关闭返回同一个 Promise。关闭只移除编辑器自己的 DOM 和内部资源,保留宿主容器与 provider。
|
|
57
|
+
|
|
58
|
+
原理图器件拖动按细网格间距吸附(`gridSize / gridSubdivisions`,默认 5 页面单位);预览与提交使用同一位置,未拖动的轴保持原坐标。引脚连接处分支数超过 2(包含引脚短线)时自动绘制连接圆点,使用当前预览几何,不向文档新增 junction 记录。
|
|
59
|
+
|
|
60
|
+
## 画布编辑器
|
|
61
|
+
|
|
62
|
+
`createCanvasEditor({ container, uri, fileSystem, deviceLibrary, widgetLibrary, readOnly? })` 加载一个 `.cnv` 文档,准备关联原理图、描述和资源,创建内部 sandbox 后挂载画布。门面与原理图一致:`uri`、`state`、`onDidChangeContent`、`executeCommand` 和 `dispose`。
|
|
63
|
+
|
|
64
|
+
画布支持单个 widget 选中、拖动、角点调整尺寸、任意角度旋转、删除与撤销重做。拖动选中框顶部引线末端的圆形手柄可绕 widget 中心旋转,手柄大小、引线长度和命中范围不随缩放变化。旋转保留按下时的角度偏移,拖动仅预览,松开指针提交一次可撤销的修改;Escape、失焦、指针取消、丢失捕获、外部文档修改或切换到仿真模式会取消编辑预览。旋转后仍可沿 widget 自身轴线调整尺寸并拖动位置;尺寸手柄在悬停与拖动时显示随 widget 角度变化的方向指针。仿真模式将局部坐标的交互事件交给 widget;文档编辑在编辑模式执行。只读选项禁止文档修改,仍允许仿真交互。
|
|
65
|
+
|
|
66
|
+
滚轮以指针位置为中心缩放视图,范围为 10%–800%;鼠标中键拖动或按住空格后左键拖动可平移视图。这些操作在编辑、仿真和只读模式均可用。视图变化只保留在当前编辑器实例中,不修改文档、不进入撤销历史,也不触发 `onDidChangeContent`。
|
|
67
|
+
|
|
68
|
+
| ID | 参数与行为 |
|
|
69
|
+
| ---------------------------------------------- | ------------------------------------------------------------------- |
|
|
70
|
+
| `canvas.setProperty` / `canvas.removeProperty` | `{ instanceId, key, value? }`,设置或重置 widget 属性 |
|
|
71
|
+
| `canvas.setProperties` | `{ instanceId, values, remove? }`,批量设置及重置,一步撤销 |
|
|
72
|
+
| `canvas.setBinding` | `{ instanceId, port, target }`,目标为 `{ symbol, port }` 或 `null` |
|
|
73
|
+
| `canvas.setSchematic` | `{ path, bindings? }`,切换或解除关联,见下文 |
|
|
74
|
+
| `canvas.addWidget` / `canvas.removeWidget` | 添加或移除 widget |
|
|
75
|
+
| `canvas.setPlacement` / `canvas.setZ` | 修改位置、尺寸、角度或绘制顺序 |
|
|
76
|
+
| `canvas.undo` / `canvas.redo` | 撤销或重做一个文档修改 |
|
|
77
|
+
| `canvas.setMode` | `{ mode: 'edit' \| 'simulation' }`;切换会重建初始运行状态 |
|
|
78
|
+
| `canvas.run` / `canvas.pause` | 开始或暂停固定步长仿真 |
|
|
79
|
+
| `canvas.step` / `canvas.reset` | 执行一个固定步长或重建初始运行状态 |
|
|
80
|
+
| `canvas.zoomIn` / `canvas.zoomOut` | 以视口中心为锚点放大或缩小视图 |
|
|
81
|
+
| `canvas.fitView` / `canvas.resetView` | 适应全部旋转边界或恢复 100% 视图 |
|
|
82
|
+
|
|
83
|
+
完整参数和返回值见导出的 `ICanvasCommandMap`。
|
|
84
|
+
|
|
85
|
+
可选 `voltageReferences: { VCC: 5 }` 为同名原理图网络配置固定板级电压,接地网络保持 0 V。电源标记只命名网络,电压由该选项显式提供。
|
|
86
|
+
|
|
87
|
+
运行会话负责唯一帧调度器,以 25 ms 固定步长推进仿真;暂停时继续刷新 widget 而不推进仿真时间。话题数据通过两个 guest 之间的直连 RPC 通道传递,editor 配置绑定,不在 UI 线程转发 payload。位置、旋转和层级只属于编辑器;改变执行输入时先建立候选会话,全部准备成功后替换旧会话。文档与历史在准备失败时保持原值。
|
|
88
|
+
|
|
89
|
+
library 的代码只在 sandbox 中执行,资源由 editor 通过只读文件系统预先读取。关闭 editor 会取消时钟、移除视图,并释放内部运行实例、RPC、bitmap 和 sandbox;外部 provider 保留宿主所有权。
|
|
90
|
+
|
|
91
|
+
内部服务通过构造参数装饰器注入,使用此包的 TypeScript 配置启用 `experimentalDecorators`。DI 容器和服务标识保留在包内,应用通过具体编辑器工厂创建实例。
|
|
92
|
+
|
|
93
|
+
## 宿主集成
|
|
94
|
+
|
|
95
|
+
- `getDocument()` 返回只读文档快照;`onDidChangeContent` 只在提交、撤销及重做后发送,拖动预览不触发。
|
|
96
|
+
- `getSelection()` / `setSelection()` 与 `onDidChangeSelection` 用于对象树、搜索和编辑视图联动。原理图按目标类型区分器件、导线等对象;画布目标为 `{ kind: 'widget', id }`,当前一次选择一个 widget。
|
|
97
|
+
- `onDidClick`、`onDidDoubleClick`、`onDidContextMenu` 携带目标(空白为 `null`)、文档坐标 `position`、CSS 客户端坐标 `clientPosition`、按钮、修饰键及编辑模式。点击导致的选中变化先通知,重复点击相同对象仍发送点击事件;拖动、尺寸调整、旋转及平移不作为点击。
|
|
98
|
+
- 双击沿用浏览器语义,允许此前已发送单击通知。右键事件供宿主定位菜单,仿真交互通知与 widget 运行时输入分开处理。
|
|
99
|
+
- `getProperties(id)` 返回属性名称、类型、有效值、默认值、覆盖值、覆盖状态及只读状态。面板在选中变化和内容变化时刷新;修改通过类型化命令提交。
|
|
100
|
+
- `getState()` / `onDidChangeState` 提供只读、模式和撤销重做状态;`onDidError` 提供来源及原始错误。命令失败同时拒绝 Promise,宿主可统一展示反馈。
|
|
101
|
+
- 事件订阅返回 Disposable,宿主卸载面板时释放订阅;编辑器关闭时释放自身订阅和事件。
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
const refresh = () => {
|
|
105
|
+
const selection = editor.getSelection();
|
|
106
|
+
const document = editor.getDocument();
|
|
107
|
+
renderObjectTree(document, selection);
|
|
108
|
+
};
|
|
109
|
+
const subscriptions = [
|
|
110
|
+
editor.onDidChangeContent(refresh),
|
|
111
|
+
editor.onDidChangeSelection(refresh),
|
|
112
|
+
editor.onDidDoubleClick((event) => openDetails(event.target)),
|
|
113
|
+
editor.onDidError(({ error }) => showError(error)),
|
|
114
|
+
];
|
|
115
|
+
refresh();
|
|
116
|
+
// On host unmount:
|
|
117
|
+
subscriptions.forEach((subscription) => subscription.dispose());
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 话题绑定及原理图关联
|
|
121
|
+
|
|
122
|
+
`canvas.getBindings(instanceId)` 返回 widget 端口的当前目标和器件端口候选。候选包含兼容状态及不兼容原因,编辑器在提交时重新校验方向、负载类型和投递语义。绑定目标使用器件实例 ID 与端口名,运行时负责话题路由。
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
await canvas.executeCommand('canvas.setBinding', {
|
|
126
|
+
instanceId,
|
|
127
|
+
port: 'press',
|
|
128
|
+
target: { symbol: symbolId, port: 'in' },
|
|
129
|
+
});
|
|
130
|
+
await canvas.executeCommand('canvas.setSchematic', {
|
|
131
|
+
path: 'circuits/main.sch',
|
|
132
|
+
bindings: 'clear',
|
|
133
|
+
});
|
|
134
|
+
await canvas.executeCommand('canvas.setSchematic', { path: null });
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
`projectRoot` 可指定项目根目录的绝对 URI,关联路径相对该根目录解析;省略时使用画布 URI 所在目录。切换默认 `bindings: 'preserve'`,保留并校验原绑定;选择 `clear` 清空全部绑定,解除关联也会清空绑定。路径、绑定、资源和候选运行时全部准备成功后提交,一步撤销恢复原关联及绑定;失败时文档与活动运行时保持原状态。只读或仿真模式下拒绝文档修改。
|
|
138
|
+
|
|
139
|
+
## Provider 契约
|
|
140
|
+
|
|
141
|
+
本包导出以下 provider 类型:
|
|
142
|
+
|
|
143
|
+
- `IFileSystemProvider` 复用只读 HostFs 的 `read(uri)`,以绝对 URI 读取完整字节内容,失败拒绝 Promise。
|
|
144
|
+
- `IDeviceLibrary.resolve(id)` 返回 `IDeviceDescription | undefined`。
|
|
145
|
+
- `IWidgetLibrary.resolve(id)` 返回 `IWidgetDescription | undefined`;它与现有 WidgetProvider 结构兼容。
|
|
146
|
+
|
|
147
|
+
`id` 是文档中的完整标识,例如 `demo:button`,不是 URI。两个 library 只提供 `resolve`;未找到返回 `undefined`,加载失败拒绝 Promise。
|
|
148
|
+
|
|
149
|
+
描述对象均为自包含的 `definition` 与 `code`,不引用外部资源:
|
|
150
|
+
|
|
151
|
+
| 描述 | 元数据 | 代码约定 |
|
|
152
|
+
| -------------------- | ----------------------------------------- | ------------------------------------------------ |
|
|
153
|
+
| `IDeviceDescription` | `IDeviceDefinition`:SDK `DeviceMetadata` | 自包含 SDK ESM,具名导出 `model` 与同步 `create` |
|
|
154
|
+
| `IWidgetDescription` | 复用现有 WidgetModule 的 definition | 自包含 ESM,默认导出现有 WidgetFactory |
|
|
155
|
+
|
|
156
|
+
`IDeviceDefinition` 复用 `@mica-js/sdk/metadata` 的 `DeviceMetadata`。SDK 将 DDL 编译为共享器件模型,并与同步适配器打包成 `device.js`;画布会话在内部 sandbox 中装载 `model` 和 `create`,使用 `createDeviceLibrary` / `createBoard` 运行。元数据用于符号、属性与话题绑定校验,解析阶段不执行代码。字段及 JSON Schema 见 [device.json 格式](../../docs/formats/device.md),作者构建入口见 [SDK](../sdk/README.md)。
|
|
157
|
+
|
|
158
|
+
新版 `symbol.graphics` 按声明绘制线段、折线、矩形、圆、圆弧和文本;`bounds` 用于选择区域,`symbol.pins` 指定接线锚点、方向与标签,`annotations.designator` 指定位号位置和对齐。图元坐标随器件平移和旋转,填充与描边使用编辑器主题。省略 `symbol` 时,根据顶层引脚合成符号。属性面板数据保留必填性、分组、排序和编辑器提示,枚举选项使用 `values` 与 `editor.labels`。
|
|
159
|
+
|
|
160
|
+
内部解析服务在实例范围内合并相同 ID 的并发解析并缓存成功结果;未找到和失败结果允许重试。解析只获取描述,不执行代码。已返回的描述在该实例内按稳定只读值使用;重新创建实例会重新解析。Provider 由宿主拥有,编辑器只释放自己的解析缓存。
|
|
161
|
+
|
|
162
|
+
## 开发
|
|
163
|
+
|
|
164
|
+
文档契约来自 `@mica-js/document/schematic`;历史管理、命中测试与拖动预览由本包内部持有。
|
|
165
|
+
|
|
166
|
+
测试使用依赖包的发布入口,首次在干净检出中运行前需先构建依赖。
|
|
167
|
+
|
|
168
|
+
```powershell
|
|
169
|
+
pnpm --filter @mica-js/editor... build
|
|
170
|
+
pnpm --filter @mica-js/editor typecheck
|
|
171
|
+
pnpm --filter @mica-js/editor test
|
|
172
|
+
pnpm --filter @mica-js/editor build
|
|
173
|
+
```
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import { CanvasBindingTarget } from '@mica-js/document/canvas';
|
|
2
|
+
import { CanvasDocument } from '@mica-js/document/canvas';
|
|
3
|
+
import { CanvasPortDescriptor } from '@mica-js/document/canvas';
|
|
4
|
+
import { CanvasWidgetInstance } from '@mica-js/document/canvas';
|
|
5
|
+
import { DeviceFactory } from '@mica-js/simulator';
|
|
6
|
+
import { DeviceMetadata } from '@mica-js/sdk/metadata';
|
|
7
|
+
import { Event as Event_2 } from '@mica-js/core/lifecycle';
|
|
8
|
+
import { HostFs } from '@mica-js/widget';
|
|
9
|
+
import { Point } from '@mica-js/document/schematic';
|
|
10
|
+
import { PropertyDescriptor as PropertyDescriptor_2 } from '@mica-js/document/schematic';
|
|
11
|
+
import { PropertyValue } from '@mica-js/document/schematic';
|
|
12
|
+
import { SchematicCommand } from '@mica-js/document/schematic';
|
|
13
|
+
import { SchematicDocument } from '@mica-js/document/schematic';
|
|
14
|
+
import { WidgetModule } from '@mica-js/widget';
|
|
15
|
+
import { WidgetPlacement } from '@mica-js/document/canvas';
|
|
16
|
+
|
|
17
|
+
declare type AddDevice = Omit<Extract<SchematicCommand, {
|
|
18
|
+
type: 'add-symbol';
|
|
19
|
+
}>, 'type' | 'device'> & {
|
|
20
|
+
readonly deviceId: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export declare function createCanvasEditor(options: ICanvasEditorOptions): Promise<ICanvasEditor>;
|
|
24
|
+
|
|
25
|
+
/** Loads one document and mounts one schematic view; the returned instance owns all internal services. */
|
|
26
|
+
export declare function createSchematicEditor(options: ISchematicEditorOptions): Promise<ISchematicEditor>;
|
|
27
|
+
|
|
28
|
+
export { DeviceFactory }
|
|
29
|
+
|
|
30
|
+
export declare type EditorCommandArgs<C extends {
|
|
31
|
+
readonly params: unknown;
|
|
32
|
+
}> = [C['params']] extends [void] ? [] : [params: C['params']];
|
|
33
|
+
|
|
34
|
+
export declare type EditorState = 'created' | 'starting' | 'ready' | 'failed' | 'disposing' | 'disposed';
|
|
35
|
+
|
|
36
|
+
export declare type EditorTool = 'select' | 'wire' | 'power' | 'ground' | 'label' | 'text';
|
|
37
|
+
|
|
38
|
+
export declare interface ICanvasBindingCandidate {
|
|
39
|
+
readonly target: CanvasBindingTarget;
|
|
40
|
+
readonly label: string;
|
|
41
|
+
readonly compatible: boolean;
|
|
42
|
+
readonly reason?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export declare interface ICanvasBindingInfo extends CanvasPortDescriptor {
|
|
46
|
+
readonly port: string;
|
|
47
|
+
readonly target: CanvasBindingTarget | null;
|
|
48
|
+
readonly candidates: readonly ICanvasBindingCandidate[];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export declare interface ICanvasCommandMap {
|
|
52
|
+
'canvas.setProperty': IEditorCommand<{
|
|
53
|
+
instanceId: string;
|
|
54
|
+
key: string;
|
|
55
|
+
value: unknown;
|
|
56
|
+
}>;
|
|
57
|
+
'canvas.removeProperty': IEditorCommand<{
|
|
58
|
+
instanceId: string;
|
|
59
|
+
key: string;
|
|
60
|
+
}>;
|
|
61
|
+
'canvas.setProperties': IEditorCommand<{
|
|
62
|
+
instanceId: string;
|
|
63
|
+
values: Readonly<Record<string, unknown>>;
|
|
64
|
+
remove?: readonly string[];
|
|
65
|
+
}>;
|
|
66
|
+
'canvas.setBinding': IEditorCommand<{
|
|
67
|
+
instanceId: string;
|
|
68
|
+
port: string;
|
|
69
|
+
target: CanvasBindingTarget | null;
|
|
70
|
+
}>;
|
|
71
|
+
'canvas.setSchematic': IEditorCommand<{
|
|
72
|
+
path: string | null;
|
|
73
|
+
bindings?: 'preserve' | 'clear';
|
|
74
|
+
}>;
|
|
75
|
+
'canvas.addWidget': IEditorCommand<{
|
|
76
|
+
instance: CanvasWidgetInstance;
|
|
77
|
+
z?: number;
|
|
78
|
+
}>;
|
|
79
|
+
'canvas.removeWidget': IEditorCommand<{
|
|
80
|
+
instanceId: string;
|
|
81
|
+
}>;
|
|
82
|
+
'canvas.setPlacement': IEditorCommand<{
|
|
83
|
+
instanceId: string;
|
|
84
|
+
placement: WidgetPlacement;
|
|
85
|
+
}>;
|
|
86
|
+
'canvas.setZ': IEditorCommand<{
|
|
87
|
+
instanceId: string;
|
|
88
|
+
z: number;
|
|
89
|
+
}>;
|
|
90
|
+
'canvas.setMode': IEditorCommand<{
|
|
91
|
+
mode: 'edit' | 'simulation';
|
|
92
|
+
}>;
|
|
93
|
+
'canvas.undo': IEditorCommand;
|
|
94
|
+
'canvas.redo': IEditorCommand;
|
|
95
|
+
'canvas.run': IEditorCommand;
|
|
96
|
+
'canvas.pause': IEditorCommand;
|
|
97
|
+
'canvas.step': IEditorCommand;
|
|
98
|
+
'canvas.reset': IEditorCommand;
|
|
99
|
+
'canvas.zoomIn': IEditorCommand;
|
|
100
|
+
'canvas.zoomOut': IEditorCommand;
|
|
101
|
+
'canvas.resetView': IEditorCommand;
|
|
102
|
+
'canvas.fitView': IEditorCommand;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export declare interface ICanvasEditor {
|
|
106
|
+
readonly uri: string;
|
|
107
|
+
readonly state: EditorState;
|
|
108
|
+
readonly onDidChangeContent: Event_2<CanvasDocument>;
|
|
109
|
+
getDocument(): CanvasDocument;
|
|
110
|
+
getSelection(): readonly ICanvasTarget[];
|
|
111
|
+
setSelection(selection: readonly ICanvasTarget[]): void;
|
|
112
|
+
readonly onDidChangeSelection: Event_2<readonly ICanvasTarget[]>;
|
|
113
|
+
readonly onDidClick: Event_2<IEditorPointerEvent<ICanvasTarget>>;
|
|
114
|
+
readonly onDidDoubleClick: Event_2<IEditorPointerEvent<ICanvasTarget>>;
|
|
115
|
+
readonly onDidContextMenu: Event_2<IEditorPointerEvent<ICanvasTarget>>;
|
|
116
|
+
getProperties(instanceId: string): readonly IEditorProperty[];
|
|
117
|
+
getBindings(instanceId: string): readonly ICanvasBindingInfo[];
|
|
118
|
+
getState(): IEditorIntegrationState;
|
|
119
|
+
readonly onDidChangeState: Event_2<IEditorIntegrationState>;
|
|
120
|
+
readonly onDidError: Event_2<IEditorErrorEvent>;
|
|
121
|
+
executeCommand<K extends keyof ICanvasCommandMap>(id: K, ...args: EditorCommandArgs<ICanvasCommandMap[K]>): Promise<ICanvasCommandMap[K]['result']>;
|
|
122
|
+
dispose(): Promise<void>;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export declare interface ICanvasEditorOptions {
|
|
126
|
+
readonly container: HTMLElement;
|
|
127
|
+
readonly uri: string;
|
|
128
|
+
readonly fileSystem: IFileSystemProvider_2;
|
|
129
|
+
readonly deviceLibrary: IDeviceLibrary_2;
|
|
130
|
+
readonly widgetLibrary: IWidgetLibrary_2;
|
|
131
|
+
readonly readOnly?: boolean;
|
|
132
|
+
/** Fixed board voltages by exact schematic net name; ignored without a schematic. Ground stays zero. */
|
|
133
|
+
readonly voltageReferences?: Readonly<Record<string, number>>;
|
|
134
|
+
readonly projectRoot?: string;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export declare interface ICanvasTarget {
|
|
138
|
+
readonly kind: 'widget';
|
|
139
|
+
readonly id: string;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export declare interface ICommandContribution {
|
|
143
|
+
readonly id: string;
|
|
144
|
+
readonly execute: (...args: readonly unknown[]) => unknown;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** SDK device JSON consumed without executing its paired module. */
|
|
148
|
+
export declare type IDeviceDefinition = DeviceMetadata;
|
|
149
|
+
|
|
150
|
+
export declare interface IDeviceDescription {
|
|
151
|
+
readonly definition: IDeviceDefinition;
|
|
152
|
+
/** Self-contained SDK ESM with named model and synchronous create exports. */
|
|
153
|
+
readonly code: string;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export declare interface IDeviceLibrary {
|
|
157
|
+
/** Full document ID, e.g. demo:button. Unknown IDs resolve to undefined; failures reject. */
|
|
158
|
+
resolve(id: string): Promise<IDeviceDescription | undefined>;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
declare type IDeviceLibrary_2 = IDeviceLibrary;
|
|
162
|
+
|
|
163
|
+
declare const IDeviceLibrary_2: IServiceIdentifier<IDeviceLibrary>;
|
|
164
|
+
|
|
165
|
+
export declare interface IEditorCommand<P = void, R = void> {
|
|
166
|
+
readonly params: P;
|
|
167
|
+
readonly result: R;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export declare interface IEditorErrorEvent {
|
|
171
|
+
readonly source: 'load' | 'render' | 'runtime' | 'command';
|
|
172
|
+
readonly error: unknown;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export declare interface IEditorIntegrationState {
|
|
176
|
+
readonly readOnly: boolean;
|
|
177
|
+
readonly mode: 'edit' | 'simulation';
|
|
178
|
+
readonly canUndo: boolean;
|
|
179
|
+
readonly canRedo: boolean;
|
|
180
|
+
readonly tool?: string;
|
|
181
|
+
readonly running?: boolean;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export declare interface IEditorPoint {
|
|
185
|
+
readonly x: number;
|
|
186
|
+
readonly y: number;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** Coordinates are CSS pixels for clientPosition and document units for position. */
|
|
190
|
+
export declare interface IEditorPointerEvent<T> {
|
|
191
|
+
readonly target: T | null;
|
|
192
|
+
readonly position: IEditorPoint;
|
|
193
|
+
readonly clientPosition: IEditorPoint;
|
|
194
|
+
readonly button: number;
|
|
195
|
+
readonly altKey: boolean;
|
|
196
|
+
readonly ctrlKey: boolean;
|
|
197
|
+
readonly metaKey: boolean;
|
|
198
|
+
readonly shiftKey: boolean;
|
|
199
|
+
readonly mode: 'edit' | 'simulation';
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Detached property-panel data; value includes the definition default when inherited.
|
|
204
|
+
*
|
|
205
|
+
* The shared fields describe what every panel needs; the remaining optional metadata is the
|
|
206
|
+
* declaration's original descriptor (`group`, `order`, `editor`, `unit`, `maxLength`, `nullable`,
|
|
207
|
+
* `alpha`, byte/pixel limits, …), which hosts forward untouched to pick the right control.
|
|
208
|
+
*/
|
|
209
|
+
export declare interface IEditorProperty extends Omit<PropertyDescriptor_2, 'key' | 'type' | 'description' | 'default' | 'options' | 'min' | 'max' | 'step'> {
|
|
210
|
+
readonly key: string;
|
|
211
|
+
readonly label: string;
|
|
212
|
+
readonly type: string;
|
|
213
|
+
readonly description?: string;
|
|
214
|
+
readonly value: unknown;
|
|
215
|
+
readonly defaultValue: unknown;
|
|
216
|
+
readonly overrideValue: unknown;
|
|
217
|
+
readonly overridden: boolean;
|
|
218
|
+
readonly readOnly: boolean;
|
|
219
|
+
readonly options?: readonly {
|
|
220
|
+
readonly value: unknown;
|
|
221
|
+
readonly label: string;
|
|
222
|
+
}[];
|
|
223
|
+
readonly min?: number;
|
|
224
|
+
readonly max?: number;
|
|
225
|
+
readonly step?: number;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** Absolute resource URIs; providers remain owned by the caller. */
|
|
229
|
+
export declare type IFileSystemProvider = HostFs;
|
|
230
|
+
|
|
231
|
+
declare type IFileSystemProvider_2 = IFileSystemProvider;
|
|
232
|
+
|
|
233
|
+
declare const IFileSystemProvider_2: IServiceIdentifier<HostFs>;
|
|
234
|
+
|
|
235
|
+
/** Semantic host operations. Document editing commands remain implementation details. */
|
|
236
|
+
export declare interface ISchematicCommandMap {
|
|
237
|
+
readonly 'schematic.setProperty': IEditorCommand<{
|
|
238
|
+
readonly symbolId: string;
|
|
239
|
+
readonly key: string;
|
|
240
|
+
readonly value: PropertyValue;
|
|
241
|
+
}>;
|
|
242
|
+
readonly 'schematic.removeProperty': IEditorCommand<{
|
|
243
|
+
readonly symbolId: string;
|
|
244
|
+
readonly key: string;
|
|
245
|
+
}>;
|
|
246
|
+
/** Removed keys are separate so that null remains a property value. Removals run first. */
|
|
247
|
+
readonly 'schematic.setProperties': IEditorCommand<{
|
|
248
|
+
readonly symbolId: string;
|
|
249
|
+
readonly values: Readonly<Record<string, PropertyValue>>;
|
|
250
|
+
readonly remove?: readonly string[];
|
|
251
|
+
}>;
|
|
252
|
+
readonly 'schematic.addDevice': IEditorCommand<AddDevice, string>;
|
|
253
|
+
readonly 'schematic.removeDevice': IEditorCommand<{
|
|
254
|
+
readonly symbolId: string;
|
|
255
|
+
}>;
|
|
256
|
+
readonly 'schematic.updateDevice': IEditorCommand<UpdateDevice>;
|
|
257
|
+
readonly 'schematic.addWire': IEditorCommand<{
|
|
258
|
+
readonly id?: string;
|
|
259
|
+
readonly points: readonly Point[];
|
|
260
|
+
}, string>;
|
|
261
|
+
readonly 'schematic.removeWire': IEditorCommand<{
|
|
262
|
+
readonly wireId: string;
|
|
263
|
+
}>;
|
|
264
|
+
readonly 'schematic.setWirePoints': IEditorCommand<{
|
|
265
|
+
readonly wireId: string;
|
|
266
|
+
readonly points: readonly Point[];
|
|
267
|
+
}>;
|
|
268
|
+
readonly 'schematic.deleteSelection': IEditorCommand;
|
|
269
|
+
readonly 'schematic.moveSelection': IEditorCommand<{
|
|
270
|
+
readonly dx: number;
|
|
271
|
+
readonly dy: number;
|
|
272
|
+
}>;
|
|
273
|
+
readonly 'schematic.rotateSelection': IEditorCommand<{
|
|
274
|
+
readonly degrees: number;
|
|
275
|
+
}>;
|
|
276
|
+
readonly 'schematic.placeDevice': IEditorCommand<{
|
|
277
|
+
readonly deviceId: string;
|
|
278
|
+
}>;
|
|
279
|
+
readonly 'schematic.undo': IEditorCommand;
|
|
280
|
+
readonly 'schematic.redo': IEditorCommand;
|
|
281
|
+
readonly 'schematic.setTool': IEditorCommand<{
|
|
282
|
+
readonly tool: EditorTool;
|
|
283
|
+
}>;
|
|
284
|
+
readonly 'schematic.zoom': IEditorCommand<{
|
|
285
|
+
readonly scale: number;
|
|
286
|
+
}>;
|
|
287
|
+
readonly 'schematic.fit': IEditorCommand;
|
|
288
|
+
readonly 'schematic.resetView': IEditorCommand;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export declare interface ISchematicEditor {
|
|
292
|
+
readonly uri: string;
|
|
293
|
+
readonly state: EditorState;
|
|
294
|
+
readonly onDidChangeContent: Event_2<SchematicDocument>;
|
|
295
|
+
readonly onDidChangeSelection: Event_2<readonly SchematicTarget[]>;
|
|
296
|
+
readonly onDidClick: Event_2<IEditorPointerEvent<SchematicTarget>>;
|
|
297
|
+
readonly onDidDoubleClick: Event_2<IEditorPointerEvent<SchematicTarget>>;
|
|
298
|
+
readonly onDidContextMenu: Event_2<IEditorPointerEvent<SchematicTarget>>;
|
|
299
|
+
readonly onDidChangeState: Event_2<IEditorIntegrationState>;
|
|
300
|
+
readonly onDidError: Event_2<IEditorErrorEvent>;
|
|
301
|
+
getDocument(): SchematicDocument;
|
|
302
|
+
getSelection(): readonly SchematicTarget[];
|
|
303
|
+
setSelection(selection: readonly SchematicTarget[]): void;
|
|
304
|
+
getProperties(symbolId: string): readonly IEditorProperty[];
|
|
305
|
+
getState(): IEditorIntegrationState;
|
|
306
|
+
executeCommand<K extends keyof ISchematicCommandMap>(id: K, ...args: EditorCommandArgs<ISchematicCommandMap[K]>): Promise<ISchematicCommandMap[K]['result']>;
|
|
307
|
+
dispose(): Promise<void>;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export declare interface ISchematicEditorOptions {
|
|
311
|
+
readonly container: HTMLElement;
|
|
312
|
+
readonly uri: string;
|
|
313
|
+
readonly fileSystem: IFileSystemProvider_2;
|
|
314
|
+
readonly deviceLibrary: IDeviceLibrary_2;
|
|
315
|
+
readonly readOnly?: boolean;
|
|
316
|
+
readonly theme?: Partial<ISchematicTheme>;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Rendering and chrome tokens. The renderer never hard-codes colors: every visible
|
|
321
|
+
* value comes from a theme.
|
|
322
|
+
*/
|
|
323
|
+
declare interface ISchematicTheme {
|
|
324
|
+
background: ThemeColor;
|
|
325
|
+
grid: ThemeColor;
|
|
326
|
+
gridMajor: ThemeColor;
|
|
327
|
+
wire: ThemeColor;
|
|
328
|
+
wireSelected: ThemeColor;
|
|
329
|
+
junction: ThemeColor;
|
|
330
|
+
junctionSelected: ThemeColor;
|
|
331
|
+
pendingWire: ThemeColor;
|
|
332
|
+
symbolFill: ThemeColor;
|
|
333
|
+
symbolStroke: ThemeColor;
|
|
334
|
+
symbolText: ThemeColor;
|
|
335
|
+
symbolPlaceholder: ThemeColor;
|
|
336
|
+
pin: ThemeColor;
|
|
337
|
+
pinText: ThemeColor;
|
|
338
|
+
pinOpen: ThemeColor;
|
|
339
|
+
labelAnchor: ThemeColor;
|
|
340
|
+
labelText: ThemeColor;
|
|
341
|
+
selection: ThemeColor;
|
|
342
|
+
hover: ThemeColor;
|
|
343
|
+
uiBackground: ThemeColor;
|
|
344
|
+
uiSurface: ThemeColor;
|
|
345
|
+
uiBorder: ThemeColor;
|
|
346
|
+
uiText: ThemeColor;
|
|
347
|
+
uiMutedText: ThemeColor;
|
|
348
|
+
uiAccent: ThemeColor;
|
|
349
|
+
uiAccentText: ThemeColor;
|
|
350
|
+
focusRing: ThemeColor;
|
|
351
|
+
fontFamily: string;
|
|
352
|
+
fontSize: number;
|
|
353
|
+
/** Pin name text; smaller than `fontSize` so labels stay inside the body. */
|
|
354
|
+
pinFontSize: number;
|
|
355
|
+
/** Device name drawn in the symbol centre. */
|
|
356
|
+
symbolFontSize: number;
|
|
357
|
+
gridSize: number;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
declare interface IServiceIdentifier<T> {
|
|
361
|
+
(target: object, propertyKey: string | symbol | undefined, parameterIndex: number): void;
|
|
362
|
+
readonly type: T;
|
|
363
|
+
toString(): string;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/** Existing widget definition and self-contained ESM source default-exporting WidgetFactory. */
|
|
367
|
+
export declare type IWidgetDescription = WidgetModule;
|
|
368
|
+
|
|
369
|
+
export declare interface IWidgetLibrary {
|
|
370
|
+
/** Full document ID, e.g. demo:indicator. Unknown IDs resolve to undefined; failures reject. */
|
|
371
|
+
resolve(id: string): Promise<IWidgetDescription | undefined>;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
declare type IWidgetLibrary_2 = IWidgetLibrary;
|
|
375
|
+
|
|
376
|
+
declare const IWidgetLibrary_2: IServiceIdentifier<IWidgetLibrary>;
|
|
377
|
+
|
|
378
|
+
/** One addressable element of the document that an editor can select or edit. */
|
|
379
|
+
export declare type SchematicTarget = {
|
|
380
|
+
readonly kind: 'symbol';
|
|
381
|
+
readonly id: string;
|
|
382
|
+
} | {
|
|
383
|
+
readonly kind: 'pin';
|
|
384
|
+
readonly symbolId: string;
|
|
385
|
+
readonly pinId: string;
|
|
386
|
+
} | {
|
|
387
|
+
readonly kind: 'reference';
|
|
388
|
+
readonly symbolId: string;
|
|
389
|
+
} | {
|
|
390
|
+
readonly kind: 'wire';
|
|
391
|
+
readonly id: string;
|
|
392
|
+
} | {
|
|
393
|
+
readonly kind: 'junction';
|
|
394
|
+
readonly id: string;
|
|
395
|
+
} | {
|
|
396
|
+
readonly kind: 'vertex';
|
|
397
|
+
readonly wireId: string;
|
|
398
|
+
readonly index: number;
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
/** Any CSS color string; Canvas and CSS parse it. */
|
|
402
|
+
declare type ThemeColor = string;
|
|
403
|
+
|
|
404
|
+
declare type UpdateDevice = Omit<Extract<SchematicCommand, {
|
|
405
|
+
type: 'update-symbol';
|
|
406
|
+
}>, 'type' | 'id' | 'device'> & {
|
|
407
|
+
readonly symbolId: string;
|
|
408
|
+
readonly deviceId?: string;
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
export { }
|