@bpmn-nova/studio 0.3.0-preview → 0.3.2-preview
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.md +245 -20
- package/dist/canvas.js +7 -4
- package/dist/context-menu.js +2 -2
- package/dist/controller.js +84 -6
- package/dist/index.d.ts +138 -38
- package/dist/index.js +12 -11
- package/dist/interactions.js +1 -1
- package/dist/modules/bpmn-model/index.d.ts +11 -0
- package/dist/modules/bpmn-model/index.js +703 -0
- package/dist/modules/core/containment.js +590 -0
- package/dist/modules/core/gateway.js +72 -0
- package/dist/modules/core/history.js +32 -0
- package/dist/modules/core/index.d.ts +268 -0
- package/dist/modules/core/index.js +7 -0
- package/dist/modules/core/layout.js +644 -0
- package/dist/modules/core/model.js +287 -0
- package/dist/modules/core/runtime-transition-route.js +360 -0
- package/dist/modules/core/scope.js +99 -0
- package/dist/modules/designer/index.d.ts +79 -0
- package/dist/modules/designer/index.js +607 -0
- package/dist/modules/engine-activiti/index.d.ts +19 -0
- package/dist/modules/engine-activiti/index.js +160 -0
- package/dist/modules/engine-flowable/index.d.ts +19 -0
- package/dist/modules/engine-flowable/index.js +160 -0
- package/dist/modules/export-svg/index.d.ts +112 -0
- package/dist/modules/export-svg/index.js +2 -0
- package/dist/modules/export-svg/preview.js +327 -0
- package/dist/modules/export-svg/render.js +718 -0
- package/dist/modules/icons/index.d.ts +24 -0
- package/dist/modules/icons/index.js +264 -0
- package/dist/modules/palette/index.d.ts +74 -0
- package/dist/modules/palette/index.js +99 -0
- package/dist/modules/palette/panel.js +99 -0
- package/dist/modules/properties/index.d.ts +20 -0
- package/dist/modules/properties/index.js +19 -0
- package/dist/modules/properties-activiti/index.d.ts +3 -0
- package/dist/modules/properties-activiti/index.js +97 -0
- package/dist/modules/properties-bpmn/index.d.ts +3 -0
- package/dist/modules/properties-bpmn/index.js +518 -0
- package/dist/modules/properties-core/index.d.ts +124 -0
- package/dist/modules/properties-core/index.js +312 -0
- package/dist/modules/properties-flowable/index.d.ts +3 -0
- package/dist/modules/properties-flowable/index.js +114 -0
- package/dist/modules/properties-renderer/index.d.ts +25 -0
- package/dist/modules/properties-renderer/index.js +491 -0
- package/dist/modules/renderer-svg/index.d.ts +118 -0
- package/dist/modules/renderer-svg/index.js +1460 -0
- package/dist/modules/runtime/index.d.ts +169 -0
- package/dist/modules/runtime/index.js +535 -0
- package/dist/modules/theme/index.d.ts +95 -0
- package/dist/modules/theme/index.js +368 -0
- package/dist/modules/viewer/index.d.ts +265 -0
- package/dist/modules/viewer/index.js +1011 -0
- package/dist/modules/viewer/runtime-content.js +123 -0
- package/dist/modules/viewer/runtime-details-motion.js +228 -0
- package/dist/modules/viewer/runtime-trace.js +574 -0
- package/dist/modules/viewer/timeline.js +276 -0
- package/dist/selection-layout.js +1 -1
- package/dist/shell.js +210 -26
- package/dist/styles.css +116 -7
- package/llms-full.txt +3082 -0
- package/llms.txt +225 -0
- package/package.json +39 -16
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { BpmnNode, NodeDefinition, NodeType, ProcessModel } from '../core/index.js'
|
|
2
|
+
|
|
3
|
+
export interface IconPathDescriptor { d: string; [attribute: string]: string }
|
|
4
|
+
export interface IconDescriptor {
|
|
5
|
+
id: string
|
|
6
|
+
viewBox: string
|
|
7
|
+
paths: IconPathDescriptor[]
|
|
8
|
+
fill?: string
|
|
9
|
+
}
|
|
10
|
+
export type NodeVisualSurface = 'palette' | 'canvas' | 'viewer' | 'timeline'
|
|
11
|
+
export interface NodeVisualResolution { iconId: string | null; activityMarkerIds: string[] }
|
|
12
|
+
|
|
13
|
+
export const DEFAULT_ICONS: readonly IconDescriptor[]
|
|
14
|
+
export function resolveNodeVisual(input: NodeType | BpmnNode, options?: { surface?: NodeVisualSurface; model?: ProcessModel | null }): NodeVisualResolution
|
|
15
|
+
export function iconIdForNode(type: NodeType, definition?: NodeDefinition): string | null
|
|
16
|
+
export class IconRegistry {
|
|
17
|
+
constructor(icons?: IconDescriptor[])
|
|
18
|
+
register(icon: IconDescriptor): () => void
|
|
19
|
+
resolve(id: string, fallback?: string | null): IconDescriptor | null
|
|
20
|
+
has(id: string): boolean
|
|
21
|
+
}
|
|
22
|
+
export function createIconElement(descriptor: IconDescriptor | null, options?: { className?: string; title?: string }): SVGSVGElement | null
|
|
23
|
+
export function hydrateIcons(root: ParentNode, registry: IconRegistry): void
|
|
24
|
+
export function createDefaultIconRegistry(extraIcons?: IconDescriptor[]): IconRegistry
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { NODE_DEFINITIONS } from '../core/index.js';
|
|
2
|
+
|
|
3
|
+
const icon = (id, d, options = {}) => ({
|
|
4
|
+
id,
|
|
5
|
+
viewBox: '0 0 24 24',
|
|
6
|
+
paths: (Array.isArray(d) ? d : [d]).map((path) => typeof path === 'string' ? { d: path } : path),
|
|
7
|
+
...options,
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const uiIcon = (id, d) => ({
|
|
11
|
+
id,
|
|
12
|
+
viewBox: '0 0 24 24',
|
|
13
|
+
paths: (Array.isArray(d) ? d : [d]).map((path) => ({
|
|
14
|
+
d: path,
|
|
15
|
+
fill: 'none',
|
|
16
|
+
stroke: 'currentColor',
|
|
17
|
+
'stroke-width': '1.8',
|
|
18
|
+
'stroke-linecap': 'round',
|
|
19
|
+
'stroke-linejoin': 'round',
|
|
20
|
+
})),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export const DEFAULT_ICONS = Object.freeze([
|
|
24
|
+
uiIcon('ui.chevron', 'm7 9.5 5 5 5-5'),
|
|
25
|
+
uiIcon('ui.check', 'm5.5 12.5 4 4 9-9'),
|
|
26
|
+
uiIcon('ui.undo', ['M9 7H5v4', 'M5.5 10.5c2.2-3.4 5.1-5.1 8.6-4.5 3.1.5 5.4 3 5.4 6.2 0 3.4-2.8 6.3-6.3 6.3H9.5']),
|
|
27
|
+
uiIcon('ui.redo', ['M15 7h4v4', 'M18.5 10.5c-2.2-3.4-5.1-5.1-8.6-4.5-3.1.5-5.4 3-5.4 6.2 0 3.4 2.8 6.3 6.3 6.3h3.7']),
|
|
28
|
+
uiIcon('ui.magic', ['m12 3 1.1 3.3L16.5 7.5l-3.4 1.2L12 12l-1.1-3.3-3.4-1.2 3.4-1.2z', 'm18.5 13 .7 2.1 2.1.7-2.1.7-.7 2.1-.7-2.1-2.1-.7 2.1-.7z', 'M5 14v5M2.5 16.5h5']),
|
|
29
|
+
uiIcon('ui.layoutHorizontal', ['M4 7h5v5H4zM15 12h5v5h-5z', 'M9 9.5h4a4 4 0 0 1 4 4v.5', 'm14 11 3 3 3-3']),
|
|
30
|
+
uiIcon('ui.layoutVertical', ['M7 4h5v5H7zM12 15h5v5h-5z', 'M9.5 9v2a4 4 0 0 0 4 4h.5', 'm11 12 3 3-3 3']),
|
|
31
|
+
uiIcon('ui.parallelDiverging', ['M2 12h6', 'm8 12 4-4 4 4-4 4z', 'M10 12h4M12 10v4', 'M16 12h1c3 0 3-4 5-4', 'M16 12h1c3 0 3 4 5 4', 'm20 6 2 2-2 2', 'm20 14 2 2-2 2']),
|
|
32
|
+
uiIcon('ui.parallelConverging', ['M2 8c3 0 3 4 6 4M2 16c3 0 3-4 6-4', 'm2 6-2 2 2 2M2 14l-2 2 2 2', 'm8 12 4-4 4 4-4 4z', 'M10 12h4M12 10v4', 'M16 12h6', 'm20 10 2 2-2 2']),
|
|
33
|
+
uiIcon('ui.routeRounded', ['M4 7h8a5 5 0 0 1 5 5v5h3', 'm17 14 3 3-3 3']),
|
|
34
|
+
uiIcon('ui.routeSmooth', ['M4 17c4.5 0 4.5-10 9-10s4.5 10 7 10', 'm17 14 3 3-3 3']),
|
|
35
|
+
uiIcon('ui.zoomIn', ['M10.5 5a5.5 5.5 0 1 0 0 11 5.5 5.5 0 0 0 0-11Z', 'm15 15 4 4M10.5 8v5M8 10.5h5']),
|
|
36
|
+
uiIcon('ui.zoomOut', ['M10.5 5a5.5 5.5 0 1 0 0 11 5.5 5.5 0 0 0 0-11Z', 'm15 15 4 4M8 10.5h5']),
|
|
37
|
+
uiIcon('ui.fitView', ['M9 4H4v5M15 4h5v5M9 20H4v-5M15 20h5v-5']),
|
|
38
|
+
uiIcon('ui.alignLeft', ['M5 4v16', 'M8 7h10M8 12h7M8 17h11']),
|
|
39
|
+
uiIcon('ui.alignCenterHorizontal', ['M12 4v16', 'M7 7h10M8.5 12h7M6.5 17h11']),
|
|
40
|
+
uiIcon('ui.alignRight', ['M19 4v16', 'M6 7h10M9 12h7M5 17h11']),
|
|
41
|
+
uiIcon('ui.alignTop', ['M4 5h16', 'M7 8v10M12 8v7M17 8v11']),
|
|
42
|
+
uiIcon('ui.alignCenterVertical', ['M4 12h16', 'M7 7v10M12 8.5v7M17 6.5v11']),
|
|
43
|
+
uiIcon('ui.alignBottom', ['M4 19h16', 'M7 6v10M12 9v7M17 5v11']),
|
|
44
|
+
uiIcon('ui.distributeHorizontal', ['M4 5v14M20 5v14', 'M8 8h3v8H8zM14 8h3v8h-3z']),
|
|
45
|
+
uiIcon('ui.distributeVertical', ['M5 4h14M5 20h14', 'M8 8h8v3H8zM8 14h8v3H8z']),
|
|
46
|
+
uiIcon('ui.layoutSelection', ['M4 5h6v5H4zM14 5h6v5h-6zM4 14h6v5H4zM14 14h6v5h-6z', 'm11 7.5 2 0M11 16.5h2M7 11v2M17 11v2']),
|
|
47
|
+
uiIcon('ui.rerouteSelection', ['M4 7h7a3 3 0 0 1 3 3v4a3 3 0 0 0 3 3h3', 'm17 14 3 3-3 3']),
|
|
48
|
+
uiIcon('ui.fitSelection', ['M8 4H4v4M16 4h4v4M8 20H4v-4M16 20h4v-4', 'M8 9h8v6H8z']),
|
|
49
|
+
uiIcon('ui.pointer', ['M6 3.5 18 12l-5.6 1.2-2.6 5.3z']),
|
|
50
|
+
uiIcon('ui.marquee', ['M5 4h4M15 4h4v4M19 14v5h-4M9 19H5v-5M5 9V4', 'm9 9 6 6M15 9v6H9']),
|
|
51
|
+
uiIcon('ui.hand', ['M7.5 11V7.5a1.5 1.5 0 0 1 3 0V10 6a1.5 1.5 0 0 1 3 0v4-3a1.5 1.5 0 0 1 3 0v3-1.8a1.5 1.5 0 0 1 3 0v4.3c0 4-2.5 6.5-6.5 6.5h-1.2c-2.3 0-3.8-1.1-5.1-3L4 14.8a1.6 1.6 0 0 1 2.4-2z']),
|
|
52
|
+
uiIcon('ui.locate', ['M8 16 17 7M10 7h7v7']),
|
|
53
|
+
uiIcon('ui.edit', ['M5 19h4L19 9l-4-4L5 15z', 'm13.5 6.5 4 4']),
|
|
54
|
+
uiIcon('ui.locateSource', ['M19 12H6', 'm10 8-4 4 4 4', 'M5 7v10']),
|
|
55
|
+
uiIcon('ui.locateTarget', ['M5 12h13', 'm14 8 4 4-4 4', 'M19 7v10']),
|
|
56
|
+
uiIcon('ui.add', ['M12 5v14M5 12h14']),
|
|
57
|
+
uiIcon('ui.connect', ['M5 12h14', 'm15 8 4 4-4 4']),
|
|
58
|
+
uiIcon('ui.enterScope', ['M5 5h6v2H7v10h4v2H5z', 'M10 12h9', 'm15 8 4 4-4 4']),
|
|
59
|
+
uiIcon('ui.leaveScope', ['M19 12H5', 'm9 8-4 4 4 4']),
|
|
60
|
+
uiIcon('ui.close', ['M7 7l10 10M17 7 7 17']),
|
|
61
|
+
uiIcon('ui.delete', ['M5 7h14M9 7V5h6v2M7 7l1 13h8l1-13M10 10v6M14 10v6']),
|
|
62
|
+
uiIcon('ui.design', ['m12 3 1.1 3.3L16.5 7.5l-3.4 1.2L12 12l-1.1-3.3-3.4-1.2 3.4-1.2z', 'M5 15v4M3 17h4M18 14v5M15.5 16.5h5']),
|
|
63
|
+
uiIcon('ui.preview', ['M3.5 12s3.2-5 8.5-5 8.5 5 8.5 5-3.2 5-8.5 5-8.5-5-8.5-5Z', 'M12 9.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5Z']),
|
|
64
|
+
uiIcon('ui.trace', ['M6 6h.01M18 18h.01', 'M6 6c7 0 1 12 12 12', 'm15 15 3 3-3 3']),
|
|
65
|
+
uiIcon('ui.statusCompleted', ['M12 3.5a8.5 8.5 0 1 0 0 17 8.5 8.5 0 0 0 0-17Z', 'm8 12 2.5 2.5 5.5-6']),
|
|
66
|
+
uiIcon('ui.statusActive', ['M12 3.5a8.5 8.5 0 1 0 0 17 8.5 8.5 0 0 0 0-17Z', 'M12 7.5V12l3 2']),
|
|
67
|
+
uiIcon('ui.statusFailed', ['M12 3.5a8.5 8.5 0 1 0 0 17 8.5 8.5 0 0 0 0-17Z', 'm9 9 6 6M15 9l-6 6']),
|
|
68
|
+
uiIcon('ui.statusRejected', ['M8 8H4v4', 'M4.5 11.5C6.2 7.8 9 6 12.5 6a6 6 0 1 1-5.2 9', 'm5 15 2.5.2L7.2 18']),
|
|
69
|
+
uiIcon('ui.statusSkipped', ['M12 3.5a8.5 8.5 0 1 0 0 17 8.5 8.5 0 0 0 0-17Z', 'M8 12h8']),
|
|
70
|
+
uiIcon('ui.statusIdle', 'M12 3.5a8.5 8.5 0 1 0 0 17 8.5 8.5 0 0 0 0-17Z'),
|
|
71
|
+
icon('node.generic', 'M5 5h14v14H5z'),
|
|
72
|
+
icon('node.task', 'M4 5.5h16v13H4z'),
|
|
73
|
+
icon('node.userTask', ['M12 4.2a3 3 0 1 1 0 6 3 3 0 0 1 0-6Z', 'M6.5 19.5c.4-4 2.2-6.1 5.5-6.1s5.1 2.1 5.5 6.1']),
|
|
74
|
+
icon('node.manualTask', ['M5.2 12.4c1.1-1 2.1-.5 2.8.1V7.2c0-1.4 2-1.4 2 0v3.2-4.6c0-1.4 2-1.4 2 0v4.4-3.7c0-1.4 2-1.4 2 0v4-2.8c0-1.4 2-1.4 2 0v5.8c0 4.2-2 6.2-5.5 6.2-2.8 0-4.1-1.7-5.7-4.4-.6-1-.5-2.1.4-2.9Z']),
|
|
75
|
+
icon('node.serviceTask', ['M10.2 6.2a4.3 4.3 0 1 0 0 8.6 4.3 4.3 0 0 0 0-8.6Z', 'M10.2 3v1.5M10.2 17.9v1.5M2.7 10.5h1.5M16.2 10.5h1.5M4.9 5.2 6 6.3M14.5 14.6l1.1 1.1M15.6 5.2l-1.1 1.1M6 14.6l-1.1 1.1', 'M17.2 13.7a2.9 2.9 0 1 0 0 5.8 2.9 2.9 0 0 0 0-5.8Z', 'M17.2 11.6v.9M17.2 19.2v.9M13.4 15.4h.9M20.1 15.4h.9']),
|
|
76
|
+
icon('node.scriptTask', ['M6 4.5h9.5l2.5 2.7v12.3H6z', 'M15.5 4.5v3h2.5', 'M8.5 10h7M8.5 13h7M8.5 16h4.5']),
|
|
77
|
+
icon('node.businessRuleTask', ['M4 5h16v14H4z', 'M4 10h16M10 5v14M14 10v9']),
|
|
78
|
+
icon('node.sendTask', [
|
|
79
|
+
{ d: 'M3.5 6.5h17v11h-17z', fill: 'currentColor', stroke: 'none' },
|
|
80
|
+
{ d: 'm4.5 7.8 7.5 5.5 7.5-5.5', fill: 'none', stroke: '#fff', 'stroke-width': '1.6' },
|
|
81
|
+
]),
|
|
82
|
+
icon('node.receiveTask', ['M3.5 6.5h17v11h-17z', 'm4.5 7.8 7.5 5.5 7.5-5.5']),
|
|
83
|
+
icon('node.receiveTask.instantiate', ['M12 2.8a9.2 9.2 0 1 0 0 18.4 9.2 9.2 0 0 0 0-18.4Z', 'M6 8.2h12v7.6H6z', 'm6.5 9 5.5 4 5.5-4']),
|
|
84
|
+
icon('node.subProcess', ['M5 5h14v14H5z', 'M8 12h8M12 8v8']),
|
|
85
|
+
icon('node.eventSubProcess', [
|
|
86
|
+
{ d: 'M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16Z', dash: '2 2' },
|
|
87
|
+
'M12 8.5a3.5 3.5 0 1 0 0 7 3.5 3.5 0 0 0 0-7Z',
|
|
88
|
+
]),
|
|
89
|
+
icon('node.callActivity', { d: 'M4 5.5h16v13H4z', 'stroke-width': '3' }),
|
|
90
|
+
icon('node.gateway.exclusive', ['M5 5l14 14M19 5 5 19']),
|
|
91
|
+
icon('node.gateway.parallel', ['M12 4v16M4 12h16']),
|
|
92
|
+
icon('node.gateway.inclusive', 'M12 5.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13Z'),
|
|
93
|
+
icon('node.gateway.eventBased', ['M12 4.5 18.5 9v7L12 19.5 5.5 16V9z', 'M12 7.5a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9Z']),
|
|
94
|
+
icon('node.gateway.eventBased.exclusive', ['M12 4.5a7.5 7.5 0 1 0 0 15 7.5 7.5 0 0 0 0-15Z', 'M12 6.5a5.5 5.5 0 1 0 0 11 5.5 5.5 0 0 0 0-11Z', 'm12 8 3.8 2.8-1.4 4.4h-4.8l-1.4-4.4z']),
|
|
95
|
+
icon('node.gateway.eventBased.exclusiveInstantiate', ['M12 4.5a7.5 7.5 0 1 0 0 15 7.5 7.5 0 0 0 0-15Z', 'm12 8 3.8 2.8-1.4 4.4h-4.8l-1.4-4.4z']),
|
|
96
|
+
icon('node.gateway.eventBased.parallelInstantiate', ['M12 4.5a7.5 7.5 0 1 0 0 15 7.5 7.5 0 0 0 0-15Z', 'M12 8v8M8 12h8']),
|
|
97
|
+
icon('node.gateway.complex', ['M12 4v16M4 12h16M6.3 6.3l11.4 11.4M17.7 6.3 6.3 17.7']),
|
|
98
|
+
icon('event.none', 'M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16Z'),
|
|
99
|
+
icon('event.none.catch', 'M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16Z'),
|
|
100
|
+
icon('event.none.throw', { d: 'M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16Z', 'stroke-width': '3' }),
|
|
101
|
+
icon('event.message', ['M5 7h14v10H5z', 'm5 8 7 5 7-5']),
|
|
102
|
+
icon('event.message.catch', ['M5 7h14v10H5z', 'm5 8 7 5 7-5']),
|
|
103
|
+
icon('event.message.throw', [
|
|
104
|
+
{ d: 'M5 7h14v10H5z', fill: 'currentColor', stroke: 'none' },
|
|
105
|
+
{ d: 'm5.7 8 6.3 4.7L18.3 8', fill: 'none', stroke: '#fff', 'stroke-width': '1.5' },
|
|
106
|
+
]),
|
|
107
|
+
icon('event.timer', ['M12 5a7 7 0 1 0 0 14 7 7 0 0 0 0-14Z', 'M12 8v4l3 2']),
|
|
108
|
+
icon('event.timer.catch', ['M12 5a7 7 0 1 0 0 14 7 7 0 0 0 0-14Z', 'M12 8v4l3 2']),
|
|
109
|
+
icon('event.conditional', ['M7 6h10v12H7z', 'M9 9h6M9 12h6M9 15h4']),
|
|
110
|
+
icon('event.conditional.catch', ['M7 6h10v12H7z', 'M9 9h6M9 12h6M9 15h4']),
|
|
111
|
+
icon('event.signal', 'M12 5 19 18H5z'),
|
|
112
|
+
icon('event.signal.catch', 'M12 5 19 18H5z'),
|
|
113
|
+
icon('event.signal.throw', { d: 'M12 5 19 18H5z', fill: 'currentColor', stroke: 'none' }),
|
|
114
|
+
icon('event.error', 'm13 4-7 9h5l-1 7 8-10h-5z'),
|
|
115
|
+
icon('event.error.catch', 'm13 4-7 9h5l-1 7 8-10h-5z'),
|
|
116
|
+
icon('event.error.throw', { d: 'm13 4-7 9h5l-1 7 8-10h-5z', fill: 'currentColor', stroke: 'none' }),
|
|
117
|
+
icon('event.escalation', 'm12 5 6 13-6-5-6 5z'),
|
|
118
|
+
icon('event.escalation.catch', 'm12 5 6 13-6-5-6 5z'),
|
|
119
|
+
icon('event.escalation.throw', { d: 'm12 5 6 13-6-5-6 5z', fill: 'currentColor', stroke: 'none' }),
|
|
120
|
+
icon('event.compensate', ['M12 7 6 12l6 5z', 'm18 7-6 5 6 5z']),
|
|
121
|
+
icon('event.compensate.catch', ['M12 7 6 12l6 5z', 'm18 7-6 5 6 5z']),
|
|
122
|
+
icon('event.compensate.throw', [
|
|
123
|
+
{ d: 'M12 7 6 12l6 5z', fill: 'currentColor', stroke: 'none' },
|
|
124
|
+
{ d: 'm18 7-6 5 6 5z', fill: 'currentColor', stroke: 'none' },
|
|
125
|
+
]),
|
|
126
|
+
icon('event.link', ['M5 12h13', 'm14 8 4 4-4 4']),
|
|
127
|
+
icon('event.link.catch', ['M19 12H6', 'm10 8-4 4 4 4']),
|
|
128
|
+
icon('event.link.throw', [{ d: 'M5 10h9V7l5 5-5 5v-3H5z', fill: 'currentColor', stroke: 'none' }]),
|
|
129
|
+
icon('event.cancel', ['M7 7l10 10M17 7 7 17']),
|
|
130
|
+
icon('event.cancel.throw', ['M7 7l10 10M17 7 7 17']),
|
|
131
|
+
icon('event.terminate', 'M12 6a6 6 0 1 0 0 12 6 6 0 0 0 0-12Z', { fill: 'currentColor' }),
|
|
132
|
+
icon('event.terminate.throw', { d: 'M12 6a6 6 0 1 0 0 12 6 6 0 0 0 0-12Z', fill: 'currentColor', stroke: 'none' }),
|
|
133
|
+
icon('marker.loop', ['M17.5 8.5A6.5 6.5 0 1 0 18 15', 'm17.5 4v4.5H13']),
|
|
134
|
+
icon('marker.multiInstance.parallel', ['M7 5v14M12 5v14M17 5v14']),
|
|
135
|
+
icon('marker.multiInstance.sequential', ['M5 7h14M5 12h14M5 17h14']),
|
|
136
|
+
icon('marker.compensation', ['M12 6 5 12l7 6z', 'm19 6-7 6 7 6z']),
|
|
137
|
+
icon('marker.subProcess', ['M5 5h14v14H5z', 'M8 12h8M12 8v8']),
|
|
138
|
+
icon('marker.adHoc', 'M5 13c2-5 4 5 7 0s5 5 7 0'),
|
|
139
|
+
icon('node.data', ['M6 4h9l3 3v13H6z', 'M15 4v4h4']),
|
|
140
|
+
icon('node.dataStore', ['M5 6c0-2 14-2 14 0v12c0 2-14 2-14 0z', 'M5 6c0 2 14 2 14 0M5 12c0 2 14 2 14 0']),
|
|
141
|
+
icon('node.annotation', ['M7 5H4v14h3M9 8h11M9 12h9M9 16h7']),
|
|
142
|
+
icon('node.group', ['M5 5h14v14H5z'], { dash: '3 2' }),
|
|
143
|
+
icon('node.participant', ['M3 5h18v14H3z', 'M7 5v14']),
|
|
144
|
+
icon('node.lane', ['M3 7h18v10H3z', 'M8 7v10']),
|
|
145
|
+
]);
|
|
146
|
+
|
|
147
|
+
export function resolveNodeVisual(input, { surface = 'canvas', model = null } = {}) {
|
|
148
|
+
const type = typeof input === 'string' ? input : input?.type;
|
|
149
|
+
const properties = typeof input === 'string' ? {} : (input?.properties || {});
|
|
150
|
+
const activityMarkerIds = [];
|
|
151
|
+
if (properties.loopType === 'standard') activityMarkerIds.push('marker.loop');
|
|
152
|
+
if (properties.loopType === 'parallel') activityMarkerIds.push('marker.multiInstance.parallel');
|
|
153
|
+
if (properties.loopType === 'sequential') activityMarkerIds.push('marker.multiInstance.sequential');
|
|
154
|
+
if (properties.isForCompensation) activityMarkerIds.push('marker.compensation');
|
|
155
|
+
if (['subProcess', 'eventSubProcess', 'transaction', 'adHocSubProcess'].includes(type)) activityMarkerIds.push('marker.subProcess');
|
|
156
|
+
if (type === 'adHocSubProcess') activityMarkerIds.push('marker.adHoc');
|
|
157
|
+
const taskIds = {
|
|
158
|
+
userTask: 'node.userTask',
|
|
159
|
+
manualTask: 'node.manualTask',
|
|
160
|
+
serviceTask: 'node.serviceTask',
|
|
161
|
+
scriptTask: 'node.scriptTask',
|
|
162
|
+
businessRuleTask: 'node.businessRuleTask',
|
|
163
|
+
sendTask: 'node.sendTask',
|
|
164
|
+
receiveTask: properties.instantiate ? 'node.receiveTask.instantiate' : 'node.receiveTask',
|
|
165
|
+
};
|
|
166
|
+
if (type === 'task') return { iconId: surface === 'palette' ? 'node.task' : null, activityMarkerIds };
|
|
167
|
+
if (type === 'callActivity') return { iconId: surface === 'palette' ? 'node.callActivity' : null, activityMarkerIds };
|
|
168
|
+
if (taskIds[type]) return { iconId: taskIds[type], activityMarkerIds };
|
|
169
|
+
if (type === 'eventSubProcess') {
|
|
170
|
+
const startEvent = model?.nodes?.find((node) => node.scopeId === input?.id && NODE_DEFINITIONS[node.type]?.eventStage === 'start');
|
|
171
|
+
const startVisual = startEvent ? resolveNodeVisual(startEvent, { surface, model }) : null;
|
|
172
|
+
return { iconId: startVisual?.iconId || 'node.eventSubProcess', activityMarkerIds };
|
|
173
|
+
}
|
|
174
|
+
const definition = NODE_DEFINITIONS[type];
|
|
175
|
+
if (definition?.eventDefinition || definition?.kind === 'event' || definition?.kind === 'boundary') {
|
|
176
|
+
const role = definition.eventRole || (definition.eventStage === 'end' ? 'throw' : 'catch');
|
|
177
|
+
if (!definition.eventDefinition) return { iconId: surface === 'palette' ? `event.none.${role}` : null, activityMarkerIds };
|
|
178
|
+
return { iconId: `event.${definition.eventDefinition}.${role}`, activityMarkerIds };
|
|
179
|
+
}
|
|
180
|
+
if (type === 'eventBasedGateway') {
|
|
181
|
+
const variant = properties.instantiate
|
|
182
|
+
? (properties.eventGatewayType === 'Parallel' ? 'parallelInstantiate' : 'exclusiveInstantiate')
|
|
183
|
+
: 'exclusive';
|
|
184
|
+
return { iconId: `node.gateway.eventBased.${variant}`, activityMarkerIds };
|
|
185
|
+
}
|
|
186
|
+
return { iconId: iconIdForNode(type), activityMarkerIds };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export function iconIdForNode(type, definition = NODE_DEFINITIONS[type]) {
|
|
190
|
+
if (definition?.eventDefinition) return `event.${definition.eventDefinition}`;
|
|
191
|
+
if (definition?.kind === 'event' || definition?.kind === 'boundary') return 'event.none';
|
|
192
|
+
const ids = {
|
|
193
|
+
task: 'node.task', userTask: 'node.userTask', manualTask: 'node.manualTask', serviceTask: 'node.serviceTask',
|
|
194
|
+
scriptTask: 'node.scriptTask', businessRuleTask: 'node.businessRuleTask', sendTask: 'node.sendTask', receiveTask: 'node.receiveTask',
|
|
195
|
+
subProcess: 'node.subProcess', eventSubProcess: 'node.subProcess', transaction: 'node.subProcess', adHocSubProcess: 'node.subProcess', callActivity: 'node.callActivity',
|
|
196
|
+
exclusiveGateway: 'node.gateway.exclusive', parallelGateway: 'node.gateway.parallel', inclusiveGateway: 'node.gateway.inclusive',
|
|
197
|
+
eventBasedGateway: 'node.gateway.eventBased', complexGateway: 'node.gateway.complex', dataObjectReference: 'node.data', dataStoreReference: 'node.dataStore',
|
|
198
|
+
textAnnotation: 'node.annotation', group: 'node.group', participant: 'node.participant', lane: 'node.lane',
|
|
199
|
+
};
|
|
200
|
+
return ids[type] || 'node.generic';
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export class IconRegistry {
|
|
204
|
+
constructor(icons = []) {
|
|
205
|
+
this._icons = new Map();
|
|
206
|
+
for (const descriptor of icons) this.register(descriptor);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
register(descriptor) {
|
|
210
|
+
if (!descriptor?.id || !descriptor?.viewBox || !Array.isArray(descriptor.paths)) throw new Error('Icon descriptor requires id, viewBox and paths.');
|
|
211
|
+
this._icons.set(descriptor.id, Object.freeze({ ...descriptor, paths: descriptor.paths.map((path) => Object.freeze({ ...path })) }));
|
|
212
|
+
return () => this._icons.delete(descriptor.id);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
resolve(id, fallback = 'node.generic') { return this._icons.get(id) || this._icons.get(fallback) || null; }
|
|
216
|
+
has(id) { return this._icons.has(id); }
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function createIconElement(descriptor, { className = '', title = '' } = {}) {
|
|
220
|
+
if (!descriptor || typeof document === 'undefined') return null;
|
|
221
|
+
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
222
|
+
svg.setAttribute('viewBox', descriptor.viewBox);
|
|
223
|
+
svg.setAttribute('aria-hidden', title ? 'false' : 'true');
|
|
224
|
+
svg.setAttribute('focusable', 'false');
|
|
225
|
+
if (className) svg.setAttribute('class', className);
|
|
226
|
+
if (title) {
|
|
227
|
+
const titleNode = document.createElementNS(svg.namespaceURI, 'title');
|
|
228
|
+
titleNode.textContent = title;
|
|
229
|
+
svg.appendChild(titleNode);
|
|
230
|
+
}
|
|
231
|
+
for (const path of descriptor.paths) {
|
|
232
|
+
const node = document.createElementNS(svg.namespaceURI, 'path');
|
|
233
|
+
for (const [key, value] of Object.entries(path)) {
|
|
234
|
+
const attribute = key === 'dash' ? 'stroke-dasharray' : key;
|
|
235
|
+
node.setAttribute(attribute, String(value));
|
|
236
|
+
}
|
|
237
|
+
svg.appendChild(node);
|
|
238
|
+
}
|
|
239
|
+
if (descriptor.fill) svg.style.fill = descriptor.fill;
|
|
240
|
+
return svg;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export function hydrateIcons(root, registry) {
|
|
244
|
+
if (!root?.querySelectorAll || !registry || typeof document === 'undefined') return;
|
|
245
|
+
for (const host of root.querySelectorAll('[data-icon]')) {
|
|
246
|
+
const id = host.dataset.icon;
|
|
247
|
+
if (!id) continue;
|
|
248
|
+
if (host.dataset.iconHydrated === id && host.querySelector?.('svg')) continue;
|
|
249
|
+
host.replaceChildren?.();
|
|
250
|
+
const descriptor = registry.resolve(id, null);
|
|
251
|
+
if (!descriptor) {
|
|
252
|
+
host.dataset.iconMissing = 'true';
|
|
253
|
+
delete host.dataset.iconHydrated;
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
delete host.dataset.iconMissing;
|
|
257
|
+
const svg = createIconElement(descriptor, { className: 'nova-icon-svg', title: host.dataset.iconTitle || '' });
|
|
258
|
+
if (!svg) continue;
|
|
259
|
+
host.appendChild(svg);
|
|
260
|
+
host.dataset.iconHydrated = id;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export function createDefaultIconRegistry(extraIcons = []) { return new IconRegistry([...DEFAULT_ICONS, ...extraIcons]); }
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { NodeType } from '../core/index.js'
|
|
2
|
+
import type { IconRegistry } from '../icons/index.js'
|
|
3
|
+
import type { NovaThemeInput, NovaThemeMode, NovaThemeState, ThemeController } from '../theme/index.js'
|
|
4
|
+
|
|
5
|
+
export interface PalettePosition { before?: string; after?: string; replace?: string; remove?: string; prepend?: boolean; append?: boolean }
|
|
6
|
+
export type PaletteCreateIntent =
|
|
7
|
+
| { kind: 'node'; nodeType: NodeType; preset?: Record<string, unknown> }
|
|
8
|
+
| { kind: 'template'; templateId: string; [key: string]: unknown }
|
|
9
|
+
| { kind: 'action'; [key: string]: unknown }
|
|
10
|
+
export interface PaletteItem {
|
|
11
|
+
id: string
|
|
12
|
+
label: string
|
|
13
|
+
description?: string
|
|
14
|
+
iconId?: string
|
|
15
|
+
create?: PaletteCreateIntent
|
|
16
|
+
position?: PalettePosition
|
|
17
|
+
visible?: (context: unknown) => boolean
|
|
18
|
+
}
|
|
19
|
+
export interface PaletteSection {
|
|
20
|
+
id: string
|
|
21
|
+
label: string
|
|
22
|
+
items: PaletteItem[]
|
|
23
|
+
collapsed?: boolean
|
|
24
|
+
position?: PalettePosition
|
|
25
|
+
visible?: (context: unknown) => boolean
|
|
26
|
+
}
|
|
27
|
+
export interface PaletteProvider {
|
|
28
|
+
id: string
|
|
29
|
+
priority?: number
|
|
30
|
+
getSections?(context: unknown): PaletteSection[]
|
|
31
|
+
sections?: PaletteSection[]
|
|
32
|
+
}
|
|
33
|
+
export class PaletteRegistry {
|
|
34
|
+
registerProvider(priority: number, provider: PaletteProvider): () => void
|
|
35
|
+
registerProvider(provider: PaletteProvider): () => void
|
|
36
|
+
resolve(context?: unknown): PaletteSection[]
|
|
37
|
+
}
|
|
38
|
+
export const defaultBpmnPaletteProvider: PaletteProvider
|
|
39
|
+
export function createPaletteRegistry(): PaletteRegistry
|
|
40
|
+
export function createDefaultPaletteRegistry(options?: { providers?: PaletteProvider[] }): PaletteRegistry
|
|
41
|
+
|
|
42
|
+
export type PaletteItemRenderer = (context: {
|
|
43
|
+
container: HTMLElement
|
|
44
|
+
item: PaletteItem
|
|
45
|
+
panel: PalettePanel
|
|
46
|
+
beginCreate(): unknown
|
|
47
|
+
}) => void | (() => void)
|
|
48
|
+
export type PaletteSectionRenderer = (context: {
|
|
49
|
+
container: HTMLElement
|
|
50
|
+
section: PaletteSection
|
|
51
|
+
panel: PalettePanel
|
|
52
|
+
}) => void | (() => void)
|
|
53
|
+
|
|
54
|
+
export interface PalettePanelOptions {
|
|
55
|
+
container: HTMLElement
|
|
56
|
+
registry: PaletteRegistry
|
|
57
|
+
studio: { getState(): unknown }
|
|
58
|
+
interactions: { beginCreate(intent: PaletteCreateIntent): unknown; serialize(session: unknown): string }
|
|
59
|
+
canvas?: unknown
|
|
60
|
+
iconRegistry?: IconRegistry
|
|
61
|
+
renderItem?: PaletteItemRenderer | null
|
|
62
|
+
renderSection?: PaletteSectionRenderer | null
|
|
63
|
+
themeController?: ThemeController | null
|
|
64
|
+
theme?: NovaThemeInput | null
|
|
65
|
+
onThemeChange?: ((state: NovaThemeState) => void) | null
|
|
66
|
+
}
|
|
67
|
+
export class PalettePanel {
|
|
68
|
+
constructor(options: PalettePanelOptions)
|
|
69
|
+
render(): void
|
|
70
|
+
setTheme(theme: NovaThemeInput): NovaThemeState
|
|
71
|
+
setThemeMode(mode: NovaThemeMode): NovaThemeState
|
|
72
|
+
getThemeState(): NovaThemeState
|
|
73
|
+
destroy(): void
|
|
74
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { NODE_DEFINITIONS, PALETTE_GROUPS, PARALLEL_GATEWAY_PRESETS } from '../core/index.js';
|
|
2
|
+
import { resolveNodeVisual } from '../icons/index.js';
|
|
3
|
+
|
|
4
|
+
function insert(records, record) {
|
|
5
|
+
if (!record?.id) return records;
|
|
6
|
+
const position = record.position || {};
|
|
7
|
+
if (position.remove) return records.filter((item) => item.id !== position.remove && item.id !== record.id);
|
|
8
|
+
const next = [...records];
|
|
9
|
+
let index = next.length;
|
|
10
|
+
const existing = next.findIndex((item) => item.id === record.id);
|
|
11
|
+
if (existing >= 0) { index = existing; next.splice(existing, 1); }
|
|
12
|
+
if (position.replace) {
|
|
13
|
+
const target = next.findIndex((item) => item.id === position.replace);
|
|
14
|
+
if (target >= 0) { index = target; next.splice(target, 1); }
|
|
15
|
+
} else if (position.prepend) index = 0;
|
|
16
|
+
else if (position.before) { const target = next.findIndex((item) => item.id === position.before); if (target >= 0) index = target; }
|
|
17
|
+
else if (position.after) { const target = next.findIndex((item) => item.id === position.after); if (target >= 0) index = target + 1; }
|
|
18
|
+
index = Math.max(0, Math.min(index, next.length));
|
|
19
|
+
next.splice(index, 0, record);
|
|
20
|
+
return next;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class PaletteRegistry {
|
|
24
|
+
constructor() { this._providers = []; }
|
|
25
|
+
|
|
26
|
+
registerProvider(priority = 500, provider) {
|
|
27
|
+
if (typeof priority === 'object') { provider = priority; priority = provider.priority ?? 500; }
|
|
28
|
+
if (!provider?.id) throw new Error('Palette provider requires an id.');
|
|
29
|
+
const record = { priority, provider, order: this._providers.length };
|
|
30
|
+
this._providers.push(record);
|
|
31
|
+
this._providers.sort((a, b) => b.priority - a.priority || a.order - b.order);
|
|
32
|
+
return () => { this._providers = this._providers.filter((item) => item !== record); };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
resolve(context = {}) {
|
|
36
|
+
let sections = [];
|
|
37
|
+
// Resolve low priority first so higher-priority providers can intentionally
|
|
38
|
+
// replace or reposition default sections/items.
|
|
39
|
+
for (const { provider } of [...this._providers].reverse()) {
|
|
40
|
+
const output = typeof provider.getSections === 'function' ? provider.getSections(context) : provider.sections;
|
|
41
|
+
for (const rawSection of output || []) {
|
|
42
|
+
if (!rawSection || (typeof rawSection.visible === 'function' && !rawSection.visible(context))) continue;
|
|
43
|
+
const previous = sections.find((section) => section.id === rawSection.id);
|
|
44
|
+
let items = previous?.items || [];
|
|
45
|
+
for (const item of rawSection.items || []) {
|
|
46
|
+
if (!item || (typeof item.visible === 'function' && !item.visible(context))) continue;
|
|
47
|
+
items = insert(items, item);
|
|
48
|
+
}
|
|
49
|
+
sections = insert(sections, { ...previous, ...rawSection, items });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return sections;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const defaultBpmnPaletteProvider = {
|
|
57
|
+
id: 'bpmn-default-palette',
|
|
58
|
+
priority: 100,
|
|
59
|
+
getSections(context = {}) {
|
|
60
|
+
return PALETTE_GROUPS.map((group) => {
|
|
61
|
+
const items = [];
|
|
62
|
+
for (const nodeType of group.types.filter((type) => context.studio?.allowsNodeType?.(type) !== false)) {
|
|
63
|
+
if (nodeType === 'parallelGateway') {
|
|
64
|
+
items.push({
|
|
65
|
+
id: 'node-parallelGateway',
|
|
66
|
+
label: PARALLEL_GATEWAY_PRESETS.diverging.label,
|
|
67
|
+
description: '并行启动多条后续线路',
|
|
68
|
+
iconId: PARALLEL_GATEWAY_PRESETS.diverging.iconId,
|
|
69
|
+
create: { kind: 'node', nodeType, preset: PARALLEL_GATEWAY_PRESETS.diverging.preset },
|
|
70
|
+
}, {
|
|
71
|
+
id: 'node-parallelGateway-converging',
|
|
72
|
+
label: PARALLEL_GATEWAY_PRESETS.converging.label,
|
|
73
|
+
description: '等待所有并行入口到达',
|
|
74
|
+
iconId: PARALLEL_GATEWAY_PRESETS.converging.iconId,
|
|
75
|
+
create: { kind: 'node', nodeType, preset: PARALLEL_GATEWAY_PRESETS.converging.preset },
|
|
76
|
+
});
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
items.push({
|
|
80
|
+
id: `node-${nodeType}`,
|
|
81
|
+
label: NODE_DEFINITIONS[nodeType].label,
|
|
82
|
+
description: NODE_DEFINITIONS[nodeType].bpmnType,
|
|
83
|
+
iconId: resolveNodeVisual(nodeType, { surface: 'palette' }).iconId,
|
|
84
|
+
create: { kind: 'node', nodeType },
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return { id: group.id, label: group.label, collapsed: group.id !== 'favorites', items };
|
|
88
|
+
}).filter((section) => section.items.length);
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export function createPaletteRegistry() { return new PaletteRegistry(); }
|
|
93
|
+
export function createDefaultPaletteRegistry({ providers = [] } = {}) {
|
|
94
|
+
const registry = createPaletteRegistry();
|
|
95
|
+
registry.registerProvider(defaultBpmnPaletteProvider.priority, defaultBpmnPaletteProvider);
|
|
96
|
+
for (const provider of providers) registry.registerProvider(provider.priority ?? 500, provider);
|
|
97
|
+
return registry;
|
|
98
|
+
}
|
|
99
|
+
export * from './panel.js';
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { createDefaultIconRegistry, createIconElement, hydrateIcons } from '../icons/index.js';
|
|
2
|
+
import { ThemeController } from '../theme/index.js';
|
|
3
|
+
|
|
4
|
+
// Kept identical to the interaction protocol without importing Studio back into
|
|
5
|
+
// Palette; this prevents a Palette -> Studio -> Palette module cycle.
|
|
6
|
+
const CREATE_INTENT_MIME = 'application/x-bpmn-nova-create-intent+json';
|
|
7
|
+
|
|
8
|
+
function element(tag, className, text) {
|
|
9
|
+
const node = document.createElement(tag);
|
|
10
|
+
if (className) node.className = className;
|
|
11
|
+
if (text !== undefined) node.textContent = text;
|
|
12
|
+
return node;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class PalettePanel {
|
|
16
|
+
constructor({ container, registry, studio, interactions, canvas = null, iconRegistry = createDefaultIconRegistry(), renderItem = null, renderSection = null, themeController = null, theme = null, onThemeChange = null } = {}) {
|
|
17
|
+
if (!container || !registry || !studio || !interactions) throw new Error('PalettePanel requires container, registry, studio and interactions.');
|
|
18
|
+
Object.assign(this, { container, registry, studio, interactions, canvas, iconRegistry, renderItem, renderSection });
|
|
19
|
+
this.themeController = themeController || new ThemeController({ root: container, theme, onChange: onThemeChange });
|
|
20
|
+
this._ownsThemeController = !themeController;
|
|
21
|
+
this._cleanups = [];
|
|
22
|
+
this.render();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
render() {
|
|
26
|
+
this._cleanups.splice(0).forEach((cleanup) => cleanup?.());
|
|
27
|
+
this.container.innerHTML = '';
|
|
28
|
+
this.container.classList.add('nova-palette');
|
|
29
|
+
const sections = this.registry.resolve({ studio: this.studio, model: this.studio.model });
|
|
30
|
+
for (const section of sections) {
|
|
31
|
+
if (this.renderSection) {
|
|
32
|
+
const cleanup = this.renderSection({ container: this.container, section, panel: this });
|
|
33
|
+
if (typeof cleanup === 'function') this._cleanups.push(cleanup);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const wrapper = element('section', `nova-palette-section${section.collapsed ? ' is-collapsed' : ''}`);
|
|
37
|
+
wrapper.dataset.sectionId = section.id;
|
|
38
|
+
const toggle = element('button', 'nova-palette-section-toggle');
|
|
39
|
+
toggle.type = 'button';
|
|
40
|
+
toggle.setAttribute('aria-expanded', section.collapsed ? 'false' : 'true');
|
|
41
|
+
const chevron = element('span', 'nova-icon nova-icon-sm nova-palette-chevron');
|
|
42
|
+
chevron.dataset.icon = 'ui.chevron';
|
|
43
|
+
toggle.append(chevron, element('strong', '', section.label), element('small', '', String(section.items.length)));
|
|
44
|
+
toggle.addEventListener('click', () => {
|
|
45
|
+
wrapper.classList.toggle('is-collapsed');
|
|
46
|
+
toggle.setAttribute('aria-expanded', wrapper.classList.contains('is-collapsed') ? 'false' : 'true');
|
|
47
|
+
});
|
|
48
|
+
const items = element('div', 'nova-palette-items');
|
|
49
|
+
for (const item of section.items) items.appendChild(this._item(item));
|
|
50
|
+
wrapper.append(toggle, items);
|
|
51
|
+
this.container.appendChild(wrapper);
|
|
52
|
+
}
|
|
53
|
+
hydrateIcons(this.container, this.iconRegistry);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
_item(item) {
|
|
57
|
+
const host = element('div', 'nova-palette-item-host');
|
|
58
|
+
if (this.renderItem) {
|
|
59
|
+
const cleanup = this.renderItem({ container: host, item, panel: this, beginCreate: () => this.interactions.beginCreate(item.create) });
|
|
60
|
+
if (typeof cleanup === 'function') this._cleanups.push(cleanup);
|
|
61
|
+
return host;
|
|
62
|
+
}
|
|
63
|
+
const button = element('button', 'nova-palette-item');
|
|
64
|
+
button.type = 'button';
|
|
65
|
+
button.draggable = Boolean(item.create && item.create.kind !== 'action');
|
|
66
|
+
button.title = item.description || item.label;
|
|
67
|
+
const iconHost = element('span', 'nova-palette-item-icon');
|
|
68
|
+
const icon = createIconElement(this.iconRegistry.resolve(item.iconId), { title: item.label });
|
|
69
|
+
if (icon) iconHost.appendChild(icon);
|
|
70
|
+
const text = element('span', 'nova-palette-item-copy');
|
|
71
|
+
text.append(element('strong', '', item.label), element('small', '', item.description || ''));
|
|
72
|
+
button.append(iconHost, text);
|
|
73
|
+
button.addEventListener('dragstart', (event) => {
|
|
74
|
+
const session = this.interactions.beginCreate(item.create);
|
|
75
|
+
const value = this.interactions.serialize(session);
|
|
76
|
+
event.dataTransfer.effectAllowed = 'copy';
|
|
77
|
+
event.dataTransfer.setData(CREATE_INTENT_MIME, value);
|
|
78
|
+
event.dataTransfer.setData('text/plain', value);
|
|
79
|
+
});
|
|
80
|
+
button.addEventListener('click', () => {
|
|
81
|
+
if (!this.canvas || !item.create) return;
|
|
82
|
+
const point = this.canvas.getViewportCenterWorld();
|
|
83
|
+
this.interactions.drop(this.interactions.beginCreate(item.create), { clientX: 0, clientY: 0 }, { clientToWorld: () => point });
|
|
84
|
+
});
|
|
85
|
+
host.appendChild(button);
|
|
86
|
+
return host;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
destroy() {
|
|
90
|
+
this._cleanups.splice(0).forEach((cleanup) => cleanup?.());
|
|
91
|
+
this.container.innerHTML = '';
|
|
92
|
+
this.container.classList.remove('nova-palette');
|
|
93
|
+
if (this._ownsThemeController) this.themeController.destroy();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
setTheme(theme) { return this.themeController.setTheme(theme); }
|
|
97
|
+
setThemeMode(mode) { return this.themeController.setMode(mode); }
|
|
98
|
+
getThemeState() { return this.themeController.getState(); }
|
|
99
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export * from '../properties-core/index.js'
|
|
2
|
+
export * from '../properties-bpmn/index.js'
|
|
3
|
+
export * from '../properties-flowable/index.js'
|
|
4
|
+
export * from '../properties-activiti/index.js'
|
|
5
|
+
export * from '../properties-renderer/index.js'
|
|
6
|
+
|
|
7
|
+
import type {
|
|
8
|
+
PropertiesProvider,
|
|
9
|
+
PropertiesRegistry,
|
|
10
|
+
PropertiesStudio,
|
|
11
|
+
PropertyComponentRenderer,
|
|
12
|
+
} from '../properties-core/index.js'
|
|
13
|
+
|
|
14
|
+
export function createDefaultPropertiesRegistry(options?: {
|
|
15
|
+
studio?: PropertiesStudio | null
|
|
16
|
+
designer?: PropertiesStudio | null
|
|
17
|
+
components?: Record<string, PropertyComponentRenderer>
|
|
18
|
+
dataProviders?: Record<string, unknown>
|
|
19
|
+
providers?: PropertiesProvider[]
|
|
20
|
+
}): PropertiesRegistry
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export * from '../properties-core/index.js';
|
|
2
|
+
export * from '../properties-bpmn/index.js';
|
|
3
|
+
export * from '../properties-flowable/index.js';
|
|
4
|
+
export * from '../properties-activiti/index.js';
|
|
5
|
+
export * from '../properties-renderer/index.js';
|
|
6
|
+
|
|
7
|
+
import { createPropertiesRegistry } from '../properties-core/index.js';
|
|
8
|
+
import { registerBpmnProperties } from '../properties-bpmn/index.js';
|
|
9
|
+
import { registerFlowableProperties } from '../properties-flowable/index.js';
|
|
10
|
+
import { registerActivitiProperties } from '../properties-activiti/index.js';
|
|
11
|
+
|
|
12
|
+
export function createDefaultPropertiesRegistry({ studio = null, designer = null, components = {}, dataProviders = {}, providers = [] } = {}) {
|
|
13
|
+
const registry = createPropertiesRegistry({ studio: studio || designer, components, dataProviders });
|
|
14
|
+
registerBpmnProperties(registry);
|
|
15
|
+
registerFlowableProperties(registry);
|
|
16
|
+
registerActivitiProperties(registry);
|
|
17
|
+
for (const provider of providers) registry.registerProvider(provider.priority ?? 500, provider);
|
|
18
|
+
return registry;
|
|
19
|
+
}
|