@logicflow/extension 2.0.21 → 2.1.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.
@@ -1,4 +1,5 @@
1
1
  import LogicFlow from '@logicflow/core'
2
+ import { createTeleportContainer } from '@logicflow/vue-node-registry'
2
3
 
3
4
  import Position = LogicFlow.Position
4
5
  import MiniMapOption = MiniMap.MiniMapOption
@@ -355,6 +356,10 @@ export class MiniMap {
355
356
  // minimap中禁用adapter。
356
357
  // this.lfMap.adapterIn = (a) => a
357
358
  // this.lfMap.adapterOut = (a) => a
359
+
360
+ // 创建teleport容器(vue3中生效)
361
+ createTeleportContainer(miniMapWrap, this.lfMap.graphModel.flowId)
362
+
358
363
  this.miniMapWrap = miniMapWrap
359
364
  this.createViewPort()
360
365
  miniMapWrap.addEventListener('click', this.mapClick)
@@ -162,15 +162,27 @@
162
162
  transition: all 120ms ease-in-out;
163
163
  }
164
164
 
165
+ .lf-menu-item {
166
+ display: flex;
167
+ gap: 4px;
168
+ align-items: center;
169
+ justify-content: flex-start;
170
+ list-style: none;
171
+ }
172
+
173
+ .lf-menu-item:hover {
174
+ background: #f3f3f3;
175
+ }
176
+
165
177
  .lf-menu-item__disabled {
166
178
  color: #aaa;
167
- cursor: default;
179
+ cursor: not-allowed !important;
168
180
  opacity: 0.88;
169
- pointer-events: none;
181
+ pointer-events: inherit !important;
170
182
  }
171
183
 
