@knotx/render 0.4.12 → 0.4.13

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 (3) hide show
  1. package/README.en.md +584 -0
  2. package/README.md +584 -0
  3. package/package.json +7 -7
package/README.en.md ADDED
@@ -0,0 +1,584 @@
1
+ # @knotx/render
2
+
3
+ A React component library providing edge rendering capabilities for the Knotx graph editor.
4
+
5
+ ## 📦 Installation
6
+
7
+ ```bash
8
+ npm install @knotx/render
9
+ ```
10
+
11
+ ```bash
12
+ yarn add @knotx/render
13
+ ```
14
+
15
+ ```bash
16
+ pnpm add @knotx/render
17
+ ```
18
+
19
+ ## 🚀 Overview
20
+
21
+ `@knotx/render` is a rendering layer component library in the Knotx ecosystem, specifically designed for rendering edges (connections) in graph editors. It provides multiple edge types (straight lines, Bezier curves) and rich customization options, supporting arrow markers, labels, style customization, and more.
22
+
23
+ ### Key Features
24
+
25
+ - 🎨 **Multiple Edge Types**: Support for straight lines, Bezier curves, and other connection types
26
+ - 🎯 **Arrow Markers**: Built-in arrow marker styles with support for custom markers
27
+ - 🏷️ **Label Support**: Add text labels to edges
28
+ - 🎛️ **Highly Customizable**: Support for styles, colors, widths, and various property customizations
29
+ - 🔧 **Extensible**: Based on abstract path builder design for easy extension of new edge types
30
+ - ⚡ **Performance Optimized**: SVG rendering with interaction area optimization
31
+
32
+ ## 📋 API Documentation
33
+
34
+ ### Components
35
+
36
+ #### `BaseEdge<TPathBuilderContext>`
37
+
38
+ Base edge component that serves as the foundation for all other edge components.
39
+
40
+ **Props**
41
+
42
+ ```tsx
43
+ interface BaseEdgeProps<TPathBuilderContext = void> extends EdgeProps {
44
+ className?: string // Custom CSS class name
45
+ style?: Record<string, any> // Custom style object
46
+ interactionWidth?: number // Interaction area width, default 20
47
+ label?: string // Edge label text
48
+ markerEnd?: string | MarkerProps // End marker
49
+ markerStart?: string | MarkerProps // Start marker
50
+ pathBuilder: PathBuilderType<any, TPathBuilderContext> // Path builder
51
+ context: TPathBuilderContext // Path builder context
52
+ }
53
+ ```
54
+
55
+ **Usage Example**
56
+
57
+ ```tsx
58
+ import { BaseEdge, StraightPathBuilder } from '@knotx/render'
59
+
60
+ function CustomEdge() {
61
+ return (
62
+ <BaseEdge
63
+ sourceX={0}
64
+ sourceY={0}
65
+ targetX={100}
66
+ targetY={100}
67
+ pathBuilder={StraightPathBuilder}
68
+ context={undefined}
69
+ label="Connection"
70
+ style={{ stroke: '#1890ff', strokeWidth: 2 }}
71
+ />
72
+ )
73
+ }
74
+ ```
75
+
76
+ #### `BezierEdge`
77
+
78
+ Bezier curve edge component, suitable for smooth curve connections.
79
+
80
+ **Props**
81
+
82
+ ```tsx
83
+ interface BezierEdgeProps extends Omit<BaseEdgeProps, 'pathBuilder' | 'context'> {}
84
+ ```
85
+
86
+ **Usage Example**
87
+
88
+ ```tsx
89
+ import { BezierEdge, getArrowMarker } from '@knotx/render'
90
+
91
+ function CurvedConnection() {
92
+ const arrowMarker = getArrowMarker('#ff4d4f')
93
+
94
+ return (
95
+ <BezierEdge
96
+ sourceX={50}
97
+ sourceY={50}
98
+ targetX={250}
99
+ targetY={150}
100
+ markerEnd={arrowMarker}
101
+ style={{ stroke: '#ff4d4f', strokeWidth: 2 }}
102
+ label="Bezier Curve"
103
+ />
104
+ )
105
+ }
106
+ ```
107
+
108
+ #### `StraightEdge`
109
+
110
+ Straight line edge component for simple direct connections.
111
+
112
+ **Props**
113
+
114
+ ```tsx
115
+ interface StraightEdgeProps extends Omit<BaseEdgeProps, 'pathBuilder' | 'context'> {}
116
+ ```
117
+
118
+ **Usage Example**
119
+
120
+ ```tsx
121
+ import { getArrowClosedMarker, StraightEdge } from '@knotx/render'
122
+
123
+ function DirectConnection() {
124
+ const arrowMarker = getArrowClosedMarker('#52c41a')
125
+
126
+ return (
127
+ <StraightEdge
128
+ sourceX={0}
129
+ sourceY={0}
130
+ targetX={200}
131
+ targetY={100}
132
+ markerEnd={arrowMarker}
133
+ markerStart={arrowMarker}
134
+ style={{ stroke: '#52c41a', strokeWidth: 3 }}
135
+ interactionWidth={30}
136
+ />
137
+ )
138
+ }
139
+ ```
140
+
141
+ #### `MarkerDefinitions`
142
+
143
+ Marker definition component for centralized marker management and reuse.
144
+
145
+ **Props**
146
+
147
+ ```typescript
148
+ interface MarkerDefinitionsProps {
149
+ markers: MarkerProps[]
150
+ }
151
+ ```
152
+
153
+ **Usage Example**
154
+
155
+ ```tsx
156
+ import { getArrowClosedMarker, getArrowMarker, MarkerDefinitions } from '@knotx/render'
157
+
158
+ function EdgeContainer() {
159
+ const markers = [
160
+ getArrowMarker('#1890ff'),
161
+ getArrowClosedMarker('#ff4d4f'),
162
+ getArrowMarker('#52c41a')
163
+ ]
164
+
165
+ return (
166
+ <svg>
167
+ <MarkerDefinitions markers={markers} />
168
+ {/* Your edge components */}
169
+ </svg>
170
+ )
171
+ }
172
+ ```
173
+
174
+ ### Path Builders
175
+
176
+ #### `PathBuilder<TType, TContext>`
177
+
178
+ Abstract path builder base class for creating custom edge types.
179
+
180
+ **Abstract Methods**
181
+
182
+ ```tsx
183
+ abstract class PathBuilder<TType extends string, TContext = never> {
184
+ constructor(
185
+ readonly sourceX: number,
186
+ readonly sourceY: number,
187
+ readonly targetX: number,
188
+ readonly targetY: number
189
+ ) {}
190
+
191
+ abstract type: TType
192
+ abstract buildPath(context: TContext): string
193
+ abstract interpolate(t: number, context: TContext): { x: number, y: number }
194
+ }
195
+ ```
196
+
197
+ **Custom Path Builder Example**
198
+
199
+ ```tsx
200
+ class CustomPathBuilder extends PathBuilder<'custom'> {
201
+ type = 'custom' as const
202
+
203
+ buildPath(): string {
204
+ // Create custom SVG path
205
+ const midX = (this.sourceX + this.targetX) / 2
206
+ const midY = (this.sourceY + this.targetY) / 2
207
+
208
+ return `M ${this.sourceX} ${this.sourceY}
209
+ Q ${midX} ${midY - 50} ${this.targetX} ${this.targetY}`
210
+ }
211
+
212
+ interpolate(t: number): { x: number, y: number } {
213
+ // Implement path point interpolation
214
+ const x = this.sourceX + t * (this.targetX - this.sourceX)
215
+ const y = this.sourceY + t * (this.targetY - this.sourceY)
216
+ return { x, y }
217
+ }
218
+ }
219
+ ```
220
+
221
+ #### `StraightPathBuilder`
222
+
223
+ Straight line path builder that generates straight line paths.
224
+
225
+ ```tsx
226
+ class StraightPathBuilder extends PathBuilder<'straight'> {
227
+ type = 'straight' as const
228
+ buildPath(): string
229
+ interpolate(t: number): { x: number, y: number }
230
+ }
231
+ ```
232
+
233
+ #### `BezierPathBuilder`
234
+
235
+ Bezier curve path builder that generates smooth curve paths.
236
+
237
+ ```tsx
238
+ class BezierPathBuilder extends PathBuilder<'bezier'> {
239
+ type = 'bezier' as const
240
+ buildPath(): string
241
+ interpolate(t: number): { x: number, y: number }
242
+ }
243
+ ```
244
+
245
+ ### Marker Utility Functions
246
+
247
+ #### `getArrowMarker(color?: string)`
248
+
249
+ Create a standard arrow marker.
250
+
251
+ **Parameters**
252
+ - `color` (optional): Marker color, defaults to `currentColor`
253
+
254
+ **Returns**
255
+ - `MarkerProps`: Arrow marker configuration object
256
+
257
+ **Usage Example**
258
+
259
+ ```tsx
260
+ import { getArrowMarker, StraightEdge } from '@knotx/render'
261
+
262
+ function EdgeWithArrow() {
263
+ const marker = getArrowMarker('#1890ff')
264
+
265
+ return (
266
+ <StraightEdge
267
+ sourceX={0}
268
+ sourceY={0}
269
+ targetX={100}
270
+ targetY={100}
271
+ markerEnd={marker}
272
+ />
273
+ )
274
+ }
275
+ ```
276
+
277
+ #### `getArrowClosedMarker(color?: string)`
278
+
279
+ Create a closed (filled) arrow marker.
280
+
281
+ **Parameters**
282
+ - `color` (optional): Marker color, defaults to `currentColor`
283
+
284
+ **Returns**
285
+ - `MarkerProps`: Closed arrow marker configuration object
286
+
287
+ **Usage Example**
288
+
289
+ ```tsx
290
+ import { BezierEdge, getArrowClosedMarker } from '@knotx/render'
291
+
292
+ function EdgeWithClosedArrow() {
293
+ const marker = getArrowClosedMarker('#ff4d4f')
294
+
295
+ return (
296
+ <BezierEdge
297
+ sourceX={50}
298
+ sourceY={50}
299
+ targetX={200}
300
+ targetY={150}
301
+ markerEnd={marker}
302
+ style={{ stroke: '#ff4d4f' }}
303
+ />
304
+ )
305
+ }
306
+ ```
307
+
308
+ #### `getCustomMarker(type: string, options?: Partial<MarkerProps>)`
309
+
310
+ Create a custom marker.
311
+
312
+ **Parameters**
313
+ - `type`: Marker type identifier
314
+ - `options` (optional): Custom marker options
315
+
316
+ **Returns**
317
+ - `MarkerProps`: Custom marker configuration object
318
+
319
+ **Usage Example**
320
+
321
+ ```tsx
322
+ import { BaseEdge, getCustomMarker, StraightPathBuilder } from '@knotx/render'
323
+
324
+ function EdgeWithCustomMarker() {
325
+ const marker = getCustomMarker('diamond', {
326
+ color: '#722ed1',
327
+ width: 12,
328
+ height: 12,
329
+ strokeWidth: 2
330
+ })
331
+
332
+ return (
333
+ <BaseEdge
334
+ sourceX={0}
335
+ sourceY={0}
336
+ targetX={150}
337
+ targetY={100}
338
+ pathBuilder={StraightPathBuilder}
339
+ context={undefined}
340
+ markerEnd={marker}
341
+ />
342
+ )
343
+ }
344
+ ```
345
+
346
+ #### `getArrowHeadMarkers(color?: string)`
347
+
348
+ Create two closed arrows as start and end markers.
349
+
350
+ **Parameters**
351
+ - `color` (optional): Marker color
352
+
353
+ **Returns**
354
+ - Object containing `markerStart` and `markerEnd`
355
+
356
+ **Usage Example**
357
+
358
+ ```tsx
359
+ import { getArrowHeadMarkers, StraightEdge } from '@knotx/render'
360
+
361
+ function DoubleArrowEdge() {
362
+ const { markerStart, markerEnd } = getArrowHeadMarkers('#13c2c2')
363
+
364
+ return (
365
+ <StraightEdge
366
+ sourceX={0}
367
+ sourceY={0}
368
+ targetX={200}
369
+ targetY={100}
370
+ markerStart={markerStart}
371
+ markerEnd={markerEnd}
372
+ style={{ stroke: '#13c2c2', strokeWidth: 2 }}
373
+ />
374
+ )
375
+ }
376
+ ```
377
+
378
+ ### Type Definitions
379
+
380
+ #### `MarkerType`
381
+
382
+ ```typescript
383
+ enum MarkerType {
384
+ Arrow = 'arrow',
385
+ ArrowClosed = 'arrowclosed'
386
+ }
387
+ ```
388
+
389
+ #### `MarkerProps`
390
+
391
+ ```typescript
392
+ interface MarkerProps {
393
+ id: string // Unique marker identifier
394
+ type: MarkerType | string // Marker type
395
+ color?: string // Marker color
396
+ width?: number // Marker width
397
+ height?: number // Marker height
398
+ markerUnits?: string // Marker units
399
+ orient?: string // Marker orientation
400
+ strokeWidth?: number // Stroke width
401
+ }
402
+ ```
403
+
404
+ #### `PathBuilderType`
405
+
406
+ ```tsx
407
+ type PathBuilderType<T extends string = any, TContext = void> =
408
+ new (...args: ConstructorParameters<typeof PathBuilder<T, TContext>>) =>
409
+ PathBuilder<T, TContext>
410
+ ```
411
+
412
+ ## 🗂️ Directory Structure
413
+
414
+ ```
415
+ packages/render/
416
+ ├── src/
417
+ │ ├── edges/
418
+ │ │ ├── base-edge.tsx # Base edge component
419
+ │ │ ├── bezier.tsx # Bezier curve edge
420
+ │ │ ├── straight.tsx # Straight line edge
421
+ │ │ ├── markers.tsx # Marker-related functionality
422
+ │ │ ├── path-builder.ts # Path builders
423
+ │ │ └── index.ts # Edge module exports
424
+ │ └── index.ts # Main entry point
425
+ ├── dist/ # Build output directory
426
+ ├── package.json # Package configuration
427
+ ├── tsconfig.json # TypeScript configuration
428
+ ├── build.config.ts # Build configuration
429
+ └── README.md # Documentation
430
+ ```
431
+
432
+ ## 🎯 Complete Usage Examples
433
+
434
+ ### Basic Usage
435
+
436
+ ```tsx
437
+ import {
438
+ BezierEdge,
439
+ getArrowClosedMarker,
440
+ getArrowMarker,
441
+ StraightEdge
442
+ } from '@knotx/render'
443
+ import React from 'react'
444
+
445
+ function GraphEditor() {
446
+ return (
447
+ <div style={{ position: 'relative', width: 800, height: 600 }}>
448
+ {/* Straight line connection */}
449
+ <StraightEdge
450
+ sourceX={50}
451
+ sourceY={50}
452
+ targetX={200}
453
+ targetY={100}
454
+ markerEnd={getArrowMarker('#1890ff')}
455
+ style={{ stroke: '#1890ff', strokeWidth: 2 }}
456
+ label="Straight Connection"
457
+ />
458
+
459
+ {/* Bezier curve connection */}
460
+ <BezierEdge
461
+ sourceX={50}
462
+ sourceY={150}
463
+ targetX={250}
464
+ targetY={200}
465
+ markerEnd={getArrowClosedMarker('#ff4d4f')}
466
+ style={{ stroke: '#ff4d4f', strokeWidth: 2 }}
467
+ label="Curved Connection"
468
+ />
469
+ </div>
470
+ )
471
+ }
472
+ ```
473
+
474
+ ### Custom Edge Types
475
+
476
+ ```tsx
477
+ import { BaseEdge, PathBuilder } from '@knotx/render'
478
+
479
+ // Create custom path builder
480
+ class StepPathBuilder extends PathBuilder<'step'> {
481
+ type = 'step' as const
482
+
483
+ buildPath(): string {
484
+ const midX = (this.sourceX + this.targetX) / 2
485
+ return `M ${this.sourceX} ${this.sourceY}
486
+ L ${midX} ${this.sourceY}
487
+ L ${midX} ${this.targetY}
488
+ L ${this.targetX} ${this.targetY}`
489
+ }
490
+
491
+ interpolate(t: number): { x: number, y: number } {
492
+ const midX = (this.sourceX + this.targetX) / 2
493
+
494
+ if (t <= 0.33) {
495
+ const localT = t / 0.33
496
+ return {
497
+ x: this.sourceX + localT * (midX - this.sourceX),
498
+ y: this.sourceY
499
+ }
500
+ }
501
+ else if (t <= 0.66) {
502
+ const localT = (t - 0.33) / 0.33
503
+ return {
504
+ x: midX,
505
+ y: this.sourceY + localT * (this.targetY - this.sourceY)
506
+ }
507
+ }
508
+ else {
509
+ const localT = (t - 0.66) / 0.34
510
+ return {
511
+ x: midX + localT * (this.targetX - midX),
512
+ y: this.targetY
513
+ }
514
+ }
515
+ }
516
+ }
517
+
518
+ // Use custom path builder
519
+ function StepEdge(props: Omit<BaseEdgeProps, 'pathBuilder' | 'context'>) {
520
+ return (
521
+ <BaseEdge
522
+ {...props}
523
+ pathBuilder={StepPathBuilder}
524
+ context={undefined}
525
+ />
526
+ )
527
+ }
528
+ ```
529
+
530
+ ### Advanced Marker Management
531
+
532
+ ```tsx
533
+ import { getArrowMarker, getCustomMarker, MarkerDefinitions } from '@knotx/render'
534
+
535
+ function AdvancedGraph() {
536
+ // Pre-define markers
537
+ const markers = [
538
+ getArrowMarker('#1890ff'),
539
+ getArrowMarker('#ff4d4f'),
540
+ getCustomMarker('circle', {
541
+ color: '#52c41a',
542
+ width: 8,
543
+ height: 8
544
+ })
545
+ ]
546
+
547
+ return (
548
+ <svg width="800" height="600">
549
+ <MarkerDefinitions markers={markers} />
550
+
551
+ {/* Use predefined markers */}
552
+ <StraightEdge
553
+ sourceX={100}
554
+ sourceY={100}
555
+ targetX={300}
556
+ targetY={200}
557
+ markerEnd={markers[0]}
558
+ style={{ stroke: '#1890ff' }}
559
+ />
560
+
561
+ <BezierEdge
562
+ sourceX={100}
563
+ sourceY={200}
564
+ targetX={400}
565
+ targetY={150}
566
+ markerEnd={markers[1]}
567
+ style={{ stroke: '#ff4d4f' }}
568
+ />
569
+ </svg>
570
+ )
571
+ }
572
+ ```
573
+
574
+ ## 📄 License
575
+
576
+ MIT
577
+
578
+ ## 🤝 Contributing
579
+
580
+ Issues and pull requests are welcome. See [CONTRIBUTING.md](../../CONTRIBUTING.md) for details.
581
+
582
+ ## 📞 Support
583
+
584
+ If you encounter any issues or need help, please submit an issue on [GitHub Issues](https://github.com/boenfu/knotx/issues).
package/README.md ADDED
@@ -0,0 +1,584 @@
1
+ # @knotx/render
2
+
3
+ 一个专为 Knotx 图形编辑器提供边缘(Edge)渲染功能的 React 组件库。
4
+
5
+ ## 📦 安装
6
+
7
+ ```bash
8
+ npm install @knotx/render
9
+ ```
10
+
11
+ ```bash
12
+ yarn add @knotx/render
13
+ ```
14
+
15
+ ```bash
16
+ pnpm add @knotx/render
17
+ ```
18
+
19
+ ## 🚀 基本概述
20
+
21
+ `@knotx/render` 是 Knotx 生态系统中的渲染层组件库,专门用于渲染图形编辑器中的边缘(连接线)。它提供了多种边缘类型(直线、贝塞尔曲线)和丰富的自定义选项,支持箭头标记、标签、样式定制等功能。
22
+
23
+ ### 主要特性
24
+
25
+ - 🎨 **多种边缘类型**: 支持直线、贝塞尔曲线等多种连接线类型
26
+ - 🎯 **箭头标记**: 内置多种箭头标记样式,支持自定义标记
27
+ - 🏷️ **标签支持**: 支持在边缘上添加文本标签
28
+ - 🎛️ **高度可定制**: 支持样式、颜色、宽度等各种属性自定义
29
+ - 🔧 **扩展性强**: 基于抽象路径构建器设计,可轻松扩展新的边缘类型
30
+ - ⚡ **性能优化**: 采用 SVG 渲染,支持交互区域优化
31
+
32
+ ## 📋 API 文档
33
+
34
+ ### 组件
35
+
36
+ #### `BaseEdge<TPathBuilderContext>`
37
+
38
+ 基础边缘组件,所有其他边缘组件的基础。
39
+
40
+ **Props**
41
+
42
+ ```tsx
43
+ interface BaseEdgeProps<TPathBuilderContext = void> extends EdgeProps {
44
+ className?: string // 自定义 CSS 类名
45
+ style?: Record<string, any> // 自定义样式对象
46
+ interactionWidth?: number // 交互区域宽度,默认 20
47
+ label?: string // 边缘标签文本
48
+ markerEnd?: string | MarkerProps // 终点标记
49
+ markerStart?: string | MarkerProps // 起点标记
50
+ pathBuilder: PathBuilderType<any, TPathBuilderContext> // 路径构建器
51
+ context: TPathBuilderContext // 路径构建器上下文
52
+ }
53
+ ```
54
+
55
+ **使用示例**
56
+
57
+ ```tsx
58
+ import { BaseEdge, StraightPathBuilder } from '@knotx/render'
59
+
60
+ function CustomEdge() {
61
+ return (
62
+ <BaseEdge
63
+ sourceX={0}
64
+ sourceY={0}
65
+ targetX={100}
66
+ targetY={100}
67
+ pathBuilder={StraightPathBuilder}
68
+ context={undefined}
69
+ label="连接线"
70
+ style={{ stroke: '#1890ff', strokeWidth: 2 }}
71
+ />
72
+ )
73
+ }
74
+ ```
75
+
76
+ #### `BezierEdge`
77
+
78
+ 贝塞尔曲线边缘组件,适用于需要平滑曲线连接的场景。
79
+
80
+ **Props**
81
+
82
+ ```tsx
83
+ interface BezierEdgeProps extends Omit<BaseEdgeProps, 'pathBuilder' | 'context'> {}
84
+ ```
85
+
86
+ **使用示例**
87
+
88
+ ```tsx
89
+ import { BezierEdge, getArrowMarker } from '@knotx/render'
90
+
91
+ function CurvedConnection() {
92
+ const arrowMarker = getArrowMarker('#ff4d4f')
93
+
94
+ return (
95
+ <BezierEdge
96
+ sourceX={50}
97
+ sourceY={50}
98
+ targetX={250}
99
+ targetY={150}
100
+ markerEnd={arrowMarker}
101
+ style={{ stroke: '#ff4d4f', strokeWidth: 2 }}
102
+ label="贝塞尔曲线"
103
+ />
104
+ )
105
+ }
106
+ ```
107
+
108
+ #### `StraightEdge`
109
+
110
+ 直线边缘组件,适用于简单的直线连接。
111
+
112
+ **Props**
113
+
114
+ ```tsx
115
+ interface StraightEdgeProps extends Omit<BaseEdgeProps, 'pathBuilder' | 'context'> {}
116
+ ```
117
+
118
+ **使用示例**
119
+
120
+ ```tsx
121
+ import { getArrowClosedMarker, StraightEdge } from '@knotx/render'
122
+
123
+ function DirectConnection() {
124
+ const arrowMarker = getArrowClosedMarker('#52c41a')
125
+
126
+ return (
127
+ <StraightEdge
128
+ sourceX={0}
129
+ sourceY={0}
130
+ targetX={200}
131
+ targetY={100}
132
+ markerEnd={arrowMarker}
133
+ markerStart={arrowMarker}
134
+ style={{ stroke: '#52c41a', strokeWidth: 3 }}
135
+ interactionWidth={30}
136
+ />
137
+ )
138
+ }
139
+ ```
140
+
141
+ #### `MarkerDefinitions`
142
+
143
+ 标记定义组件,用于集中管理和重用标记。
144
+
145
+ **Props**
146
+
147
+ ```typescript
148
+ interface MarkerDefinitionsProps {
149
+ markers: MarkerProps[]
150
+ }
151
+ ```
152
+
153
+ **使用示例**
154
+
155
+ ```tsx
156
+ import { getArrowClosedMarker, getArrowMarker, MarkerDefinitions } from '@knotx/render'
157
+
158
+ function EdgeContainer() {
159
+ const markers = [
160
+ getArrowMarker('#1890ff'),
161
+ getArrowClosedMarker('#ff4d4f'),
162
+ getArrowMarker('#52c41a')
163
+ ]
164
+
165
+ return (
166
+ <svg>
167
+ <MarkerDefinitions markers={markers} />
168
+ {/* 你的边缘组件 */}
169
+ </svg>
170
+ )
171
+ }
172
+ ```
173
+
174
+ ### 路径构建器
175
+
176
+ #### `PathBuilder<TType, TContext>`
177
+
178
+ 抽象路径构建器基类,用于创建自定义边缘类型。
179
+
180
+ **抽象方法**
181
+
182
+ ```tsx
183
+ abstract class PathBuilder<TType extends string, TContext = never> {
184
+ constructor(
185
+ readonly sourceX: number,
186
+ readonly sourceY: number,
187
+ readonly targetX: number,
188
+ readonly targetY: number
189
+ ) {}
190
+
191
+ abstract type: TType
192
+ abstract buildPath(context: TContext): string
193
+ abstract interpolate(t: number, context: TContext): { x: number, y: number }
194
+ }
195
+ ```
196
+
197
+ **创建自定义路径构建器示例**
198
+
199
+ ```tsx
200
+ class CustomPathBuilder extends PathBuilder<'custom'> {
201
+ type = 'custom' as const
202
+
203
+ buildPath(): string {
204
+ // 创建自定义的 SVG 路径
205
+ const midX = (this.sourceX + this.targetX) / 2
206
+ const midY = (this.sourceY + this.targetY) / 2
207
+
208
+ return `M ${this.sourceX} ${this.sourceY}
209
+ Q ${midX} ${midY - 50} ${this.targetX} ${this.targetY}`
210
+ }
211
+
212
+ interpolate(t: number): { x: number, y: number } {
213
+ // 实现路径上点的插值计算
214
+ const x = this.sourceX + t * (this.targetX - this.sourceX)
215
+ const y = this.sourceY + t * (this.targetY - this.sourceY)
216
+ return { x, y }
217
+ }
218
+ }
219
+ ```
220
+
221
+ #### `StraightPathBuilder`
222
+
223
+ 直线路径构建器,生成直线路径。
224
+
225
+ ```tsx
226
+ class StraightPathBuilder extends PathBuilder<'straight'> {
227
+ type = 'straight' as const
228
+ buildPath(): string
229
+ interpolate(t: number): { x: number, y: number }
230
+ }
231
+ ```
232
+
233
+ #### `BezierPathBuilder`
234
+
235
+ 贝塞尔曲线路径构建器,生成平滑的曲线路径。
236
+
237
+ ```tsx
238
+ class BezierPathBuilder extends PathBuilder<'bezier'> {
239
+ type = 'bezier' as const
240
+ buildPath(): string
241
+ interpolate(t: number): { x: number, y: number }
242
+ }
243
+ ```
244
+
245
+ ### 标记工具函数
246
+
247
+ #### `getArrowMarker(color?: string)`
248
+
249
+ 创建标准箭头标记。
250
+
251
+ **参数**
252
+ - `color` (可选): 标记颜色,默认为 `currentColor`
253
+
254
+ **返回值**
255
+ - `MarkerProps`: 箭头标记配置对象
256
+
257
+ **使用示例**
258
+
259
+ ```tsx
260
+ import { getArrowMarker, StraightEdge } from '@knotx/render'
261
+
262
+ function EdgeWithArrow() {
263
+ const marker = getArrowMarker('#1890ff')
264
+
265
+ return (
266
+ <StraightEdge
267
+ sourceX={0}
268
+ sourceY={0}
269
+ targetX={100}
270
+ targetY={100}
271
+ markerEnd={marker}
272
+ />
273
+ )
274
+ }
275
+ ```
276
+
277
+ #### `getArrowClosedMarker(color?: string)`
278
+
279
+ 创建实心箭头标记。
280
+
281
+ **参数**
282
+ - `color` (可选): 标记颜色,默认为 `currentColor`
283
+
284
+ **返回值**
285
+ - `MarkerProps`: 实心箭头标记配置对象
286
+
287
+ **使用示例**
288
+
289
+ ```tsx
290
+ import { BezierEdge, getArrowClosedMarker } from '@knotx/render'
291
+
292
+ function EdgeWithClosedArrow() {
293
+ const marker = getArrowClosedMarker('#ff4d4f')
294
+
295
+ return (
296
+ <BezierEdge
297
+ sourceX={50}
298
+ sourceY={50}
299
+ targetX={200}
300
+ targetY={150}
301
+ markerEnd={marker}
302
+ style={{ stroke: '#ff4d4f' }}
303
+ />
304
+ )
305
+ }
306
+ ```
307
+
308
+ #### `getCustomMarker(type: string, options?: Partial<MarkerProps>)`
309
+
310
+ 创建自定义标记。
311
+
312
+ **参数**
313
+ - `type`: 标记类型标识符
314
+ - `options` (可选): 自定义标记选项
315
+
316
+ **返回值**
317
+ - `MarkerProps`: 自定义标记配置对象
318
+
319
+ **使用示例**
320
+
321
+ ```tsx
322
+ import { BaseEdge, getCustomMarker, StraightPathBuilder } from '@knotx/render'
323
+
324
+ function EdgeWithCustomMarker() {
325
+ const marker = getCustomMarker('diamond', {
326
+ color: '#722ed1',
327
+ width: 12,
328
+ height: 12,
329
+ strokeWidth: 2
330
+ })
331
+
332
+ return (
333
+ <BaseEdge
334
+ sourceX={0}
335
+ sourceY={0}
336
+ targetX={150}
337
+ targetY={100}
338
+ pathBuilder={StraightPathBuilder}
339
+ context={undefined}
340
+ markerEnd={marker}
341
+ />
342
+ )
343
+ }
344
+ ```
345
+
346
+ #### `getArrowHeadMarkers(color?: string)`
347
+
348
+ 创建两个实心箭头作为起点和终点的标记。
349
+
350
+ **参数**
351
+ - `color` (可选): 标记颜色
352
+
353
+ **返回值**
354
+ - 包含 `markerStart` 和 `markerEnd` 的对象
355
+
356
+ **使用示例**
357
+
358
+ ```tsx
359
+ import { getArrowHeadMarkers, StraightEdge } from '@knotx/render'
360
+
361
+ function DoubleArrowEdge() {
362
+ const { markerStart, markerEnd } = getArrowHeadMarkers('#13c2c2')
363
+
364
+ return (
365
+ <StraightEdge
366
+ sourceX={0}
367
+ sourceY={0}
368
+ targetX={200}
369
+ targetY={100}
370
+ markerStart={markerStart}
371
+ markerEnd={markerEnd}
372
+ style={{ stroke: '#13c2c2', strokeWidth: 2 }}
373
+ />
374
+ )
375
+ }
376
+ ```
377
+
378
+ ### 类型定义
379
+
380
+ #### `MarkerType`
381
+
382
+ ```typescript
383
+ enum MarkerType {
384
+ Arrow = 'arrow',
385
+ ArrowClosed = 'arrowclosed'
386
+ }
387
+ ```
388
+
389
+ #### `MarkerProps`
390
+
391
+ ```typescript
392
+ interface MarkerProps {
393
+ id: string // 标记唯一标识符
394
+ type: MarkerType | string // 标记类型
395
+ color?: string // 标记颜色
396
+ width?: number // 标记宽度
397
+ height?: number // 标记高度
398
+ markerUnits?: string // 标记单位
399
+ orient?: string // 标记方向
400
+ strokeWidth?: number // 描边宽度
401
+ }
402
+ ```
403
+
404
+ #### `PathBuilderType`
405
+
406
+ ```tsx
407
+ type PathBuilderType<T extends string = any, TContext = void> =
408
+ new (...args: ConstructorParameters<typeof PathBuilder<T, TContext>>) =>
409
+ PathBuilder<T, TContext>
410
+ ```
411
+
412
+ ## 🗂️ 文件目录结构
413
+
414
+ ```
415
+ packages/render/
416
+ ├── src/
417
+ │ ├── edges/
418
+ │ │ ├── base-edge.tsx # 基础边缘组件
419
+ │ │ ├── bezier.tsx # 贝塞尔曲线边缘
420
+ │ │ ├── straight.tsx # 直线边缘
421
+ │ │ ├── markers.tsx # 标记相关功能
422
+ │ │ ├── path-builder.ts # 路径构建器
423
+ │ │ └── index.ts # 边缘模块导出
424
+ │ └── index.ts # 主入口文件
425
+ ├── dist/ # 构建输出目录
426
+ ├── package.json # 包配置文件
427
+ ├── tsconfig.json # TypeScript 配置
428
+ ├── build.config.ts # 构建配置
429
+ └── README.md # 文档文件
430
+ ```
431
+
432
+ ## 🎯 完整使用示例
433
+
434
+ ### 基础使用
435
+
436
+ ```tsx
437
+ import {
438
+ BezierEdge,
439
+ getArrowClosedMarker,
440
+ getArrowMarker,
441
+ StraightEdge
442
+ } from '@knotx/render'
443
+ import React from 'react'
444
+
445
+ function GraphEditor() {
446
+ return (
447
+ <div style={{ position: 'relative', width: 800, height: 600 }}>
448
+ {/* 直线连接 */}
449
+ <StraightEdge
450
+ sourceX={50}
451
+ sourceY={50}
452
+ targetX={200}
453
+ targetY={100}
454
+ markerEnd={getArrowMarker('#1890ff')}
455
+ style={{ stroke: '#1890ff', strokeWidth: 2 }}
456
+ label="直线连接"
457
+ />
458
+
459
+ {/* 贝塞尔曲线连接 */}
460
+ <BezierEdge
461
+ sourceX={50}
462
+ sourceY={150}
463
+ targetX={250}
464
+ targetY={200}
465
+ markerEnd={getArrowClosedMarker('#ff4d4f')}
466
+ style={{ stroke: '#ff4d4f', strokeWidth: 2 }}
467
+ label="曲线连接"
468
+ />
469
+ </div>
470
+ )
471
+ }
472
+ ```
473
+
474
+ ### 自定义边缘类型
475
+
476
+ ```tsx
477
+ import { BaseEdge, PathBuilder } from '@knotx/render'
478
+
479
+ // 创建自定义路径构建器
480
+ class StepPathBuilder extends PathBuilder<'step'> {
481
+ type = 'step' as const
482
+
483
+ buildPath(): string {
484
+ const midX = (this.sourceX + this.targetX) / 2
485
+ return `M ${this.sourceX} ${this.sourceY}
486
+ L ${midX} ${this.sourceY}
487
+ L ${midX} ${this.targetY}
488
+ L ${this.targetX} ${this.targetY}`
489
+ }
490
+
491
+ interpolate(t: number): { x: number, y: number } {
492
+ const midX = (this.sourceX + this.targetX) / 2
493
+
494
+ if (t <= 0.33) {
495
+ const localT = t / 0.33
496
+ return {
497
+ x: this.sourceX + localT * (midX - this.sourceX),
498
+ y: this.sourceY
499
+ }
500
+ }
501
+ else if (t <= 0.66) {
502
+ const localT = (t - 0.33) / 0.33
503
+ return {
504
+ x: midX,
505
+ y: this.sourceY + localT * (this.targetY - this.sourceY)
506
+ }
507
+ }
508
+ else {
509
+ const localT = (t - 0.66) / 0.34
510
+ return {
511
+ x: midX + localT * (this.targetX - midX),
512
+ y: this.targetY
513
+ }
514
+ }
515
+ }
516
+ }
517
+
518
+ // 使用自定义路径构建器
519
+ function StepEdge(props: Omit<BaseEdgeProps, 'pathBuilder' | 'context'>) {
520
+ return (
521
+ <BaseEdge
522
+ {...props}
523
+ pathBuilder={StepPathBuilder}
524
+ context={undefined}
525
+ />
526
+ )
527
+ }
528
+ ```
529
+
530
+ ### 高级标记管理
531
+
532
+ ```tsx
533
+ import { getArrowMarker, getCustomMarker, MarkerDefinitions } from '@knotx/render'
534
+
535
+ function AdvancedGraph() {
536
+ // 预定义标记
537
+ const markers = [
538
+ getArrowMarker('#1890ff'),
539
+ getArrowMarker('#ff4d4f'),
540
+ getCustomMarker('circle', {
541
+ color: '#52c41a',
542
+ width: 8,
543
+ height: 8
544
+ })
545
+ ]
546
+
547
+ return (
548
+ <svg width="800" height="600">
549
+ <MarkerDefinitions markers={markers} />
550
+
551
+ {/* 使用预定义标记 */}
552
+ <StraightEdge
553
+ sourceX={100}
554
+ sourceY={100}
555
+ targetX={300}
556
+ targetY={200}
557
+ markerEnd={markers[0]}
558
+ style={{ stroke: '#1890ff' }}
559
+ />
560
+
561
+ <BezierEdge
562
+ sourceX={100}
563
+ sourceY={200}
564
+ targetX={400}
565
+ targetY={150}
566
+ markerEnd={markers[1]}
567
+ style={{ stroke: '#ff4d4f' }}
568
+ />
569
+ </svg>
570
+ )
571
+ }
572
+ ```
573
+
574
+ ## 📄 许可证
575
+
576
+ MIT
577
+
578
+ ## 🤝 贡献
579
+
580
+ 欢迎提交问题和拉取请求。详见 [CONTRIBUTING.md](../../CONTRIBUTING.md)
581
+
582
+ ## 📞 支持
583
+
584
+ 如果您遇到任何问题或需要帮助,请在 [GitHub Issues](https://github.com/boenfu/knotx/issues) 中提交问题。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knotx/render",
3
- "version": "0.4.12",
3
+ "version": "0.4.13",
4
4
  "description": "Render for Knotx",
5
5
  "author": "boenfu",
6
6
  "license": "MIT",
@@ -28,18 +28,18 @@
28
28
  "dist"
29
29
  ],
30
30
  "peerDependencies": {
31
- "@knotx/jsx": "0.4.12"
31
+ "@knotx/jsx": "0.4.13"
32
32
  },
33
33
  "dependencies": {
34
34
  "bezier-js": "^6.1.4",
35
- "@knotx/core": "0.4.12"
35
+ "@knotx/core": "0.4.13"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/bezier-js": "^4.1.3",
39
- "@knotx/build-config": "0.4.12",
40
- "@knotx/eslint-config": "0.4.12",
41
- "@knotx/jsx": "0.4.12",
42
- "@knotx/typescript-config": "0.4.12"
39
+ "@knotx/build-config": "0.4.13",
40
+ "@knotx/eslint-config": "0.4.13",
41
+ "@knotx/jsx": "0.4.13",
42
+ "@knotx/typescript-config": "0.4.13"
43
43
  },
44
44
  "scripts": {
45
45
  "build": "unbuild",