drawui-core 0.1.0 → 0.2.1

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/dist/index.d.cts CHANGED
@@ -14,7 +14,7 @@ interface ShapeStyle {
14
14
  strokeWidth: number;
15
15
  strokeDash: number[] | null;
16
16
  }
17
- type ShapeType = 'rectangle' | 'rounded-rectangle' | 'circle' | 'ellipse' | 'diamond' | 'triangle' | 'hexagon' | 'parallelogram' | 'trapezoid' | 'pentagon' | 'octagon' | 'star' | 'uml-class' | 'uml-interface' | 'line' | 'arrow' | 'text' | 'draw';
17
+ type ShapeType = 'rectangle' | 'rounded-rectangle' | 'circle' | 'ellipse' | 'diamond' | 'triangle' | 'hexagon' | 'parallelogram' | 'trapezoid' | 'pentagon' | 'octagon' | 'star' | 'uml-class' | 'uml-interface' | 'mind-map' | 'line' | 'arrow' | 'text' | 'draw';
18
18
  interface BaseShape {
19
19
  id: string;
20
20
  type: ShapeType;
@@ -181,8 +181,29 @@ interface DrawShape extends BaseShape {
181
181
  type: 'draw';
182
182
  points: Vec2[];
183
183
  }
184
- type Shape = RectangleShape | RoundedRectangleShape | CircleShape | EllipseShape | DiamondShape | TriangleShape | HexagonShape | ParallelogramShape | TrapezoidShape | PentagonShape | OctagonShape | StarShape | UmlClassShape | UmlInterfaceShape | LineShape | ArrowShape | TextShape | DrawShape;
185
- type ToolType = 'select' | 'hand' | 'rectangle' | 'rounded-rectangle' | 'circle' | 'ellipse' | 'diamond' | 'triangle' | 'hexagon' | 'parallelogram' | 'trapezoid' | 'pentagon' | 'octagon' | 'star' | 'uml-class' | 'uml-interface' | 'line' | 'arrow' | 'text' | 'draw' | 'pen' | 'highlighter';
184
+ /** 思维导图节点:可带子节点;颜色/图标/属性说明均可手动覆盖,默认取层级色 */
185
+ interface MindMapNode {
186
+ id: string;
187
+ text: string;
188
+ /** 手动覆盖的节点颜色;不设置时按层级取默认色 */
189
+ color?: string;
190
+ /** 左侧图标(任意短文本/emoji),默认无 */
191
+ icon?: string;
192
+ /** 左上角属性说明,默认无 */
193
+ note?: string;
194
+ /** 说明标签颜色,默认与节点颜色一致 */
195
+ noteColor?: string;
196
+ collapsed?: boolean;
197
+ children?: MindMapNode[];
198
+ }
199
+ interface MindMapShape extends BaseShape {
200
+ type: 'mind-map';
201
+ width: number;
202
+ height: number;
203
+ root: MindMapNode;
204
+ }
205
+ type Shape = RectangleShape | RoundedRectangleShape | CircleShape | EllipseShape | DiamondShape | TriangleShape | HexagonShape | ParallelogramShape | TrapezoidShape | PentagonShape | OctagonShape | StarShape | UmlClassShape | UmlInterfaceShape | LineShape | ArrowShape | TextShape | DrawShape | MindMapShape;
206
+ type ToolType = 'select' | 'hand' | 'rectangle' | 'rounded-rectangle' | 'circle' | 'ellipse' | 'diamond' | 'triangle' | 'hexagon' | 'parallelogram' | 'trapezoid' | 'pentagon' | 'octagon' | 'star' | 'uml-class' | 'uml-interface' | 'line' | 'arrow' | 'text' | 'draw' | 'pen' | 'highlighter' | 'eraser' | 'mind-map';
186
207
  interface CameraState {
187
208
  x: number;
188
209
  y: number;
@@ -194,6 +215,11 @@ interface EditorState {
194
215
  activeTool: ToolType;
195
216
  camera: CameraState;
196
217
  }
218
+ /** 对外对接数据:图形 + 相机(用于 data 初始化 / onChange 回调 / getData) */
219
+ interface EditorData {
220
+ shapes: Shape[];
221
+ camera: CameraState;
222
+ }
197
223
 
198
224
  interface Mat2d {
199
225
  a: number;
@@ -240,6 +266,334 @@ declare class Camera {
240
266
  }, padding?: number): void;
241
267
  }
242
268
 
269
+ /**
270
+ * 主题颜色常量 - 统一管理画布内渲染颜色
271
+ * 默认值在此定义;运行时通过 setTheme() 局部覆盖,修改后全局生效。
272
+ * React 侧主题色(CSS 变量 --dw-*)由 packages/react/src/theme.less 管理,
273
+ * CanvasBoard 的 themeColor 参数会同时写入两套主题源。
274
+ */
275
+ interface DrawuiThemeSelection {
276
+ /** 选中边框颜色 */
277
+ outline: string;
278
+ /** 选中控制点边框颜色 */
279
+ handleStroke: string;
280
+ /** 选中控制点填充颜色 */
281
+ handleFill: string;
282
+ /** 选中区域填充颜色 (半透明) */
283
+ outlineFill: string;
284
+ /** 选中阴影颜色 */
285
+ shadow: string;
286
+ }
287
+ interface DrawuiTheme {
288
+ /** 主题主色(手柄/生成点等强调色) */
289
+ primary: string;
290
+ /** 选中态 */
291
+ selection: DrawuiThemeSelection;
292
+ /** 网格颜色 */
293
+ grid: string;
294
+ /** 默认文字颜色 */
295
+ text: string;
296
+ /** 文本编辑框边框 */
297
+ editBorder: string;
298
+ /** 框选矩形填充/描边 */
299
+ brushFill: string;
300
+ brushStroke: string;
301
+ /** 对齐参考线(浅色虚线) */
302
+ guide: string;
303
+ /** 连线选中高亮辅助线 */
304
+ lineHighlight: string;
305
+ /** 生成点位预览:源点圆点/虚线线条 */
306
+ genDot: string;
307
+ genLine: string;
308
+ }
309
+ /** 主题对象(同一引用,渲染器直接读取;setTheme 就地覆盖字段) */
310
+ declare const THEME: DrawuiTheme;
311
+ type ThemeListener = () => void;
312
+ /** 订阅主题变化(如小地图等 canvas 组件需要据此重绘) */
313
+ declare function subscribeTheme(listener: ThemeListener): () => void;
314
+ /** 局部覆盖主题字段(selection 内字段单独合并) */
315
+ declare function setTheme(theme: Partial<DrawuiTheme>): void;
316
+ /** 获取当前主题(方便未来扩展为动态主题切换) */
317
+ declare function getTheme(): DrawuiTheme;
318
+ /** #rrggbb / #rgb → rgba(r, g, b, a);解析失败原样返回 */
319
+ declare function hexToRgba(hex: string, alpha: number): string;
320
+ /** 颜色变暗/变亮:percent 负数变暗、正数变亮 */
321
+ declare function shadeColor(hex: string, percent: number): string;
322
+
323
+ /**
324
+ * 国际化:框架无关的轻量字典 + 语言切换。
325
+ * React 侧通过 useLanguage() 订阅语言变化自动重渲染。
326
+ */
327
+ type Language = 'zh-CN' | 'en-US';
328
+ declare const dictionaries: {
329
+ readonly 'zh-CN': {
330
+ readonly 'save.success': "已保存";
331
+ readonly 'save.fail': "保存失败";
332
+ readonly 'tool.select': "选择工具";
333
+ readonly 'tool.hand': "拖拽视口";
334
+ readonly 'tool.rectangle': "矩形";
335
+ readonly 'tool.rounded-rectangle': "圆角矩形";
336
+ readonly 'tool.circle': "圆形";
337
+ readonly 'tool.ellipse': "椭圆";
338
+ readonly 'tool.diamond': "菱形";
339
+ readonly 'tool.triangle': "三角形";
340
+ readonly 'tool.hexagon': "六边形";
341
+ readonly 'tool.parallelogram': "平行四边形";
342
+ readonly 'tool.trapezoid': "梯形";
343
+ readonly 'tool.pentagon': "五边形";
344
+ readonly 'tool.octagon': "八边形";
345
+ readonly 'tool.star': "星形";
346
+ readonly 'tool.uml-class': "UML 类图";
347
+ readonly 'tool.uml-interface': "UML 接口";
348
+ readonly 'tool.line': "直线";
349
+ readonly 'tool.arrow': "线条";
350
+ readonly 'tool.text': "文本";
351
+ readonly 'tool.draw': "画笔";
352
+ readonly 'tool.pen': "画笔";
353
+ readonly 'tool.highlighter': "荧光笔";
354
+ readonly 'tool.eraser': "橡皮擦";
355
+ readonly 'status.none': "未选择";
356
+ readonly 'status.selected': "已选择 {n} 个图形";
357
+ readonly 'toolbar.select': "选择 (V)";
358
+ readonly 'toolbar.hand': "拖拽视口 (H)";
359
+ readonly 'toolbar.shapes': "形状";
360
+ readonly 'toolbar.grid': "网格";
361
+ readonly 'toolbar.undo': "撤销 (Ctrl+Z)";
362
+ readonly 'toolbar.redo': "重做 (Ctrl+Shift+Z)";
363
+ readonly 'toolbar.arrow': "箭头";
364
+ readonly 'toolbar.text': "文本";
365
+ readonly 'toolbar.pen': "画笔";
366
+ readonly 'toolbar.highlighter': "荧光笔";
367
+ readonly 'toolbar.eraser': "橡皮擦";
368
+ readonly 'toolbar.uml-class': "UML 类图";
369
+ readonly 'toolbar.uml-interface': "UML 接口";
370
+ readonly 'zoom.in': "放大";
371
+ readonly 'zoom.out': "缩小";
372
+ readonly 'zoom.reset': "重置";
373
+ readonly 'style.stroke': "边框";
374
+ readonly 'style.fill': "填充";
375
+ readonly 'style.text': "文字";
376
+ readonly 'style.highlight': "高亮";
377
+ readonly 'style.none': "无";
378
+ readonly 'style.connection': "连线";
379
+ readonly 'style.arrow': "箭头";
380
+ readonly 'style.dashed': "虚线";
381
+ readonly 'style.solid': "实线";
382
+ readonly 'style.connection.straight': "直线";
383
+ readonly 'style.connection.polyline': "折线";
384
+ readonly 'style.connection.orthogonal': "直角折线";
385
+ readonly 'style.connection.curve': "曲线";
386
+ readonly 'style.arrowhead.none': "无箭头";
387
+ readonly 'style.arrowhead.end': "终点箭头";
388
+ readonly 'style.arrowhead.start': "起点箭头";
389
+ readonly 'style.arrowhead.both': "双箭头";
390
+ readonly 'style.arrowhead.inheritance': "继承";
391
+ readonly 'style.arrowhead.composition': "组合";
392
+ readonly 'style.arrowhead.aggregation': "聚合";
393
+ readonly 'menu.title': "选择新图形";
394
+ readonly 'menu.cancel': "点击空白处取消";
395
+ readonly 'shape.rectangle': "矩形";
396
+ readonly 'shape.rounded-rectangle': "圆角";
397
+ readonly 'shape.circle': "圆形";
398
+ readonly 'shape.ellipse': "椭圆";
399
+ readonly 'shape.diamond': "菱形";
400
+ readonly 'shape.triangle': "三角";
401
+ readonly 'shape.hexagon': "六边形";
402
+ readonly 'shape.parallelogram': "平行";
403
+ readonly 'shape.trapezoid': "梯形";
404
+ readonly 'shape.pentagon': "五边形";
405
+ readonly 'shape.octagon': "八边形";
406
+ readonly 'shape.star': "星形";
407
+ readonly 'shape.uml-class': "类图";
408
+ readonly 'shape.uml-interface': "接口";
409
+ readonly 'uml.drag': "拖拽排序";
410
+ readonly 'uml.delete': "删除该行";
411
+ readonly 'uml.textColor': "文字颜色";
412
+ readonly 'uml.defaultColor': "默认颜色";
413
+ readonly 'uml.fontSize': "字号";
414
+ readonly 'uml.strikethrough': "删除线";
415
+ readonly 'uml.attribute': "属性";
416
+ readonly 'uml.method': "方法";
417
+ readonly 'minimap.title': "小地图";
418
+ readonly 'minimap.expand': "展开小地图";
419
+ readonly 'minimap.collapse': "收起小地图";
420
+ readonly 'tool.mind-map': "思维导图";
421
+ readonly 'toolbar.mind-map': "思维导图";
422
+ readonly 'toolbar.export': "导出";
423
+ readonly 'toolbar.export.png': "PNG 图片";
424
+ readonly 'toolbar.export.svg': "SVG 矢量图";
425
+ readonly 'toolbar.export.pdf': "PDF 文档";
426
+ readonly 'shape.mind-map': "思维导图";
427
+ readonly 'mindmap.defaultRoot': "中心主题";
428
+ readonly 'mindmap.defaultBranch': "分支主题";
429
+ readonly 'mindmap.nodeText': "节点文本";
430
+ readonly 'mindmap.addChild': "子节点";
431
+ readonly 'mindmap.addSibling': "兄弟节点";
432
+ readonly 'mindmap.deleteNode': "删除节点";
433
+ readonly 'mindmap.color': "颜色";
434
+ readonly 'mindmap.levelColor': "默认层级色";
435
+ readonly 'mindmap.icon': "图标";
436
+ readonly 'mindmap.noIcon': "无图标";
437
+ readonly 'mindmap.note': "属性说明";
438
+ readonly 'mindmap.notePlaceholder': "说明内容(可选)";
439
+ readonly 'mindmap.noteColor': "说明颜色";
440
+ readonly 'mindmap.noteColorDefault': "同节点色";
441
+ readonly 'mindmap.collapse': "折叠";
442
+ readonly 'mindmap.expand': "展开";
443
+ readonly 'mindmap.close': "关闭编辑";
444
+ readonly 'mindmap.more': "更多设置";
445
+ };
446
+ readonly 'en-US': {
447
+ readonly 'save.success': "Saved";
448
+ readonly 'save.fail': "Save failed";
449
+ readonly 'tool.select': "Select tool";
450
+ readonly 'tool.hand': "Pan view";
451
+ readonly 'tool.rectangle': "Rectangle";
452
+ readonly 'tool.rounded-rectangle': "Rounded rectangle";
453
+ readonly 'tool.circle': "Circle";
454
+ readonly 'tool.ellipse': "Ellipse";
455
+ readonly 'tool.diamond': "Diamond";
456
+ readonly 'tool.triangle': "Triangle";
457
+ readonly 'tool.hexagon': "Hexagon";
458
+ readonly 'tool.parallelogram': "Parallelogram";
459
+ readonly 'tool.trapezoid': "Trapezoid";
460
+ readonly 'tool.pentagon': "Pentagon";
461
+ readonly 'tool.octagon': "Octagon";
462
+ readonly 'tool.star': "Star";
463
+ readonly 'tool.uml-class': "UML class";
464
+ readonly 'tool.uml-interface': "UML interface";
465
+ readonly 'tool.line': "Line";
466
+ readonly 'tool.arrow': "Line";
467
+ readonly 'tool.text': "Text";
468
+ readonly 'tool.draw': "Pen";
469
+ readonly 'tool.pen': "Pen";
470
+ readonly 'tool.highlighter': "Highlighter";
471
+ readonly 'tool.eraser': "Eraser";
472
+ readonly 'status.none': "Nothing selected";
473
+ readonly 'status.selected': "{n} shapes selected";
474
+ readonly 'toolbar.select': "Select (V)";
475
+ readonly 'toolbar.hand': "Pan view (H)";
476
+ readonly 'toolbar.shapes': "Shapes";
477
+ readonly 'toolbar.grid': "Grid";
478
+ readonly 'toolbar.undo': "Undo (Ctrl+Z)";
479
+ readonly 'toolbar.redo': "Redo (Ctrl+Shift+Z)";
480
+ readonly 'toolbar.arrow': "Arrow";
481
+ readonly 'toolbar.text': "Text";
482
+ readonly 'toolbar.pen': "Pen";
483
+ readonly 'toolbar.highlighter': "Highlighter";
484
+ readonly 'toolbar.eraser': "Eraser";
485
+ readonly 'toolbar.uml-class': "UML class";
486
+ readonly 'toolbar.uml-interface': "UML interface";
487
+ readonly 'zoom.in': "Zoom in";
488
+ readonly 'zoom.out': "Zoom out";
489
+ readonly 'zoom.reset': "Reset";
490
+ readonly 'style.stroke': "Border";
491
+ readonly 'style.fill': "Fill";
492
+ readonly 'style.text': "Text";
493
+ readonly 'style.highlight': "Highlight";
494
+ readonly 'style.none': "None";
495
+ readonly 'style.connection': "Connection";
496
+ readonly 'style.arrow': "Arrow head";
497
+ readonly 'style.dashed': "Dashed";
498
+ readonly 'style.solid': "Solid";
499
+ readonly 'style.connection.straight': "Straight";
500
+ readonly 'style.connection.polyline': "Polyline";
501
+ readonly 'style.connection.orthogonal': "Orthogonal";
502
+ readonly 'style.connection.curve': "Curve";
503
+ readonly 'style.arrowhead.none': "None";
504
+ readonly 'style.arrowhead.end': "End";
505
+ readonly 'style.arrowhead.start': "Start";
506
+ readonly 'style.arrowhead.both': "Both";
507
+ readonly 'style.arrowhead.inheritance': "Inheritance";
508
+ readonly 'style.arrowhead.composition': "Composition";
509
+ readonly 'style.arrowhead.aggregation': "Aggregation";
510
+ readonly 'menu.title': "Create shape";
511
+ readonly 'menu.cancel': "Click empty space to cancel";
512
+ readonly 'shape.rectangle': "Rectangle";
513
+ readonly 'shape.rounded-rectangle': "Rounded";
514
+ readonly 'shape.circle': "Circle";
515
+ readonly 'shape.ellipse': "Ellipse";
516
+ readonly 'shape.diamond': "Diamond";
517
+ readonly 'shape.triangle': "Triangle";
518
+ readonly 'shape.hexagon': "Hexagon";
519
+ readonly 'shape.parallelogram': "Parallelogram";
520
+ readonly 'shape.trapezoid': "Trapezoid";
521
+ readonly 'shape.pentagon': "Pentagon";
522
+ readonly 'shape.octagon': "Octagon";
523
+ readonly 'shape.star': "Star";
524
+ readonly 'shape.uml-class': "Class";
525
+ readonly 'shape.uml-interface': "Interface";
526
+ readonly 'uml.drag': "Drag to reorder";
527
+ readonly 'uml.delete': "Delete row";
528
+ readonly 'uml.textColor': "Text color";
529
+ readonly 'uml.defaultColor': "Default color";
530
+ readonly 'uml.fontSize': "Font size";
531
+ readonly 'uml.strikethrough': "Strikethrough";
532
+ readonly 'uml.attribute': "Attributes";
533
+ readonly 'uml.method': "Methods";
534
+ readonly 'minimap.title': "Minimap";
535
+ readonly 'minimap.expand': "Expand minimap";
536
+ readonly 'minimap.collapse': "Collapse minimap";
537
+ readonly 'tool.mind-map': "Mind map";
538
+ readonly 'toolbar.mind-map': "Mind map";
539
+ readonly 'toolbar.export': "Export";
540
+ readonly 'toolbar.export.png': "PNG image";
541
+ readonly 'toolbar.export.svg': "SVG vector";
542
+ readonly 'toolbar.export.pdf': "PDF document";
543
+ readonly 'shape.mind-map': "Mind map";
544
+ readonly 'mindmap.defaultRoot': "Central topic";
545
+ readonly 'mindmap.defaultBranch': "Branch topic";
546
+ readonly 'mindmap.nodeText': "Node text";
547
+ readonly 'mindmap.addChild': "Child";
548
+ readonly 'mindmap.addSibling': "Sibling";
549
+ readonly 'mindmap.deleteNode': "Delete node";
550
+ readonly 'mindmap.color': "Color";
551
+ readonly 'mindmap.levelColor': "Default level color";
552
+ readonly 'mindmap.icon': "Icon";
553
+ readonly 'mindmap.noIcon': "No icon";
554
+ readonly 'mindmap.note': "Note";
555
+ readonly 'mindmap.notePlaceholder': "Note content (optional)";
556
+ readonly 'mindmap.noteColor': "Note color";
557
+ readonly 'mindmap.noteColorDefault': "Same as node";
558
+ readonly 'mindmap.collapse': "Collapse";
559
+ readonly 'mindmap.expand': "Expand";
560
+ readonly 'mindmap.close': "Close editor";
561
+ readonly 'mindmap.more': "More settings";
562
+ };
563
+ };
564
+ type MessageKey = keyof typeof dictionaries['zh-CN'];
565
+ type LanguageListener = () => void;
566
+ declare function setLanguage(language: Language): void;
567
+ declare function getLanguage(): Language;
568
+ declare function subscribeLanguage(listener: LanguageListener): () => void;
569
+ /** 取文案;{n} 等占位符由 params 替换 */
570
+ declare function t(key: MessageKey, params?: Record<string, string | number>): string;
571
+
572
+ type ExportFormat = 'png' | 'svg' | 'pdf';
573
+ interface ExportOptions {
574
+ /** 输出缩放倍数(仅位图 PNG 生效,默认 2,矢量 SVG 始终无损) */
575
+ scale?: number;
576
+ /** 内容四周留白(页面坐标,默认 24) */
577
+ padding?: number;
578
+ /** 背景色,null = 透明;不传默认白色('#ffffff') */
579
+ background?: string | null;
580
+ }
581
+ /** 计算所有图形的并集包围盒(含留白),用于导出画布尺寸与视口 */
582
+ declare function getContentBounds(shapes: Shape[], padding?: number): {
583
+ x: number;
584
+ y: number;
585
+ width: number;
586
+ height: number;
587
+ };
588
+ /** 把图形渲染到一张离屏 canvas(白底 / 指定缩放)并返回 */
589
+ declare function renderToCanvas(shapes: Shape[], opts?: ExportOptions): HTMLCanvasElement;
590
+ /** 生成完整 SVG 字符串(矢量,全部图形类型)。返回可直接保存为 .svg 的文本。 */
591
+ declare function renderSVGString(shapes: Shape[], opts?: ExportOptions): string;
592
+ /** 导出为 Blob(png/svg/pdf) */
593
+ declare function exportToBlob(shapes: Shape[], format: ExportFormat, opts?: ExportOptions): Promise<Blob>;
594
+ /** 浏览器端触发下载 */
595
+ declare function downloadBlob(blob: Blob, fileName: string): void;
596
+
243
597
  type Listener = () => void;
244
598
  type NotificationListener = (message: string) => void;
245
599
  /** 核心 → React 的 UI 指令事件 */
@@ -251,6 +605,17 @@ type UiEvent = {
251
605
  existingArrowId?: string;
252
606
  defaultShapeType: ShapeType;
253
607
  };
608
+ /** Editor 构造选项:主题色 / 语言 / 初始数据 / 本地持久化开关 */
609
+ interface EditorOptions {
610
+ /** 画布渲染主题色等颜色,见 setTheme */
611
+ theme?: Partial<DrawuiTheme>;
612
+ /** 界面语言(默认 'zh-CN') */
613
+ language?: Language;
614
+ /** 初始图形数据;提供后不再从 localStorage 加载 */
615
+ shapes?: Shape[];
616
+ /** 是否启用 localStorage 持久化(默认 true;提供 shapes 时自动关闭) */
617
+ persist?: boolean;
618
+ }
254
619
  declare class Editor {
255
620
  private canvas;
256
621
  private renderer;
@@ -279,18 +644,26 @@ declare class Editor {
279
644
  private snapGuides;
280
645
  private connectingTargetId;
281
646
  private genPreview;
282
- /** 拖动松开后待确认图形的上下文(配合"选择新图形"菜单) */
283
- private pendingGen;
647
+ private eraserPoint;
648
+ private mindMapEditingShapeId;
649
+ private mindMapSelectedNode;
650
+ private mindMapHoverNode;
284
651
  private renderScheduled;
285
652
  private pointerIsDown;
286
653
  private notifyScheduled;
287
- constructor(canvas: HTMLCanvasElement);
654
+ /** 是否启用 localStorage 持久化 */
655
+ private persist;
656
+ constructor(canvas: HTMLCanvasElement, options?: EditorOptions);
288
657
  private setupEventListeners;
289
658
  private handlePointerDown;
290
659
  private handlePointerMove;
291
660
  private handlePointerUp;
292
661
  /** 根据当前工具的命中结果更新鼠标样式(伸缩手柄↔/↕、拖拽 grabbing 等) */
293
662
  private updateCursor;
663
+ /**
664
+ * 滚轮:普通滚动平移视口(内容跟随常规滚动方向),
665
+ * Ctrl/Cmd + 滚轮以光标为中心缩放,Shift + 滚轮水平平移。
666
+ */
294
667
  private handleWheel;
295
668
  private handleKeyDown;
296
669
  private handleKeyUp;
@@ -359,6 +732,61 @@ declare class Editor {
359
732
  getSelectedUml(): UmlClassShape | UmlInterfaceShape | null;
360
733
  /** 按 id 查找 UML(类图或接口) */
361
734
  private getUmlById;
735
+ /** 获取选中的思维导图(恰好选中一个时) */
736
+ getSelectedMindMap(): MindMapShape | null;
737
+ /** 页面坐标下的思维导图节点命中:返回所在导图与节点 id */
738
+ getMindMapNodeAtPoint(point: Vec2): {
739
+ shapeId: string;
740
+ nodeId: string;
741
+ } | null;
742
+ /** 屏幕坐标(画布左上角为原点)下的思维导图节点命中 */
743
+ getMindMapNodeAtScreenPoint(screenPoint: Vec2): {
744
+ shapeId: string;
745
+ nodeId: string;
746
+ } | null;
747
+ /** 光标语义命中:仅节点框或折叠/展开标记内才命中(节点间空档不命中,避免空白处误显小手) */
748
+ getMindMapCursorHitAtPoint(point: Vec2): {
749
+ shapeId: string;
750
+ nodeId: string;
751
+ } | null;
752
+ /** 选中思维导图节点(不进入编辑态):选中导图并定位节点高亮 */
753
+ selectMindMapNode(shapeId: string, nodeId: string): void;
754
+ /** 当前思维导图编辑态 id(null 表示未在编辑) */
755
+ getMindMapEditingShapeId(): string | null;
756
+ /** 当前选中的思维导图节点 */
757
+ getMindMapSelectedNode(): {
758
+ shapeId: string;
759
+ nodeId: string;
760
+ } | null;
761
+ /** 读取思维导图指定节点(只读引用,勿修改) */
762
+ getMindMapNode(shapeId: string, nodeId: string): MindMapNode | null;
763
+ /** 思维导图某节点在屏幕上的外框矩形(左上角坐标 + 尺寸),用于就地编辑定位 */
764
+ getMindMapNodeScreenRect(shapeId: string, nodeId: string): {
765
+ x: number;
766
+ y: number;
767
+ width: number;
768
+ height: number;
769
+ } | null;
770
+ /** 页面坐标下折叠/展开标记的命中检测(返回所在导图与节点 id) */
771
+ getMindMapCollapseHitAtPoint(point: Vec2): {
772
+ shapeId: string;
773
+ nodeId: string;
774
+ } | null;
775
+ /** 进入思维导图编辑态(双击节点触发):选中导图并定位到节点 */
776
+ beginMindMapEdit(shapeId: string, nodeId: string | null): void;
777
+ /** 退出思维导图编辑态 */
778
+ exitMindMapEdit(): void;
779
+ /** 更新思维导图某节点(文本/颜色/图标/说明等),自动重算布局尺寸。
780
+ * commit=false 时仅应用变更、不写历史(就地文本编辑逐键调用用);首个变更传入 commit=true 形成单个撤销点。 */
781
+ updateMindMapNode(shapeId: string, nodeId: string, patch: Partial<MindMapNode>, commit?: boolean): void;
782
+ /** 给指定节点添加一个子节点 */
783
+ addMindMapChild(shapeId: string, nodeId: string): void;
784
+ /** 给指定节点添加一个兄弟节点(根节点无兄弟) */
785
+ addMindMapSibling(shapeId: string, nodeId: string): void;
786
+ /** 删除指定节点(含子树);删除根节点则移除整个思维导图 */
787
+ deleteMindMapNode(shapeId: string, nodeId: string): void;
788
+ /** 折叠/展开指定节点 */
789
+ toggleMindMapCollapse(shapeId: string, nodeId: string): void;
362
790
  /** 给指定 UML 类追加一条属性 */
363
791
  addUmlAttribute(shapeId: string): void;
364
792
  /** 给指定 UML(类图或接口)追加一条方法 */
@@ -393,10 +821,33 @@ declare class Editor {
393
821
  setActiveTool(tool: ToolType): void;
394
822
  getActiveTool(): ToolType;
395
823
  getShapes(): Shape[];
824
+ /** 导出当前数据(图形 + 相机),供外部保存/对接 */
825
+ getData(): EditorData;
826
+ /** 用外部数据整体替换画布内容(清空选择与历史),返回是否成功 */
827
+ setShapes(shapes: Shape[]): boolean;
828
+ /** 更新画布渲染主题色(选中态/手柄/网格等),立即重绘 */
829
+ setTheme(theme: Partial<DrawuiTheme>): void;
830
+ /** 切换界面语言(核心通知等文案;React 组件通过 useLanguage 自动刷新) */
831
+ setLanguage(language: Language): void;
396
832
  getSelectedIds(): string[];
397
833
  getCamera(): Camera;
398
834
  /** 指针是否处于按下状态(拖拽/画线/框选中) */
399
835
  isPointerDown(): boolean;
836
+ /** 当前画布内容的包围盒(世界坐标,含留白),导出时用于确定画布尺寸与视口 */
837
+ getContentBounds(padding?: number): {
838
+ x: number;
839
+ y: number;
840
+ width: number;
841
+ height: number;
842
+ };
843
+ /**
844
+ * 导出当前画布为图片 Blob。
845
+ * @param format png | svg | pdf
846
+ * @param opts scale(PNG 倍率,默认 2)/ padding(四周留白)/ background(背景色,默认白色,null 透明)
847
+ */
848
+ exportImage(format: ExportFormat, opts?: ExportOptions): Promise<Blob>;
849
+ /** 导出并触发浏览器下载 */
850
+ downloadImage(fileName?: string, format?: ExportFormat, opts?: ExportOptions): Promise<void>;
400
851
  zoomIn(): void;
401
852
  zoomOut(): void;
402
853
  resetZoom(): void;
@@ -449,6 +900,12 @@ declare class Editor {
449
900
  private getShapeScreenBounds;
450
901
  getShapeAtScreenPoint(screenPoint: Vec2): Shape | null;
451
902
  getShapeAtPoint(point: Vec2, excludeId?: string): Shape | null;
903
+ /** 橡皮擦:返回与圆形笔刷相交的所有图形(不含线条的命中由其线段距离判定) */
904
+ getShapesInBrushRadius(point: Vec2, radius: number): Shape[];
905
+ private shapeIntersectsBrush;
906
+ /** 点到线段的最短距离 */
907
+ private pointToSegmentDist;
908
+ setEraserPoint(point: Vec2 | null): void;
452
909
  private isPointInShape;
453
910
  updateArrowBinding(arrowId: string, terminal: 'start' | 'end', targetShapeId: string | null, binding?: ArrowBinding): void;
454
911
  private getClosestHandle;
@@ -470,7 +927,7 @@ declare class Renderer {
470
927
  /** 文本排版缓存:避免每帧对每个字符做 measureText */
471
928
  private textLayoutCache;
472
929
  private static readonly TEXT_CACHE_LIMIT;
473
- constructor(canvas: HTMLCanvasElement);
930
+ constructor(canvas: HTMLCanvasElement, dpr?: number);
474
931
  resize(width: number, height: number): void;
475
932
  setShowGrid(show: boolean): void;
476
933
  render(shapes: Shape[], camera: Camera, selectedIds: Set<string>, brushRect?: {
@@ -478,7 +935,17 @@ declare class Renderer {
478
935
  y: number;
479
936
  width: number;
480
937
  height: number;
481
- } | null, snapGuides?: SnapGuide[], connectingTarget?: string | null, generationPreview?: GenerationPreview | null): void;
938
+ } | null, snapGuides?: SnapGuide[], connectingTarget?: string | null, generationPreview?: GenerationPreview | null, eraserPoint?: Vec2 | null, mindMapSelection?: {
939
+ shapeId: string;
940
+ nodeId: string;
941
+ } | null, mindMapHover?: {
942
+ shapeId: string;
943
+ nodeId: string;
944
+ } | null,
945
+ /** 导出用:非 null 时先以该颜色铺满整块画布(白底等),默认不铺(透明) */
946
+ background?: string | null): void;
947
+ /** 橡皮擦:半透明主色圆 + 主色描边,半径与笔刷命中范围一致(屏幕像素恒定) */
948
+ private drawEraserBrush;
482
949
  /** 连接进行中,高亮目标图形四边中点的可连锚点 */
483
950
  private drawConnectingTargetHighlight;
484
951
  /** 世界坐标下的轴对齐包围盒(未考虑旋转) */
@@ -516,6 +983,15 @@ declare class Renderer {
516
983
  private static readonly CONNECTION_LEAD;
517
984
  /** 连接的源/目标图形作为障碍时使用的避让间距(足够阻挡中段折回穿过,又允许紧邻节点直连) */
518
985
  private static readonly CONNECTED_PAD;
986
+ /**
987
+ * 思维导图:先画连线(父右缘 → 子左缘的平滑曲线),再画节点
988
+ * (白底圆角矩形 + 层级色描边 + 图标/文本/左上角属性说明/折叠标记)。
989
+ */
990
+ private drawMindMap;
991
+ private drawMindMapConnections;
992
+ private drawMindMapNodes;
993
+ /** 按像素宽度截断文本并加省略号 */
994
+ private ellipsizeText;
519
995
  private drawLine;
520
996
  private drawArrow;
521
997
  /** 选中连线 → 在线条上叠加一条高亮辅助线 */
@@ -651,6 +1127,10 @@ interface ToolContext {
651
1127
  panBy(dx: number, dy: number): void;
652
1128
  setCameraPosition(x: number, y: number): void;
653
1129
  getShapeAtPoint(point: Vec2, excludeId?: string): Shape | null;
1130
+ /** 返回与圆形笔刷(圆心 point、半径 radius,世界单位)相交的所有图形,橡皮擦用 */
1131
+ getShapesInBrushRadius(point: Vec2, radius: number): Shape[];
1132
+ /** 设置橡皮擦笔刷位置(画布绘制指示圈;null 清除) */
1133
+ setEraserPoint(point: Vec2 | null): void;
654
1134
  updateArrowBinding(arrowId: string, terminal: 'start' | 'end', targetShapeId: string | null, binding?: ArrowBinding): void;
655
1135
  enterEditing(shapeId: string): void;
656
1136
  exitEditing(): void;
@@ -681,6 +1161,13 @@ interface ToolContext {
681
1161
  highlightColor?: string;
682
1162
  }): void;
683
1163
  updateConnectionType(connectionType: ConnectionType): void;
1164
+ /** 光标语义命中:思维导图节点框或折叠标记内才命中(节点间空档不命中) */
1165
+ getMindMapCursorHitAtPoint(point: Vec2): {
1166
+ shapeId: string;
1167
+ nodeId: string;
1168
+ } | null;
1169
+ /** 选中思维导图节点(不进入编辑态) */
1170
+ selectMindMapNode(shapeId: string, nodeId: string): void;
684
1171
  }
685
1172
  declare abstract class Tool {
686
1173
  abstract type: ToolType;
@@ -758,7 +1245,6 @@ declare class SelectTool extends Tool {
758
1245
  /** 生成拖动:更新预览(线条 + 框)与目标高亮 */
759
1246
  private handleGenerating;
760
1247
  private handleRotating;
761
- private edgeMidpointWorld;
762
1248
  /** 根据绑定信息返回目标图形的实际吸附点 */
763
1249
  private bindingPosition;
764
1250
  private isPointInShape;
@@ -840,7 +1326,7 @@ declare class ShapeTool extends Tool {
840
1326
  onPointerUp(_point: Vec2, _event: PointerEvent): void;
841
1327
  onKeyDown(_event: KeyboardEvent): void;
842
1328
  onKeyUp(_event: KeyboardEvent): void;
843
- getCursor(): string | null;
1329
+ getCursor(point: Vec2): string | null;
844
1330
  }
845
1331
 
846
1332
  declare class LineTool extends Tool {
@@ -905,44 +1391,42 @@ declare class ArrowTool extends Tool {
905
1391
  private getCircleBindingPosition;
906
1392
  }
907
1393
 
1394
+ /** 不同层级节点的默认颜色,超过 6 层后循环复用 */
1395
+ declare const MINDMAP_COLORS: string[];
1396
+ declare const MINDMAP_FONT_SIZE = 14;
1397
+ declare const MINDMAP_NODE_HEIGHT = 40;
1398
+ declare const MINDMAP_MIN_WIDTH = 80;
1399
+ declare const MINDMAP_MAX_WIDTH = 240;
1400
+ interface MindMapNodePos {
1401
+ x: number;
1402
+ y: number;
1403
+ depth: number;
1404
+ width: number;
1405
+ height: number;
1406
+ }
1407
+ interface MindMapLayoutResult {
1408
+ positions: Map<string, MindMapNodePos>;
1409
+ width: number;
1410
+ height: number;
1411
+ }
1412
+ /** 节点颜色:手动设置优先,否则按层级取默认色 */
1413
+ declare function mindMapNodeColor(node: MindMapNode, depth: number): string;
1414
+ /** 节点框尺寸:由文本长度决定(CJK 按全宽估算),图标占位额外加宽 */
1415
+ declare function mindMapNodeSize(node: MindMapNode): {
1416
+ width: number;
1417
+ height: number;
1418
+ };
1419
+ /** 深拷贝节点树(撤销/重做快照用) */
1420
+ declare function cloneMindMapNode(node: MindMapNode): MindMapNode;
1421
+ declare function findMindMapNode(root: MindMapNode, nodeId: string): MindMapNode | null;
1422
+ declare function getMindMapNodeDepth(root: MindMapNode, nodeId: string): number;
1423
+ declare function getMindMapParent(root: MindMapNode, nodeId: string): MindMapNode | null;
1424
+ declare function countMindMapNodes(root: MindMapNode): number;
908
1425
  /**
909
- * 主题颜色常量 - 统一管理所有 UI 颜色
910
- * 修改此处即可全局生效
1426
+ * 横向树布局:根在左,子节点向右展开,每个节点垂直居中于其子树。
1427
+ * 返回以内容包围盒中心为原点的局部坐标(shape.x/y 即该中心),
1428
+ * 便于复用现有选中框/旋转/命中检测逻辑。
911
1429
  */
912
- declare const THEME: {
913
- readonly selection: {
914
- /** 选中边框颜色 */
915
- readonly outline: "#3b82f6";
916
- /** 选中控制点边框颜色 */
917
- readonly handleStroke: "#3b82f6";
918
- /** 选中控制点填充颜色 */
919
- readonly handleFill: "#ffffff";
920
- /** 选中区域填充颜色 (半透明) */
921
- readonly outlineFill: "rgba(59, 130, 246, 0.1)";
922
- /** 选中阴影颜色 */
923
- readonly shadow: "#3b82f6";
924
- };
925
- readonly grid: "#e5e7eb";
926
- readonly text: "#1f2937";
927
- readonly editBorder: "#3b82f6";
928
- };
929
- /** 获取当前主题(方便未来扩展为动态主题切换) */
930
- declare function getTheme(): {
931
- readonly selection: {
932
- /** 选中边框颜色 */
933
- readonly outline: "#3b82f6";
934
- /** 选中控制点边框颜色 */
935
- readonly handleStroke: "#3b82f6";
936
- /** 选中控制点填充颜色 */
937
- readonly handleFill: "#ffffff";
938
- /** 选中区域填充颜色 (半透明) */
939
- readonly outlineFill: "rgba(59, 130, 246, 0.1)";
940
- /** 选中阴影颜色 */
941
- readonly shadow: "#3b82f6";
942
- };
943
- readonly grid: "#e5e7eb";
944
- readonly text: "#1f2937";
945
- readonly editBorder: "#3b82f6";
946
- };
1430
+ declare function layoutMindMap(root: MindMapNode): MindMapLayoutResult;
947
1431
 
948
- export { type ArrowBinding, type ArrowHeadType, type ArrowShape, ArrowTool, Camera, type CameraState, type CircleShape, type ConnectionType, type DiamondShape, type DrawShape, Editor, type EditorState, type EllipseShape, type FreehandMode, FreehandTool, type GenerationContext, HandTool, type HexagonShape, type LineShape, LineTool, Mat2d, type OctagonShape, type ParallelogramShape, type PentagonShape, type Rect, type RectangleShape, Renderer, type RoundedRectangleShape, SelectTool, type Shape, type ShapeStyle, ShapeTool, type ShapeType, type SnapGuide, type StarShape, THEME, type TextShape, type ToolType, type TrapezoidShape, type TriangleShape, UML_FONT_SIZE, UML_HEADER_HEIGHT, UML_LINE_HEIGHT, UML_MIN_WIDTH, UML_PADDING_X, UML_PADDING_Y, type UmlAttribute, type UmlClassShape, type UmlInterfaceShape, type UmlMethod, type UmlVisibility, Vec, type Vec2 as Vec2Type, calcUmlClassSize, getTheme };
1432
+ export { type ArrowBinding, type ArrowHeadType, type ArrowShape, ArrowTool, Camera, type CameraState, type CircleShape, type ConnectionType, type DiamondShape, type DrawShape, type DrawuiTheme, type DrawuiThemeSelection, Editor, type EditorData, type EditorOptions, type EditorState, type EllipseShape, type ExportFormat, type ExportOptions, type FreehandMode, FreehandTool, type GenerationContext, HandTool, type HexagonShape, type Language, type LineShape, LineTool, MINDMAP_COLORS, MINDMAP_FONT_SIZE, MINDMAP_MAX_WIDTH, MINDMAP_MIN_WIDTH, MINDMAP_NODE_HEIGHT, Mat2d, type MessageKey, type MindMapLayoutResult, type MindMapNode, type MindMapNodePos, type MindMapShape, type OctagonShape, type ParallelogramShape, type PentagonShape, type Rect, type RectangleShape, Renderer, type RoundedRectangleShape, SelectTool, type Shape, type ShapeStyle, ShapeTool, type ShapeType, type SnapGuide, type StarShape, THEME, type TextShape, type ToolType, type TrapezoidShape, type TriangleShape, UML_FONT_SIZE, UML_HEADER_HEIGHT, UML_LINE_HEIGHT, UML_MIN_WIDTH, UML_PADDING_X, UML_PADDING_Y, type UiEvent, type UmlAttribute, type UmlClassShape, type UmlInterfaceShape, type UmlMethod, type UmlVisibility, Vec, type Vec2 as Vec2Type, calcUmlClassSize, cloneMindMapNode, countMindMapNodes, downloadBlob, exportToBlob, findMindMapNode, getContentBounds, getLanguage, getMindMapNodeDepth, getMindMapParent, getTheme, hexToRgba, layoutMindMap, mindMapNodeColor, mindMapNodeSize, renderSVGString, renderToCanvas, setLanguage, setTheme, shadeColor, subscribeLanguage, subscribeTheme, t };