172
- .lf-menu-item:hover {
173
- background: #f3f3f3;
184
+ .lf-menu-item__disabled:hover {
185
+ background: #fff;
174
186
  }
175
187
 
176
188
  /* dndpanel */
package/src/style/raw.ts CHANGED
@@ -142,14 +142,24 @@ export const content = `@import url('medium-editor/dist/css/medium-editor.min.cs
142
142
  cursor: pointer;
143
143
  transition: all 120ms ease-in-out;
144
144
  }
145
+ .lf-menu-item {
146
+ display: flex;
147
+ gap: 4px;
148
+ align-items: center;
149
+ justify-content: flex-start;
150
+ list-style: none;
151
+ }
152
+ .lf-menu-item:hover {
153
+ background: #f3f3f3;
154
+ }
145
155
  .lf-menu-item__disabled {
146
156
  color: #aaa;
147
- cursor: default;
157
+ cursor: not-allowed !important;
148
158
  opacity: 0.88;
149
- pointer-events: none;
159
+ pointer-events: inherit !important;
150
160
  }
151
- .lf-menu-item:hover {
152
- background: #f3f3f3;
161
+ .lf-menu-item__disabled:hover {
162
+ background: #fff;
153
163
  }
154
164
  /* dndpanel */
155
165
  .lf-dndpanel {
@@ -157,15 +157,14 @@ export class Label implements Extension {
157
157
  const textEdit = element.BaseType === 'node' ? nodeTextEdit : edgeTextEdit
158
158
  const textDraggable =
159
159
  element.BaseType === 'node' ? nodeTextDraggable : edgeTextDraggable
160
-
161
160
  return {
162
161
  ...config,
163
162
  zIndex,
164
163
  labelWidth,
165
164
  content: content ?? value,
166
165
  vertical: vertical ?? false,
167
- editable: textEdit && editable,
168
- draggable: textDraggable && draggable,
166
+ editable: Boolean(textEdit) && editable,
167
+ draggable: Boolean(textDraggable) && draggable,
169
168
  textOverflowMode: labelTextOverflowMode ?? textOverflowMode,
170
169
  }
171
170
  })
@@ -347,8 +346,17 @@ export class Label implements Extension {
347
346
  const element = graphModel.getElement(data.id)
348
347
  if (element) {
349
348
  this.rewriteInnerMethods(element)
350
- const formatedLabel = this.formatConfig(graphModel, data)
351
- element.setProperty('_label', formatedLabel)
349
+ // 检查_label是否已经是格式化后的数组格式,如果是则跳过格式化
350
+ // 这样可以避免在复制粘贴时重复处理已经格式化好的label数据
351
+ const currentLabel = element.properties._label
352
+ if (
353
+ !isArray(currentLabel) ||
354
+ currentLabel.length === 0 ||
355
+ !currentLabel[0].id
356
+ ) {
357
+ const formatedLabel = this.formatConfig(graphModel, data)
358
+ element.setProperty('_label', formatedLabel)
359
+ }
352
360
  }
353
361
  })
354
362
  }
@@ -92,7 +92,6 @@ export class ProximityConnect {
92
92
  x: e.clientX,
93
93
  y: e.clientY,
94
94
  })
95
-
96
95
  if (edgeModel && this.virtualEdge) {
97
96
  const { id: virtualEdgeId } = this.virtualEdge as BaseEdgeModel
98
97
  const { targetNodeId } = edgeModel as BaseEdgeModel
@@ -100,7 +99,7 @@ export class ProximityConnect {
100
99
  this.lf.graphModel.getNodeModelById(targetNodeId)
101
100
  if (
102
101
  targetNodeModel &&
103
- isInNode({ x: eventX, y: eventY }, targetNodeModel)
102
+ isInNode({ x: eventX, y: eventY }, targetNodeModel, 10)
104
103
  ) {
105
104
  // 如果当前拖拽点在锚点上,就不触发插件的连线
106
105
  this.lf.deleteEdge(virtualEdgeId)
@@ -306,6 +306,34 @@ export class Snapshot {
306
306
  return rules
307
307
  }
308
308
 
309
+ /**
310
+ * 根据浏览器类型获取Canvas尺寸限制
311
+ * @returns 包含最大主维度和次维度的对象
312
+ */
313
+ private getCanvasDimensionsByBrowser(): {
314
+ maxCanvasDimension: number
315
+ otherMaxCanvasDimension: number
316
+ } {
317
+ const userAgent = navigator.userAgent
318
+
319
+ // 默认值
320
+ let maxCanvasDimension = 65535
321
+ let otherMaxCanvasDimension = 4096
322
+
323
+ if (
324
+ userAgent.indexOf('Chrome') !== -1 ||
325
+ userAgent.indexOf('Edge') !== -1
326
+ ) {
327
+ maxCanvasDimension = 65535
328
+ otherMaxCanvasDimension = 4096
329
+ } else if (userAgent.indexOf('Firefox') !== -1) {
330
+ maxCanvasDimension = 32767
331
+ otherMaxCanvasDimension = 3814
332
+ }
333
+
334
+ return { maxCanvasDimension, otherMaxCanvasDimension }
335
+ }
336
+
309
337
  /**
310
338
  * 将 svg 转化为 canvas
311
339
  * @param svg - svg 元素
@@ -357,12 +385,6 @@ export class Snapshot {
357
385
  const actualWidth = (bbox.width / SCALE_X) * safetyFactor
358
386
  const actualHeight = (bbox.height / SCALE_Y) * safetyFactor
359
387
 
360
- // 将导出区域移动到左上角,canvas 绘制的时候是从左上角开始绘制的
361
- // 在transform矩阵中加入padding值,确保左侧元素不会被截断
362
- ;(copy.lastChild as SVGElement).style.transform = `matrix(1, 0, 0, 1, ${
363
- (-offsetX + TRANSLATE_X) * (1 / SCALE_X) + padding / dpr
364
- }, ${(-offsetY + TRANSLATE_Y) * (1 / SCALE_Y) + padding / dpr})`
365
-
366
388
  // 包含所有元素的最小宽高,确保足够大以容纳所有元素
367
389
  const bboxWidth = Math.ceil(actualWidth)
368
390
  const bboxHeight = Math.ceil(actualHeight)
@@ -373,13 +395,62 @@ export class Snapshot {
373
395
  // 宽高值 默认加padding 40,保证图形不会紧贴着下载图片
374
396
  // 为宽画布添加额外的安全边距,确保不会裁剪
375
397
  const safetyMargin = 40 // 额外的安全边距
376
- canvas.width = bboxWidth * dpr + padding * 2 + safetyMargin
377
- canvas.height = bboxHeight * dpr + padding * 2 + safetyMargin
398
+
399
+ // 获取当前浏览器类型,不同浏览器对canvas的限制不同
400
+ const { maxCanvasDimension, otherMaxCanvasDimension } =
401
+ this.getCanvasDimensionsByBrowser()
402
+ const MAX_CANVAS_DIMENSION = maxCanvasDimension
403
+ const OTHER_MAX_CANVAS_DIMENSION = otherMaxCanvasDimension
404
+
405
+ let targetWidth = bboxWidth * dpr + padding * 2 + safetyMargin
406
+ let targetHeight = bboxHeight * dpr + padding * 2 + safetyMargin
407
+ let scaleWidth = 1 //宽 缩放
408
+ let scaleHeight = 1 //高 缩放
409
+ // 对宽和高分别进行缩放,如chrome,矩形单边最大宽度不超过65535,如宽超过65535,那么高不能超过4096,否则像素会超,也会显示不出。
410
+ if (
411
+ targetWidth > MAX_CANVAS_DIMENSION &&
412
+ targetHeight > OTHER_MAX_CANVAS_DIMENSION
413
+ ) {
414
+ scaleWidth = MAX_CANVAS_DIMENSION / targetWidth
415
+ scaleHeight = OTHER_MAX_CANVAS_DIMENSION / targetHeight
416
+ } else if (
417
+ targetWidth > OTHER_MAX_CANVAS_DIMENSION &&
418
+ targetHeight > MAX_CANVAS_DIMENSION
419
+ ) {
420
+ scaleWidth = OTHER_MAX_CANVAS_DIMENSION / targetWidth
421
+ scaleHeight = MAX_CANVAS_DIMENSION / targetHeight
422
+ } else if (
423
+ targetWidth > MAX_CANVAS_DIMENSION &&
424
+ targetHeight < OTHER_MAX_CANVAS_DIMENSION
425
+ ) {
426
+ scaleHeight = scaleWidth = MAX_CANVAS_DIMENSION / targetWidth
427
+ } else if (
428
+ targetWidth < OTHER_MAX_CANVAS_DIMENSION &&
429
+ targetHeight > MAX_CANVAS_DIMENSION
430
+ ) {
431
+ scaleHeight = scaleWidth = MAX_CANVAS_DIMENSION / targetHeight
432
+ }
433
+
434
+ if (scaleWidth < 1 || scaleHeight < 1) {
435
+ targetWidth = Math.floor(targetWidth * scaleWidth)
436
+ targetHeight = Math.floor(targetHeight * scaleHeight)
437
+ }
438
+ // 将导出区域移动到左上角,canvas 绘制的时候是从左上角开始绘制的
439
+ // 在transform矩阵中加入padding值,确保左侧元素不会被截断
440
+ // 对这个矩阵进行缩放,否则会导致截断
441
+ ;(copy.lastChild as SVGElement).style.transform =
442
+ `matrix(${scaleWidth}, 0, 0, ${scaleHeight}, ${
443
+ (-offsetX + TRANSLATE_X) * (1 / SCALE_X) * scaleWidth + padding / dpr
444
+ }, ${
445
+ (-offsetY + TRANSLATE_Y) * (1 / SCALE_Y) * scaleHeight + padding / dpr
446
+ })`
447
+ canvas.width = targetWidth
448
+ canvas.height = targetHeight
378
449
  const ctx = canvas.getContext('2d')
379
450
  if (ctx) {
380
451
  // 清空canvas
381
452
  ctx.clearRect(0, 0, canvas.width, canvas.height)
382
- ctx.scale(dpr, dpr)
453
+ ctx.scale(dpr * scaleWidth, dpr * scaleHeight)
383
454
  // 如果有背景色,设置流程图导出的背景色
384
455
  if (backgroundColor) {
385
456
  ctx.fillStyle = backgroundColor