@bpmn-nova/studio 0.3.0-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.
@@ -0,0 +1,447 @@
1
+ export * from '@bpmn-nova/core'
2
+ export * from '@bpmn-nova/bpmn-model'
3
+ export * from '@bpmn-nova/runtime'
4
+ export * from '@bpmn-nova/theme'
5
+ export * from '@bpmn-nova/designer'
6
+ export * from '@bpmn-nova/viewer'
7
+ export * from '@bpmn-nova/flowable'
8
+ export * from '@bpmn-nova/activiti'
9
+ export * from '@bpmn-nova/properties'
10
+ export * from '@bpmn-nova/icons'
11
+ export * from '@bpmn-nova/palette'
12
+
13
+ import type {
14
+ BpmnEdge,
15
+ BpmnNode,
16
+ ElementSelection,
17
+ EngineId,
18
+ LayoutOptions,
19
+ NodeType,
20
+ Point,
21
+ ProcessModel,
22
+ SelectionRect,
23
+ } from '@bpmn-nova/core'
24
+ import type { IconRegistry } from '@bpmn-nova/icons'
25
+ import type { PaletteRegistry } from '@bpmn-nova/palette'
26
+ import type { PropertiesRegistry } from '@bpmn-nova/properties'
27
+ import type { DiagramNodeRenderer, DiagramRendererOptions } from '@bpmn-nova/renderer'
28
+ import type {
29
+ ActivityInstance as RuntimeActivityInstance,
30
+ ProcessInstanceSnapshot as RuntimeProcessInstanceSnapshot,
31
+ } from '@bpmn-nova/runtime'
32
+ import type { NovaThemeInput, NovaThemeMode, NovaThemeState, RuntimeAppearanceOptions, RuntimeAppearanceResolver } from '@bpmn-nova/theme'
33
+ import type {
34
+ RuntimeDetailsRenderer,
35
+ RuntimeTransitionDetailsRenderer,
36
+ } from '@bpmn-nova/viewer'
37
+
38
+ // Aggregate compatibility surface. Studio re-exports the package-level types,
39
+ // and keeps these frequently consumed declarations visible at its own entry.
40
+ export interface ScopedElement { scopeId?: string }
41
+ export type NodeVisualSurface = 'palette' | 'canvas' | 'viewer' | 'timeline'
42
+ export interface NodeRendererContext {
43
+ container: HTMLElement
44
+ node: BpmnNode
45
+ mode: 'design' | 'viewer' | 'instance'
46
+ renderSemanticIcon(target?: Element, options?: { className?: string; title?: string }): SVGSVGElement | null
47
+ }
48
+ export function hydrateIcons(root: ParentNode, registry: IconRegistry): void
49
+ export type PropertyEntryType =
50
+ | 'text' | 'textarea' | 'code' | 'expression' | 'number' | 'select' | 'switch' | 'range' | 'readonly' | 'action' | 'tags'
51
+ | 'table' | 'branchList' | 'flow-list' | 'node-list' | 'user-select' | 'form-select' | 'process-select' | 'resource-select' | 'node-select'
52
+ | (string & {})
53
+ export interface PropertyEntry {
54
+ id: string
55
+ type?: PropertyEntryType
56
+ label?: string
57
+ iconId?: string
58
+ relation?: 'source' | 'target'
59
+ }
60
+ export interface GatewayRoleResolution {
61
+ topologyComplete: boolean
62
+ [key: string]: unknown
63
+ }
64
+
65
+ export interface RuntimeTransitionRouteOptions {
66
+ occupiedRoutes?: Array<Point[] | { points: Point[] }>
67
+ obstacles?: SelectionRect[]
68
+ labelSize?: { width: number; height: number }
69
+ nodeClearance?: number
70
+ laneGap?: number
71
+ laneSpacing?: number
72
+ nearParallelDistance?: number
73
+ anchorOverlapTolerance?: number
74
+ maxLanesPerSide?: number
75
+ }
76
+ export interface RuntimeTransitionRoute {
77
+ points: Point[]
78
+ labelPoint: Point
79
+ direction: 'horizontal' | 'vertical'
80
+ laneSide: 'top' | 'bottom' | 'left' | 'right'
81
+ laneIndex: number
82
+ sourceSide: 'top' | 'right' | 'bottom' | 'left'
83
+ targetSide: 'top' | 'right' | 'bottom' | 'left'
84
+ anchorStrategy: 'outer-same-side' | 'flow-axis-fallback'
85
+ portConflicts: number
86
+ }
87
+ export function routeRuntimeTransition(model: ProcessModel, transition: import('@bpmn-nova/runtime').RuntimeTransition, options?: RuntimeTransitionRouteOptions): RuntimeTransitionRoute | null
88
+
89
+ export type RuntimeParticipant = import('@bpmn-nova/runtime').RuntimeParticipant
90
+ export type RuntimeTransition = import('@bpmn-nova/runtime').RuntimeTransition
91
+ export type NodeRuntimePresentation = import('@bpmn-nova/runtime').NodeRuntimePresentation
92
+ export type RuntimePresentation = import('@bpmn-nova/runtime').RuntimePresentation
93
+ export interface ActivityInstance extends RuntimeActivityInstance {
94
+ visitId?: string
95
+ multiInstanceId?: string
96
+ participant?: RuntimeParticipant
97
+ approvalMode?: 'single' | 'all' | 'any'
98
+ multiInstanceMode?: 'parallel' | 'sequential'
99
+ totalInstances?: number
100
+ requiredInstances?: number
101
+ }
102
+ export interface ProcessInstanceSnapshot extends RuntimeProcessInstanceSnapshot {
103
+ transitions?: RuntimeTransition[]
104
+ }
105
+
106
+ export type ViewerProjection = 'auto' | 'standard' | 'approval' | 'compact'
107
+ export type RuntimeTraceProjection = import('@bpmn-nova/viewer').RuntimeTraceProjection
108
+ export type RuntimeTraceItem = import('@bpmn-nova/viewer').RuntimeTraceItem
109
+ export type RuntimeTraceLink = import('@bpmn-nova/viewer').RuntimeTraceLink
110
+ export type RuntimeTraceGroup = import('@bpmn-nova/viewer').RuntimeTraceGroup
111
+ export interface RuntimeTraceProjectionOptions {
112
+ includePredicted?: boolean
113
+ showStartMilestone?: boolean
114
+ showEndMilestone?: boolean
115
+ }
116
+ export interface ViewerTimelineOptions {
117
+ title?: string | null | ((context: import('@bpmn-nova/viewer').ViewerTimelineContext) => string | null)
118
+ description?: string | null | ((context: import('@bpmn-nova/viewer').ViewerTimelineContext) => string | null)
119
+ }
120
+ export interface RuntimeDetailsLayoutOptions {
121
+ placement?: 'popover' | 'center' | 'bottom'
122
+ width?: number | string
123
+ maxHeight?: number | string
124
+ backdrop?: boolean
125
+ dragToDismiss?: boolean
126
+ }
127
+ export interface RuntimeDetailsOptions {
128
+ autoOpen?: boolean
129
+ desktop?: RuntimeDetailsLayoutOptions
130
+ mobile?: RuntimeDetailsLayoutOptions
131
+ }
132
+ export type RuntimeTimelineRenderer = import('@bpmn-nova/viewer').RuntimeTimelineRenderer
133
+ export type RuntimeTraceClickEvent = import('@bpmn-nova/viewer').RuntimeTraceClickEvent
134
+ export interface ViewerOptions {
135
+ container: HTMLElement
136
+ model: ProcessModel
137
+ runtime?: ProcessInstanceSnapshot | null
138
+ iconRegistry?: IconRegistry
139
+ projection?: ViewerProjection
140
+ responsive?: boolean
141
+ timeline?: ViewerTimelineOptions
142
+ runtimeDetails?: RuntimeDetailsOptions
143
+ runtimeTraceOptions?: RuntimeTraceProjectionOptions
144
+ onTraceClick?: (event: RuntimeTraceClickEvent) => void
145
+ runtimePresenter?: (context: { model: ProcessModel; runtime: ProcessInstanceSnapshot | null; appearance: RuntimeAppearanceResolver }) => RuntimePresentation
146
+ runtimeDetailsRenderer?: RuntimeDetailsRenderer | null
147
+ onRuntimeDetailsOpen?: Function
148
+ runtimeTransitionDetailsRenderer?: RuntimeTransitionDetailsRenderer | null
149
+ onRuntimeTransitionDetailsOpen?: Function
150
+ }
151
+ export class BpmnViewer {
152
+ constructor(options: ViewerOptions)
153
+ setDisplayOptions(options: { timeline?: ViewerTimelineOptions; runtimeDetails?: RuntimeDetailsOptions; runtimeTraceOptions?: RuntimeTraceProjectionOptions }): void
154
+ fitView(): void
155
+ destroy(): void
156
+ }
157
+
158
+ export type NodeRenderer = DiagramNodeRenderer
159
+ export interface StudioState {
160
+ model: ProcessModel
161
+ selection: ElementSelection | null
162
+ selectedElement: ProcessModel | BpmnNode | BpmnEdge | Array<BpmnNode | BpmnEdge> | null
163
+ connectingSource: string | null
164
+ canUndo: boolean
165
+ canRedo: boolean
166
+ engine: EngineId
167
+ propertiesProfile: 'business' | 'developer'
168
+ activeScopeId: string
169
+ scopePath: Array<{ id: string; name: string; kind: 'process' | 'subProcess' }>
170
+ }
171
+ export interface NodePreset extends Partial<Omit<BpmnNode, 'properties'>> { properties?: Record<string, unknown> }
172
+ export interface TemplateDefinition {
173
+ nodes: Array<{ key: string; nodeType: NodeType; offset?: Point; preset?: NodePreset }>
174
+ edges?: Array<{ source: string; target: string; preset?: Partial<BpmnEdge> }>
175
+ }
176
+ export type SelectionLayoutOperation =
177
+ | { type: 'align'; alignment: 'left' | 'centerX' | 'right' | 'top' | 'centerY' | 'bottom' }
178
+ | { type: 'distribute'; axis: 'horizontal' | 'vertical' }
179
+ | { type: 'layout' }
180
+ | { type: 'reroute' }
181
+ export interface StudioExtension {
182
+ id: string
183
+ setup(context: { studio: BpmnStudioController }): void | (() => void)
184
+ }
185
+ export interface StudioControllerOptions {
186
+ model: ProcessModel
187
+ historyLimit?: number
188
+ extensions?: StudioExtension[]
189
+ propertiesProfile?: 'business' | 'developer'
190
+ }
191
+ export interface StudioCommands {
192
+ createNode(input: { nodeType: NodeType; point?: Point; preset?: NodePreset }): BpmnNode
193
+ createTemplate(template: TemplateDefinition, point: Point): { nodes: BpmnNode[]; edges: BpmnEdge[] }
194
+ connect(source: string, target: string, overrides?: Partial<BpmnEdge>): BpmnEdge | null
195
+ updateProcess(patch: Partial<ProcessModel>): void
196
+ updateNode(id: string, patch: Partial<BpmnNode>): boolean
197
+ updateEdge(id: string, patch: Partial<BpmnEdge>): boolean
198
+ updateEdges(patches: Array<{ id: string; patch: Partial<BpmnEdge> }>): boolean
199
+ remove(selection?: ElementSelection | null): boolean
200
+ changeElementId(kind: 'process' | 'node' | 'edge', oldId: string, nextId: string): boolean
201
+ changeNodeType(id: string, type: NodeType): boolean
202
+ quickAdd(sourceId: string, type?: NodeType, preset?: NodePreset): BpmnNode | null
203
+ autoLayout(direction?: 'horizontal' | 'vertical'): void
204
+ beautify(options?: LayoutOptions): void
205
+ rerouteEdges(options?: LayoutOptions): void
206
+ resetEdgeRoute(id: string): boolean
207
+ setEngine(engine: EngineId): void
208
+ setPropertiesProfile(profile: 'business' | 'developer'): void
209
+ select(selection: ElementSelection | null): boolean
210
+ selectInRect(rect: SelectionRect, options?: { mode?: 'replace' | 'add' | 'toggle' }): ElementSelection
211
+ getSelectionBounds(): SelectionRect | null
212
+ arrangeSelection(operation: SelectionLayoutOperation): boolean
213
+ groupSelection(): BpmnNode | null
214
+ ungroup(id?: string): boolean
215
+ attachLane(laneId: string, participantId: string, index?: number): boolean
216
+ detachLane(laneId: string, point?: Point): boolean
217
+ enterScope(subProcessId: string): boolean
218
+ leaveScope(): boolean
219
+ navigateToScope(scopeId: string): boolean
220
+ getActiveGraph(): ProcessModel
221
+ undo(): boolean
222
+ redo(): boolean
223
+ }
224
+ export interface StudioEvent {
225
+ type: 'modelChanged' | 'selectionChanged' | 'historyChanged' | 'scopeChanged' | 'propertiesProfileChanged' | string
226
+ reason?: string
227
+ state: StudioState
228
+ [key: string]: unknown
229
+ }
230
+ export function canCreateSequenceFlow(model: ProcessModel, sourceId: string, targetId: string): boolean
231
+ export class BpmnStudioController {
232
+ constructor(options: StudioControllerOptions)
233
+ readonly model: ProcessModel
234
+ selection: ElementSelection | null
235
+ connectingSource: string | null
236
+ activeScopeId: string
237
+ propertiesProfile: 'business' | 'developer'
238
+ readonly commands: StudioCommands
239
+ getState(): StudioState
240
+ getSelectedElement(): StudioState['selectedElement']
241
+ getActiveGraph(): ProcessModel
242
+ subscribe(listener: (event: StudioEvent) => void): () => void
243
+ select(selection: ElementSelection | null): boolean
244
+ selectInRect(rect: SelectionRect, options?: { mode?: 'replace' | 'add' | 'toggle' }): ElementSelection
245
+ getSelectionBounds(): SelectionRect | null
246
+ arrangeSelection(operation: SelectionLayoutOperation): boolean
247
+ groupSelection(): BpmnNode | null
248
+ ungroup(id?: string): boolean
249
+ attachLane(laneId: string, participantId: string, index?: number): boolean
250
+ detachLane(laneId: string, point?: Point): boolean
251
+ enterScope(subProcessId: string): boolean
252
+ leaveScope(): boolean
253
+ navigateToScope(scopeId: string): boolean
254
+ setModel(model: ProcessModel, options?: { resetHistory?: boolean }): void
255
+ setPropertiesProfile(profile: 'business' | 'developer'): void
256
+ startConnect(sourceId: string): boolean
257
+ cancelConnect(): void
258
+ createNode(input: Parameters<StudioCommands['createNode']>[0]): BpmnNode
259
+ createTemplate(template: TemplateDefinition, point: Point): ReturnType<StudioCommands['createTemplate']>
260
+ connect(source: string, target: string, overrides?: Partial<BpmnEdge>): BpmnEdge | null
261
+ updateProcess(patch: Partial<ProcessModel>): void
262
+ updateNode(id: string, patch: Partial<BpmnNode>): boolean
263
+ updateEdge(id: string, patch: Partial<BpmnEdge>): boolean
264
+ updateEdges(patches: Array<{ id: string; patch: Partial<BpmnEdge> }>): boolean
265
+ remove(selection?: ElementSelection | null): boolean
266
+ changeElementId(kind: 'process' | 'node' | 'edge', oldId: string, nextId: string): boolean
267
+ changeNodeType(id: string, type: NodeType): boolean
268
+ quickAdd(sourceId: string, type?: NodeType, preset?: NodePreset): BpmnNode | null
269
+ autoLayout(direction?: 'horizontal' | 'vertical'): void
270
+ beautify(options?: LayoutOptions): void
271
+ rerouteEdges(options?: LayoutOptions): void
272
+ resetEdgeRoute(id: string): boolean
273
+ setEngine(engine: EngineId): void
274
+ undo(): boolean
275
+ redo(): boolean
276
+ exportXml(engine?: EngineId): string
277
+ importXml(xml: string, engine?: EngineId): ProcessModel
278
+ registerExtension(extension: StudioExtension): () => void
279
+ destroy(): void
280
+ }
281
+ export function createStudioController(options: StudioControllerOptions): BpmnStudioController
282
+
283
+ export const CREATE_INTENT_MIME: 'application/x-bpmn-nova-create-intent+json'
284
+ export type CreateIntent =
285
+ | { kind: 'node'; nodeType: NodeType; preset?: NodePreset }
286
+ | { kind: 'template'; templateId: string; [key: string]: unknown }
287
+ | { kind: 'action'; [key: string]: unknown }
288
+ export interface TemplateRegistration {
289
+ id: string
290
+ label?: string
291
+ create(context: unknown): TemplateDefinition
292
+ }
293
+ export class TemplateRegistry {
294
+ constructor(templates?: TemplateRegistration[])
295
+ register(template: TemplateRegistration): () => void
296
+ resolve(id: string): TemplateRegistration | null
297
+ list(): TemplateRegistration[]
298
+ }
299
+ export class InteractionController {
300
+ constructor(options: { studio: BpmnStudioController; templates?: TemplateRegistry })
301
+ beginCreate(intent: CreateIntent): { intent: CreateIntent; startedAt: number }
302
+ serialize(session: unknown): string
303
+ deserialize(value: string): unknown
304
+ drop(session: unknown, pointer: { clientX: number; clientY: number }, canvas: { clientToWorld(x: number, y: number): Point }): unknown
305
+ }
306
+ export function createTemplateRegistry(templates?: TemplateRegistration[]): TemplateRegistry
307
+ export function createInteractionController(options: ConstructorParameters<typeof InteractionController>[0]): InteractionController
308
+
309
+ export type ContextMenuTarget =
310
+ | { kind: 'canvas'; id: string }
311
+ | { kind: 'node' | 'edge'; id: string }
312
+ | { kind: 'multi'; items: Array<{ kind: 'node' | 'edge'; id: string }> }
313
+ export interface ContextMenuContext {
314
+ studio: BpmnStudioController
315
+ canvas: BpmnCanvas
316
+ target: ContextMenuTarget
317
+ selection: ElementSelection | null
318
+ position?: Point
319
+ }
320
+ export interface ContextMenuAction {
321
+ id: string
322
+ label?: string
323
+ iconId?: string
324
+ group?: string
325
+ disabled?: boolean | ((context: ContextMenuContext) => boolean)
326
+ danger?: boolean
327
+ visible?: (context: ContextMenuContext) => boolean
328
+ position?: { before?: string; after?: string; replace?: string; remove?: string; prepend?: boolean; append?: boolean }
329
+ execute?(context: ContextMenuContext): unknown
330
+ }
331
+ export interface ContextMenuProvider { id: string; priority?: number; getActions?(context: ContextMenuContext): ContextMenuAction[]; actions?: ContextMenuAction[] }
332
+ export const defaultContextMenuProvider: ContextMenuProvider
333
+ export class ContextMenuRegistry {
334
+ registerProvider(priority: number, provider: ContextMenuProvider): () => void
335
+ registerProvider(provider: ContextMenuProvider): () => void
336
+ resolve(context: ContextMenuContext): ContextMenuAction[]
337
+ }
338
+ export function createContextMenuRegistry(): ContextMenuRegistry
339
+ export function createDefaultContextMenuRegistry(options?: { providers?: ContextMenuProvider[] }): ContextMenuRegistry
340
+
341
+ export type SelectionToolbarSlot = (context: {
342
+ container: HTMLElement
343
+ studio: BpmnStudioController
344
+ canvas: BpmnCanvas
345
+ selection: Extract<ElementSelection, { kind: 'multi' }>
346
+ elements: BpmnNode[]
347
+ bounds: SelectionRect
348
+ actions: {
349
+ align(alignment: Extract<SelectionLayoutOperation, { type: 'align' }>['alignment']): boolean
350
+ distribute(axis: Extract<SelectionLayoutOperation, { type: 'distribute' }>['axis']): boolean
351
+ layout(): boolean
352
+ reroute(): boolean
353
+ fit(): boolean
354
+ group(): BpmnNode | null
355
+ }
356
+ }) => void | (() => void)
357
+ export type ContextMenuSlot = (context: ContextMenuContext & {
358
+ container: HTMLElement
359
+ position: Point
360
+ actions: ContextMenuAction[]
361
+ execute(id: string): boolean
362
+ close(): void
363
+ }) => void | (() => void)
364
+ export interface BpmnCanvasOptions {
365
+ container: HTMLElement
366
+ studio: BpmnStudioController
367
+ rendererOptions?: DiagramRendererOptions
368
+ interactions?: InteractionController | null
369
+ selectionToolbar?: HTMLElement | SelectionToolbarSlot | null
370
+ contextMenu?: HTMLElement | ContextMenuSlot | null
371
+ contextMenuRegistry?: ContextMenuRegistry
372
+ pointerMode?: 'select' | 'marquee' | 'pan'
373
+ theme?: NovaThemeInput
374
+ onThemeChange?: (state: NovaThemeState) => void
375
+ }
376
+ export class BpmnCanvas {
377
+ constructor(options: BpmnCanvasOptions)
378
+ clientToWorld(clientX: number, clientY: number): Point
379
+ getViewportCenterWorld(): Point
380
+ fitView(padding?: number, options?: Record<string, unknown>): void
381
+ fitSelection(padding?: number): boolean
382
+ setPointerMode(mode: 'select' | 'marquee' | 'pan'): boolean
383
+ getPointerMode(): 'select' | 'marquee' | 'pan'
384
+ zoomBy(factor: number): void
385
+ actualSize(padding?: number): void
386
+ getViewportState(): { zoom: number; pan: Point }
387
+ setTheme(theme: NovaThemeInput): NovaThemeState
388
+ setThemeMode(mode: NovaThemeMode): NovaThemeState
389
+ getThemeState(): NovaThemeState
390
+ closeContextMenu(): void
391
+ destroy(): void
392
+ }
393
+ export function createBpmnCanvas(options: BpmnCanvasOptions): BpmnCanvas
394
+
395
+ export interface StudioShellSlots {
396
+ left?: HTMLElement | ((context: Record<string, unknown>) => void | (() => void))
397
+ right?: HTMLElement | ((context: Record<string, unknown>) => void | (() => void))
398
+ header?: HTMLElement | ((context: Record<string, unknown>) => void | (() => void))
399
+ contextMenu?: ContextMenuSlot
400
+ selectionToolbar?: SelectionToolbarSlot
401
+ runtimeDetails?: RuntimeDetailsRenderer
402
+ runtimeTransitionDetails?: RuntimeTransitionDetailsRenderer
403
+ runtimeTimeline?: RuntimeTimelineRenderer
404
+ [name: string]: HTMLElement | Function | undefined
405
+ }
406
+ export interface StudioShellOptions {
407
+ container: HTMLElement
408
+ studio: BpmnStudioController
409
+ iconRegistry?: IconRegistry
410
+ paletteRegistry?: PaletteRegistry
411
+ propertiesRegistry?: PropertiesRegistry
412
+ templateRegistry?: TemplateRegistry
413
+ contextMenuRegistry?: ContextMenuRegistry
414
+ rendererOptions?: DiagramRendererOptions & {
415
+ runtimeTraceOptions?: RuntimeTraceProjectionOptions
416
+ timeline?: ViewerTimelineOptions
417
+ }
418
+ slots?: StudioShellSlots
419
+ layout?: (context: Record<string, unknown>) => void | (() => void)
420
+ runtime?: ProcessInstanceSnapshot | null
421
+ mode?: 'design' | 'viewer' | 'instance'
422
+ projection?: ViewerProjection
423
+ responsive?: boolean
424
+ projectionOptions?: Array<{ value: ViewerProjection; label: string }>
425
+ leftWidth?: number
426
+ rightWidth?: number
427
+ theme?: NovaThemeInput
428
+ runtimeAppearance?: RuntimeAppearanceOptions
429
+ onThemeChange?: (state: NovaThemeState) => void
430
+ }
431
+ export class BpmnStudioShell {
432
+ constructor(options: StudioShellOptions)
433
+ canvas?: BpmnCanvas
434
+ viewer?: BpmnViewer
435
+ setMode(mode: 'design' | 'viewer' | 'instance'): void
436
+ setRuntime(runtime: ProcessInstanceSnapshot | null): void
437
+ setProjection(projection: ViewerProjection): void
438
+ setTheme(theme: NovaThemeInput): NovaThemeState
439
+ setThemeMode(mode: NovaThemeMode): NovaThemeState
440
+ getThemeState(): NovaThemeState
441
+ subscribeTheme(listener: (state: NovaThemeState) => void): () => void
442
+ setRuntimeAppearance(options: RuntimeAppearanceOptions | null): void
443
+ fitView(): void
444
+ zoomBy(factor: number): void
445
+ destroy(): void
446
+ }
447
+ export function createStudioShell(options: StudioShellOptions): BpmnStudioShell
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ export * from '@bpmn-nova/core';
2
+ export * from '@bpmn-nova/bpmn-model';
3
+ export * from '@bpmn-nova/runtime';
4
+ export * from '@bpmn-nova/theme';
5
+ export * from '@bpmn-nova/designer';
6
+ export * from '@bpmn-nova/viewer';
7
+ export * from '@bpmn-nova/flowable';
8
+ export * from '@bpmn-nova/activiti';
9
+ export * from '@bpmn-nova/properties';
10
+ export * from './controller.js';
11
+ export * from './interactions.js';
12
+ export * from './canvas.js';
13
+ export * from './context-menu.js';
14
+ export * from './shell.js';
15
+ export * from '@bpmn-nova/icons';
16
+ export * from '@bpmn-nova/palette';
@@ -0,0 +1,54 @@
1
+ import { NODE_DEFINITIONS } from '@bpmn-nova/core';
2
+
3
+ export const CREATE_INTENT_MIME = 'application/x-bpmn-nova-create-intent+json';
4
+
5
+ export class TemplateRegistry {
6
+ constructor(templates = []) { this._templates = new Map(); for (const template of templates) this.register(template); }
7
+ register(template) {
8
+ if (!template?.id || typeof template.create !== 'function') throw new Error('Template requires id and create().');
9
+ this._templates.set(template.id, template);
10
+ return () => this._templates.delete(template.id);
11
+ }
12
+ resolve(id) { return this._templates.get(id) || null; }
13
+ list() { return [...this._templates.values()]; }
14
+ }
15
+
16
+ export class InteractionController {
17
+ constructor({ studio, templates = new TemplateRegistry() } = {}) {
18
+ if (!studio) throw new Error('InteractionController requires a studio controller.');
19
+ this.studio = studio;
20
+ this.templates = templates;
21
+ }
22
+
23
+ beginCreate(intent) {
24
+ if (!intent || !['node', 'template', 'action'].includes(intent.kind)) throw new Error('Unsupported create intent.');
25
+ const copy = intent.kind === 'action' ? { ...intent } : JSON.parse(JSON.stringify(intent));
26
+ return Object.freeze({ intent: copy, startedAt: Date.now() });
27
+ }
28
+
29
+ serialize(session) {
30
+ if (session?.intent?.kind === 'action') throw new Error('Action intents are click-only and cannot be serialized for drag and drop.');
31
+ return JSON.stringify(session.intent);
32
+ }
33
+ deserialize(value) { return this.beginCreate(JSON.parse(value)); }
34
+
35
+ drop(session, pointer, canvas) {
36
+ if (!session?.intent || !canvas?.clientToWorld) throw new Error('Drop requires a create session and canvas coordinate adapter.');
37
+ const point = canvas.clientToWorld(pointer.clientX, pointer.clientY);
38
+ const intent = session.intent;
39
+ if (intent.kind === 'node') {
40
+ const definition = NODE_DEFINITIONS[intent.nodeType];
41
+ const centered = definition ? { x: point.x - definition.width / 2, y: point.y - definition.height / 2 } : point;
42
+ return this.studio.commands.createNode({ nodeType: intent.nodeType, point: centered, preset: intent.preset });
43
+ }
44
+ if (intent.kind === 'template') {
45
+ const template = this.templates.resolve(intent.templateId);
46
+ if (!template) throw new Error(`Unknown template: ${intent.templateId}`);
47
+ return this.studio.commands.createTemplate(template.create({ studio: this.studio, point, intent }), point);
48
+ }
49
+ return intent.run?.({ studio: this.studio, point }) || null;
50
+ }
51
+ }
52
+
53
+ export function createTemplateRegistry(templates) { return new TemplateRegistry(templates); }
54
+ export function createInteractionController(options) { return new InteractionController(options); }