drawui-core 0.4.2 → 0.5.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/README.md +46 -0
- package/dist/index.cjs +27 -27
- package/dist/index.d.cts +480 -57
- package/dist/index.d.ts +480 -57
- package/dist/index.js +27 -27
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -18,7 +18,7 @@ interface ShapeStyle {
|
|
|
18
18
|
/** 描边色透明度(0-1),缺省为 1;与 strokeColor 叠加使用 */
|
|
19
19
|
strokeOpacity?: number;
|
|
20
20
|
}
|
|
21
|
-
type ShapeType = 'rectangle' | 'rounded-rectangle' | 'circle' | 'ellipse' | 'diamond' | 'triangle' | 'hexagon' | 'parallelogram' | 'trapezoid' | 'pentagon' | 'octagon' | 'star' | 'cylinder' | 'cloud' | 'heart' | 'block-arrow-right' | 'block-arrow-left' | 'block-arrow-up' | 'block-arrow-down' | 'block-arrow-double' | 'right-triangle' | 'cross' | 'speech-rect' | 'speech-round' | 'cube' | 'sector' | 'delay' | 'predefined-process' | 'document' | 'stadium' | 'class-catalog' | 'chevron' | 'brace-left' | 'brace-right' | 'envelope' | 'checkbox' | 'sticky-note' | 'triangular-pyramid' | 'quadrangular-pyramid' | 'cuboid' | 'sphere' | 'ellipsoid' | 'pie' | 'hollow-pie' | 'uml-class' | 'uml-interface' | 'mind-map' | 'table' | 'icon' | 'line' | 'arrow' | 'text' | 'draw';
|
|
21
|
+
type ShapeType = 'rectangle' | 'rounded-rectangle' | 'circle' | 'ellipse' | 'diamond' | 'triangle' | 'hexagon' | 'parallelogram' | 'trapezoid' | 'pentagon' | 'octagon' | 'star' | 'cylinder' | 'cloud' | 'heart' | 'block-arrow-right' | 'block-arrow-left' | 'block-arrow-up' | 'block-arrow-down' | 'block-arrow-double' | 'right-triangle' | 'cross' | 'speech-rect' | 'speech-round' | 'cube' | 'sector' | 'delay' | 'predefined-process' | 'document' | 'stadium' | 'class-catalog' | 'chevron' | 'brace-left' | 'brace-right' | 'envelope' | 'checkbox' | 'sticky-note' | 'triangular-pyramid' | 'quadrangular-pyramid' | 'cuboid' | 'sphere' | 'ellipsoid' | 'pie' | 'hollow-pie' | 'uml-class' | 'uml-interface' | 'mind-map' | 'table' | 'icon' | 'line' | 'arrow' | 'text' | 'draw' | 'image';
|
|
22
22
|
interface BaseShape {
|
|
23
23
|
id: string;
|
|
24
24
|
type: ShapeType;
|
|
@@ -167,6 +167,23 @@ interface IconShape extends BaseShape {
|
|
|
167
167
|
* 尺寸模型与矩形完全一致(以 (x,y) 为中心 + width/height),差异只在轮廓,
|
|
168
168
|
* 轮廓定义见 `shapePaths.ts`,canvas 与 SVG 导出共用。
|
|
169
169
|
*/
|
|
170
|
+
/**
|
|
171
|
+
* 图片图形:`src` 是图片地址 —— 可以是第三方上传接口返回的远端 URL,
|
|
172
|
+
* 也可以是本地上传的临时地址(`blob:`/`data:`,此时 `temporary: true`,刷新即失效)。
|
|
173
|
+
*/
|
|
174
|
+
interface ImageShape extends BaseShape {
|
|
175
|
+
type: 'image';
|
|
176
|
+
width: number;
|
|
177
|
+
height: number;
|
|
178
|
+
src: string;
|
|
179
|
+
/** src 是本地临时地址(blob:/data:),没有配置上传接口时的兜底,刷新后失效 */
|
|
180
|
+
temporary?: boolean;
|
|
181
|
+
/** 原始像素宽高:用于等比缩放与「恢复到原始比例」 */
|
|
182
|
+
naturalWidth?: number;
|
|
183
|
+
naturalHeight?: number;
|
|
184
|
+
/** 圆角半径(世界单位) */
|
|
185
|
+
borderRadius?: number;
|
|
186
|
+
}
|
|
170
187
|
interface PathShape extends BaseShape {
|
|
171
188
|
type: 'block-arrow-double' | 'right-triangle' | 'cross' | 'speech-rect' | 'speech-round' | 'cube' | 'sector' | 'delay' | 'predefined-process' | 'document' | 'class-catalog' | 'chevron' | 'brace-left' | 'brace-right' | 'envelope' | 'checkbox' | 'triangular-pyramid' | 'quadrangular-pyramid' | 'cuboid' | 'sphere' | 'ellipsoid' | 'pie' | 'hollow-pie';
|
|
172
189
|
width: number;
|
|
@@ -237,6 +254,11 @@ interface GenerationPreview {
|
|
|
237
254
|
to: Vec2;
|
|
238
255
|
/** 待放置图形的类型;不提供(指向已有图形)时只画线条 */
|
|
239
256
|
type?: ShapeType;
|
|
257
|
+
/** 待放置图形的尺寸(同型生成时沿用源图形尺寸,虚框必须按它画才与最终一致) */
|
|
258
|
+
size?: {
|
|
259
|
+
width: number;
|
|
260
|
+
height: number;
|
|
261
|
+
};
|
|
240
262
|
/** 源图形 id 与出线边:预览走与最终创建相同的「出线边同轴接入」路由 */
|
|
241
263
|
sourceShapeId?: string;
|
|
242
264
|
sourceEdge?: 'n' | 'e' | 's' | 'w';
|
|
@@ -323,6 +345,7 @@ interface DrawShape extends BaseShape {
|
|
|
323
345
|
points: Vec2[];
|
|
324
346
|
}
|
|
325
347
|
/** 思维导图节点:可带子节点;颜色/图标/属性说明均可手动覆盖,默认取层级色 */
|
|
348
|
+
type MindMapDirection = 'right' | 'left' | 'up' | 'down';
|
|
326
349
|
interface MindMapNode {
|
|
327
350
|
id: string;
|
|
328
351
|
text: string;
|
|
@@ -336,6 +359,13 @@ interface MindMapNode {
|
|
|
336
359
|
noteColor?: string;
|
|
337
360
|
collapsed?: boolean;
|
|
338
361
|
children?: MindMapNode[];
|
|
362
|
+
/** 该节点相对于父节点的生长方向;根节点无方向,子节点继承父方向(缺省为 right) */
|
|
363
|
+
direction?: MindMapDirection;
|
|
364
|
+
/** 手动拖拽产生的偏移(导图局部坐标,相对自动布局位置);拖拽节点时连子树一起平移 */
|
|
365
|
+
offset?: {
|
|
366
|
+
dx: number;
|
|
367
|
+
dy: number;
|
|
368
|
+
};
|
|
339
369
|
}
|
|
340
370
|
interface MindMapShape extends BaseShape {
|
|
341
371
|
type: 'mind-map';
|
|
@@ -373,8 +403,8 @@ interface TableShape extends BaseShape {
|
|
|
373
403
|
/** cells[row][col] */
|
|
374
404
|
cells: TableCell[][];
|
|
375
405
|
}
|
|
376
|
-
type Shape = RectangleShape | RoundedRectangleShape | CircleShape | EllipseShape | DiamondShape | TriangleShape | HexagonShape | ParallelogramShape | TrapezoidShape | PentagonShape | OctagonShape | StarShape | CylinderShape | CloudShape | HeartShape | BlockArrowShape | StadiumShape | StickyNoteShape | IconShape | PathShape | UmlClassShape | UmlInterfaceShape | LineShape | ArrowShape | TextShape | DrawShape | MindMapShape | TableShape;
|
|
377
|
-
type ToolType = 'select' | 'hand' | 'rectangle' | 'rounded-rectangle' | 'circle' | 'ellipse' | 'diamond' | 'triangle' | 'hexagon' | 'parallelogram' | 'trapezoid' | 'pentagon' | 'octagon' | 'star' | 'cylinder' | 'cloud' | 'heart' | 'block-arrow-right' | 'block-arrow-left' | 'block-arrow-up' | 'block-arrow-down' | 'block-arrow-double' | 'right-triangle' | 'cross' | 'speech-rect' | 'speech-round' | 'cube' | 'sector' | 'delay' | 'predefined-process' | 'document' | 'stadium' | 'class-catalog' | 'chevron' | 'brace-left' | 'brace-right' | 'envelope' | 'checkbox' | 'sticky-note' | 'triangular-pyramid' | 'quadrangular-pyramid' | 'cuboid' | 'sphere' | 'ellipsoid' | 'pie' | 'hollow-pie' | 'uml-class' | 'uml-interface' | 'line' | 'arrow' | 'text' | 'draw' | 'pen' | 'highlighter' | 'eraser' | 'mind-map' | 'table' | 'icon';
|
|
406
|
+
type Shape = RectangleShape | RoundedRectangleShape | CircleShape | EllipseShape | DiamondShape | TriangleShape | HexagonShape | ParallelogramShape | TrapezoidShape | PentagonShape | OctagonShape | StarShape | CylinderShape | CloudShape | HeartShape | BlockArrowShape | StadiumShape | StickyNoteShape | IconShape | ImageShape | PathShape | UmlClassShape | UmlInterfaceShape | LineShape | ArrowShape | TextShape | DrawShape | MindMapShape | TableShape;
|
|
407
|
+
type ToolType = 'select' | 'hand' | 'rectangle' | 'rounded-rectangle' | 'circle' | 'ellipse' | 'diamond' | 'triangle' | 'hexagon' | 'parallelogram' | 'trapezoid' | 'pentagon' | 'octagon' | 'star' | 'cylinder' | 'cloud' | 'heart' | 'block-arrow-right' | 'block-arrow-left' | 'block-arrow-up' | 'block-arrow-down' | 'block-arrow-double' | 'right-triangle' | 'cross' | 'speech-rect' | 'speech-round' | 'cube' | 'sector' | 'delay' | 'predefined-process' | 'document' | 'stadium' | 'class-catalog' | 'chevron' | 'brace-left' | 'brace-right' | 'envelope' | 'checkbox' | 'sticky-note' | 'triangular-pyramid' | 'quadrangular-pyramid' | 'cuboid' | 'sphere' | 'ellipsoid' | 'pie' | 'hollow-pie' | 'uml-class' | 'uml-interface' | 'line' | 'arrow' | 'text' | 'draw' | 'pen' | 'highlighter' | 'eraser' | 'mind-map' | 'table' | 'icon' | 'image';
|
|
378
408
|
interface CameraState {
|
|
379
409
|
x: number;
|
|
380
410
|
y: number;
|
|
@@ -392,6 +422,53 @@ interface EditorData {
|
|
|
392
422
|
camera: CameraState;
|
|
393
423
|
}
|
|
394
424
|
|
|
425
|
+
/**
|
|
426
|
+
* 图片上传通道。
|
|
427
|
+
*
|
|
428
|
+
* 两种模式(由接入方决定):
|
|
429
|
+
* A. 配了上传接口 `ImageUploadConfig`(url 必填)→ 由**接入方自己的服务器**接收文件,
|
|
430
|
+
* 返回图片地址,我们拿到地址后只存 URL(刷新不丢)。
|
|
431
|
+
* B. 没配 → 退回**本地临时二进制流**(`URL.createObjectURL(file)`,标记 temporary),
|
|
432
|
+
* 图片只在当前页面内存里有效,刷新即失效。
|
|
433
|
+
*
|
|
434
|
+
* 也支持直接给一个函数(`ImageUploader`):需要签名、分片、转存等自定义逻辑时用它,
|
|
435
|
+
* 优先级高于 URL 配置。
|
|
436
|
+
*/
|
|
437
|
+
|
|
438
|
+
/** 上传通道内置的图片体积上限:30 MB。超过此体积禁止上传,由接入方通过 `maxSizeBytes` 覆盖。 */
|
|
439
|
+
declare const DEFAULT_IMAGE_MAX_SIZE_BYTES: number;
|
|
440
|
+
/** 上传接口配置(走内置 fetch 实现) */
|
|
441
|
+
interface ImageUploadConfig {
|
|
442
|
+
/** 上传地址,例如 https://api.example.com/upload */
|
|
443
|
+
url: string;
|
|
444
|
+
/** 请求方法,默认 POST */
|
|
445
|
+
method?: 'POST' | 'PUT';
|
|
446
|
+
/** 文件字段名,默认 'file' */
|
|
447
|
+
fieldName?: string;
|
|
448
|
+
/** 额外请求头(如 Authorization) */
|
|
449
|
+
headers?: Record<string, string>;
|
|
450
|
+
/** 额外表单字段 */
|
|
451
|
+
fields?: Record<string, string>;
|
|
452
|
+
/** 是否带 cookie,默认 'same-origin' */
|
|
453
|
+
withCredentials?: boolean;
|
|
454
|
+
/** 从响应 JSON 里取 url 的路径,如 'data.url';不填则自动探测 */
|
|
455
|
+
responseUrlPath?: string;
|
|
456
|
+
/** 超时(毫秒),默认 60000 */
|
|
457
|
+
timeoutMs?: number;
|
|
458
|
+
/** 单张图片体积上限(字节)。超过此大小直接抛出 `image.tooLarge`,不会真的发请求。默认 30 MB。 */
|
|
459
|
+
maxSizeBytes?: number;
|
|
460
|
+
}
|
|
461
|
+
/** 自定义上传函数:返回图片可访问的 URL */
|
|
462
|
+
type ImageUploader = (file: File) => Promise<string>;
|
|
463
|
+
type ImageUploadOption = ImageUploadConfig | ImageUploader;
|
|
464
|
+
declare function isUploaderFunction(v: unknown): v is ImageUploader;
|
|
465
|
+
/** 从响应体文本里解析出图片地址(导出给接入方复用时也用得上) */
|
|
466
|
+
declare function parseUploadResponse(body: string, responseUrlPath?: string): string;
|
|
467
|
+
/** 走配置里的 URL 上传文件,返回图片地址 */
|
|
468
|
+
declare function uploadImageViaConfig(file: File, cfg: ImageUploadConfig): Promise<string>;
|
|
469
|
+
/** 从一批图形里找出「本地临时图片」的地址(刷新后会失效,界面可据此提示) */
|
|
470
|
+
declare function collectTemporaryImageSrcs(shapes: Shape[]): string[];
|
|
471
|
+
|
|
395
472
|
interface Mat2d {
|
|
396
473
|
a: number;
|
|
397
474
|
b: number;
|
|
@@ -706,16 +783,23 @@ declare const zhCN: {
|
|
|
706
783
|
readonly 'ctx.sendToBack': "置于底层";
|
|
707
784
|
readonly 'ctx.copyStyle': "复制样式";
|
|
708
785
|
readonly 'ctx.pasteStyle': "粘贴样式";
|
|
709
|
-
readonly 'ctx.
|
|
710
|
-
readonly 'ctx.
|
|
786
|
+
readonly 'ctx.rotate90': "90°";
|
|
787
|
+
readonly 'ctx.rotate180': "180°";
|
|
788
|
+
readonly 'ctx.rotate270': "270°";
|
|
711
789
|
readonly 'ctx.rotate': "旋转";
|
|
712
790
|
readonly 'ctx.group': "成组";
|
|
713
791
|
readonly 'ctx.ungroup': "解组";
|
|
714
792
|
readonly 'ctx.lock': "锁定";
|
|
715
793
|
readonly 'ctx.unlock': "解锁";
|
|
716
|
-
readonly 'ctx.unlockGroup': "解锁本组";
|
|
717
794
|
readonly 'ctx.delete': "删除";
|
|
718
795
|
readonly 'toolbar.icon': "图标";
|
|
796
|
+
readonly 'toolbar.image': "图片";
|
|
797
|
+
readonly 'tool.image': "图片";
|
|
798
|
+
readonly 'image.uploadFailed': "图片上传失败";
|
|
799
|
+
readonly 'image.insertFailed': "图片插入失败";
|
|
800
|
+
readonly 'image.tooLarge': "图片超过 30 MB,无法上传";
|
|
801
|
+
readonly 'image.temporaryInserted': "已插入临时图片(未配置上传接口,刷新后会丢失)";
|
|
802
|
+
readonly 'image.naturalSize': "原图尺寸";
|
|
719
803
|
readonly 'icon.search': "搜索图标";
|
|
720
804
|
readonly 'icon.empty': "没有匹配的图标";
|
|
721
805
|
readonly 'icon.recent': "最近使用";
|
|
@@ -775,7 +859,96 @@ declare function exportToBlob(shapes: Shape[], format: ExportFormat, opts?: Expo
|
|
|
775
859
|
/** 浏览器端触发下载 */
|
|
776
860
|
declare function downloadBlob(blob: Blob, fileName: string): void;
|
|
777
861
|
|
|
778
|
-
|
|
862
|
+
/** 不同层级节点的默认颜色,超过 6 层后循环复用 */
|
|
863
|
+
declare const MINDMAP_COLORS: string[];
|
|
864
|
+
declare const MINDMAP_FONT_SIZE = 14;
|
|
865
|
+
declare const MINDMAP_NODE_HEIGHT = 40;
|
|
866
|
+
declare const MINDMAP_MIN_WIDTH = 80;
|
|
867
|
+
declare const MINDMAP_MAX_WIDTH = 240;
|
|
868
|
+
/** 节点上「+」快捷按钮的圆钮半径(页面单位,随缩放一起放大,与折叠标记一致) */
|
|
869
|
+
declare const MINDMAP_HANDLE_RADIUS = 9;
|
|
870
|
+
/** 「+」圆钮的命中半径(比视觉半径大一点,好点中) */
|
|
871
|
+
declare const MINDMAP_HANDLE_HIT_RADIUS = 12;
|
|
872
|
+
declare const MINDMAP_DIRECTIONS: MindMapDirection[];
|
|
873
|
+
type MindMapHandleKind = 'child' | 'sibling';
|
|
874
|
+
interface MindMapHandlePos {
|
|
875
|
+
kind: MindMapHandleKind;
|
|
876
|
+
/** 该加号对应的子节点生长方向(根节点 child 加号有效;非根节点 child 与节点自身方向一致) */
|
|
877
|
+
direction: MindMapDirection;
|
|
878
|
+
/** 导图局部坐标(与 layoutMindMap 的 positions 同系,相对导图中心) */
|
|
879
|
+
x: number;
|
|
880
|
+
/** 导图局部坐标 */
|
|
881
|
+
y: number;
|
|
882
|
+
}
|
|
883
|
+
interface MindMapNodePos {
|
|
884
|
+
x: number;
|
|
885
|
+
y: number;
|
|
886
|
+
depth: number;
|
|
887
|
+
width: number;
|
|
888
|
+
height: number;
|
|
889
|
+
/** 该节点在布局中的有效生长方向 */
|
|
890
|
+
direction: MindMapDirection;
|
|
891
|
+
}
|
|
892
|
+
interface MindMapLayoutResult {
|
|
893
|
+
positions: Map<string, MindMapNodePos>;
|
|
894
|
+
width: number;
|
|
895
|
+
height: number;
|
|
896
|
+
}
|
|
897
|
+
declare function isHorizontalDirection(d: MindMapDirection): boolean;
|
|
898
|
+
/** 子节点的有效方向:自己显式设置优先,否则继承父方向 */
|
|
899
|
+
declare function effectiveDirection(node: MindMapNode, parentDir?: MindMapDirection): MindMapDirection;
|
|
900
|
+
/** 节点颜色:手动设置优先,否则按层级取默认色 */
|
|
901
|
+
declare function mindMapNodeColor(node: MindMapNode, depth: number): string;
|
|
902
|
+
/** 节点框尺寸:由文本长度决定(CJK 按全宽估算),图标占位额外加宽 */
|
|
903
|
+
declare function mindMapNodeSize(node: MindMapNode): {
|
|
904
|
+
width: number;
|
|
905
|
+
height: number;
|
|
906
|
+
};
|
|
907
|
+
/** 深拷贝节点树(撤销/重做快照用) */
|
|
908
|
+
declare function cloneMindMapNode(node: MindMapNode): MindMapNode;
|
|
909
|
+
declare function findMindMapNode(root: MindMapNode, nodeId: string): MindMapNode | null;
|
|
910
|
+
declare function getMindMapNodeDepth(root: MindMapNode, nodeId: string): number;
|
|
911
|
+
declare function getMindMapParent(root: MindMapNode, nodeId: string): MindMapNode | null;
|
|
912
|
+
declare function countMindMapNodes(root: MindMapNode): number;
|
|
913
|
+
/**
|
|
914
|
+
* 四方向树布局:根节点在中心,子节点可向 right/left/up/down 四个方向展开。
|
|
915
|
+
* 每个子节点继承所在分支的方向;同方向节点按顺序垂直/水平排列。
|
|
916
|
+
* 返回以内容包围盒中心为原点的局部坐标(shape.x/y 即该中心)。
|
|
917
|
+
*/
|
|
918
|
+
declare function layoutMindMap(root: MindMapNode): MindMapLayoutResult;
|
|
919
|
+
/**
|
|
920
|
+
* 活动节点上的「+」快捷按钮位置(导图局部坐标;绘制与命中检测共用这一份规则)。
|
|
921
|
+
*
|
|
922
|
+
* - 根节点:四个方向各一个 child 加号;
|
|
923
|
+
* - 非根节点:一个 child 加号(沿自身生长方向),一个 sibling 加号(水平节点在下方、垂直节点在右方)。
|
|
924
|
+
*/
|
|
925
|
+
declare function mindMapNodeHandles(root: MindMapNode, nodeId: string): MindMapHandlePos[];
|
|
926
|
+
/**
|
|
927
|
+
* 在一份**已算好的布局**上找「+」按钮(局部坐标):整棵树只走一遍,
|
|
928
|
+
* 避免「每个节点各算一次布局」的 O(N²)。命中检测走这个,绘制走 mindMapNodeHandles。
|
|
929
|
+
*/
|
|
930
|
+
declare function mindMapHandleAtLocalPoint(root: MindMapNode, positions: Map<string, MindMapNodePos>, lx: number, ly: number): {
|
|
931
|
+
nodeId: string;
|
|
932
|
+
kind: MindMapHandleKind;
|
|
933
|
+
direction: MindMapDirection;
|
|
934
|
+
} | null;
|
|
935
|
+
/**
|
|
936
|
+
* 获取节点在父节点同方向兄弟列表中的信息。
|
|
937
|
+
* 根节点的子节点按 direction 分组;普通节点的子节点全部继承父方向。
|
|
938
|
+
*/
|
|
939
|
+
declare function getMindMapNodeSiblings(root: MindMapNode, nodeId: string): {
|
|
940
|
+
parent: MindMapNode;
|
|
941
|
+
siblings: MindMapNode[];
|
|
942
|
+
index: number;
|
|
943
|
+
direction: MindMapDirection;
|
|
944
|
+
} | null;
|
|
945
|
+
/**
|
|
946
|
+
* 将指定节点在其同方向兄弟列表中移动到新的索引位置。
|
|
947
|
+
* newIndex 是相对于同 direction siblings 的索引。
|
|
948
|
+
*/
|
|
949
|
+
declare function reorderMindMapNodeInTree(root: MindMapNode, nodeId: string, newIndex: number): MindMapNode;
|
|
950
|
+
|
|
951
|
+
type Listener$1 = () => void;
|
|
779
952
|
type NotificationListener = (message: string) => void;
|
|
780
953
|
/** 核心 → React 的 UI 指令事件 */
|
|
781
954
|
type UiEvent = {
|
|
@@ -785,6 +958,11 @@ type UiEvent = {
|
|
|
785
958
|
context: GenerationContext;
|
|
786
959
|
existingArrowId?: string;
|
|
787
960
|
defaultShapeType: ShapeType;
|
|
961
|
+
}
|
|
962
|
+
/** 图片上传/加载失败(接入方可据此弹 toast) */
|
|
963
|
+
| {
|
|
964
|
+
kind: 'imageError';
|
|
965
|
+
message: string;
|
|
788
966
|
};
|
|
789
967
|
/** Editor 构造选项:主题色 / 语言 / 初始数据 / 本地持久化开关 */
|
|
790
968
|
interface EditorOptions {
|
|
@@ -796,6 +974,14 @@ interface EditorOptions {
|
|
|
796
974
|
shapes?: Shape[];
|
|
797
975
|
/** 是否启用 localStorage 持久化(默认 true;提供 shapes 时自动关闭) */
|
|
798
976
|
persist?: boolean;
|
|
977
|
+
/**
|
|
978
|
+
* 图片上传通道(「图片」按钮 / 粘贴 / 拖入文件时用):
|
|
979
|
+
* - 传 `{ url }` 配置:文件会 POST 到接入方自己的服务器,服务器返回图片地址 → 只存 URL,刷新不丢
|
|
980
|
+
* - 传函数:完全自定义上传(签名、分片、转存等)
|
|
981
|
+
* - 不传:退回**本地临时二进制流**(`URL.createObjectURL`),图形带 `temporary: true`,
|
|
982
|
+
* 图片只活在这个页面里,刷新即失效
|
|
983
|
+
*/
|
|
984
|
+
imageUpload?: ImageUploadOption;
|
|
799
985
|
}
|
|
800
986
|
declare class Editor {
|
|
801
987
|
private canvas;
|
|
@@ -831,6 +1017,20 @@ declare class Editor {
|
|
|
831
1017
|
private mindMapEditingShapeId;
|
|
832
1018
|
private mindMapSelectedNode;
|
|
833
1019
|
private mindMapHoverNode;
|
|
1020
|
+
/** 按下的节点「+」快捷按钮(抬手时若仍在同一按钮上才新建节点) */
|
|
1021
|
+
private pendingMindMapHandle;
|
|
1022
|
+
/**
|
|
1023
|
+
* 按在某个思维导图节点上的拖拽候选:移动超过阈值即开始「同方向重排序」。
|
|
1024
|
+
* 新交互下节点位置由布局决定,拖拽只改变同 direction 兄弟的排列顺序。
|
|
1025
|
+
*/
|
|
1026
|
+
private mindMapNodeDragCandidate;
|
|
1027
|
+
/** 是否已进入「拖动节点」状态(超过阈值后才算,避免单击误触发) */
|
|
1028
|
+
private isNodeDragging;
|
|
1029
|
+
/**
|
|
1030
|
+
* 重排序时的目标插入索引(相对于同 direction siblings);null 表示未确定。
|
|
1031
|
+
* siblingIds 已按 cross 坐标排好序,方便 Renderer 直接画插入指示线。
|
|
1032
|
+
*/
|
|
1033
|
+
private mindMapReorderTarget;
|
|
834
1034
|
private tableSelection;
|
|
835
1035
|
private tableEditing;
|
|
836
1036
|
private renderScheduled;
|
|
@@ -848,6 +1048,16 @@ declare class Editor {
|
|
|
848
1048
|
* 同样「只影响之后创建的便签」;改选中便签的颜色走 updateSelectedShapesStyle。
|
|
849
1049
|
*/
|
|
850
1050
|
private stickyNoteColor;
|
|
1051
|
+
/** 图片上传通道(null = 本地临时 blob 兜底) */
|
|
1052
|
+
private imageUploadOption;
|
|
1053
|
+
/** 图片加载完成 → 重绘的取消订阅函数 */
|
|
1054
|
+
private removeImageReadyListener;
|
|
1055
|
+
/** 本编辑器创建的临时图片地址(blob:),图形删掉后释放 */
|
|
1056
|
+
private ownImageUrls;
|
|
1057
|
+
/** 插入图片的错开步进,避免多张图完全重叠 */
|
|
1058
|
+
private imageInsertSeq;
|
|
1059
|
+
/** Ctrl+V 时若系统剪贴板里是图片,paste 事件已处理 → 跳过一次内部粘贴 */
|
|
1060
|
+
private imagePasteHandled;
|
|
851
1061
|
/** 连续插入图标时的错开计数(避免每次都叠在同一处) */
|
|
852
1062
|
private iconInsertSeq;
|
|
853
1063
|
private clipboardShapes;
|
|
@@ -978,7 +1188,7 @@ declare class Editor {
|
|
|
978
1188
|
/**
|
|
979
1189
|
* 创建"新图形 + 连线":在 to 处放置指定类型图形;若提供了 existingArrowId,
|
|
980
1190
|
* 则把那条(已存在的浮动)线条末端接到新图形,否则新建一条连线。
|
|
981
|
-
*
|
|
1191
|
+
* 新图形样式继承源图形(若有),**同型时尺寸也继承**(见 sourceSize)。
|
|
982
1192
|
*/
|
|
983
1193
|
createGeneratedConnection(context: GenerationContext, options: {
|
|
984
1194
|
type: ShapeType;
|
|
@@ -1027,7 +1237,12 @@ declare class Editor {
|
|
|
1027
1237
|
* 文字/连线/表格/UML/思维导图/便签不支持翻转(isFlippableShapeType),会被跳过。
|
|
1028
1238
|
*/
|
|
1029
1239
|
flipSelected(axis: 'horizontal' | 'vertical'): boolean;
|
|
1030
|
-
/**
|
|
1240
|
+
/**
|
|
1241
|
+
* 按角度旋转选中图形(**顺时针为正**,单位:度)。每个图形绕自身中心转,
|
|
1242
|
+
* 与拖拽旋转手柄一致;整体一步撤销。锁定图形不参与。
|
|
1243
|
+
*/
|
|
1244
|
+
rotateSelected(degrees: number): boolean;
|
|
1245
|
+
/** 选中图形旋转 90°(clockwise=false 为逆时针);保留旧签名,内部走 rotateSelected */
|
|
1031
1246
|
rotateSelected90(clockwise?: boolean): boolean;
|
|
1032
1247
|
/** 锁定/解锁选中图形;锁定后自动取消选中(锁定图形不可选中) */
|
|
1033
1248
|
setSelectedShapesLocked(locked: boolean): boolean;
|
|
@@ -1064,6 +1279,45 @@ declare class Editor {
|
|
|
1064
1279
|
* - 计入撤销历史;图标 id 不存在时返回 undefined(不做任何事)。
|
|
1065
1280
|
*/
|
|
1066
1281
|
insertIcon(iconId: string, size?: number): string | undefined;
|
|
1282
|
+
/** 运行时配置图片上传通道(null = 退回本地临时 blob)。常见于接入方拿到用户配置后再注入 */
|
|
1283
|
+
setImageUpload(option: ImageUploadOption | null): void;
|
|
1284
|
+
getImageUpload(): ImageUploadOption | null;
|
|
1285
|
+
/** 是否配置了上传通道:false 表示插入的图片是本地临时 blob,刷新即失效 */
|
|
1286
|
+
hasImageUploader(): boolean;
|
|
1287
|
+
/** 画布上所有「本地临时图片」的地址(接入方保存前可据此提示「刷新会丢」) */
|
|
1288
|
+
getTemporaryImageSrcs(): string[];
|
|
1289
|
+
hasTemporaryImages(): boolean;
|
|
1290
|
+
/**
|
|
1291
|
+
* 插入一张图片图形(同步)。尺寸按原始像素等比缩放到长边不超过 `IMAGE_MAX_SIDE`;
|
|
1292
|
+
* 拿不到原始尺寸时用 320×240 兜底。返回新图形 id。
|
|
1293
|
+
*/
|
|
1294
|
+
insertImageShape(opts: {
|
|
1295
|
+
src: string;
|
|
1296
|
+
naturalWidth?: number;
|
|
1297
|
+
naturalHeight?: number;
|
|
1298
|
+
temporary?: boolean;
|
|
1299
|
+
at?: Vec2;
|
|
1300
|
+
}): string;
|
|
1301
|
+
/**
|
|
1302
|
+
* 上传(或本地兜底)后插入一张图片:
|
|
1303
|
+
* - 配了上传通道 → 调接入方接口拿远端 URL(`temporary` 不置位,刷新不丢)
|
|
1304
|
+
* - 没配 → `URL.createObjectURL(file)` 本地临时地址(`temporary: true`,刷新即失效)
|
|
1305
|
+
* 上传失败会抛出(错误信息可直接展示给用户);返回新图形 id。
|
|
1306
|
+
*
|
|
1307
|
+
* 单张图片超过 30 MB 会被直接拒绝;`ImageUploadConfig` 可通过 `maxSizeBytes` 自定义上限。
|
|
1308
|
+
*/
|
|
1309
|
+
insertImageFile(file: File, at?: Vec2): Promise<string>;
|
|
1310
|
+
/** 批量插入(工具栏多选 / 拖入多个文件 / 粘贴多张图) */
|
|
1311
|
+
insertImageFiles(files: FileList | File[], at?: Vec2): Promise<string[]>;
|
|
1312
|
+
/** 直接用图片地址插入(已有素材库 / 贴图片链接) */
|
|
1313
|
+
insertImageFromUrl(src: string, at?: Vec2): Promise<string>;
|
|
1314
|
+
/** 释放已经没有任何图形引用的临时图片地址(删除/清空/替换数据后调用) */
|
|
1315
|
+
private releaseUnusedImageUrls;
|
|
1316
|
+
/**
|
|
1317
|
+
* 系统剪贴板粘贴:剪贴板里有图片就直接插图(优先级高于内部图形剪贴板)。
|
|
1318
|
+
* 截图后 Ctrl+V 贴进画布走的就是这里。
|
|
1319
|
+
*/
|
|
1320
|
+
private handlePasteEvent;
|
|
1067
1321
|
/** 视口中心(世界坐标):插入类操作(图标)的默认落点 */
|
|
1068
1322
|
private viewportCenter;
|
|
1069
1323
|
/** 修改「新建便签」的纸面色:只影响之后创建的便签;非法色值会被忽略 */
|
|
@@ -1085,6 +1339,10 @@ declare class Editor {
|
|
|
1085
1339
|
getSelectedUml(): UmlClassShape | UmlInterfaceShape | null;
|
|
1086
1340
|
/** 按 id 查找 UML(类图或接口) */
|
|
1087
1341
|
private getUmlById;
|
|
1342
|
+
/** 页面坐标 → 思维导图局部坐标(逆旋转 + 平移) */
|
|
1343
|
+
private pageToMindMapLocal;
|
|
1344
|
+
/** 计算拖拽节点时,在其同方向兄弟列表中的目标插入索引 */
|
|
1345
|
+
private calcMindMapReorderTarget;
|
|
1088
1346
|
/** 获取选中的思维导图(恰好选中一个时) */
|
|
1089
1347
|
getSelectedMindMap(): MindMapShape | null;
|
|
1090
1348
|
/** 页面坐标下的思维导图节点命中:返回所在导图与节点 id */
|
|
@@ -1097,7 +1355,13 @@ declare class Editor {
|
|
|
1097
1355
|
shapeId: string;
|
|
1098
1356
|
nodeId: string;
|
|
1099
1357
|
} | null;
|
|
1100
|
-
/**
|
|
1358
|
+
/** 精确节点框命中:仅当页面坐标落在某个节点框内才返回该节点,导图空白/间隙返回 null
|
|
1359
|
+
* (区别于 getMindMapNodeAtPoint 的「落在包围盒内就回退根节点」,用于节点拖拽判定) */
|
|
1360
|
+
getMindMapNodeBoxAtPoint(point: Vec2): {
|
|
1361
|
+
shapeId: string;
|
|
1362
|
+
nodeId: string;
|
|
1363
|
+
} | null;
|
|
1364
|
+
/** 光标语义命中:仅节点框(含「+」快捷按钮、折叠/展开标记)内才命中,节点间空档不命中 */
|
|
1101
1365
|
getMindMapCursorHitAtPoint(point: Vec2): {
|
|
1102
1366
|
shapeId: string;
|
|
1103
1367
|
nodeId: string;
|
|
@@ -1125,17 +1389,44 @@ declare class Editor {
|
|
|
1125
1389
|
shapeId: string;
|
|
1126
1390
|
nodeId: string;
|
|
1127
1391
|
} | null;
|
|
1392
|
+
/** 页面坐标下「+」快捷新建按钮的命中检测(子节点 / 同级节点) */
|
|
1393
|
+
getMindMapHandleAtPoint(point: Vec2): {
|
|
1394
|
+
shapeId: string;
|
|
1395
|
+
nodeId: string;
|
|
1396
|
+
kind: MindMapHandleKind;
|
|
1397
|
+
direction: MindMapDirection;
|
|
1398
|
+
} | null;
|
|
1399
|
+
/**
|
|
1400
|
+
* 点「+」快捷按钮:新建子/同级节点并把新节点作为活动节点。
|
|
1401
|
+
* 新需求:点击加号**不进入就地文本编辑**,只添加节点。
|
|
1402
|
+
*/
|
|
1403
|
+
private addMindMapNodeFromHandle;
|
|
1128
1404
|
/** 进入思维导图编辑态(双击节点触发):选中导图并定位到节点 */
|
|
1129
1405
|
beginMindMapEdit(shapeId: string, nodeId: string | null): void;
|
|
1130
|
-
/**
|
|
1406
|
+
/**
|
|
1407
|
+
* 退出思维导图就地文本编辑(输入框收起)。
|
|
1408
|
+
* **活动节点保留**:导图仍被选中时,「+」快捷按钮继续挂在那个节点上,
|
|
1409
|
+
* 方便连续加节点;导图取消选中时由 render 里的钩子把活动节点一并清掉。
|
|
1410
|
+
*/
|
|
1131
1411
|
exitMindMapEdit(): void;
|
|
1132
1412
|
/** 更新思维导图某节点(文本/颜色/图标/说明等),自动重算布局尺寸。
|
|
1133
1413
|
* commit=false 时仅应用变更、不写历史(就地文本编辑逐键调用用);首个变更传入 commit=true 形成单个撤销点。 */
|
|
1134
1414
|
updateMindMapNode(shapeId: string, nodeId: string, patch: Partial<MindMapNode>, commit?: boolean): void;
|
|
1135
|
-
/**
|
|
1136
|
-
|
|
1137
|
-
|
|
1415
|
+
/** 设置思维导图某节点的手动偏移(拖拽用):连子树一起平移;不写历史(调用方在拖拽开始时 commitHistory 一次) */
|
|
1416
|
+
setMindMapNodeOffset(shapeId: string, nodeId: string, offset: {
|
|
1417
|
+
dx: number;
|
|
1418
|
+
dy: number;
|
|
1419
|
+
}): void;
|
|
1420
|
+
/**
|
|
1421
|
+
* 给指定节点添加一个子节点。
|
|
1422
|
+
* - 根节点:必须传入 direction,决定新子节点生长在哪个方向;
|
|
1423
|
+
* - 非根节点:direction 缺省则继承该节点自身方向。
|
|
1424
|
+
*/
|
|
1425
|
+
addMindMapChild(shapeId: string, nodeId: string, direction?: MindMapDirection): void;
|
|
1426
|
+
/** 给指定节点添加一个兄弟节点(根节点无兄弟);兄弟继承该节点方向 */
|
|
1138
1427
|
addMindMapSibling(shapeId: string, nodeId: string): void;
|
|
1428
|
+
/** 将节点在其同方向兄弟列表中移动到目标索引 */
|
|
1429
|
+
reorderMindMapNode(shapeId: string, nodeId: string, targetIndex: number): void;
|
|
1139
1430
|
/** 删除指定节点(含子树);删除根节点则移除整个思维导图 */
|
|
1140
1431
|
deleteMindMapNode(shapeId: string, nodeId: string): void;
|
|
1141
1432
|
/** 折叠/展开指定节点 */
|
|
@@ -1309,6 +1600,14 @@ declare class Editor {
|
|
|
1309
1600
|
width: number;
|
|
1310
1601
|
height: number;
|
|
1311
1602
|
};
|
|
1603
|
+
/** 当前可视区对应的世界坐标范围(用于画板范围、小地图等) */
|
|
1604
|
+
getViewportBounds(): Rect;
|
|
1605
|
+
/**
|
|
1606
|
+
* 画板「应覆盖的范围」(世界坐标):内容包围盒 ∪ 当前可视区,再各加 padding。
|
|
1607
|
+
* 一次性的纯计算,不做任何状态保留;宿主若要「删了图形后延迟缩回」的语义,
|
|
1608
|
+
* 用 `BoardExtentKeeper`(见 core 的 boardExtent.ts)包一层。
|
|
1609
|
+
*/
|
|
1610
|
+
getBoardExtent(padding?: number): Rect;
|
|
1312
1611
|
/**
|
|
1313
1612
|
* 导出当前画布为图片 Blob。
|
|
1314
1613
|
* @param format png | svg | pdf
|
|
@@ -1339,7 +1638,7 @@ declare class Editor {
|
|
|
1339
1638
|
render(): void;
|
|
1340
1639
|
/** 合帧渲染:同一帧内多次调用只会触发一次实际重绘 */
|
|
1341
1640
|
private scheduleRender;
|
|
1342
|
-
subscribe(listener: Listener): () => boolean;
|
|
1641
|
+
subscribe(listener: Listener$1): () => boolean;
|
|
1343
1642
|
subscribeNotifications(listener: NotificationListener): () => boolean;
|
|
1344
1643
|
private notify;
|
|
1345
1644
|
private notifyListeners;
|
|
@@ -1518,6 +1817,12 @@ declare class Renderer {
|
|
|
1518
1817
|
} | null, mindMapHover?: {
|
|
1519
1818
|
shapeId: string;
|
|
1520
1819
|
nodeId: string;
|
|
1820
|
+
} | null, mindMapReorderTarget?: {
|
|
1821
|
+
shapeId: string;
|
|
1822
|
+
nodeId: string;
|
|
1823
|
+
targetIndex: number;
|
|
1824
|
+
direction: MindMapDirection;
|
|
1825
|
+
siblingIds: string[];
|
|
1521
1826
|
} | null,
|
|
1522
1827
|
/** 导出用:非 null 时先以该颜色铺满整块画布(白底等),默认不铺(透明) */
|
|
1523
1828
|
background?: string | null,
|
|
@@ -1570,6 +1875,12 @@ declare class Renderer {
|
|
|
1570
1875
|
* - 线宽用「网格单位」而不是屏幕单位,所以图标放大时线条跟着变粗,像字体图标那样;
|
|
1571
1876
|
* - 用 `Path2D` 直接吃 SVG path 字符串,与 SVG 导出共用同一份路径数据(含圆弧,无需自己解析)。
|
|
1572
1877
|
*/
|
|
1878
|
+
/**
|
|
1879
|
+
* 图片:命中缓存就画,没命中先画占位块(斜线 + 灰底/失败时红底)。
|
|
1880
|
+
* `peekImage()` 会顺手启动异步加载,加载完成后 imageStore 通知 Editor 重绘,
|
|
1881
|
+
* 所以这里不需要任何 await —— 画布永远是同步画一帧。
|
|
1882
|
+
*/
|
|
1883
|
+
private drawImageShape;
|
|
1573
1884
|
private drawIcon;
|
|
1574
1885
|
private drawUmlClass;
|
|
1575
1886
|
/**
|
|
@@ -1595,6 +1906,17 @@ declare class Renderer {
|
|
|
1595
1906
|
private drawMindMap;
|
|
1596
1907
|
private drawMindMapConnections;
|
|
1597
1908
|
private drawMindMapNodes;
|
|
1909
|
+
/**
|
|
1910
|
+
* 节点拖拽重排序时的「落点占位」预览。
|
|
1911
|
+
* 不再只画一条小线,而是在松手后会插入的位置画一个与节点等大的虚线圆角框:
|
|
1912
|
+
* 内边与同方向兄弟对齐、按 CROSS_GAP 让出缝隙,一眼能看出节点会落到哪里。
|
|
1913
|
+
*/
|
|
1914
|
+
private drawMindMapReorderIndicator;
|
|
1915
|
+
/**
|
|
1916
|
+
* 节点上的「+」快捷按钮:实心主色圆 + 白色加号,外圈再套一圈白环,
|
|
1917
|
+
* 让它压在连线上也能被看清楚。位置来自 mindMapNodeHandles(与命中检测同源)。
|
|
1918
|
+
*/
|
|
1919
|
+
private drawMindMapHandles;
|
|
1598
1920
|
/** 按像素宽度截断文本并加省略号 */
|
|
1599
1921
|
private ellipsizeText;
|
|
1600
1922
|
/**
|
|
@@ -1775,6 +2097,14 @@ declare class Renderer {
|
|
|
1775
2097
|
* 独立于选中态 —— 锁定的图形通常选不中,得靠这枚锁告诉用户「它为什么点不动」。
|
|
1776
2098
|
*/
|
|
1777
2099
|
private drawLockBadge;
|
|
2100
|
+
/**
|
|
2101
|
+
* 锁定组的统一标记:整组只画**一把锁**,挂在组包围盒顶部居中,
|
|
2102
|
+
* 而不是组里每个成员各挂一把(一堆锁没法看)。只要组处于锁定状态就画,
|
|
2103
|
+
* 与选中无关(锁定的组本来也选不中,这枚锁就是唯一的视觉提示)。
|
|
2104
|
+
*/
|
|
2105
|
+
private drawGroupLockBadges;
|
|
2106
|
+
/** 在指定位置(徽标左上角,世界坐标)画一枚挂锁徽标 */
|
|
2107
|
+
private drawLockBadgeAt;
|
|
1778
2108
|
/**
|
|
1779
2109
|
* 组外框:选中集恰好是一个完整的组(且不止一个成员)时,给整组描一圈虚线,
|
|
1780
2110
|
* 提示「这些图形是绑在一起的」。整组锁定的成员画不到(成员不可选),不需要外框。
|
|
@@ -1828,8 +2158,12 @@ declare const STICKY_NOTE_DEFAULT_COLOR: string;
|
|
|
1828
2158
|
*/
|
|
1829
2159
|
declare const STICKY_FOLD_RATIO = 0.2;
|
|
1830
2160
|
/**
|
|
1831
|
-
* 便签文字的可用区域缩放:常规内边距 0.85
|
|
1832
|
-
*
|
|
2161
|
+
* 便签文字的可用区域缩放:常规内边距 0.85 再让掉半个折角 = 0.75。
|
|
2162
|
+
*
|
|
2163
|
+
* 为什么这样就够、不需要再把文字整体往左上挪:文字块是**居中**摆放的,
|
|
2164
|
+
* 可用区 0.75 倍时文字块右下角最多落在 (0.875w, 0.875h);而折角三角区是
|
|
2165
|
+
* `Δx/0.2w + Δy/0.2h > 1` 的那一块,把 0.875 代进去是 0.375+0.375 = 0.75 < 1,
|
|
2166
|
+
* **已经在折角斜边之外**。所以居中排版天然不会压到折角。
|
|
1833
2167
|
*/
|
|
1834
2168
|
declare const STICKY_TEXT_SCALE: number;
|
|
1835
2169
|
|
|
@@ -1914,6 +2248,76 @@ declare const ICON_CATEGORY_INK: Record<IconCategoryId, string>;
|
|
|
1914
2248
|
/** 取某个图标的默认墨色:图标自带 ink 优先(全彩贴纸),否则用分类主色,最后退回全局默认 */
|
|
1915
2249
|
declare function iconInk(icon: IconDef): string;
|
|
1916
2250
|
|
|
2251
|
+
/**
|
|
2252
|
+
* 画板范围(Board Extent)—— 宿主用来决定「画板这块 DOM / 可滚区域该多大」。
|
|
2253
|
+
*
|
|
2254
|
+
* 语义(与产品约定一致):
|
|
2255
|
+
* - **长出去就立刻长**:内容跑到更远处时,画板范围马上跟着扩(这合理,不需要等待)。
|
|
2256
|
+
* - **缩回来要谨慎**:内容被删掉后空出来的那块,不能马上收 ——
|
|
2257
|
+
* · 鼠标没动过 → 先不变(否则指针底下的东西会突然跳/滚动位置变了)
|
|
2258
|
+
* · 鼠标动过、但要让出的那块还在可视区里 → 还是不变(用户正看着它)
|
|
2259
|
+
* · 鼠标动过、且要让出的那块已经完全在可视区之外 → 这时才把这块空间收回
|
|
2260
|
+
*
|
|
2261
|
+
* 本文件不碰 DOM,纯几何 + 状态机,宿主(React / 业务容器)拿到结果自己去设尺寸。
|
|
2262
|
+
*/
|
|
2263
|
+
|
|
2264
|
+
declare function isEmptyRect(r: Rect | null | undefined): boolean;
|
|
2265
|
+
/** 两个矩形求并(任一为空则返回另一个的副本) */
|
|
2266
|
+
declare function unionRect(a: Rect | null, b: Rect | null): Rect | null;
|
|
2267
|
+
/** 两个矩形是否相交(边界接触不算相交) */
|
|
2268
|
+
declare function rectsIntersect(a: Rect | null, b: Rect | null): boolean;
|
|
2269
|
+
/** 向内收缩 r,得到「target 之外、r 之内的部分」是否有内容(用于判断「要让出的那块」是否与可视区重叠) */
|
|
2270
|
+
declare function subtractUnion(a: Rect, b: Rect): Rect[];
|
|
2271
|
+
interface BoardExtentUpdate {
|
|
2272
|
+
/** 内容包围盒(世界坐标);没有内容传 null */
|
|
2273
|
+
content: Rect | null;
|
|
2274
|
+
/** 当前可视区(世界坐标) */
|
|
2275
|
+
viewport: Rect;
|
|
2276
|
+
/** 自上次 update 以来指针是否移动过(宿主提供;决定能不能缩回) */
|
|
2277
|
+
pointerMoved: boolean;
|
|
2278
|
+
/** 内容外的留白 */
|
|
2279
|
+
padding?: number;
|
|
2280
|
+
/**
|
|
2281
|
+
* 画板范围是否必须覆盖当前可视区:
|
|
2282
|
+
* - true(默认):相机式画布 —— 画布必须盖住整屏,否则滚动出画面
|
|
2283
|
+
* - false:可滚动画板 —— 范围只跟内容走,空出来的远处空间才有机会被「收回」
|
|
2284
|
+
*/
|
|
2285
|
+
includeViewport?: boolean;
|
|
2286
|
+
/** 内容为空时,画板至少保留这么大(默认 = 一个视口大小) */
|
|
2287
|
+
minSize?: {
|
|
2288
|
+
width: number;
|
|
2289
|
+
height: number;
|
|
2290
|
+
};
|
|
2291
|
+
/** 内容为空时画板回到的位置(默认世界原点)——可滚动画板的「默认画板位置」 */
|
|
2292
|
+
anchor?: {
|
|
2293
|
+
x: number;
|
|
2294
|
+
y: number;
|
|
2295
|
+
};
|
|
2296
|
+
}
|
|
2297
|
+
interface BoardExtentResult {
|
|
2298
|
+
/** 本次应该采用的画板范围 */
|
|
2299
|
+
extent: Rect;
|
|
2300
|
+
/** 相比上次是否有变化(宿主据此决定要不要改 DOM 尺寸 / 滚动位置) */
|
|
2301
|
+
changed: boolean;
|
|
2302
|
+
/** 本次是「长大」还是「缩回」还是没变 */
|
|
2303
|
+
action: 'grow' | 'shrink' | 'hold' | 'init';
|
|
2304
|
+
/** hold 时说明原因(便于调试 / 埋点) */
|
|
2305
|
+
holdReason?: 'pointer-still' | 'still-visible';
|
|
2306
|
+
}
|
|
2307
|
+
/**
|
|
2308
|
+
* 画板范围状态机:调用 `update()` 传入当前内容/可视区/指针状态,拿回应该采用的范围。
|
|
2309
|
+
* 一次会话里保持同一个实例即可。
|
|
2310
|
+
*/
|
|
2311
|
+
declare class BoardExtentKeeper {
|
|
2312
|
+
private current;
|
|
2313
|
+
/** 重置(例如加载了新文档 / 宿主容器尺寸变了) */
|
|
2314
|
+
reset(extent?: Rect | null): void;
|
|
2315
|
+
get(): Rect | null;
|
|
2316
|
+
/** 本次「理想范围」:内容 + 留白;内容为空时退化成「默认画板」那一块 */
|
|
2317
|
+
private desiredOf;
|
|
2318
|
+
update(input: BoardExtentUpdate): BoardExtentResult;
|
|
2319
|
+
}
|
|
2320
|
+
|
|
1917
2321
|
interface ToolContext {
|
|
1918
2322
|
addShape(shape: Shape): void;
|
|
1919
2323
|
updateShape(id: string, updates: Partial<Shape>): void;
|
|
@@ -2144,6 +2548,12 @@ declare class SelectTool extends Tool {
|
|
|
2144
2548
|
/** 生成点位命中阈值 / 单击 vs 拖动判定阈值 */
|
|
2145
2549
|
private static readonly GEN_HIT_THRESHOLD;
|
|
2146
2550
|
private static readonly CLICK_MOVE_THRESHOLD;
|
|
2551
|
+
/**
|
|
2552
|
+
* 「点击锚点生成图形」时源图形与新图形之间的默认间距(页面单位,**边到边**)。
|
|
2553
|
+
* 旧实现是「中心沿法线外移 96」:对默认矩形(120×60)实际边距只有 36,看着太挤;
|
|
2554
|
+
* 现在直接按边距算,取 36 + 40 = 76(用户要求 +40px),且不再随图形大小变化。
|
|
2555
|
+
*/
|
|
2556
|
+
private static readonly GEN_GAP;
|
|
2147
2557
|
/** 支持四边连接锚点的图形类型(矩形类、流程图形、UML 等) */
|
|
2148
2558
|
private static readonly GEN_SUPPORTED_TYPES;
|
|
2149
2559
|
/**
|
|
@@ -2155,8 +2565,18 @@ declare class SelectTool extends Tool {
|
|
|
2155
2565
|
private hitGenPoint;
|
|
2156
2566
|
/** 悬停(未按下)时指针所在的、支持连线锚点的图形 id(已选中的交给选择手柄,返回 null) */
|
|
2157
2567
|
private findHoverAnchorShape;
|
|
2158
|
-
/**
|
|
2568
|
+
/**
|
|
2569
|
+
* 生成点位预览的落点:拖动时跟随光标;静止/悬浮时沿出线方向外移
|
|
2570
|
+
* 「默认间距 GEN_GAP + 新图形在该方向上的半个尺寸」,即**两个图形边到边**留出 GEN_GAP。
|
|
2571
|
+
*/
|
|
2159
2572
|
private genPreviewTarget;
|
|
2573
|
+
/**
|
|
2574
|
+
* 「将要新建的图形」本体(预览虚框 / 避让 / 接入点计算共用):
|
|
2575
|
+
* 尺寸与最终 createGeneratedConnection 创建出来的完全一致(同型时沿用源图形尺寸)。
|
|
2576
|
+
*/
|
|
2577
|
+
private genGhostShape;
|
|
2578
|
+
/** 「将要新建的图形」的尺寸(页面单位) */
|
|
2579
|
+
private genGhostSize;
|
|
2160
2580
|
/** 生成拖动:更新预览(真实样式的连线 + 待放置图形虚框)与目标高亮 */
|
|
2161
2581
|
private handleGenerating;
|
|
2162
2582
|
private handleRotating;
|
|
@@ -2361,44 +2781,6 @@ declare class ArrowTool extends Tool {
|
|
|
2361
2781
|
private getCircleBindingPosition;
|
|
2362
2782
|
}
|
|
2363
2783
|
|
|
2364
|
-
/** 不同层级节点的默认颜色,超过 6 层后循环复用 */
|
|
2365
|
-
declare const MINDMAP_COLORS: string[];
|
|
2366
|
-
declare const MINDMAP_FONT_SIZE = 14;
|
|
2367
|
-
declare const MINDMAP_NODE_HEIGHT = 40;
|
|
2368
|
-
declare const MINDMAP_MIN_WIDTH = 80;
|
|
2369
|
-
declare const MINDMAP_MAX_WIDTH = 240;
|
|
2370
|
-
interface MindMapNodePos {
|
|
2371
|
-
x: number;
|
|
2372
|
-
y: number;
|
|
2373
|
-
depth: number;
|
|
2374
|
-
width: number;
|
|
2375
|
-
height: number;
|
|
2376
|
-
}
|
|
2377
|
-
interface MindMapLayoutResult {
|
|
2378
|
-
positions: Map<string, MindMapNodePos>;
|
|
2379
|
-
width: number;
|
|
2380
|
-
height: number;
|
|
2381
|
-
}
|
|
2382
|
-
/** 节点颜色:手动设置优先,否则按层级取默认色 */
|
|
2383
|
-
declare function mindMapNodeColor(node: MindMapNode, depth: number): string;
|
|
2384
|
-
/** 节点框尺寸:由文本长度决定(CJK 按全宽估算),图标占位额外加宽 */
|
|
2385
|
-
declare function mindMapNodeSize(node: MindMapNode): {
|
|
2386
|
-
width: number;
|
|
2387
|
-
height: number;
|
|
2388
|
-
};
|
|
2389
|
-
/** 深拷贝节点树(撤销/重做快照用) */
|
|
2390
|
-
declare function cloneMindMapNode(node: MindMapNode): MindMapNode;
|
|
2391
|
-
declare function findMindMapNode(root: MindMapNode, nodeId: string): MindMapNode | null;
|
|
2392
|
-
declare function getMindMapNodeDepth(root: MindMapNode, nodeId: string): number;
|
|
2393
|
-
declare function getMindMapParent(root: MindMapNode, nodeId: string): MindMapNode | null;
|
|
2394
|
-
declare function countMindMapNodes(root: MindMapNode): number;
|
|
2395
|
-
/**
|
|
2396
|
-
* 横向树布局:根在左,子节点向右展开,每个节点垂直居中于其子树。
|
|
2397
|
-
* 返回以内容包围盒中心为原点的局部坐标(shape.x/y 即该中心),
|
|
2398
|
-
* 便于复用现有选中框/旋转/命中检测逻辑。
|
|
2399
|
-
*/
|
|
2400
|
-
declare function layoutMindMap(root: MindMapNode): MindMapLayoutResult;
|
|
2401
|
-
|
|
2402
2784
|
/**
|
|
2403
2785
|
* 表格的纯数据操作(唯一实现):行列增删、合并/拆分、命中定位。
|
|
2404
2786
|
*
|
|
@@ -2564,4 +2946,45 @@ declare function umlAttrRowText(a: UmlAttribute): string;
|
|
|
2564
2946
|
/** 方法行:`+ name(params): returnType`;同上 */
|
|
2565
2947
|
declare function umlMethodRowText(m: UmlMethod): string;
|
|
2566
2948
|
|
|
2567
|
-
|
|
2949
|
+
/**
|
|
2950
|
+
* 图片资源仓库:`src` → 已加载的 HTMLImageElement 缓存 + 异步加载 + 就绪回调。
|
|
2951
|
+
*
|
|
2952
|
+
* 设计要点(都是踩过的坑):
|
|
2953
|
+
* - Renderer 是**同步一次性绘制**的,所以绘制时只做 `peekImage()`:命中就画,没命中先画占位;
|
|
2954
|
+
* 加载完成后通过监听者通知(Editor 会把它接到 requestRender 上)自动重绘补齐。
|
|
2955
|
+
* - 远端 http(s) 图片默认加 `crossOrigin='anonymous'`:不加的话画布会被污染(tainted),
|
|
2956
|
+
* 之后 `toDataURL()`/导出会直接抛错。
|
|
2957
|
+
* - 加载失败要**记住失败**,否则每帧都会重新 new Image 去打一个坏地址(疯狂重试)。
|
|
2958
|
+
* - 本地兜底的 `blob:` 地址由我们创建,删除图形时通过 `releaseObjectUrl()` 释放。
|
|
2959
|
+
*/
|
|
2960
|
+
|
|
2961
|
+
interface LoadedImage {
|
|
2962
|
+
img: HTMLImageElement;
|
|
2963
|
+
width: number;
|
|
2964
|
+
height: number;
|
|
2965
|
+
src: string;
|
|
2966
|
+
}
|
|
2967
|
+
type Listener = () => void;
|
|
2968
|
+
/** 图片加载完成/失败时通知(Editor 接到 requestRender)。返回取消订阅函数 */
|
|
2969
|
+
declare function addImageReadyListener(cb: Listener): () => void;
|
|
2970
|
+
/** 配置远端图的 crossOrigin(传 null 表示不加) */
|
|
2971
|
+
declare function setImageCrossOrigin(value: string | null): void;
|
|
2972
|
+
/** 同步取已加载的图片(未加载/失败返回 null,并顺带触发加载) */
|
|
2973
|
+
declare function peekImage(src: string): LoadedImage | null;
|
|
2974
|
+
/** 该地址是否已确认加载失败 */
|
|
2975
|
+
declare function isImageFailed(src: string): boolean;
|
|
2976
|
+
/** 该地址是否正在加载 */
|
|
2977
|
+
declare function isImageLoading(src: string): boolean;
|
|
2978
|
+
/** 加载图片(命中缓存直接返回)。失败返回 null,并记录失败状态 */
|
|
2979
|
+
declare function loadImage(src: string): Promise<LoadedImage | null>;
|
|
2980
|
+
/** 让一批图形里的图片全部就绪(导出前调用,否则导出的图会是空的) */
|
|
2981
|
+
declare function ensureImagesLoaded(shapes: Shape[]): Promise<void>;
|
|
2982
|
+
/**
|
|
2983
|
+
* 取图片的 dataURL(导出 SVG 内嵌用):
|
|
2984
|
+
* 已加载的图片画到离屏 canvas 再 toDataURL;跨域被拒等失败时返回 null(调用方退回原始地址)。
|
|
2985
|
+
*/
|
|
2986
|
+
declare function imageDataUrl(src: string): string | null;
|
|
2987
|
+
/** 清空缓存(测试/卸载时用;会释放自己创建的 blob 地址) */
|
|
2988
|
+
declare function clearImageCache(): void;
|
|
2989
|
+
|
|
2990
|
+
export { type ArrowBinding, type ArrowHeadType, type ArrowShape, type ArrowStyle, ArrowTool, BoardExtentKeeper, type BoardExtentResult, type BoardExtentUpdate, Camera, type CameraState, type CircleShape, type ConnectionType, DEFAULT_HIGHLIGHTER_COLOR, DEFAULT_IMAGE_MAX_SIZE_BYTES, 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, ICONS, ICON_CATEGORIES, ICON_CATEGORY_INK, ICON_DEFAULT_INK, ICON_DEFAULT_SIZE, ICON_GRID, type IconCategoryId, type IconDef, type IconLayer, type IconShape, type ImageShape, type ImageUploadConfig, type ImageUploadOption, type ImageUploader, LANGUAGES, type Language, type LineShape, LineTool, MINDMAP_COLORS, MINDMAP_DIRECTIONS, MINDMAP_FONT_SIZE, MINDMAP_HANDLE_HIT_RADIUS, MINDMAP_HANDLE_RADIUS, MINDMAP_MAX_WIDTH, MINDMAP_MIN_WIDTH, MINDMAP_NODE_HEIGHT, MIN_HANDLE_SEGMENT, MIN_JOG, Mat2d, type MessageKey, type MindMapDirection, type MindMapHandleKind, type MindMapHandlePos, type MindMapLayoutResult, type MindMapNode, type MindMapNodePos, type MindMapShape, type OctagonShape, type ParallelogramShape, type PentagonShape, type Rect, type RectangleShape, Renderer, type RoundedRectangleShape, STICKY_FOLD_RATIO, STICKY_NOTE_COLORS, STICKY_NOTE_DEFAULT_COLOR, STICKY_TEXT_SCALE, type SegmentHandle, SelectTool, type Shape, type ShapeStyle, ShapeTool, type ShapeType, type SnapGuide, type StarShape, type StickyNoteShape, TABLE_CELL_PADDING_X, TABLE_CELL_PADDING_Y, TABLE_DEFAULT_COL_WIDTH, TABLE_DEFAULT_ROW_HEIGHT, TABLE_FONT_SIZE, TABLE_HEADER_FILL, TABLE_LINE_HEIGHT_RATIO, TABLE_MAX_AUTO_LINES, TABLE_MIN_COL_WIDTH, TABLE_MIN_ROW_HEIGHT, TABLE_MOVE_HANDLE_GAP, TABLE_MOVE_HANDLE_HEIGHT, TABLE_MOVE_HANDLE_WIDTH, THEME, type TableCell, type TableShape, 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, addImageReadyListener, calcUmlClassSize, clearImageCache, cloneMindMapNode, cloneTable, cloneTableCells, collapseRoute, collectTemporaryImageSrcs, connectorSegmentHandles, countMindMapNodes, createTableCells, downloadBlob, effectiveDirection, ensureImagesLoaded, exportToBlob, findMindMapNode, getContentBounds, getIcon, getLanguage, getMindMapNodeDepth, getMindMapNodeSiblings, getMindMapParent, getTheme, hasIcon, hexToRgba, hitTableBody, hitTableMoveHandle, iconInk, iconsByCategory, imageDataUrl, isEmptyRect, isFlippableShapeType, isHorizontalDirection, isImageFailed, isImageLoading, isStubCorner, isUploaderFunction, layoutMindMap, loadImage, mindMapHandleAtLocalPoint, mindMapNodeColor, mindMapNodeHandles, mindMapNodeSize, offsetConnectorSegment, parseUploadResponse, peekImage, pickSegmentHandle, pointToSegmentDistance, pruneStubBends, rectsIntersect, renderSVGString, renderToCanvas, reorderMindMapNodeInTree, routeToUserPoints, sameRoute, searchIcons, setImageCrossOrigin, setLanguage, setTheme, shadeColor, subscribeLanguage, subscribeTheme, subtractUnion, t, tableAnchorAt, tableCellAtLocalClamped, tableCellLineCount, tableCellLocalRect, tableCellTextStartOffset, tableCoveredMap, tableDeleteColumn, tableDeleteRow, tableExpandRangeToMerges, tableGrowRowHeights, tableInsertColumn, tableInsertRow, tableLocalPoint, tableMerge, tableMoveHandleLocalRect, tablePagePoint, tableRangeHasMerge, tableRangeLocalRect, tableRowAtPoint, tableSplit, tableSplitRange, tableTotalHeight, tableTotalWidth, umlAttrRowText, umlMethodRowText, unionRect, uploadImageViaConfig };
|