@flowgram.ai/free-lines-plugin 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.
@@ -0,0 +1,613 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __decorateClass = (decorators, target, key, kind) => {
4
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
+ if (decorator = decorators[i])
7
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
+ if (kind && result) __defProp(target, key, result);
9
+ return result;
10
+ };
11
+
12
+ // src/components/workflow-port-render/index.tsx
13
+ import ReactDOM from "react-dom";
14
+ import React2, { useEffect, useState } from "react";
15
+ import classNames from "clsx";
16
+ import {
17
+ WorkflowHoverService,
18
+ usePlaygroundReadonlyState,
19
+ WorkflowLinesManager
20
+ } from "@flowgram.ai/free-layout-core";
21
+ import { useService } from "@flowgram.ai/core";
22
+
23
+ // src/constants/points.ts
24
+ var STROKE_WIDTH_SLECTED = 3;
25
+ var STROKE_WIDTH = 2;
26
+ var PORT_BG_CLASS_NAME = "workflow-port-bg";
27
+
28
+ // src/components/workflow-port-render/style.ts
29
+ import styled from "styled-components";
30
+ var WorkflowPointStyle = styled.div`
31
+ width: 20px;
32
+ height: 20px;
33
+ border-radius: 50%;
34
+ margin-top: -10px;
35
+ margin-left: -10px;
36
+ left: 50%;
37
+ top: 50%;
38
+ position: absolute;
39
+ // 非 hover 状态下的样式
40
+ border: none;
41
+
42
+ & > .symbol {
43
+ opacity: 0;
44
+ }
45
+
46
+ .bg-circle {
47
+ display: flex;
48
+ align-items: center;
49
+ justify-content: center;
50
+ position: absolute;
51
+ border-radius: 50%;
52
+ width: 20px;
53
+ height: 20px;
54
+ background-color: #fff;
55
+ transform: scale(0.5);
56
+ transition: all 0.2s linear 0s;
57
+ }
58
+
59
+ .bg {
60
+ display: flex;
61
+ align-items: center;
62
+ justify-content: center;
63
+ position: relative;
64
+ width: 100%;
65
+ height: 100%;
66
+ border-radius: 50%;
67
+ background: #9197F1;
68
+ transform: scale(0.4, 0.4);
69
+ transition: all 0.2s linear 0s;
70
+
71
+ &.hasError {
72
+ background: red;
73
+ }
74
+
75
+ .symbol {
76
+ position: absolute;
77
+ width: 14px;
78
+ height: 14px;
79
+ opacity: 0;
80
+ pointer-events: none;
81
+ color: #fff;
82
+ transition: opacity 0.2s linear 0s;
83
+
84
+ & > svg {
85
+ width: 14px;
86
+ height: 14px;
87
+ }
88
+ }
89
+
90
+ .focus-circle {
91
+ position: absolute;
92
+ display: flex;
93
+ justify-content: center;
94
+ align-items: center;
95
+ width: 8px;
96
+ height: 8px;
97
+ opacity: 0;
98
+ background: #9197f1;
99
+ border-radius: 50%;
100
+ transition: opacity 0.2s linear 0s;
101
+ }
102
+ }
103
+
104
+ &.linked .bg:not(.hasError) {
105
+ background: #4d53e8;
106
+ }
107
+
108
+ &.hovered .bg:not(.hasError) {
109
+ border: none;
110
+ cursor: crosshair;
111
+ transform: scale(1, 1);
112
+ background: #4d53e8;
113
+
114
+ & > .symbol {
115
+ opacity: 1;
116
+ }
117
+ }
118
+
119
+ .cross-hair {
120
+ position: relative;
121
+ left: 2px;
122
+ top: 2px;
123
+
124
+ &::after,
125
+ &::before {
126
+ content: '';
127
+ background: #fff;
128
+ border-radius: 2px;
129
+ position: absolute;
130
+ }
131
+
132
+ &::after {
133
+ left: 4px;
134
+ width: 2px;
135
+ height: 6px;
136
+ box-shadow: 0 4px #fff;
137
+ }
138
+
139
+ &::before {
140
+ top: 4px;
141
+ width: 6px;
142
+ height: 2px;
143
+ box-shadow: 4px 0 #fff;
144
+ }
145
+ `;
146
+
147
+ // src/components/workflow-port-render/cross-hair.tsx
148
+ import React from "react";
149
+ function CrossHair() {
150
+ return /* @__PURE__ */ React.createElement("div", { className: "symbol" }, /* @__PURE__ */ React.createElement("div", { className: "cross-hair" }));
151
+ }
152
+
153
+ // src/components/workflow-port-render/index.tsx
154
+ var WorkflowPortRender = (
155
+ // eslint-disable-next-line react/display-name
156
+ React2.memo((props) => {
157
+ const hoverService = useService(WorkflowHoverService);
158
+ const linesManager = useService(WorkflowLinesManager);
159
+ const { entity, onClick } = props;
160
+ const { portType, relativePosition, disabled } = entity;
161
+ const [targetElement, setTargetElement] = useState(entity.targetElement);
162
+ const [posX, updatePosX] = useState(relativePosition.x);
163
+ const [posY, updatePosY] = useState(relativePosition.y);
164
+ const [hovered, setHovered] = useState(false);
165
+ const [linked, setLinked] = useState(Boolean(entity?.lines?.length));
166
+ const [hasError, setHasError] = useState(props.entity.hasError);
167
+ const readonly = usePlaygroundReadonlyState();
168
+ useEffect(() => {
169
+ entity.validate();
170
+ setHasError(entity.hasError);
171
+ const dispose = entity.onEntityChange(() => {
172
+ if (entity.targetElement) {
173
+ if (entity.targetElement !== targetElement) {
174
+ setTargetElement(entity.targetElement);
175
+ }
176
+ return;
177
+ }
178
+ const newPos = entity.relativePosition;
179
+ updatePosX(Math.round(newPos.x));
180
+ updatePosY(Math.round(newPos.y));
181
+ });
182
+ const dispose2 = hoverService.onHoveredChange((id) => {
183
+ setHovered(hoverService.isHovered(entity.id));
184
+ });
185
+ const dispose3 = entity.onErrorChanged(() => {
186
+ setHasError(entity.hasError);
187
+ });
188
+ const dispose4 = linesManager.onAvailableLinesChange(() => {
189
+ setTimeout(() => {
190
+ if (linesManager.disposed || entity.disposed) return;
191
+ setLinked(Boolean(entity.lines.length));
192
+ }, 0);
193
+ });
194
+ return () => {
195
+ dispose.dispose();
196
+ dispose2.dispose();
197
+ dispose3.dispose();
198
+ dispose4.dispose();
199
+ };
200
+ }, [hoverService, entity, targetElement]);
201
+ const className = classNames(props.className || "", {
202
+ hovered: !readonly && hovered && !disabled && portType !== "input",
203
+ // 有线条链接的时候深蓝色小圆点
204
+ linked
205
+ });
206
+ const content = /* @__PURE__ */ React2.createElement(
207
+ WorkflowPointStyle,
208
+ {
209
+ className,
210
+ style: targetElement ? props.style : { ...props.style, left: posX, top: posY },
211
+ onClick,
212
+ "data-port-entity-id": entity.id,
213
+ "data-port-entity-type": entity.portType,
214
+ "data-testid": "sdk.workflow.canvas.node.port"
215
+ },
216
+ /* @__PURE__ */ React2.createElement("div", { className: classNames("bg-circle", "workflow-bg-circle") }),
217
+ /* @__PURE__ */ React2.createElement(
218
+ "div",
219
+ {
220
+ className: classNames({
221
+ bg: true,
222
+ [PORT_BG_CLASS_NAME]: true,
223
+ "workflow-point-bg": true,
224
+ hasError
225
+ })
226
+ },
227
+ /* @__PURE__ */ React2.createElement(CrossHair, null)
228
+ ),
229
+ /* @__PURE__ */ React2.createElement("div", { className: "focus-circle" })
230
+ );
231
+ if (targetElement) {
232
+ return ReactDOM.createPortal(content, targetElement);
233
+ }
234
+ return content;
235
+ })
236
+ );
237
+
238
+ // src/constants/lines.ts
239
+ var LINE_OFFSET = 6;
240
+
241
+ // src/create-free-lines-plugin.ts
242
+ import { definePluginCreator } from "@flowgram.ai/core";
243
+
244
+ // src/layer/lines-layer.tsx
245
+ import ReactDOM2 from "react-dom";
246
+ import React7, { useLayoutEffect, useState as useState2 } from "react";
247
+ import { inject, injectable } from "inversify";
248
+ import { domUtils } from "@flowgram.ai/utils";
249
+ import {
250
+ nanoid,
251
+ WorkflowDocument,
252
+ WorkflowHoverService as WorkflowHoverService2,
253
+ WorkflowLineEntity,
254
+ WorkflowNodeEntity,
255
+ WorkflowPortEntity,
256
+ WorkflowSelectService
257
+ } from "@flowgram.ai/free-layout-core";
258
+ import { Layer, observeEntities, observeEntityDatas, TransformData } from "@flowgram.ai/core";
259
+
260
+ // src/components/lines/index.tsx
261
+ import React6, { memo } from "react";
262
+ import { LineType } from "@flowgram.ai/free-layout-core";
263
+
264
+ // src/components/lines/fold-line/index.tsx
265
+ import React4 from "react";
266
+ import { POINT_RADIUS } from "@flowgram.ai/free-layout-core";
267
+
268
+ // src/components/lines/index.style.ts
269
+ import styled2 from "styled-components";
270
+ var LineStyle = styled2.div.attrs({
271
+ className: "gedit-flow-activity-edge"
272
+ })`
273
+ position: absolute;
274
+
275
+ @keyframes flowingDash {
276
+ to {
277
+ stroke-dashoffset: -13;
278
+ }
279
+ }
280
+
281
+ .flowing-line {
282
+ stroke-dasharray: 8, 5;
283
+ animation: flowingDash 0.5s linear infinite;
284
+ }
285
+ `;
286
+
287
+ // src/components/lines/arrow/index.tsx
288
+ import React3 from "react";
289
+ function ArrowRenderer({
290
+ id,
291
+ pos,
292
+ reverseArrow,
293
+ strokeWidth,
294
+ vertical,
295
+ hide
296
+ }) {
297
+ if (hide) {
298
+ return null;
299
+ }
300
+ const arrowPath = vertical ? reverseArrow ? `M ${pos.x - LINE_OFFSET},${pos.y} L ${pos.x},${pos.y - LINE_OFFSET} L ${pos.x + LINE_OFFSET},${pos.y}` : `M ${pos.x - LINE_OFFSET},${pos.y - LINE_OFFSET} L ${pos.x},${pos.y} L ${pos.x + LINE_OFFSET},${pos.y - LINE_OFFSET}` : reverseArrow ? `M ${pos.x},${pos.y + LINE_OFFSET} L ${pos.x - LINE_OFFSET},${pos.y} L ${pos.x},${pos.y - LINE_OFFSET}` : `M ${pos.x - LINE_OFFSET},${pos.y - LINE_OFFSET} L ${pos.x},${pos.y} L ${pos.x - LINE_OFFSET},${pos.y + LINE_OFFSET}`;
301
+ return /* @__PURE__ */ React3.createElement(
302
+ "path",
303
+ {
304
+ d: arrowPath,
305
+ strokeLinecap: "round",
306
+ stroke: `url(#${id})`,
307
+ fill: "none",
308
+ strokeWidth
309
+ }
310
+ );
311
+ }
312
+
313
+ // src/components/lines/fold-line/index.tsx
314
+ var FoldLineRender = (props) => {
315
+ const { selected, color, line, children } = props;
316
+ const { to, from } = line.position;
317
+ const strokeWidth = selected ? STROKE_WIDTH_SLECTED : STROKE_WIDTH;
318
+ const arrowToPos = {
319
+ x: to.x - POINT_RADIUS,
320
+ y: to.y
321
+ };
322
+ const arrowFromPos = {
323
+ x: from.x + POINT_RADIUS + LINE_OFFSET,
324
+ y: from.y
325
+ };
326
+ return /* @__PURE__ */ React4.createElement(LineStyle, null, children, /* @__PURE__ */ React4.createElement("svg", { overflow: "visible" }, /* @__PURE__ */ React4.createElement("defs", null, /* @__PURE__ */ React4.createElement(
327
+ "linearGradient",
328
+ {
329
+ x1: "0%",
330
+ y1: "100%",
331
+ x2: "100%",
332
+ y2: "100%",
333
+ id: line.id,
334
+ gradientUnits: "userSpaceOnUse"
335
+ },
336
+ /* @__PURE__ */ React4.createElement("stop", { stopColor: color, offset: "0%" }),
337
+ /* @__PURE__ */ React4.createElement("stop", { stopColor: color, offset: "100%" })
338
+ )), /* @__PURE__ */ React4.createElement("g", null, /* @__PURE__ */ React4.createElement(
339
+ "path",
340
+ {
341
+ d: line.bezier.foldPath,
342
+ fill: "none",
343
+ strokeLinecap: "round",
344
+ stroke: color,
345
+ strokeWidth,
346
+ className: line.flowing || line.processing ? "flowing-line" : ""
347
+ }
348
+ ), /* @__PURE__ */ React4.createElement(
349
+ ArrowRenderer,
350
+ {
351
+ id: line.id,
352
+ reverseArrow: line.reverse,
353
+ pos: line.reverse ? arrowFromPos : arrowToPos,
354
+ strokeWidth,
355
+ hide: line.hideArrow
356
+ }
357
+ ))));
358
+ };
359
+
360
+ // src/components/lines/bezier-line/index.tsx
361
+ import React5 from "react";
362
+ import { POINT_RADIUS as POINT_RADIUS2 } from "@flowgram.ai/free-layout-core";
363
+ var PADDING = 12;
364
+ var BezierLineRender = (props) => {
365
+ const { line, color, fromColor, toColor, selected, children, strokePrefix } = props;
366
+ const { bbox } = line.bezier;
367
+ const { position, reverse, vertical, hideArrow } = line;
368
+ const toRelative = (p) => ({
369
+ x: p.x - bbox.x + PADDING,
370
+ y: p.y - bbox.y + PADDING
371
+ });
372
+ const fromPos = toRelative(position.from);
373
+ const toPos = toRelative(position.to);
374
+ const arrowToPos = vertical ? { x: toPos.x, y: toPos.y - POINT_RADIUS2 } : { x: toPos.x - POINT_RADIUS2, y: toPos.y };
375
+ const arrowFromPos = vertical ? { x: fromPos.x, y: fromPos.y + POINT_RADIUS2 + LINE_OFFSET } : { x: fromPos.x + POINT_RADIUS2 + LINE_OFFSET, y: fromPos.y };
376
+ const controls = line.bezier.controls.map((c) => toRelative(c));
377
+ const getLinearStartColor = () => {
378
+ if (vertical) {
379
+ return fromPos.y < arrowToPos.y ? fromColor : toColor;
380
+ }
381
+ return fromPos.x < arrowToPos.x ? fromColor : toColor;
382
+ };
383
+ const getLinearEndColor = () => {
384
+ if (vertical) {
385
+ return fromPos.y < arrowToPos.y ? toColor : fromColor;
386
+ }
387
+ return fromPos.x < arrowToPos.x ? toColor : fromColor;
388
+ };
389
+ const linearStartColor = getLinearStartColor();
390
+ const linearEndColor = getLinearEndColor();
391
+ const getPathData = () => {
392
+ const controlPoints = controls.map((s) => `${s.x} ${s.y}`).join(",");
393
+ const curveType = controls.length === 1 ? "S" : "C";
394
+ if (vertical) {
395
+ return `M${fromPos.x} ${fromPos.y + POINT_RADIUS2} ${curveType} ${controlPoints}, ${arrowToPos.x} ${arrowToPos.y}`;
396
+ }
397
+ return `M${fromPos.x + POINT_RADIUS2} ${fromPos.y} ${curveType} ${controlPoints}, ${arrowToPos.x} ${arrowToPos.y}`;
398
+ };
399
+ const pathData = getPathData();
400
+ const strokeWidth = selected ? STROKE_WIDTH_SLECTED : STROKE_WIDTH;
401
+ const strokeID = strokePrefix ? `${strokePrefix}-${line.id}` : line.id;
402
+ const path = /* @__PURE__ */ React5.createElement(
403
+ "path",
404
+ {
405
+ d: pathData,
406
+ fill: "none",
407
+ stroke: `url(#${strokeID})`,
408
+ strokeWidth,
409
+ className: line.processing || line.flowing ? "flowing-line" : ""
410
+ }
411
+ );
412
+ return /* @__PURE__ */ React5.createElement(
413
+ LineStyle,
414
+ {
415
+ style: {
416
+ left: bbox.x - PADDING,
417
+ top: bbox.y - PADDING,
418
+ position: "absolute"
419
+ }
420
+ },
421
+ children,
422
+ /* @__PURE__ */ React5.createElement("svg", { width: bbox.width + PADDING * 2, height: bbox.height + PADDING * 2 }, /* @__PURE__ */ React5.createElement("defs", null, /* @__PURE__ */ React5.createElement(
423
+ "linearGradient",
424
+ {
425
+ x1: vertical ? "100%" : "0%",
426
+ y1: vertical ? "0%" : "100%",
427
+ x2: "100%",
428
+ y2: "100%",
429
+ id: strokeID,
430
+ gradientUnits: "userSpaceOnUse"
431
+ },
432
+ /* @__PURE__ */ React5.createElement("stop", { stopColor: color || linearStartColor, offset: "0%" }),
433
+ /* @__PURE__ */ React5.createElement("stop", { stopColor: color || linearEndColor, offset: "100%" })
434
+ )), /* @__PURE__ */ React5.createElement("g", null, path, /* @__PURE__ */ React5.createElement(
435
+ ArrowRenderer,
436
+ {
437
+ id: strokeID,
438
+ reverseArrow: reverse,
439
+ pos: reverse ? arrowFromPos : arrowToPos,
440
+ strokeWidth,
441
+ vertical,
442
+ hide: hideArrow
443
+ }
444
+ ), props.showControlPoints ? controls.map((c, i) => /* @__PURE__ */ React5.createElement("circle", { key: i, cx: c.x, cy: c.y, r: "4", fill: "#ccc" })) : void 0))
445
+ );
446
+ };
447
+
448
+ // src/components/lines/index.tsx
449
+ var LineTypeRender = (props) => {
450
+ if (props.lineType === LineType.LINE_CHART) {
451
+ return /* @__PURE__ */ React6.createElement(FoldLineRender, { ...props });
452
+ }
453
+ return /* @__PURE__ */ React6.createElement(BezierLineRender, { ...props });
454
+ };
455
+ var LineRender = memo(
456
+ LineTypeRender,
457
+ (prevProps, nextProps) => prevProps.version === nextProps.version
458
+ );
459
+
460
+ // src/layer/lines-layer.tsx
461
+ var LinesLayer = class extends Layer {
462
+ constructor() {
463
+ super(...arguments);
464
+ this.layerID = nanoid();
465
+ this.mountedLines = /* @__PURE__ */ new Map();
466
+ this._version = 0;
467
+ /**
468
+ * 节点线条
469
+ */
470
+ this.node = domUtils.createDivWithClass("gedit-playground-layer gedit-flow-lines-layer");
471
+ }
472
+ onZoom(scale) {
473
+ this.node.style.transform = `scale(${scale})`;
474
+ }
475
+ onReady() {
476
+ this.pipelineNode.appendChild(this.node);
477
+ this.toDispose.pushAll([
478
+ this.selectService.onSelectionChanged(() => this.render()),
479
+ this.hoverService.onHoveredChange(() => this.render()),
480
+ this.workflowDocument.linesManager.onForceUpdate(() => {
481
+ this.mountedLines.clear();
482
+ this.bumpVersion();
483
+ this.render();
484
+ })
485
+ ]);
486
+ }
487
+ dispose() {
488
+ this.mountedLines.clear();
489
+ }
490
+ render() {
491
+ const [, forceUpdate] = useState2({});
492
+ useLayoutEffect(() => {
493
+ const updateLines = () => {
494
+ let needsUpdate = false;
495
+ this.lines.forEach((line) => {
496
+ const oldVersion = line.bezierDataVersion;
497
+ line.refreshBezier();
498
+ if (line.bezierDataVersion !== oldVersion) {
499
+ needsUpdate = true;
500
+ }
501
+ });
502
+ if (needsUpdate) {
503
+ forceUpdate({});
504
+ }
505
+ };
506
+ const rafId = requestAnimationFrame(updateLines);
507
+ return () => cancelAnimationFrame(rafId);
508
+ }, [this.lines]);
509
+ const lines = this.lines.map((line) => this.renderLine(line));
510
+ return /* @__PURE__ */ React7.createElement(React7.Fragment, null, lines);
511
+ }
512
+ // 用来绕过 memo
513
+ bumpVersion() {
514
+ this._version = this._version + 1;
515
+ if (this._version === Number.MAX_SAFE_INTEGER) {
516
+ this._version = 0;
517
+ }
518
+ }
519
+ lineProps(line) {
520
+ const { lineType } = this.workflowDocument.linesManager;
521
+ const selected = this.selectService.isSelected(line.id);
522
+ const { version: lineVersion, bezierDataVersion, color } = line;
523
+ const version = `${this._version}:${lineVersion}:${bezierDataVersion}:${lineType}:${color}:${selected}`;
524
+ return {
525
+ key: line.id,
526
+ color: line.color,
527
+ selected,
528
+ line,
529
+ lineType,
530
+ version,
531
+ strokePrefix: this.layerID
532
+ };
533
+ }
534
+ lineComponent(props) {
535
+ const RenderInsideLine = this.options.renderInsideLine ?? (() => /* @__PURE__ */ React7.createElement(React7.Fragment, null));
536
+ return /* @__PURE__ */ React7.createElement(LineRender, { ...props }, /* @__PURE__ */ React7.createElement(RenderInsideLine, { ...props }));
537
+ }
538
+ renderLine(line) {
539
+ const lineProps = this.lineProps(line);
540
+ const cache = this.mountedLines.get(line.id);
541
+ const isCached = cache !== void 0;
542
+ const { portal: cachedPortal, version: cachedVersion } = cache ?? {};
543
+ if (isCached && cachedVersion === lineProps.version) {
544
+ return cachedPortal;
545
+ }
546
+ if (!isCached) {
547
+ this.renderElement.appendChild(line.node);
548
+ line.onDispose(() => {
549
+ this.mountedLines.delete(line.id);
550
+ line.node.remove();
551
+ });
552
+ }
553
+ const portal = ReactDOM2.createPortal(this.lineComponent(lineProps), line.node);
554
+ this.mountedLines.set(line.id, { line, portal, version: lineProps.version });
555
+ return portal;
556
+ }
557
+ get renderElement() {
558
+ if (typeof this.options.renderElement === "function") {
559
+ const element = this.options.renderElement();
560
+ if (element) {
561
+ return element;
562
+ }
563
+ } else if (typeof this.options.renderElement !== "undefined") {
564
+ return this.options.renderElement;
565
+ }
566
+ return this.node;
567
+ }
568
+ };
569
+ LinesLayer.type = "WorkflowLinesLayer";
570
+ __decorateClass([
571
+ inject(WorkflowHoverService2)
572
+ ], LinesLayer.prototype, "hoverService", 2);
573
+ __decorateClass([
574
+ inject(WorkflowSelectService)
575
+ ], LinesLayer.prototype, "selectService", 2);
576
+ __decorateClass([
577
+ observeEntities(WorkflowLineEntity)
578
+ ], LinesLayer.prototype, "lines", 2);
579
+ __decorateClass([
580
+ observeEntities(WorkflowPortEntity)
581
+ ], LinesLayer.prototype, "ports", 2);
582
+ __decorateClass([
583
+ observeEntityDatas(WorkflowNodeEntity, TransformData)
584
+ ], LinesLayer.prototype, "trans", 2);
585
+ __decorateClass([
586
+ inject(WorkflowDocument)
587
+ ], LinesLayer.prototype, "workflowDocument", 2);
588
+ LinesLayer = __decorateClass([
589
+ injectable()
590
+ ], LinesLayer);
591
+
592
+ // src/create-free-lines-plugin.ts
593
+ var createFreeLinesPlugin = definePluginCreator({
594
+ onInit: (ctx, opts) => {
595
+ ctx.playground.registerLayer(LinesLayer, {
596
+ ...opts,
597
+ renderElement: () => {
598
+ if (typeof opts.renderElement === "function") {
599
+ return opts.renderElement(ctx);
600
+ } else {
601
+ return opts.renderElement;
602
+ }
603
+ }
604
+ });
605
+ }
606
+ });
607
+ export {
608
+ LINE_OFFSET,
609
+ LinesLayer,
610
+ WorkflowPortRender,
611
+ createFreeLinesPlugin
612
+ };
613
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/workflow-port-render/index.tsx","../../src/constants/points.ts","../../src/components/workflow-port-render/style.ts","../../src/components/workflow-port-render/cross-hair.tsx","../../src/constants/lines.ts","../../src/create-free-lines-plugin.ts","../../src/layer/lines-layer.tsx","../../src/components/lines/index.tsx","../../src/components/lines/fold-line/index.tsx","../../src/components/lines/index.style.ts","../../src/components/lines/arrow/index.tsx","../../src/components/lines/bezier-line/index.tsx"],"sourcesContent":["import ReactDOM from 'react-dom';\nimport React, { useEffect, useState } from 'react';\n\nimport classNames from 'clsx';\nimport {\n WorkflowHoverService,\n type WorkflowPortEntity,\n usePlaygroundReadonlyState,\n WorkflowLinesManager,\n} from '@flowgram.ai/free-layout-core';\nimport { useService } from '@flowgram.ai/core';\n\nimport { PORT_BG_CLASS_NAME } from '../../constants/points';\nimport { WorkflowPointStyle } from './style';\nimport CrossHair from './cross-hair';\n\nexport interface WorkflowPortRenderProps {\n entity: WorkflowPortEntity;\n className?: string;\n style?: React.CSSProperties;\n onClick?: React.MouseEventHandler<HTMLDivElement>;\n}\n\nexport const WorkflowPortRender: React.FC<WorkflowPortRenderProps> =\n // eslint-disable-next-line react/display-name\n React.memo<WorkflowPortRenderProps>((props: WorkflowPortRenderProps) => {\n const hoverService = useService<WorkflowHoverService>(WorkflowHoverService);\n const linesManager = useService<WorkflowLinesManager>(WorkflowLinesManager);\n const { entity, onClick } = props;\n const { portType, relativePosition, disabled } = entity;\n const [targetElement, setTargetElement] = useState(entity.targetElement);\n const [posX, updatePosX] = useState(relativePosition.x);\n const [posY, updatePosY] = useState(relativePosition.y);\n const [hovered, setHovered] = useState(false);\n const [linked, setLinked] = useState(Boolean(entity?.lines?.length));\n const [hasError, setHasError] = useState(props.entity.hasError);\n const readonly = usePlaygroundReadonlyState();\n\n useEffect(() => {\n // useEffect 时序问题可能导致 port.hasError 非最新,需重新触发一次 validate\n entity.validate();\n setHasError(entity.hasError);\n const dispose = entity.onEntityChange(() => {\n // 如果有挂载的节点,不需要更新位置信息\n if (entity.targetElement) {\n if (entity.targetElement !== targetElement) {\n setTargetElement(entity.targetElement);\n }\n return;\n }\n const newPos = entity.relativePosition;\n // 加上 round 避免点位抖动\n updatePosX(Math.round(newPos.x));\n updatePosY(Math.round(newPos.y));\n });\n const dispose2 = hoverService.onHoveredChange((id) => {\n setHovered(hoverService.isHovered(entity.id));\n });\n const dispose3 = entity.onErrorChanged(() => {\n setHasError(entity.hasError);\n });\n const dispose4 = linesManager.onAvailableLinesChange(() => {\n setTimeout(() => {\n if (linesManager.disposed || entity.disposed) return;\n setLinked(Boolean(entity.lines.length));\n }, 0);\n });\n return () => {\n dispose.dispose();\n dispose2.dispose();\n dispose3.dispose();\n dispose4.dispose();\n };\n }, [hoverService, entity, targetElement]);\n\n // 监听变化\n const className = classNames(props.className || '', {\n hovered: !readonly && hovered && !disabled && portType !== 'input',\n // 有线条链接的时候深蓝色小圆点\n linked,\n });\n const content = (\n <WorkflowPointStyle\n className={className}\n style={targetElement ? props.style : { ...props.style, left: posX, top: posY }}\n onClick={onClick}\n data-port-entity-id={entity.id}\n data-port-entity-type={entity.portType}\n data-testid=\"sdk.workflow.canvas.node.port\"\n >\n <div className={classNames('bg-circle', 'workflow-bg-circle')}></div>\n <div\n className={classNames({\n bg: true,\n [PORT_BG_CLASS_NAME]: true,\n 'workflow-point-bg': true,\n hasError,\n })}\n >\n <CrossHair />\n </div>\n <div className=\"focus-circle\" />\n </WorkflowPointStyle>\n );\n if (targetElement) {\n return ReactDOM.createPortal(content, targetElement);\n }\n return content;\n });\n","// 连接点半径\n\nexport const STROKE_WIDTH_SLECTED = 3;\n\nexport const STROKE_WIDTH = 2;\n\nexport const PORT_BG_CLASS_NAME = 'workflow-port-bg';\n","import styled from 'styled-components';\n\nexport const WorkflowPointStyle = styled.div`\n width: 20px;\n height: 20px;\n border-radius: 50%;\n margin-top: -10px;\n margin-left: -10px;\n left: 50%;\n top: 50%;\n position: absolute;\n // 非 hover 状态下的样式\n border: none;\n\n & > .symbol {\n opacity: 0;\n }\n\n .bg-circle {\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n border-radius: 50%;\n width: 20px;\n height: 20px;\n background-color: #fff;\n transform: scale(0.5);\n transition: all 0.2s linear 0s;\n }\n\n .bg {\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n background: #9197F1;\n transform: scale(0.4, 0.4);\n transition: all 0.2s linear 0s;\n\n &.hasError {\n background: red;\n }\n\n .symbol {\n position: absolute;\n width: 14px;\n height: 14px;\n opacity: 0;\n pointer-events: none;\n color: #fff;\n transition: opacity 0.2s linear 0s;\n\n & > svg {\n width: 14px;\n height: 14px;\n }\n }\n\n .focus-circle {\n position: absolute;\n display: flex;\n justify-content: center;\n align-items: center;\n width: 8px;\n height: 8px;\n opacity: 0;\n background: #9197f1;\n border-radius: 50%;\n transition: opacity 0.2s linear 0s;\n }\n }\n\n &.linked .bg:not(.hasError) {\n background: #4d53e8;\n }\n\n &.hovered .bg:not(.hasError) {\n border: none;\n cursor: crosshair;\n transform: scale(1, 1);\n background: #4d53e8;\n\n & > .symbol {\n opacity: 1;\n }\n }\n\n .cross-hair {\n position: relative;\n left: 2px;\n top: 2px;\n\n &::after,\n &::before {\n content: '';\n background: #fff;\n border-radius: 2px;\n position: absolute;\n }\n\n &::after {\n left: 4px;\n width: 2px;\n height: 6px;\n box-shadow: 0 4px #fff;\n }\n\n &::before {\n top: 4px;\n width: 6px;\n height: 2px;\n box-shadow: 4px 0 #fff;\n }\n`;\n","import React from 'react';\n\n// demo 环境自绘 cross-hair,正式环境使用 IconAdd\nexport default function CrossHair(): JSX.Element {\n return (\n <div className=\"symbol\">\n <div className=\"cross-hair\" />\n </div>\n );\n}\n","// 箭头宽度\nexport const LINE_OFFSET = 6;\n","import { definePluginCreator, PluginContext } from '@flowgram.ai/core';\n\nimport { FreeLinesPluginOptions } from './type';\nimport { LinesLayer } from './layer';\n\nexport const createFreeLinesPlugin = definePluginCreator({\n onInit: (ctx: PluginContext, opts: FreeLinesPluginOptions) => {\n ctx.playground.registerLayer(LinesLayer, {\n ...opts,\n renderElement: () => {\n if (typeof opts.renderElement === 'function') {\n return opts.renderElement(ctx);\n } else {\n return opts.renderElement;\n }\n },\n });\n },\n});\n","import ReactDOM from 'react-dom';\nimport React, { ReactNode, useLayoutEffect, useState } from 'react';\n\nimport { inject, injectable } from 'inversify';\nimport { domUtils } from '@flowgram.ai/utils';\nimport {\n nanoid,\n WorkflowDocument,\n WorkflowHoverService,\n WorkflowLineEntity,\n WorkflowNodeEntity,\n WorkflowPortEntity,\n WorkflowSelectService,\n} from '@flowgram.ai/free-layout-core';\nimport { Layer, observeEntities, observeEntityDatas, TransformData } from '@flowgram.ai/core';\n\nimport { LineRenderProps, LinesLayerOptions } from '../type';\nimport { LineRender } from '../components/lines';\n\n@injectable()\nexport class LinesLayer extends Layer<LinesLayerOptions> {\n static type = 'WorkflowLinesLayer';\n\n @inject(WorkflowHoverService) hoverService: WorkflowHoverService;\n\n @inject(WorkflowSelectService) selectService: WorkflowSelectService;\n\n @observeEntities(WorkflowLineEntity) readonly lines: WorkflowLineEntity[];\n\n @observeEntities(WorkflowPortEntity) readonly ports: WorkflowPortEntity[];\n\n @observeEntityDatas(WorkflowNodeEntity, TransformData)\n readonly trans: TransformData[];\n\n @inject(WorkflowDocument) protected workflowDocument: WorkflowDocument;\n\n private layerID = nanoid();\n\n private mountedLines: Map<\n string,\n {\n line: WorkflowLineEntity;\n portal: ReactNode;\n version: string;\n }\n > = new Map();\n\n private _version = 0;\n\n /**\n * 节点线条\n */\n public node = domUtils.createDivWithClass('gedit-playground-layer gedit-flow-lines-layer');\n\n public onZoom(scale: number): void {\n this.node.style.transform = `scale(${scale})`;\n }\n\n public onReady() {\n this.pipelineNode.appendChild(this.node);\n this.toDispose.pushAll([\n this.selectService.onSelectionChanged(() => this.render()),\n this.hoverService.onHoveredChange(() => this.render()),\n this.workflowDocument.linesManager.onForceUpdate(() => {\n this.mountedLines.clear();\n this.bumpVersion();\n this.render();\n }),\n ]);\n }\n\n public dispose() {\n this.mountedLines.clear();\n }\n\n public render(): JSX.Element {\n const [, forceUpdate] = useState({});\n\n useLayoutEffect(() => {\n const updateLines = (): void => {\n let needsUpdate = false;\n\n // 批量处理所有线条的更新\n this.lines.forEach((line) => {\n const oldVersion = line.bezierDataVersion;\n line.refreshBezier();\n // 如果有任何一条线发生变化,标记需要更新\n if (line.bezierDataVersion !== oldVersion) {\n needsUpdate = true;\n }\n });\n\n // 只在确实需要更新时触发重渲染\n if (needsUpdate) {\n forceUpdate({});\n }\n };\n\n const rafId = requestAnimationFrame(updateLines);\n return () => cancelAnimationFrame(rafId);\n }, [this.lines]); // 依赖项包含 lines\n\n const lines = this.lines.map((line) => this.renderLine(line));\n return <>{lines}</>;\n }\n\n // 用来绕过 memo\n private bumpVersion() {\n this._version = this._version + 1;\n if (this._version === Number.MAX_SAFE_INTEGER) {\n this._version = 0;\n }\n }\n\n private lineProps(line: WorkflowLineEntity): LineRenderProps {\n const { lineType } = this.workflowDocument.linesManager;\n const selected = this.selectService.isSelected(line.id);\n const { version: lineVersion, bezierDataVersion, color } = line;\n\n const version = `${this._version}:${lineVersion}:${bezierDataVersion}:${lineType}:${color}:${selected}`;\n return {\n key: line.id,\n color: line.color,\n selected,\n line,\n lineType,\n version,\n strokePrefix: this.layerID,\n };\n }\n\n private lineComponent(props: LineRenderProps): ReactNode {\n const RenderInsideLine = this.options.renderInsideLine ?? (() => <></>);\n return (\n <LineRender {...props}>\n <RenderInsideLine {...props} />\n </LineRender>\n );\n }\n\n private renderLine(line: WorkflowLineEntity): ReactNode {\n const lineProps = this.lineProps(line);\n const cache = this.mountedLines.get(line.id);\n const isCached = cache !== undefined;\n const { portal: cachedPortal, version: cachedVersion } = cache ?? {};\n if (isCached && cachedVersion === lineProps.version) {\n // 如果已有缓存且版本相同,则直接返回缓存的 portal\n return cachedPortal;\n }\n if (!isCached) {\n // 如果缓存不存在,则将 line 挂载到 renderElement 上\n this.renderElement.appendChild(line.node);\n line.onDispose(() => {\n this.mountedLines.delete(line.id);\n line.node.remove();\n });\n }\n // 刷新缓存\n const portal = ReactDOM.createPortal(this.lineComponent(lineProps), line.node);\n this.mountedLines.set(line.id, { line, portal, version: lineProps.version });\n return portal;\n }\n\n private get renderElement(): HTMLElement {\n if (typeof this.options.renderElement === 'function') {\n const element = this.options.renderElement();\n if (element) {\n return element;\n }\n } else if (typeof this.options.renderElement !== 'undefined') {\n return this.options.renderElement as HTMLElement;\n }\n return this.node;\n }\n}\n","import React, { memo } from 'react';\n\nimport { LineType } from '@flowgram.ai/free-layout-core';\n\nimport type { LineRenderProps } from '../../type';\nimport { FoldLineRender } from './fold-line';\nimport { BezierLineRender } from './bezier-line';\n\nconst LineTypeRender = (props: LineRenderProps) => {\n if (props.lineType === LineType.LINE_CHART) {\n return <FoldLineRender {...props} />;\n }\n return <BezierLineRender {...props} />;\n};\n\nexport const LineRender = memo(\n LineTypeRender,\n (prevProps, nextProps) => prevProps.version === nextProps.version\n);\n","import React from 'react';\n\nimport { POINT_RADIUS } from '@flowgram.ai/free-layout-core';\n\nimport { LineStyle } from '../index.style';\nimport ArrowRenderer from '../arrow';\nimport { LineRenderProps } from '../../../type';\nimport { STROKE_WIDTH, STROKE_WIDTH_SLECTED } from '../../../constants/points';\nimport { LINE_OFFSET } from '../../../constants/lines';\n\n/**\n * 折叠线\n */\n// eslint-disable-next-line react/display-name\nexport const FoldLineRender = (props: LineRenderProps) => {\n const { selected, color, line, children } = props;\n const { to, from } = line.position;\n const strokeWidth = selected ? STROKE_WIDTH_SLECTED : STROKE_WIDTH;\n\n // 真正连接线需要到的点的位置\n const arrowToPos = {\n x: to.x - POINT_RADIUS,\n y: to.y,\n };\n const arrowFromPos = {\n x: from.x + POINT_RADIUS + LINE_OFFSET,\n y: from.y,\n };\n\n return (\n <LineStyle>\n {children}\n <svg overflow=\"visible\">\n <defs>\n <linearGradient\n x1=\"0%\"\n y1=\"100%\"\n x2=\"100%\"\n y2=\"100%\"\n id={line.id}\n gradientUnits=\"userSpaceOnUse\"\n >\n <stop stopColor={color} offset=\"0%\" />\n <stop stopColor={color} offset=\"100%\" />\n </linearGradient>\n </defs>\n <g>\n <path\n d={line.bezier.foldPath}\n fill=\"none\"\n strokeLinecap=\"round\"\n stroke={color}\n strokeWidth={strokeWidth}\n className={line.flowing || line.processing ? 'flowing-line' : ''}\n />\n <ArrowRenderer\n id={line.id}\n reverseArrow={line.reverse}\n pos={line.reverse ? arrowFromPos : arrowToPos}\n strokeWidth={strokeWidth}\n hide={line.hideArrow}\n />\n </g>\n </svg>\n </LineStyle>\n );\n};\n","import styled from 'styled-components';\n\n// 添加一个固定类名,用于选中该节点\n\nexport const LineStyle = styled.div.attrs({\n className: 'gedit-flow-activity-edge',\n})`\n position: absolute;\n\n @keyframes flowingDash {\n to {\n stroke-dashoffset: -13;\n }\n }\n\n .flowing-line {\n stroke-dasharray: 8, 5;\n animation: flowingDash 0.5s linear infinite;\n }\n`;\n","import React from 'react';\n\nimport { LINE_OFFSET } from '../../../constants/lines';\n\nexport default function ArrowRenderer({\n id,\n pos,\n reverseArrow,\n strokeWidth,\n vertical,\n hide,\n}: {\n id: string;\n strokeWidth: number;\n reverseArrow: boolean;\n pos: {\n x: number;\n y: number;\n };\n vertical?: boolean;\n hide?: boolean;\n}) {\n if (hide) {\n return null;\n }\n const arrowPath = vertical\n ? reverseArrow\n ? `M ${pos.x - LINE_OFFSET},${pos.y} L ${pos.x},${pos.y - LINE_OFFSET} L ${\n pos.x + LINE_OFFSET\n },${pos.y}`\n : `M ${pos.x - LINE_OFFSET},${pos.y - LINE_OFFSET} L ${pos.x},${pos.y} L ${\n pos.x + LINE_OFFSET\n },${pos.y - LINE_OFFSET}`\n : reverseArrow\n ? `M ${pos.x},${pos.y + LINE_OFFSET} L ${pos.x - LINE_OFFSET},${pos.y} L ${pos.x},${\n pos.y - LINE_OFFSET\n }`\n : `M ${pos.x - LINE_OFFSET},${pos.y - LINE_OFFSET} L ${pos.x},${pos.y} L ${\n pos.x - LINE_OFFSET\n },${pos.y + LINE_OFFSET}`;\n\n return (\n <path\n d={arrowPath}\n strokeLinecap=\"round\"\n stroke={`url(#${id})`}\n fill=\"none\"\n strokeWidth={strokeWidth}\n />\n );\n}\n","import React from 'react';\n\nimport { type IPoint } from '@flowgram.ai/utils';\nimport { POINT_RADIUS } from '@flowgram.ai/free-layout-core';\n\nimport { LineStyle } from '../index.style';\nimport ArrowRenderer from '../arrow';\nimport { LineRenderProps } from '../../../type';\nimport { STROKE_WIDTH_SLECTED, STROKE_WIDTH } from '../../../constants/points';\nimport { LINE_OFFSET } from '../../../constants/lines';\n\nconst PADDING = 12;\n\n// eslint-disable-next-line react/display-name\nexport const BezierLineRender = (props: LineRenderProps) => {\n const { line, color, fromColor, toColor, selected, children, strokePrefix } = props;\n const { bbox } = line.bezier;\n const { position, reverse, vertical, hideArrow } = line;\n\n // 相对位置转换函数\n const toRelative = (p: IPoint): IPoint => ({\n x: p.x - bbox.x + PADDING,\n y: p.y - bbox.y + PADDING,\n });\n\n const fromPos = toRelative(position.from);\n const toPos = toRelative(position.to);\n\n // 箭头位置计算\n const arrowToPos: IPoint = vertical\n ? { x: toPos.x, y: toPos.y - POINT_RADIUS }\n : { x: toPos.x - POINT_RADIUS, y: toPos.y };\n const arrowFromPos: IPoint = vertical\n ? { x: fromPos.x, y: fromPos.y + POINT_RADIUS + LINE_OFFSET }\n : { x: fromPos.x + POINT_RADIUS + LINE_OFFSET, y: fromPos.y };\n\n const controls = line.bezier.controls.map((c) => toRelative(c));\n\n const getLinearStartColor = (): string | undefined => {\n if (vertical) {\n return fromPos.y < arrowToPos.y ? fromColor : toColor;\n }\n return fromPos.x < arrowToPos.x ? fromColor : toColor;\n };\n\n const getLinearEndColor = (): string | undefined => {\n if (vertical) {\n return fromPos.y < arrowToPos.y ? toColor : fromColor;\n }\n return fromPos.x < arrowToPos.x ? toColor : fromColor;\n };\n\n const linearStartColor = getLinearStartColor();\n const linearEndColor = getLinearEndColor();\n\n const getPathData = (): string => {\n const controlPoints = controls.map((s) => `${s.x} ${s.y}`).join(',');\n const curveType = controls.length === 1 ? 'S' : 'C';\n\n if (vertical) {\n return `M${fromPos.x} ${fromPos.y + POINT_RADIUS} ${curveType} ${controlPoints}, ${\n arrowToPos.x\n } ${arrowToPos.y}`;\n }\n return `M${fromPos.x + POINT_RADIUS} ${fromPos.y} ${curveType} ${controlPoints}, ${\n arrowToPos.x\n } ${arrowToPos.y}`;\n };\n const pathData = getPathData();\n\n const strokeWidth = selected ? STROKE_WIDTH_SLECTED : STROKE_WIDTH;\n\n const strokeID = strokePrefix ? `${strokePrefix}-${line.id}` : line.id;\n\n const path = (\n <path\n d={pathData}\n fill=\"none\"\n stroke={`url(#${strokeID})`}\n strokeWidth={strokeWidth}\n className={line.processing || line.flowing ? 'flowing-line' : ''}\n />\n );\n\n return (\n <LineStyle\n style={{\n left: bbox.x - PADDING,\n top: bbox.y - PADDING,\n position: 'absolute',\n }}\n >\n {children}\n <svg width={bbox.width + PADDING * 2} height={bbox.height + PADDING * 2}>\n <defs>\n <linearGradient\n x1={vertical ? '100%' : '0%'}\n y1={vertical ? '0%' : '100%'}\n x2=\"100%\"\n y2=\"100%\"\n id={strokeID}\n gradientUnits=\"userSpaceOnUse\"\n >\n <stop stopColor={color || linearStartColor} offset=\"0%\" />\n <stop stopColor={color || linearEndColor} offset=\"100%\" />\n </linearGradient>\n </defs>\n <g>\n {path}\n <ArrowRenderer\n id={strokeID}\n reverseArrow={reverse}\n pos={reverse ? arrowFromPos : arrowToPos}\n strokeWidth={strokeWidth}\n vertical={vertical}\n hide={hideArrow}\n />\n {props.showControlPoints\n ? controls.map((c, i) => <circle key={i} cx={c.x} cy={c.y} r=\"4\" fill=\"#ccc\" />)\n : undefined}\n </g>\n </svg>\n </LineStyle>\n );\n};\n"],"mappings":"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","names":["React","React","ReactDOM","React","useState","WorkflowHoverService","React","React","styled","React","React","React","React","POINT_RADIUS","POINT_RADIUS","React","React","useState","React","ReactDOM","WorkflowHoverService"]}