@flowgram-vue/renderer 0.2.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.
Files changed (50) hide show
  1. package/LICENSE +22 -0
  2. package/dist/index.cjs +2933 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.ts +721 -0
  5. package/dist/index.js +2918 -0
  6. package/dist/index.js.map +1 -0
  7. package/index.module.less +167 -0
  8. package/package.json +64 -0
  9. package/src/components/Adder.ts +107 -0
  10. package/src/components/BranchDraggableRenderer.ts +77 -0
  11. package/src/components/Collapse.ts +87 -0
  12. package/src/components/CollapseAdder.ts +94 -0
  13. package/src/components/CustomLine.ts +35 -0
  14. package/src/components/LabelsRenderer.ts +162 -0
  15. package/src/components/LinesRenderer.ts +99 -0
  16. package/src/components/MarkerActivatedArrow.ts +44 -0
  17. package/src/components/MarkerArrow.ts +44 -0
  18. package/src/components/RoundedTurningLine.ts +165 -0
  19. package/src/components/StraightLine.ts +31 -0
  20. package/src/components/utils.ts +295 -0
  21. package/src/entities/README.md +3 -0
  22. package/src/entities/flow-drag-entity.ts +267 -0
  23. package/src/entities/flow-select-config-entity.ts +114 -0
  24. package/src/entities/index.ts +8 -0
  25. package/src/entities/selector-box-config-entity.ts +88 -0
  26. package/src/env.d.ts +10 -0
  27. package/src/flow-renderer-container-module.ts +14 -0
  28. package/src/flow-renderer-contribution.ts +12 -0
  29. package/src/flow-renderer-registry.ts +155 -0
  30. package/src/flow-renderer-resize-observer.ts +56 -0
  31. package/src/hooks/use-base-color.ts +26 -0
  32. package/src/index.ts +16 -0
  33. package/src/layer-vue-provide.ts +44 -0
  34. package/src/layers/flow-context-menu-layer.ts +153 -0
  35. package/src/layers/flow-debug-layer.ts +227 -0
  36. package/src/layers/flow-drag-layer.ts +413 -0
  37. package/src/layers/flow-labels-layer.ts +100 -0
  38. package/src/layers/flow-lines-layer.ts +111 -0
  39. package/src/layers/flow-nodes-content-layer.ts +155 -0
  40. package/src/layers/flow-nodes-transform-layer.ts +151 -0
  41. package/src/layers/flow-scroll-bar-layer.ts +401 -0
  42. package/src/layers/flow-scroll-limit-layer.ts +36 -0
  43. package/src/layers/flow-selector-bounds-layer.ts +191 -0
  44. package/src/layers/flow-selector-box-layer.ts +244 -0
  45. package/src/layers/index.ts +16 -0
  46. package/src/utils/element.ts +36 -0
  47. package/src/utils/find-selected-nodes.ts +80 -0
  48. package/src/utils/index.ts +7 -0
  49. package/src/utils/scroll-bar-events.ts +13 -0
  50. package/src/utils/scroll-limit.ts +58 -0
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { h, type CSSProperties, type Component, type VNode } from 'vue';
7
+ import { type IPoint, Rectangle } from '@flowgram-vue/utils';
8
+ import {
9
+ type CustomLabelProps,
10
+ type FlowNodeTransitionData,
11
+ type FlowTransitionLabel,
12
+ FlowTransitionLabelEnum,
13
+ } from '@flowgram-vue/document';
14
+
15
+ import { type FlowRendererRegistry } from '../flow-renderer-registry';
16
+ import CollapseAdder from './CollapseAdder';
17
+ import Collapse from './Collapse';
18
+ import BranchDraggableRenderer from './BranchDraggableRenderer';
19
+ import Adder from './Adder';
20
+
21
+ export interface LabelOpts {
22
+ data: FlowNodeTransitionData;
23
+ rendererRegistry: FlowRendererRegistry;
24
+ isViewportVisible: (bounds: Rectangle) => boolean;
25
+ labelsSave: VNode[];
26
+ getLabelColor: (activated?: boolean) => string;
27
+ }
28
+
29
+ const TEXT_LABEL_STYLE: CSSProperties = {
30
+ fontSize: '12px',
31
+ color: '#8F959E',
32
+ textAlign: 'center',
33
+ whiteSpace: 'nowrap',
34
+ backgroundColor: 'var(--g-editor-background)',
35
+ lineHeight: '20px',
36
+ };
37
+
38
+ const LABEL_MAX_WIDTH = 150;
39
+ const LABEL_MAX_HEIGHT = 60;
40
+
41
+ function getLabelBounds(offset: IPoint) {
42
+ return new Rectangle(
43
+ offset.x - LABEL_MAX_WIDTH / 2,
44
+ offset.y - LABEL_MAX_HEIGHT / 2,
45
+ LABEL_MAX_WIDTH,
46
+ LABEL_MAX_HEIGHT
47
+ );
48
+ }
49
+
50
+ export function createLabels(labelProps: LabelOpts): void {
51
+ const { data, rendererRegistry, labelsSave, getLabelColor } = labelProps;
52
+ const { labels, renderData } = data || {};
53
+ const { activated } = renderData || {};
54
+
55
+ const renderLabel = (label: FlowTransitionLabel, index: number) => {
56
+ const { offset, renderKey, props, rotate, origin, type } = label || {};
57
+ const offsetX = offset.x;
58
+ const offsetY = offset.y;
59
+
60
+ let child = null as VNode | string | null;
61
+ switch (type) {
62
+ case FlowTransitionLabelEnum.BRANCH_DRAGGING_LABEL:
63
+ child = h(BranchDraggableRenderer, {
64
+ labelId: label.labelId || labelProps.data.entity.id,
65
+ rendererRegistry,
66
+ data,
67
+ ...props,
68
+ });
69
+ break;
70
+ case FlowTransitionLabelEnum.ADDER_LABEL:
71
+ child = h(Adder, {
72
+ labelId: label.labelId || labelProps.data.entity.id,
73
+ rendererRegistry,
74
+ data,
75
+ ...props,
76
+ });
77
+ break;
78
+
79
+ case FlowTransitionLabelEnum.COLLAPSE_LABEL:
80
+ child = h(Collapse, {
81
+ labelId: label.labelId || labelProps.data.entity.id,
82
+ rendererRegistry,
83
+ data,
84
+ ...props,
85
+ });
86
+ break;
87
+
88
+ case FlowTransitionLabelEnum.COLLAPSE_ADDER_LABEL:
89
+ child = h(CollapseAdder, {
90
+ labelId: label.labelId || labelProps.data.entity.id,
91
+ rendererRegistry,
92
+ data,
93
+ ...props,
94
+ });
95
+ break;
96
+
97
+ case FlowTransitionLabelEnum.TEXT_LABEL:
98
+ if (!renderKey) {
99
+ return null;
100
+ }
101
+ const text = rendererRegistry.getText(renderKey) || renderKey;
102
+ child = h(
103
+ 'div',
104
+ {
105
+ 'data-label-id': label.labelId || labelProps.data.entity.id,
106
+ style: {
107
+ ...TEXT_LABEL_STYLE,
108
+ ...props?.style,
109
+ color: getLabelColor(activated),
110
+ transform: rotate ? `rotate(${rotate})` : undefined,
111
+ },
112
+ },
113
+ text
114
+ );
115
+ break;
116
+
117
+ case FlowTransitionLabelEnum.CUSTOM_LABEL:
118
+ if (!renderKey) {
119
+ return null;
120
+ }
121
+ try {
122
+ const renderer = rendererRegistry.getRendererComponent(renderKey);
123
+ child = h(renderer.renderer as Component, {
124
+ node: data.entity,
125
+ labelId: label.labelId || labelProps.data.entity.id,
126
+ ...props,
127
+ } as CustomLabelProps);
128
+ } catch (err) {
129
+ console.error(err);
130
+ child = renderKey;
131
+ }
132
+ break;
133
+ default:
134
+ break;
135
+ }
136
+
137
+ const originX = typeof origin?.[0] === 'number' ? origin?.[0] : 0.5;
138
+ const originY = typeof origin?.[1] === 'number' ? origin?.[1] : 0.5;
139
+
140
+ return h(
141
+ 'div',
142
+ {
143
+ key: `${data.entity.id}${index}`,
144
+ 'data-label-id': label.labelId || labelProps.data.entity.id,
145
+ style: {
146
+ position: 'absolute',
147
+ left: `${offsetX}px`,
148
+ top: `${offsetY}px`,
149
+ transform: `translate(-${originX * 100}%, -${originY * 100}%)`,
150
+ },
151
+ },
152
+ [child]
153
+ );
154
+ };
155
+
156
+ labels.forEach((label, index) => {
157
+ if (labelProps.isViewportVisible(getLabelBounds(label.offset))) {
158
+ const vnode = renderLabel(label, index);
159
+ if (vnode) labelsSave.push(vnode);
160
+ }
161
+ });
162
+ }
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import type { VNode } from 'vue';
7
+ import { h } from 'vue';
8
+ import { Rectangle } from '@flowgram-vue/utils';
9
+ import {
10
+ FlowDragService,
11
+ type FlowNodeTransitionData,
12
+ type FlowTransitionLine,
13
+ FlowTransitionLineEnum,
14
+ DefaultSpacingKey,
15
+ } from '@flowgram-vue/document';
16
+ import { getDefaultSpacing } from '@flowgram-vue/document';
17
+
18
+ import { type FlowRendererRegistry } from '../flow-renderer-registry';
19
+ import StraightLine from './StraightLine';
20
+ import RoundedTurningLine from './RoundedTurningLine';
21
+ import CustomLine from './CustomLine';
22
+
23
+ export interface PropsType {
24
+ data: FlowNodeTransitionData;
25
+ rendererRegistry: FlowRendererRegistry;
26
+ isViewportVisible: (bounds: Rectangle) => boolean;
27
+ linesSave: VNode[];
28
+ dragService: FlowDragService;
29
+ }
30
+
31
+ export function createLines(props: PropsType): void {
32
+ const { data, rendererRegistry, linesSave, dragService } = props;
33
+ const { lines, entity } = data || {};
34
+
35
+ const radius = getDefaultSpacing(entity, DefaultSpacingKey.ROUNDED_LINE_RADIUS);
36
+ const xRadius = getDefaultSpacing(entity, DefaultSpacingKey.ROUNDED_LINE_X_RADIUS);
37
+ const yRadius = getDefaultSpacing(entity, DefaultSpacingKey.ROUNDED_LINE_Y_RADIUS);
38
+
39
+ const renderLine = (line: FlowTransitionLine, index: number) => {
40
+ const { renderData } = data;
41
+ const { isVertical } = data.entity;
42
+ const { lineActivated } = renderData || {};
43
+
44
+ const draggingLineHide =
45
+ (line.type === FlowTransitionLineEnum.DRAGGING_LINE || line.isDraggingLine) &&
46
+ !dragService.isDroppableBranch(data.entity, line.side);
47
+
48
+ const draggingLineActivated =
49
+ (line.type === FlowTransitionLineEnum.DRAGGING_LINE || line.isDraggingLine) &&
50
+ data.entity?.id === dragService.dropNodeId &&
51
+ line.side === dragService.labelSide;
52
+
53
+ switch (line.type) {
54
+ case FlowTransitionLineEnum.STRAIGHT_LINE:
55
+ return h(StraightLine, {
56
+ key: `${data.entity.id}_${index}`,
57
+ lineId: data.entity.id,
58
+ activated: lineActivated,
59
+ ...line,
60
+ });
61
+
62
+ case FlowTransitionLineEnum.DIVERGE_LINE:
63
+ case FlowTransitionLineEnum.DRAGGING_LINE:
64
+ case FlowTransitionLineEnum.MERGE_LINE:
65
+ case FlowTransitionLineEnum.ROUNDED_LINE:
66
+ return h(RoundedTurningLine, {
67
+ key: `${data.entity.id}_${index}`,
68
+ lineId: data.entity.id,
69
+ isHorizontal: !isVertical,
70
+ activated: lineActivated || draggingLineActivated,
71
+ radius,
72
+ ...line,
73
+ xRadius,
74
+ yRadius,
75
+ hide: draggingLineHide,
76
+ });
77
+
78
+ case FlowTransitionLineEnum.CUSTOM_LINE:
79
+ return h(CustomLine, {
80
+ key: `${data.entity.id}_${index}`,
81
+ lineId: data.entity.id,
82
+ ...line,
83
+ rendererRegistry,
84
+ });
85
+
86
+ default:
87
+ break;
88
+ }
89
+
90
+ return undefined;
91
+ };
92
+ lines.forEach((line, index) => {
93
+ const bounds = Rectangle.createRectangleWithTwoPoints(line.from, line.to).pad(10);
94
+ if (props.isViewportVisible(bounds)) {
95
+ const vnode = renderLine(line, index);
96
+ if (vnode) linesSave.push(vnode);
97
+ }
98
+ });
99
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { defineComponent, h } from 'vue';
7
+
8
+ import { useBaseColor } from '../hooks/use-base-color';
9
+
10
+ export const MARK_ACTIVATED_ARROW_ID = '$marker_arrow_activated$';
11
+
12
+ const MarkerActivatedArrow = defineComponent({
13
+ name: 'MarkerActivatedArrow',
14
+ props: {
15
+ id: {
16
+ type: String,
17
+ default: undefined,
18
+ },
19
+ },
20
+ setup(props) {
21
+ const { baseActivatedColor } = useBaseColor();
22
+ return () =>
23
+ h(
24
+ 'marker',
25
+ {
26
+ 'data-line-id': props.id,
27
+ id: props.id || MARK_ACTIVATED_ARROW_ID,
28
+ markerWidth: '11',
29
+ markerHeight: '14',
30
+ refX: '10',
31
+ refY: '7',
32
+ orient: 'auto',
33
+ },
34
+ [
35
+ h('path', {
36
+ d: 'M9.6 5.2C10.8 6.1 10.8 7.9 9.6 8.8L3.6 13.3C2.11672 14.4125 0 13.3541 0 11.5L0 2.5C0 0.645898 2.11672 -0.412461 3.6 0.7L9.6 5.2Z',
37
+ fill: baseActivatedColor,
38
+ }),
39
+ ]
40
+ );
41
+ },
42
+ });
43
+
44
+ export default MarkerActivatedArrow;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { defineComponent, h } from 'vue';
7
+
8
+ import { useBaseColor } from '../hooks/use-base-color';
9
+
10
+ export const MARK_ARROW_ID = '$marker_arrow$';
11
+
12
+ const MarkerArrow = defineComponent({
13
+ name: 'MarkerArrow',
14
+ props: {
15
+ id: {
16
+ type: String,
17
+ required: true,
18
+ },
19
+ },
20
+ setup(props) {
21
+ const { baseColor } = useBaseColor();
22
+ return () =>
23
+ h(
24
+ 'marker',
25
+ {
26
+ 'data-line-id': props.id,
27
+ id: props.id || MARK_ARROW_ID,
28
+ markerWidth: '11',
29
+ markerHeight: '14',
30
+ refX: '10',
31
+ refY: '7',
32
+ orient: 'auto',
33
+ },
34
+ [
35
+ h('path', {
36
+ d: 'M9.6 5.2C10.8 6.1 10.8 7.9 9.6 8.8L3.6 13.3C2.11672 14.4125 0 13.3541 0 11.5L0 2.5C0 0.645898 2.11672 -0.412461 3.6 0.7L9.6 5.2Z',
37
+ fill: baseColor,
38
+ }),
39
+ ]
40
+ );
41
+ },
42
+ });
43
+
44
+ export default MarkerArrow;
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { computed, defineComponent, h, inject } from 'vue';
7
+ import type { Component } from 'vue';
8
+ import { isNil } from 'lodash-es';
9
+ import { Point } from '@flowgram-vue/utils';
10
+ import { type FlowTransitionLine } from '@flowgram-vue/document';
11
+ import { PlaygroundVueContainerKey } from '@flowgram-vue/core';
12
+
13
+ import { useBaseColor } from '../hooks/use-base-color';
14
+ import { DEFAULT_LINE_ATTRS, DEFAULT_RADIUS, getHorizontalVertices, getVertices } from './utils';
15
+ import MarkerArrow, { MARK_ARROW_ID } from './MarkerArrow';
16
+ import MarkerActivatedArrow, { MARK_ACTIVATED_ARROW_ID } from './MarkerActivatedArrow';
17
+ import { FlowRendererKey, FlowRendererRegistry } from '../flow-renderer-registry';
18
+
19
+ interface PropsType extends FlowTransitionLine {
20
+ radius?: number;
21
+ hide?: boolean;
22
+ xRadius?: number;
23
+ yRadius?: number;
24
+ }
25
+
26
+ const MarkerDefs = defineComponent({
27
+ name: 'MarkerDefs',
28
+ props: {
29
+ id: { type: String, required: true },
30
+ activated: { type: Boolean, default: false },
31
+ },
32
+ setup(props) {
33
+ const container = inject(PlaygroundVueContainerKey, null as any);
34
+ return () => {
35
+ const renderRegistry = container?.get?.(FlowRendererRegistry) as
36
+ | FlowRendererRegistry
37
+ | undefined;
38
+ const ArrowRenderer = renderRegistry?.tryToGetRendererComponent(
39
+ props.activated ? FlowRendererKey.MARKER_ACTIVATE_ARROW : FlowRendererKey.MARKER_ARROW
40
+ );
41
+ if (ArrowRenderer) {
42
+ return h(ArrowRenderer.renderer as Component, { id: props.id, activated: props.activated });
43
+ }
44
+ if (props.activated) {
45
+ return h('defs', null, [h(MarkerActivatedArrow, { id: props.id })]);
46
+ }
47
+ return h('defs', null, [h(MarkerArrow, { id: props.id })]);
48
+ };
49
+ },
50
+ });
51
+
52
+ /**
53
+ * 圆角转弯线
54
+ */
55
+ const RoundedTurningLine = defineComponent({
56
+ name: 'RoundedTurningLine',
57
+ inheritAttrs: false,
58
+ setup(_, { attrs }) {
59
+ const props = attrs as unknown as PropsType;
60
+ const { baseActivatedColor, baseColor } = useBaseColor();
61
+
62
+ const realVertices = computed(() => {
63
+ const { vertices, xRadius, yRadius } = props;
64
+ return (
65
+ vertices ||
66
+ (props.isHorizontal
67
+ ? getHorizontalVertices(props, xRadius, yRadius)
68
+ : getVertices(props, xRadius, yRadius))
69
+ );
70
+ });
71
+
72
+ const middleStr = computed(() => {
73
+ const { radius = DEFAULT_RADIUS, from, to } = props;
74
+ const vertices = realVertices.value;
75
+ return vertices
76
+ .map((point, idx) => {
77
+ const prev = vertices[idx - 1] || from;
78
+ const next = vertices[idx + 1] || to;
79
+
80
+ const prevDelta = { x: Math.abs(prev.x - point.x), y: Math.abs(prev.y - point.y) };
81
+ const nextDelta = { x: Math.abs(next.x - point.x), y: Math.abs(next.y - point.y) };
82
+
83
+ const isRightAngleX = prevDelta.x === 0 && nextDelta.y === 0;
84
+ const isRightAngleY = prevDelta.y === 0 && nextDelta.x === 0;
85
+ const isRightAngle = isRightAngleX || isRightAngleY;
86
+
87
+ if (!isRightAngle) {
88
+ console.error(`vertex ${point.x},${point.y} is not right angle`);
89
+ }
90
+
91
+ const inPoint = new Point().copyFrom(point);
92
+ const outPoint = new Point().copyFrom(point);
93
+ const radiusX = isNil(point.radiusX) ? radius : point.radiusX;
94
+ const radiusY = isNil(point.radiusY) ? radius : point.radiusY;
95
+ let rx = radiusX;
96
+ let ry = radiusY;
97
+
98
+ if (isRightAngleX) {
99
+ ry = Math.min(prevDelta.y, radiusY);
100
+ const moveY = isNil(point.moveY) ? ry : point.moveY;
101
+ inPoint.y += from.y < point.y ? -moveY : +moveY;
102
+
103
+ rx = Math.min(nextDelta.x, radiusX);
104
+ const moveX = isNil(point.moveX) ? rx : point.moveX;
105
+ outPoint.x += to.x < point.x ? -moveX : +moveX;
106
+ }
107
+
108
+ if (isRightAngleY) {
109
+ rx = Math.min(prevDelta.x, radiusX);
110
+ const moveX = isNil(point.moveX) ? rx : point.moveX;
111
+ inPoint.x += from.x < point.x ? -moveX : +moveX;
112
+
113
+ ry = Math.min(nextDelta.y, radiusY);
114
+ const moveY = isNil(point.moveY) ? ry : point.moveY;
115
+ outPoint.y += to.y < point.y ? -moveY : +moveY;
116
+ }
117
+
118
+ if (point.radiusOverflow === 'truncate') {
119
+ rx = radiusX;
120
+ ry = radiusY;
121
+ }
122
+
123
+ const crossProduct =
124
+ (point.x - inPoint.x) * (outPoint.y - inPoint.y) -
125
+ (point.y - inPoint.y) * (outPoint.x - inPoint.x);
126
+ const isClockWise = crossProduct > 0;
127
+
128
+ return `L ${inPoint.x} ${inPoint.y} A ${rx} ${ry} 0 0 ${isClockWise ? 1 : 0} ${
129
+ outPoint.x
130
+ } ${outPoint.y}`;
131
+ })
132
+ .join(' ');
133
+ });
134
+
135
+ return () => {
136
+ const { hide, from, to, arrow, activated, style } = props;
137
+ if (hide) {
138
+ return null;
139
+ }
140
+
141
+ const pathStr = `M ${from.x} ${from.y} ${middleStr.value} L ${to.x} ${to.y}`;
142
+ const markerId = activated
143
+ ? `${MARK_ACTIVATED_ARROW_ID}${props.lineId}`
144
+ : `${MARK_ARROW_ID}${props.lineId}`;
145
+
146
+ return [
147
+ arrow ? h(MarkerDefs, { id: markerId, activated }) : null,
148
+ h('path', {
149
+ 'data-line-id': props.lineId,
150
+ d: pathStr,
151
+ ...DEFAULT_LINE_ATTRS,
152
+ stroke: activated ? baseActivatedColor : baseColor,
153
+ ...(arrow
154
+ ? {
155
+ markerEnd: `url(#${markerId})`,
156
+ }
157
+ : {}),
158
+ style,
159
+ }),
160
+ ];
161
+ };
162
+ },
163
+ });
164
+
165
+ export default RoundedTurningLine;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { defineComponent, h } from 'vue';
7
+ import type { FlowTransitionLine } from '@flowgram-vue/document';
8
+
9
+ import { useBaseColor } from '../hooks/use-base-color';
10
+ import { DEFAULT_LINE_ATTRS } from './utils';
11
+
12
+ const StraightLine = defineComponent({
13
+ name: 'StraightLine',
14
+ inheritAttrs: false,
15
+ setup(_, { attrs }) {
16
+ const line = attrs as unknown as FlowTransitionLine;
17
+ const { baseColor, baseActivatedColor } = useBaseColor();
18
+ return () => {
19
+ const { from, to, activated, style } = line;
20
+ return h('path', {
21
+ 'data-line-id': line.lineId,
22
+ d: `M ${from.x} ${from.y} L ${to.x} ${to.y}`,
23
+ ...DEFAULT_LINE_ATTRS,
24
+ stroke: activated ? baseActivatedColor : baseColor,
25
+ style,
26
+ });
27
+ };
28
+ },
29
+ });
30
+
31
+ export default StraightLine;