@knotx/decorators 0.4.11 → 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.
- package/README.en.md +564 -0
- package/README.md +564 -0
- package/package.json +7 -7
package/README.en.md
ADDED
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
# @knotx/decorators
|
|
2
|
+
|
|
3
|
+
A TypeScript decorator package for Knotx graph editor that simplifies plugin development.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @knotx/decorators
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or with yarn:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
yarn add @knotx/decorators
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or with pnpm:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add @knotx/decorators
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Overview
|
|
24
|
+
|
|
25
|
+
`@knotx/decorators` provides a comprehensive set of TypeScript decorators to help developers create Knotx plugins more efficiently. These decorators encapsulate common plugin development patterns including node rendering, edge rendering, data management, lifecycle management, and more.
|
|
26
|
+
|
|
27
|
+
## Key Features
|
|
28
|
+
|
|
29
|
+
- **Node Management**: Provides node type definition, operations, and pipeline processing
|
|
30
|
+
- **Edge Management**: Provides edge type definition, operations, and pipeline processing
|
|
31
|
+
- **Plugin Management**: Provides configuration management, lifecycle control, and tool function registration
|
|
32
|
+
- **Data Management**: Provides reactive data binding and dependency injection
|
|
33
|
+
- **UI Management**: Provides layer management and panel rendering
|
|
34
|
+
|
|
35
|
+
## API Documentation
|
|
36
|
+
|
|
37
|
+
### Node Decorators
|
|
38
|
+
|
|
39
|
+
#### @nodeType
|
|
40
|
+
|
|
41
|
+
Used to declare a method as a node renderer.
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { nodeType } from '@knotx/decorators'
|
|
45
|
+
|
|
46
|
+
class MyPlugin extends BasePlugin {
|
|
47
|
+
@nodeType('my-node')
|
|
48
|
+
renderNode(node: Node) {
|
|
49
|
+
return (
|
|
50
|
+
<div className="my-node">
|
|
51
|
+
<h3>{node.data.title}</h3>
|
|
52
|
+
<p>{node.data.content}</p>
|
|
53
|
+
</div>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Parameters**:
|
|
60
|
+
- `type: string` - Node type identifier
|
|
61
|
+
|
|
62
|
+
**Returns**: A React component or JSX element
|
|
63
|
+
|
|
64
|
+
#### @nodeOperator
|
|
65
|
+
|
|
66
|
+
Used to declare a method as a node operation function.
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { nodeOperator } from '@knotx/decorators'
|
|
70
|
+
|
|
71
|
+
class MyPlugin extends BasePlugin {
|
|
72
|
+
@nodeOperator()
|
|
73
|
+
addNode(x: number, y: number) {
|
|
74
|
+
return [{
|
|
75
|
+
type: 'add',
|
|
76
|
+
node: {
|
|
77
|
+
id: generateId(),
|
|
78
|
+
type: 'default',
|
|
79
|
+
position: { x, y },
|
|
80
|
+
data: { title: 'New Node' }
|
|
81
|
+
}
|
|
82
|
+
}]
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@nodeOperator()
|
|
86
|
+
deleteNode(nodeId: string) {
|
|
87
|
+
return [{
|
|
88
|
+
type: 'remove',
|
|
89
|
+
nodeId
|
|
90
|
+
}]
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Usage Notes**:
|
|
96
|
+
- Method must return an array of operations
|
|
97
|
+
- Operations are automatically dispatched to the engine for processing
|
|
98
|
+
- Supports batch operations
|
|
99
|
+
|
|
100
|
+
#### @nodePipe
|
|
101
|
+
|
|
102
|
+
Used to declare a method as a node operation pipeline for processing before and after node operations.
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { nodePipe } from '@knotx/decorators'
|
|
106
|
+
import { filter, map } from 'rxjs/operators'
|
|
107
|
+
|
|
108
|
+
class MyPlugin extends BasePlugin {
|
|
109
|
+
@nodePipe()
|
|
110
|
+
validateNodeOperation() {
|
|
111
|
+
return {
|
|
112
|
+
preOperation: () => filter((operation) => {
|
|
113
|
+
if (operation.type === 'add') {
|
|
114
|
+
return this.validateNode(operation.node)
|
|
115
|
+
}
|
|
116
|
+
return true
|
|
117
|
+
}),
|
|
118
|
+
postOperation: () => map((operation) => {
|
|
119
|
+
console.log('Operation completed:', operation)
|
|
120
|
+
return operation
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**Returns**: An object containing `preOperation` and `postOperation`
|
|
128
|
+
|
|
129
|
+
### Edge Decorators
|
|
130
|
+
|
|
131
|
+
#### @edgeType
|
|
132
|
+
|
|
133
|
+
Used to declare a method as an edge renderer.
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
import { edgeType } from '@knotx/decorators'
|
|
137
|
+
|
|
138
|
+
class MyPlugin extends BasePlugin {
|
|
139
|
+
@edgeType('my-edge', {
|
|
140
|
+
sourcePosition: 'right',
|
|
141
|
+
targetPosition: 'left',
|
|
142
|
+
sourceXOffset: 10,
|
|
143
|
+
targetXOffset: -10
|
|
144
|
+
})
|
|
145
|
+
renderEdge(edge: Edge) {
|
|
146
|
+
return (
|
|
147
|
+
<g>
|
|
148
|
+
<path
|
|
149
|
+
d={edge.path}
|
|
150
|
+
stroke="#333"
|
|
151
|
+
strokeWidth={2}
|
|
152
|
+
fill="none"
|
|
153
|
+
/>
|
|
154
|
+
<text x={edge.labelX} y={edge.labelY}>
|
|
155
|
+
{edge.label}
|
|
156
|
+
</text>
|
|
157
|
+
</g>
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Parameters**:
|
|
164
|
+
- `type: string` - Edge type identifier
|
|
165
|
+
- `edgeConfig?: EdgeConfig` - Edge configuration options
|
|
166
|
+
- `sourcePosition: Position` - Source connection point position
|
|
167
|
+
- `targetPosition: Position` - Target connection point position
|
|
168
|
+
- `sourceXOffset: number` - Source connection point X offset
|
|
169
|
+
- `sourceYOffset: number` - Source connection point Y offset
|
|
170
|
+
- `targetXOffset: number` - Target connection point X offset
|
|
171
|
+
- `targetYOffset: number` - Target connection point Y offset
|
|
172
|
+
|
|
173
|
+
#### @edgeOperator
|
|
174
|
+
|
|
175
|
+
Used to declare a method as an edge operation function.
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
import { edgeOperator } from '@knotx/decorators'
|
|
179
|
+
|
|
180
|
+
class MyPlugin extends BasePlugin {
|
|
181
|
+
@edgeOperator()
|
|
182
|
+
addEdge(sourceId: string, targetId: string) {
|
|
183
|
+
return [{
|
|
184
|
+
type: 'add',
|
|
185
|
+
edge: {
|
|
186
|
+
id: generateId(),
|
|
187
|
+
source: sourceId,
|
|
188
|
+
target: targetId,
|
|
189
|
+
type: 'default'
|
|
190
|
+
}
|
|
191
|
+
}]
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
#### @edgePipe
|
|
197
|
+
|
|
198
|
+
Used to declare a method as an edge operation pipeline.
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
import { edgePipe } from '@knotx/decorators'
|
|
202
|
+
|
|
203
|
+
class MyPlugin extends BasePlugin {
|
|
204
|
+
@edgePipe()
|
|
205
|
+
validateEdgeOperation() {
|
|
206
|
+
return {
|
|
207
|
+
preOperation: () => filter((operation) => {
|
|
208
|
+
if (operation.type === 'add') {
|
|
209
|
+
return this.validateEdge(operation.edge)
|
|
210
|
+
}
|
|
211
|
+
return true
|
|
212
|
+
})
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Plugin Decorators
|
|
219
|
+
|
|
220
|
+
#### @config
|
|
221
|
+
|
|
222
|
+
Automatically binds configuration management and lifecycle functions.
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
import { config } from '@knotx/decorators'
|
|
226
|
+
|
|
227
|
+
class MyPlugin extends BasePlugin {
|
|
228
|
+
@config()
|
|
229
|
+
config = {
|
|
230
|
+
theme: 'light',
|
|
231
|
+
showGrid: true,
|
|
232
|
+
gridSize: 20
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Configuration will be automatically updated on onInit and onConfigChange
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
#### @register
|
|
240
|
+
|
|
241
|
+
Used to register plugin properties to the engine, making them accessible to other plugins via inject.
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
import { register } from '@knotx/decorators'
|
|
245
|
+
|
|
246
|
+
class HistoryPlugin extends BasePlugin {
|
|
247
|
+
@register('canUndo')
|
|
248
|
+
canUndo = false
|
|
249
|
+
|
|
250
|
+
@register('canRedo')
|
|
251
|
+
canRedo = false
|
|
252
|
+
|
|
253
|
+
@register('history')
|
|
254
|
+
get history() {
|
|
255
|
+
return this.historyStack
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
#### @tool
|
|
261
|
+
|
|
262
|
+
Used to decorate tool functions in plugins, making them callable by the engine and other plugins.
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
import { tool } from '@knotx/decorators'
|
|
266
|
+
|
|
267
|
+
class MathPlugin extends BasePlugin {
|
|
268
|
+
@tool('Calculate distance between two points', {
|
|
269
|
+
type: 'object',
|
|
270
|
+
properties: {
|
|
271
|
+
x1: { type: 'number', description: 'X coordinate of first point' },
|
|
272
|
+
y1: { type: 'number', description: 'Y coordinate of first point' },
|
|
273
|
+
x2: { type: 'number', description: 'X coordinate of second point' },
|
|
274
|
+
y2: { type: 'number', description: 'Y coordinate of second point' }
|
|
275
|
+
},
|
|
276
|
+
required: ['x1', 'y1', 'x2', 'y2']
|
|
277
|
+
})
|
|
278
|
+
calculateDistance(params: { x1: number, y1: number, x2: number, y2: number }) {
|
|
279
|
+
const dx = params.x2 - params.x1
|
|
280
|
+
const dy = params.y2 - params.y1
|
|
281
|
+
return Math.sqrt(dx * dx + dy * dy)
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**Parameters**:
|
|
287
|
+
- `description: string` - Tool function description
|
|
288
|
+
- `parameters: Schema` - JSON Schema definition of parameters
|
|
289
|
+
|
|
290
|
+
#### @observable
|
|
291
|
+
|
|
292
|
+
Creates reactive properties that support data binding and change monitoring.
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
import { observable } from '@knotx/decorators'
|
|
296
|
+
|
|
297
|
+
class MyPlugin extends BasePlugin {
|
|
298
|
+
@observable()
|
|
299
|
+
selectedNodes: string[] = []
|
|
300
|
+
|
|
301
|
+
@observable()
|
|
302
|
+
zoomLevel = 1
|
|
303
|
+
|
|
304
|
+
updateSelection(nodeIds: string[]) {
|
|
305
|
+
this.selectedNodes = nodeIds // Automatically triggers change notification
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
#### Lifecycle Decorators
|
|
311
|
+
|
|
312
|
+
##### @OnInit
|
|
313
|
+
|
|
314
|
+
Called when the plugin is initialized.
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
import { OnInit } from '@knotx/decorators'
|
|
318
|
+
|
|
319
|
+
class MyPlugin extends BasePlugin {
|
|
320
|
+
@OnInit
|
|
321
|
+
initialize(config: PluginConfig) {
|
|
322
|
+
console.log('Plugin initialized with config:', config)
|
|
323
|
+
this.setupEventListeners()
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
##### @OnDestroy
|
|
329
|
+
|
|
330
|
+
Called when the plugin is destroyed.
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
import { OnDestroy } from '@knotx/decorators'
|
|
334
|
+
|
|
335
|
+
class MyPlugin extends BasePlugin {
|
|
336
|
+
@OnDestroy
|
|
337
|
+
cleanup() {
|
|
338
|
+
console.log('Plugin destroyed')
|
|
339
|
+
this.clearEventListeners()
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
##### @OnConfigChange
|
|
345
|
+
|
|
346
|
+
Called when plugin configuration changes.
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
import { OnConfigChange } from '@knotx/decorators'
|
|
350
|
+
|
|
351
|
+
class MyPlugin extends BasePlugin {
|
|
352
|
+
@OnConfigChange
|
|
353
|
+
handleConfigChange(newConfig: PluginConfig) {
|
|
354
|
+
console.log('Config changed:', newConfig)
|
|
355
|
+
this.applyNewConfig(newConfig)
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### Engine Decorators
|
|
361
|
+
|
|
362
|
+
#### @inject
|
|
363
|
+
|
|
364
|
+
Used to inject engine variables or data from other plugins.
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
import { inject } from '@knotx/decorators'
|
|
368
|
+
|
|
369
|
+
class MyPlugin extends BasePlugin {
|
|
370
|
+
// Inject engine variables
|
|
371
|
+
@inject.nodes()
|
|
372
|
+
nodes: Node[] = []
|
|
373
|
+
|
|
374
|
+
// Inject engine methods
|
|
375
|
+
@inject.getNodeById()
|
|
376
|
+
getNodeById!: (id: string) => Node | undefined
|
|
377
|
+
|
|
378
|
+
// Inject data from other plugins
|
|
379
|
+
@inject.history.canUndo()
|
|
380
|
+
canUndo = false
|
|
381
|
+
|
|
382
|
+
// Inject specific data using selectors
|
|
383
|
+
@inject.nodes((nodes: Node[]) => nodes.filter(n => n.selected))
|
|
384
|
+
selectedNodes: Node[] = []
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
**Usage**:
|
|
389
|
+
- `@inject.property()` - Inject engine variables
|
|
390
|
+
- `@inject.property(selector)` - Inject engine variables with selector
|
|
391
|
+
- `@inject.pluginName.property()` - Inject plugin variables
|
|
392
|
+
- `@inject.methodName()` - Inject engine methods
|
|
393
|
+
|
|
394
|
+
#### @subscribe
|
|
395
|
+
|
|
396
|
+
Used to subscribe to changes in engine variables or data from other plugins.
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
import { subscribe } from '@knotx/decorators'
|
|
400
|
+
|
|
401
|
+
class MyPlugin extends BasePlugin {
|
|
402
|
+
// Subscribe to engine variables
|
|
403
|
+
@subscribe.nodes()
|
|
404
|
+
handleNodesChange(nodes: Node[]) {
|
|
405
|
+
console.log('Nodes changed:', nodes)
|
|
406
|
+
this.updateUI(nodes)
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Subscribe to data from other plugins
|
|
410
|
+
@subscribe.history.canUndo()
|
|
411
|
+
handleUndoStateChange(canUndo: boolean) {
|
|
412
|
+
this.updateUndoButton(canUndo)
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### Layer Decorators
|
|
418
|
+
|
|
419
|
+
#### @layer
|
|
420
|
+
|
|
421
|
+
Used to declare the render layer of a method.
|
|
422
|
+
|
|
423
|
+
```tsx
|
|
424
|
+
import { Layer } from '@knotx/core'
|
|
425
|
+
import { layer } from '@knotx/decorators'
|
|
426
|
+
|
|
427
|
+
class MyPlugin extends BasePlugin {
|
|
428
|
+
@layer(Layer.BACKGROUND)
|
|
429
|
+
renderBackground() {
|
|
430
|
+
return (
|
|
431
|
+
<rect width="100%" height="100%" fill="#f0f0f0" />
|
|
432
|
+
)
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
@layer(Layer.FOREGROUND, 100)
|
|
436
|
+
renderOverlay() {
|
|
437
|
+
return (
|
|
438
|
+
<div className="overlay">
|
|
439
|
+
Overlay content
|
|
440
|
+
</div>
|
|
441
|
+
)
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
**Parameters**:
|
|
447
|
+
- `layer: Layer` - Layer enum value
|
|
448
|
+
- `offset?: number` - Layer offset value
|
|
449
|
+
|
|
450
|
+
#### @panel
|
|
451
|
+
|
|
452
|
+
Used to create panel components.
|
|
453
|
+
|
|
454
|
+
```tsx
|
|
455
|
+
import { panel } from '@knotx/decorators'
|
|
456
|
+
|
|
457
|
+
class MyPlugin extends BasePlugin {
|
|
458
|
+
@panel('top', { x: 10, y: 10 })
|
|
459
|
+
renderToolbar() {
|
|
460
|
+
return (
|
|
461
|
+
<div className="toolbar">
|
|
462
|
+
<button>Save</button>
|
|
463
|
+
<button>Load</button>
|
|
464
|
+
<button>Export</button>
|
|
465
|
+
</div>
|
|
466
|
+
)
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
@panel('bottom-right')
|
|
470
|
+
renderStatus() {
|
|
471
|
+
return (
|
|
472
|
+
<div className="status">
|
|
473
|
+
Ready
|
|
474
|
+
</div>
|
|
475
|
+
)
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
**Parameters**:
|
|
481
|
+
- `position: Position` - Panel position ('top' | 'bottom' | 'left' | 'right' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right')
|
|
482
|
+
- `offset?: PanelOffset` - Panel offset
|
|
483
|
+
- `x?: number` - X-axis offset
|
|
484
|
+
- `y?: number` - Y-axis offset
|
|
485
|
+
|
|
486
|
+
## Directory Structure
|
|
487
|
+
|
|
488
|
+
```
|
|
489
|
+
src/
|
|
490
|
+
├── index.ts # Main export file
|
|
491
|
+
├── internal.ts # Internal utility functions
|
|
492
|
+
├── edge/ # Edge-related decorators
|
|
493
|
+
│ ├── index.ts # Edge module exports
|
|
494
|
+
│ ├── edgeType.ts # Edge type decorator
|
|
495
|
+
│ ├── edgeOperator.ts # Edge operator decorator
|
|
496
|
+
│ └── edgePipe.ts # Edge pipe decorator
|
|
497
|
+
├── engine/ # Engine-related decorators
|
|
498
|
+
│ ├── index.ts # Engine module exports
|
|
499
|
+
│ ├── inject/ # Inject decorators
|
|
500
|
+
│ │ ├── index.ts # Inject module exports
|
|
501
|
+
│ │ ├── inject-data.ts # Data injection implementation
|
|
502
|
+
│ │ ├── inject-decorator.ts # Inject decorator implementation
|
|
503
|
+
│ │ ├── inject-method.ts # Method injection implementation
|
|
504
|
+
│ │ ├── inject-plugin.ts # Plugin injection implementation
|
|
505
|
+
│ │ ├── injectable.ts # Injectable interface
|
|
506
|
+
│ │ ├── injectable-proxy.ts # Injection proxy implementation
|
|
507
|
+
│ │ ├── proxy.ts # Proxy object
|
|
508
|
+
│ │ └── types.ts # Type definitions
|
|
509
|
+
│ └── subscribe/ # Subscribe decorators
|
|
510
|
+
│ ├── index.ts # Subscribe module exports
|
|
511
|
+
│ ├── proxy.ts # Subscribe proxy object
|
|
512
|
+
│ ├── subscribe-data.ts # Data subscription implementation
|
|
513
|
+
│ ├── subscribe-decorator.ts # Subscribe decorator implementation
|
|
514
|
+
│ ├── subscribe-plugin.ts # Plugin subscription implementation
|
|
515
|
+
│ └── types.ts # Type definitions
|
|
516
|
+
├── layer/ # Layer-related decorators
|
|
517
|
+
│ ├── index.ts # Layer module exports
|
|
518
|
+
│ ├── layer.ts # Layer decorator
|
|
519
|
+
│ └── panel.tsx # Panel decorator
|
|
520
|
+
├── node/ # Node-related decorators
|
|
521
|
+
│ ├── index.ts # Node module exports
|
|
522
|
+
│ ├── nodeType.ts # Node type decorator
|
|
523
|
+
│ ├── nodeOperator.ts # Node operator decorator
|
|
524
|
+
│ └── nodePipe.ts # Node pipe decorator
|
|
525
|
+
└── plugin/ # Plugin-related decorators
|
|
526
|
+
├── index.ts # Plugin module exports
|
|
527
|
+
├── config.ts # Config decorator
|
|
528
|
+
├── lifecycle.ts # Lifecycle decorators
|
|
529
|
+
├── observable.ts # Observable decorator
|
|
530
|
+
├── register.ts # Register decorator
|
|
531
|
+
└── tool.ts # Tool function decorator
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
## Dependencies
|
|
535
|
+
|
|
536
|
+
### Peer Dependencies
|
|
537
|
+
|
|
538
|
+
- `@knotx/jsx` - Knotx JSX runtime support
|
|
539
|
+
|
|
540
|
+
### Dependencies
|
|
541
|
+
|
|
542
|
+
- `@knotx/core` - Knotx core library
|
|
543
|
+
- `jsonschema` - JSON Schema validation library
|
|
544
|
+
- `lodash-es` - Utility functions library
|
|
545
|
+
- `rxjs` - Reactive programming library
|
|
546
|
+
|
|
547
|
+
## License
|
|
548
|
+
|
|
549
|
+
MIT License
|
|
550
|
+
|
|
551
|
+
## Contributing
|
|
552
|
+
|
|
553
|
+
Issues and Pull Requests are welcome. Before submitting code, please ensure:
|
|
554
|
+
|
|
555
|
+
1. Code follows the project's ESLint rules
|
|
556
|
+
2. Passes TypeScript type checking
|
|
557
|
+
3. Includes necessary test cases
|
|
558
|
+
4. Updates relevant documentation
|
|
559
|
+
|
|
560
|
+
## More Information
|
|
561
|
+
|
|
562
|
+
- [Knotx Homepage](https://github.com/boenfu/knotx)
|
|
563
|
+
- [API Documentation](https://github.com/boenfu/knotx#readme)
|
|
564
|
+
- [Example Projects](https://github.com/boenfu/knotx/tree/main/apps/playground)
|
package/README.md
ADDED
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
# @knotx/decorators
|
|
2
|
+
|
|
3
|
+
一个为 Knotx 图形编辑器提供装饰器支持的 TypeScript 包,用于简化插件开发过程。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @knotx/decorators
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
或者使用 yarn:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
yarn add @knotx/decorators
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
或者使用 pnpm:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add @knotx/decorators
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 基本概述
|
|
24
|
+
|
|
25
|
+
`@knotx/decorators` 提供了一套完整的 TypeScript 装饰器,帮助开发者更高效地创建 Knotx 插件。这些装饰器封装了常见的插件开发模式,包括节点渲染、边渲染、数据管理、生命周期管理等功能。
|
|
26
|
+
|
|
27
|
+
## 主要功能
|
|
28
|
+
|
|
29
|
+
- **节点管理**:提供节点类型定义、操作和管道处理
|
|
30
|
+
- **边管理**:提供边类型定义、操作和管道处理
|
|
31
|
+
- **插件管理**:提供配置管理、生命周期控制和工具函数注册
|
|
32
|
+
- **数据管理**:提供响应式数据绑定和依赖注入
|
|
33
|
+
- **UI 管理**:提供层级管理和面板渲染
|
|
34
|
+
|
|
35
|
+
## API 文档
|
|
36
|
+
|
|
37
|
+
### 节点相关装饰器
|
|
38
|
+
|
|
39
|
+
#### @nodeType
|
|
40
|
+
|
|
41
|
+
用于声明一个方法作为节点渲染器。
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { nodeType } from '@knotx/decorators'
|
|
45
|
+
|
|
46
|
+
class MyPlugin extends BasePlugin {
|
|
47
|
+
@nodeType('my-node')
|
|
48
|
+
renderNode(node: Node) {
|
|
49
|
+
return (
|
|
50
|
+
<div className="my-node">
|
|
51
|
+
<h3>{node.data.title}</h3>
|
|
52
|
+
<p>{node.data.content}</p>
|
|
53
|
+
</div>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**参数**:
|
|
60
|
+
- `type: string` - 节点类型标识符
|
|
61
|
+
|
|
62
|
+
**返回值**:返回一个 React 组件或 JSX 元素
|
|
63
|
+
|
|
64
|
+
#### @nodeOperator
|
|
65
|
+
|
|
66
|
+
用于声明一个方法作为节点操作函数。
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { nodeOperator } from '@knotx/decorators'
|
|
70
|
+
|
|
71
|
+
class MyPlugin extends BasePlugin {
|
|
72
|
+
@nodeOperator()
|
|
73
|
+
addNode(x: number, y: number) {
|
|
74
|
+
return [{
|
|
75
|
+
type: 'add',
|
|
76
|
+
node: {
|
|
77
|
+
id: generateId(),
|
|
78
|
+
type: 'default',
|
|
79
|
+
position: { x, y },
|
|
80
|
+
data: { title: 'New Node' }
|
|
81
|
+
}
|
|
82
|
+
}]
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@nodeOperator()
|
|
86
|
+
deleteNode(nodeId: string) {
|
|
87
|
+
return [{
|
|
88
|
+
type: 'remove',
|
|
89
|
+
nodeId
|
|
90
|
+
}]
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**使用说明**:
|
|
96
|
+
- 方法必须返回一个操作数组
|
|
97
|
+
- 操作会自动分发到引擎进行处理
|
|
98
|
+
- 支持批量操作
|
|
99
|
+
|
|
100
|
+
#### @nodePipe
|
|
101
|
+
|
|
102
|
+
用于声明一个方法作为节点操作管道,在节点操作执行前后进行处理。
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { nodePipe } from '@knotx/decorators'
|
|
106
|
+
import { filter, map } from 'rxjs/operators'
|
|
107
|
+
|
|
108
|
+
class MyPlugin extends BasePlugin {
|
|
109
|
+
@nodePipe()
|
|
110
|
+
validateNodeOperation() {
|
|
111
|
+
return {
|
|
112
|
+
preOperation: () => filter((operation) => {
|
|
113
|
+
if (operation.type === 'add') {
|
|
114
|
+
return this.validateNode(operation.node)
|
|
115
|
+
}
|
|
116
|
+
return true
|
|
117
|
+
}),
|
|
118
|
+
postOperation: () => map((operation) => {
|
|
119
|
+
console.log('Operation completed:', operation)
|
|
120
|
+
return operation
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**返回值**:返回一个包含 `preOperation` 和 `postOperation` 的对象
|
|
128
|
+
|
|
129
|
+
### 边相关装饰器
|
|
130
|
+
|
|
131
|
+
#### @edgeType
|
|
132
|
+
|
|
133
|
+
用于声明一个方法作为边渲染器。
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
import { edgeType } from '@knotx/decorators'
|
|
137
|
+
|
|
138
|
+
class MyPlugin extends BasePlugin {
|
|
139
|
+
@edgeType('my-edge', {
|
|
140
|
+
sourcePosition: 'right',
|
|
141
|
+
targetPosition: 'left',
|
|
142
|
+
sourceXOffset: 10,
|
|
143
|
+
targetXOffset: -10
|
|
144
|
+
})
|
|
145
|
+
renderEdge(edge: Edge) {
|
|
146
|
+
return (
|
|
147
|
+
<g>
|
|
148
|
+
<path
|
|
149
|
+
d={edge.path}
|
|
150
|
+
stroke="#333"
|
|
151
|
+
strokeWidth={2}
|
|
152
|
+
fill="none"
|
|
153
|
+
/>
|
|
154
|
+
<text x={edge.labelX} y={edge.labelY}>
|
|
155
|
+
{edge.label}
|
|
156
|
+
</text>
|
|
157
|
+
</g>
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**参数**:
|
|
164
|
+
- `type: string` - 边类型标识符
|
|
165
|
+
- `edgeConfig?: EdgeConfig` - 边配置选项
|
|
166
|
+
- `sourcePosition: Position` - 源连接点位置
|
|
167
|
+
- `targetPosition: Position` - 目标连接点位置
|
|
168
|
+
- `sourceXOffset: number` - 源连接点 X 偏移
|
|
169
|
+
- `sourceYOffset: number` - 源连接点 Y 偏移
|
|
170
|
+
- `targetXOffset: number` - 目标连接点 X 偏移
|
|
171
|
+
- `targetYOffset: number` - 目标连接点 Y 偏移
|
|
172
|
+
|
|
173
|
+
#### @edgeOperator
|
|
174
|
+
|
|
175
|
+
用于声明一个方法作为边操作函数。
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
import { edgeOperator } from '@knotx/decorators'
|
|
179
|
+
|
|
180
|
+
class MyPlugin extends BasePlugin {
|
|
181
|
+
@edgeOperator()
|
|
182
|
+
addEdge(sourceId: string, targetId: string) {
|
|
183
|
+
return [{
|
|
184
|
+
type: 'add',
|
|
185
|
+
edge: {
|
|
186
|
+
id: generateId(),
|
|
187
|
+
source: sourceId,
|
|
188
|
+
target: targetId,
|
|
189
|
+
type: 'default'
|
|
190
|
+
}
|
|
191
|
+
}]
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
#### @edgePipe
|
|
197
|
+
|
|
198
|
+
用于声明一个方法作为边操作管道。
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
import { edgePipe } from '@knotx/decorators'
|
|
202
|
+
|
|
203
|
+
class MyPlugin extends BasePlugin {
|
|
204
|
+
@edgePipe()
|
|
205
|
+
validateEdgeOperation() {
|
|
206
|
+
return {
|
|
207
|
+
preOperation: () => filter((operation) => {
|
|
208
|
+
if (operation.type === 'add') {
|
|
209
|
+
return this.validateEdge(operation.edge)
|
|
210
|
+
}
|
|
211
|
+
return true
|
|
212
|
+
})
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### 插件相关装饰器
|
|
219
|
+
|
|
220
|
+
#### @config
|
|
221
|
+
|
|
222
|
+
自动绑定配置管理和生命周期函数。
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
import { config } from '@knotx/decorators'
|
|
226
|
+
|
|
227
|
+
class MyPlugin extends BasePlugin {
|
|
228
|
+
@config()
|
|
229
|
+
config = {
|
|
230
|
+
theme: 'light',
|
|
231
|
+
showGrid: true,
|
|
232
|
+
gridSize: 20
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// 配置会自动在 onInit 和 onConfigChange 时更新
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
#### @register
|
|
240
|
+
|
|
241
|
+
用于将插件的属性注册到引擎中,使其他插件可以通过 inject 访问。
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
import { register } from '@knotx/decorators'
|
|
245
|
+
|
|
246
|
+
class HistoryPlugin extends BasePlugin {
|
|
247
|
+
@register('canUndo')
|
|
248
|
+
canUndo = false
|
|
249
|
+
|
|
250
|
+
@register('canRedo')
|
|
251
|
+
canRedo = false
|
|
252
|
+
|
|
253
|
+
@register('history')
|
|
254
|
+
get history() {
|
|
255
|
+
return this.historyStack
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
#### @tool
|
|
261
|
+
|
|
262
|
+
用于装饰插件中的工具函数,使其能被引擎和其他插件调用。
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
import { tool } from '@knotx/decorators'
|
|
266
|
+
|
|
267
|
+
class MathPlugin extends BasePlugin {
|
|
268
|
+
@tool('计算两点距离', {
|
|
269
|
+
type: 'object',
|
|
270
|
+
properties: {
|
|
271
|
+
x1: { type: 'number', description: '第一个点的 X 坐标' },
|
|
272
|
+
y1: { type: 'number', description: '第一个点的 Y 坐标' },
|
|
273
|
+
x2: { type: 'number', description: '第二个点的 X 坐标' },
|
|
274
|
+
y2: { type: 'number', description: '第二个点的 Y 坐标' }
|
|
275
|
+
},
|
|
276
|
+
required: ['x1', 'y1', 'x2', 'y2']
|
|
277
|
+
})
|
|
278
|
+
calculateDistance(params: { x1: number, y1: number, x2: number, y2: number }) {
|
|
279
|
+
const dx = params.x2 - params.x1
|
|
280
|
+
const dy = params.y2 - params.y1
|
|
281
|
+
return Math.sqrt(dx * dx + dy * dy)
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**参数**:
|
|
287
|
+
- `description: string` - 工具函数描述
|
|
288
|
+
- `parameters: Schema` - 参数的 JSON Schema 定义
|
|
289
|
+
|
|
290
|
+
#### @observable
|
|
291
|
+
|
|
292
|
+
创建响应式属性,支持数据绑定和变更监听。
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
import { observable } from '@knotx/decorators'
|
|
296
|
+
|
|
297
|
+
class MyPlugin extends BasePlugin {
|
|
298
|
+
@observable()
|
|
299
|
+
selectedNodes: string[] = []
|
|
300
|
+
|
|
301
|
+
@observable()
|
|
302
|
+
zoomLevel = 1
|
|
303
|
+
|
|
304
|
+
updateSelection(nodeIds: string[]) {
|
|
305
|
+
this.selectedNodes = nodeIds // 自动触发变更通知
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
#### 生命周期装饰器
|
|
311
|
+
|
|
312
|
+
##### @OnInit
|
|
313
|
+
|
|
314
|
+
在插件初始化时调用。
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
import { OnInit } from '@knotx/decorators'
|
|
318
|
+
|
|
319
|
+
class MyPlugin extends BasePlugin {
|
|
320
|
+
@OnInit
|
|
321
|
+
initialize(config: PluginConfig) {
|
|
322
|
+
console.log('Plugin initialized with config:', config)
|
|
323
|
+
this.setupEventListeners()
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
##### @OnDestroy
|
|
329
|
+
|
|
330
|
+
在插件销毁时调用。
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
import { OnDestroy } from '@knotx/decorators'
|
|
334
|
+
|
|
335
|
+
class MyPlugin extends BasePlugin {
|
|
336
|
+
@OnDestroy
|
|
337
|
+
cleanup() {
|
|
338
|
+
console.log('Plugin destroyed')
|
|
339
|
+
this.clearEventListeners()
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
##### @OnConfigChange
|
|
345
|
+
|
|
346
|
+
在插件配置变更时调用。
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
import { OnConfigChange } from '@knotx/decorators'
|
|
350
|
+
|
|
351
|
+
class MyPlugin extends BasePlugin {
|
|
352
|
+
@OnConfigChange
|
|
353
|
+
handleConfigChange(newConfig: PluginConfig) {
|
|
354
|
+
console.log('Config changed:', newConfig)
|
|
355
|
+
this.applyNewConfig(newConfig)
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### 引擎相关装饰器
|
|
361
|
+
|
|
362
|
+
#### @inject
|
|
363
|
+
|
|
364
|
+
用于注入引擎变量或其他插件的数据。
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
import { inject } from '@knotx/decorators'
|
|
368
|
+
|
|
369
|
+
class MyPlugin extends BasePlugin {
|
|
370
|
+
// 注入引擎变量
|
|
371
|
+
@inject.nodes()
|
|
372
|
+
nodes: Node[] = []
|
|
373
|
+
|
|
374
|
+
// 注入引擎方法
|
|
375
|
+
@inject.getNodeById()
|
|
376
|
+
getNodeById!: (id: string) => Node | undefined
|
|
377
|
+
|
|
378
|
+
// 注入其他插件的数据
|
|
379
|
+
@inject.history.canUndo()
|
|
380
|
+
canUndo = false
|
|
381
|
+
|
|
382
|
+
// 使用选择器注入特定数据
|
|
383
|
+
@inject.nodes((nodes: Node[]) => nodes.filter(n => n.selected))
|
|
384
|
+
selectedNodes: Node[] = []
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
**使用方式**:
|
|
389
|
+
- `@inject.property()` - 注入引擎变量
|
|
390
|
+
- `@inject.property(selector)` - 注入引擎变量并使用选择器
|
|
391
|
+
- `@inject.pluginName.property()` - 注入插件变量
|
|
392
|
+
- `@inject.methodName()` - 注入引擎方法
|
|
393
|
+
|
|
394
|
+
#### @subscribe
|
|
395
|
+
|
|
396
|
+
用于订阅引擎变量或其他插件的数据变化。
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
import { subscribe } from '@knotx/decorators'
|
|
400
|
+
|
|
401
|
+
class MyPlugin extends BasePlugin {
|
|
402
|
+
// 订阅引擎变量
|
|
403
|
+
@subscribe.nodes()
|
|
404
|
+
handleNodesChange(nodes: Node[]) {
|
|
405
|
+
console.log('Nodes changed:', nodes)
|
|
406
|
+
this.updateUI(nodes)
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// 订阅其他插件的数据
|
|
410
|
+
@subscribe.history.canUndo()
|
|
411
|
+
handleUndoStateChange(canUndo: boolean) {
|
|
412
|
+
this.updateUndoButton(canUndo)
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### 层相关装饰器
|
|
418
|
+
|
|
419
|
+
#### @layer
|
|
420
|
+
|
|
421
|
+
用于声明方法所属的渲染层级。
|
|
422
|
+
|
|
423
|
+
```tsx
|
|
424
|
+
import { Layer } from '@knotx/core'
|
|
425
|
+
import { layer } from '@knotx/decorators'
|
|
426
|
+
|
|
427
|
+
class MyPlugin extends BasePlugin {
|
|
428
|
+
@layer(Layer.BACKGROUND)
|
|
429
|
+
renderBackground() {
|
|
430
|
+
return (
|
|
431
|
+
<rect width="100%" height="100%" fill="#f0f0f0" />
|
|
432
|
+
)
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
@layer(Layer.FOREGROUND, 100)
|
|
436
|
+
renderOverlay() {
|
|
437
|
+
return (
|
|
438
|
+
<div className="overlay">
|
|
439
|
+
Overlay content
|
|
440
|
+
</div>
|
|
441
|
+
)
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
**参数**:
|
|
447
|
+
- `layer: Layer` - 层级枚举值
|
|
448
|
+
- `offset?: number` - 层级偏移值
|
|
449
|
+
|
|
450
|
+
#### @panel
|
|
451
|
+
|
|
452
|
+
用于创建面板组件。
|
|
453
|
+
|
|
454
|
+
```tsx
|
|
455
|
+
import { panel } from '@knotx/decorators'
|
|
456
|
+
|
|
457
|
+
class MyPlugin extends BasePlugin {
|
|
458
|
+
@panel('top', { x: 10, y: 10 })
|
|
459
|
+
renderToolbar() {
|
|
460
|
+
return (
|
|
461
|
+
<div className="toolbar">
|
|
462
|
+
<button>Save</button>
|
|
463
|
+
<button>Load</button>
|
|
464
|
+
<button>Export</button>
|
|
465
|
+
</div>
|
|
466
|
+
)
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
@panel('bottom-right')
|
|
470
|
+
renderStatus() {
|
|
471
|
+
return (
|
|
472
|
+
<div className="status">
|
|
473
|
+
Ready
|
|
474
|
+
</div>
|
|
475
|
+
)
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
**参数**:
|
|
481
|
+
- `position: Position` - 面板位置('top' | 'bottom' | 'left' | 'right' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right')
|
|
482
|
+
- `offset?: PanelOffset` - 面板偏移
|
|
483
|
+
- `x?: number` - X 轴偏移
|
|
484
|
+
- `y?: number` - Y 轴偏移
|
|
485
|
+
|
|
486
|
+
## 文件目录结构
|
|
487
|
+
|
|
488
|
+
```
|
|
489
|
+
src/
|
|
490
|
+
├── index.ts # 主导出文件
|
|
491
|
+
├── internal.ts # 内部工具函数
|
|
492
|
+
├── edge/ # 边相关装饰器
|
|
493
|
+
│ ├── index.ts # 边模块导出
|
|
494
|
+
│ ├── edgeType.ts # 边类型装饰器
|
|
495
|
+
│ ├── edgeOperator.ts # 边操作装饰器
|
|
496
|
+
│ └── edgePipe.ts # 边管道装饰器
|
|
497
|
+
├── engine/ # 引擎相关装饰器
|
|
498
|
+
│ ├── index.ts # 引擎模块导出
|
|
499
|
+
│ ├── inject/ # 注入装饰器
|
|
500
|
+
│ │ ├── index.ts # 注入模块导出
|
|
501
|
+
│ │ ├── inject-data.ts # 数据注入实现
|
|
502
|
+
│ │ ├── inject-decorator.ts # 注入装饰器实现
|
|
503
|
+
│ │ ├── inject-method.ts # 方法注入实现
|
|
504
|
+
│ │ ├── inject-plugin.ts # 插件注入实现
|
|
505
|
+
│ │ ├── injectable.ts # 可注入接口
|
|
506
|
+
│ │ ├── injectable-proxy.ts # 注入代理实现
|
|
507
|
+
│ │ ├── proxy.ts # 代理对象
|
|
508
|
+
│ │ └── types.ts # 类型定义
|
|
509
|
+
│ └── subscribe/ # 订阅装饰器
|
|
510
|
+
│ ├── index.ts # 订阅模块导出
|
|
511
|
+
│ ├── proxy.ts # 订阅代理对象
|
|
512
|
+
│ ├── subscribe-data.ts # 数据订阅实现
|
|
513
|
+
│ ├── subscribe-decorator.ts # 订阅装饰器实现
|
|
514
|
+
│ ├── subscribe-plugin.ts # 插件订阅实现
|
|
515
|
+
│ └── types.ts # 类型定义
|
|
516
|
+
├── layer/ # 层相关装饰器
|
|
517
|
+
│ ├── index.ts # 层模块导出
|
|
518
|
+
│ ├── layer.ts # 层装饰器
|
|
519
|
+
│ └── panel.tsx # 面板装饰器
|
|
520
|
+
├── node/ # 节点相关装饰器
|
|
521
|
+
│ ├── index.ts # 节点模块导出
|
|
522
|
+
│ ├── nodeType.ts # 节点类型装饰器
|
|
523
|
+
│ ├── nodeOperator.ts # 节点操作装饰器
|
|
524
|
+
│ └── nodePipe.ts # 节点管道装饰器
|
|
525
|
+
└── plugin/ # 插件相关装饰器
|
|
526
|
+
├── index.ts # 插件模块导出
|
|
527
|
+
├── config.ts # 配置装饰器
|
|
528
|
+
├── lifecycle.ts # 生命周期装饰器
|
|
529
|
+
├── observable.ts # 响应式装饰器
|
|
530
|
+
├── register.ts # 注册装饰器
|
|
531
|
+
└── tool.ts # 工具函数装饰器
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
## 依赖关系
|
|
535
|
+
|
|
536
|
+
### 对等依赖 (Peer Dependencies)
|
|
537
|
+
|
|
538
|
+
- `@knotx/jsx` - Knotx JSX 运行时支持
|
|
539
|
+
|
|
540
|
+
### 主要依赖 (Dependencies)
|
|
541
|
+
|
|
542
|
+
- `@knotx/core` - Knotx 核心库
|
|
543
|
+
- `jsonschema` - JSON Schema 验证库
|
|
544
|
+
- `lodash-es` - 实用工具函数库
|
|
545
|
+
- `rxjs` - 响应式编程库
|
|
546
|
+
|
|
547
|
+
## 许可证
|
|
548
|
+
|
|
549
|
+
MIT License
|
|
550
|
+
|
|
551
|
+
## 贡献指南
|
|
552
|
+
|
|
553
|
+
欢迎提交 Issue 和 Pull Request。在提交代码前,请确保:
|
|
554
|
+
|
|
555
|
+
1. 代码符合项目的 ESLint 规则
|
|
556
|
+
2. 通过 TypeScript 类型检查
|
|
557
|
+
3. 添加必要的测试用例
|
|
558
|
+
4. 更新相关文档
|
|
559
|
+
|
|
560
|
+
## 更多信息
|
|
561
|
+
|
|
562
|
+
- [Knotx 官网](https://github.com/boenfu/knotx)
|
|
563
|
+
- [API 文档](https://github.com/boenfu/knotx#readme)
|
|
564
|
+
- [示例项目](https://github.com/boenfu/knotx/tree/main/apps/playground)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knotx/decorators",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.13",
|
|
4
4
|
"description": "Decorators for Knotx",
|
|
5
5
|
"author": "boenfu",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,20 +28,20 @@
|
|
|
28
28
|
"dist"
|
|
29
29
|
],
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@knotx/jsx": "0.4.
|
|
31
|
+
"@knotx/jsx": "0.4.13"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"jsonschema": "^1.5.0",
|
|
35
35
|
"lodash-es": "^4.17.21",
|
|
36
36
|
"rxjs": "^7.8.1",
|
|
37
|
-
"@knotx/core": "0.4.
|
|
37
|
+
"@knotx/core": "0.4.13"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/lodash-es": "^4.14.12",
|
|
41
|
-
"@knotx/build-config": "0.4.
|
|
42
|
-
"@knotx/eslint-config": "0.4.
|
|
43
|
-
"@knotx/jsx": "0.4.
|
|
44
|
-
"@knotx/typescript-config": "0.4.
|
|
41
|
+
"@knotx/build-config": "0.4.13",
|
|
42
|
+
"@knotx/eslint-config": "0.4.13",
|
|
43
|
+
"@knotx/jsx": "0.4.13",
|
|
44
|
+
"@knotx/typescript-config": "0.4.13"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"build": "unbuild",
|