sequential-workflow-designer 0.18.4 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/esm/index.js CHANGED
@@ -193,8 +193,8 @@ function race(timeout, a, b, c) {
193
193
  }
194
194
 
195
195
  class ControlBarApi {
196
- static create(state, historyController, definitionModifier, viewportApi) {
197
- const api = new ControlBarApi(state, historyController, definitionModifier, viewportApi);
196
+ static create(state, historyController, stateModifier, viewportApi) {
197
+ const api = new ControlBarApi(state, historyController, stateModifier, viewportApi);
198
198
  state.onIsReadonlyChanged.subscribe(api.onStateChanged.forward);
199
199
  state.onSelectedStepIdChanged.subscribe(api.onStateChanged.forward);
200
200
  state.onIsDragDisabledChanged.subscribe(api.onStateChanged.forward);
@@ -203,19 +203,13 @@ class ControlBarApi {
203
203
  }
204
204
  return api;
205
205
  }
206
- constructor(state, historyController, definitionModifier, viewportApi) {
206
+ constructor(state, historyController, stateModifier, viewportApi) {
207
207
  this.state = state;
208
208
  this.historyController = historyController;
209
- this.definitionModifier = definitionModifier;
209
+ this.stateModifier = stateModifier;
210
210
  this.viewportApi = viewportApi;
211
211
  this.onStateChanged = new SimpleEvent();
212
212
  }
213
- /**
214
- * @deprecated Don't use this method
215
- */
216
- subscribe(handler) {
217
- this.onStateChanged.subscribe(handler);
218
- }
219
213
  resetViewport() {
220
214
  this.viewportApi.resetViewport();
221
215
  }
@@ -256,7 +250,7 @@ class ControlBarApi {
256
250
  }
257
251
  tryDelete() {
258
252
  if (this.canDelete() && this.state.selectedStepId) {
259
- this.definitionModifier.tryDelete(this.state.selectedStepId);
253
+ this.stateModifier.tryDelete(this.state.selectedStepId);
260
254
  return true;
261
255
  }
262
256
  return false;
@@ -265,7 +259,7 @@ class ControlBarApi {
265
259
  return (!!this.state.selectedStepId &&
266
260
  !this.state.isReadonly &&
267
261
  !this.state.isDragging &&
268
- this.definitionModifier.isDeletable(this.state.selectedStepId));
262
+ this.stateModifier.isDeletable(this.state.selectedStepId));
269
263
  }
270
264
  }
271
265
 
@@ -286,29 +280,30 @@ var DefinitionChangeType;
286
280
  })(DefinitionChangeType || (DefinitionChangeType = {}));
287
281
 
288
282
  class EditorRenderer {
289
- static create(state, definitionWalker, handler) {
290
- const raceEvent = race(0, state.onDefinitionChanged, state.onSelectedStepIdChanged, state.onIsReadonlyChanged);
291
- const listener = new EditorRenderer(state, definitionWalker, handler, raceEvent);
283
+ static create(state, selectedStepIdProvider, definitionWalker, handler) {
284
+ const raceEvent = race(0, state.onDefinitionChanged, selectedStepIdProvider.onSelectedStepIdChanged, state.onIsReadonlyChanged);
285
+ const listener = new EditorRenderer(state, selectedStepIdProvider, definitionWalker, handler, raceEvent);
292
286
  raceEvent.subscribe(listener.raceEventHandler);
293
- listener.renderIfStepChanged(state.selectedStepId);
287
+ listener.renderIfStepChanged(selectedStepIdProvider.selectedStepId);
294
288
  return listener;
295
289
  }
296
- constructor(state, definitionWalker, handler, raceEvent) {
290
+ constructor(state, selectedStepIdProvider, definitionWalker, handler, raceEvent) {
297
291
  this.state = state;
292
+ this.selectedStepIdProvider = selectedStepIdProvider;
298
293
  this.definitionWalker = definitionWalker;
299
294
  this.handler = handler;
300
295
  this.raceEvent = raceEvent;
301
296
  this.currentStepId = undefined;
302
297
  this.raceEventHandler = ([definitionChanged, selectedStepId, isReadonlyChanged]) => {
303
298
  if (isReadonlyChanged !== undefined) {
304
- this.render(this.state.selectedStepId);
299
+ this.render(this.selectedStepIdProvider.selectedStepId);
305
300
  }
306
301
  else if (definitionChanged) {
307
302
  if (definitionChanged.changeType === DefinitionChangeType.rootReplaced) {
308
- this.render(this.state.selectedStepId);
303
+ this.render(this.selectedStepIdProvider.selectedStepId);
309
304
  }
310
305
  else {
311
- this.renderIfStepChanged(this.state.selectedStepId);
306
+ this.renderIfStepChanged(this.selectedStepIdProvider.selectedStepId);
312
307
  }
313
308
  }
314
309
  else if (selectedStepId !== undefined) {
@@ -332,10 +327,10 @@ class EditorRenderer {
332
327
  }
333
328
 
334
329
  class EditorApi {
335
- constructor(state, definitionWalker, definitionModifier) {
330
+ constructor(state, definitionWalker, stateModifier) {
336
331
  this.state = state;
337
332
  this.definitionWalker = definitionWalker;
338
- this.definitionModifier = definitionModifier;
333
+ this.stateModifier = stateModifier;
339
334
  }
340
335
  isCollapsed() {
341
336
  return this.state.isEditorCollapsed;
@@ -352,8 +347,12 @@ class EditorApi {
352
347
  getDefinition() {
353
348
  return this.state.definition;
354
349
  }
355
- runRenderer(rendererHandler) {
356
- return EditorRenderer.create(this.state, this.definitionWalker, rendererHandler);
350
+ addDefinitionModifierDependency(dependency) {
351
+ this.stateModifier.addDependency(dependency);
352
+ }
353
+ runRenderer(rendererHandler, customSelectedStepIdProvider) {
354
+ const selectedStepIdProvider = customSelectedStepIdProvider || this.state;
355
+ return EditorRenderer.create(this.state, selectedStepIdProvider, this.definitionWalker, rendererHandler);
357
356
  }
358
357
  createStepEditorContext(stepId) {
359
358
  if (!stepId) {
@@ -368,7 +367,7 @@ class EditorApi {
368
367
  },
369
368
  notifyChildrenChanged: () => {
370
369
  this.state.notifyDefinitionChanged(DefinitionChangeType.stepChildrenChanged, stepId);
371
- this.definitionModifier.updateDependantFields();
370
+ this.stateModifier.updateDependencies();
372
371
  }
373
372
  };
374
373
  }
@@ -387,12 +386,6 @@ class PathBarApi {
387
386
  this.definitionWalker = definitionWalker;
388
387
  this.onStateChanged = race(0, this.state.onFolderPathChanged, this.state.onDefinitionChanged);
389
388
  }
390
- /**
391
- * @deprecated Don't use this method
392
- */
393
- subscribe(handler) {
394
- this.onStateChanged.subscribe(handler);
395
- }
396
389
  setFolderPath(path) {
397
390
  this.state.setFolderPath(path);
398
391
  }
@@ -473,14 +466,14 @@ class PlaceholderFinder {
473
466
  class DragStepBehavior {
474
467
  static create(designerContext, step, draggedStepComponent) {
475
468
  const view = DragStepView.create(step, designerContext.theme, designerContext.componentContext);
476
- return new DragStepBehavior(view, designerContext.workspaceController, designerContext.state, step, designerContext.definitionModifier, draggedStepComponent);
469
+ return new DragStepBehavior(view, designerContext.workspaceController, designerContext.state, step, designerContext.stateModifier, draggedStepComponent);
477
470
  }
478
- constructor(view, workspaceController, designerState, step, definitionModifier, draggedStepComponent) {
471
+ constructor(view, workspaceController, designerState, step, stateModifier, draggedStepComponent) {
479
472
  this.view = view;
480
473
  this.workspaceController = workspaceController;
481
474
  this.designerState = designerState;
482
475
  this.step = step;
483
- this.definitionModifier = definitionModifier;
476
+ this.stateModifier = stateModifier;
484
477
  this.draggedStepComponent = draggedStepComponent;
485
478
  }
486
479
  onStart(position) {
@@ -535,10 +528,10 @@ class DragStepBehavior {
535
528
  let modified = false;
536
529
  if (!interrupt && this.currentPlaceholder) {
537
530
  if (this.draggedStepComponent) {
538
- modified = this.definitionModifier.tryMove(this.draggedStepComponent.parentSequence, this.draggedStepComponent.step, this.currentPlaceholder.parentSequence, this.currentPlaceholder.index);
531
+ modified = this.stateModifier.tryMove(this.draggedStepComponent.parentSequence, this.draggedStepComponent.step, this.currentPlaceholder.parentSequence, this.currentPlaceholder.index);
539
532
  }
540
533
  else {
541
- modified = this.definitionModifier.tryInsert(this.step, this.currentPlaceholder.parentSequence, this.currentPlaceholder.index);
534
+ modified = this.stateModifier.tryInsert(this.step, this.currentPlaceholder.parentSequence, this.currentPlaceholder.index);
542
535
  }
543
536
  }
544
537
  if (!modified) {
@@ -711,15 +704,16 @@ class DesignerApi {
711
704
  const viewportController = context.services.viewportController.create(workspace);
712
705
  const viewport = new ViewportApi(context.workspaceController, viewportController);
713
706
  const toolboxDataProvider = new ToolboxDataProvider(context.componentContext.iconProvider, context.configuration.toolbox);
714
- return new DesignerApi(ControlBarApi.create(context.state, context.historyController, context.definitionModifier, viewport), new ToolboxApi(context.state, context, context.behaviorController, toolboxDataProvider, context.configuration.uidGenerator), new EditorApi(context.state, context.definitionWalker, context.definitionModifier), workspace, viewport, new PathBarApi(context.state, context.definitionWalker));
707
+ return new DesignerApi(ControlBarApi.create(context.state, context.historyController, context.stateModifier, viewport), new ToolboxApi(context.state, context, context.behaviorController, toolboxDataProvider, context.configuration.uidGenerator), new EditorApi(context.state, context.definitionWalker, context.stateModifier), workspace, viewport, new PathBarApi(context.state, context.definitionWalker), context.definitionWalker);
715
708
  }
716
- constructor(controlBar, toolbox, editor, workspace, viewport, pathBar) {
709
+ constructor(controlBar, toolbox, editor, workspace, viewport, pathBar, definitionWalker) {
717
710
  this.controlBar = controlBar;
718
711
  this.toolbox = toolbox;
719
712
  this.editor = editor;
720
713
  this.workspace = workspace;
721
714
  this.viewport = viewport;
722
715
  this.pathBar = pathBar;
716
+ this.definitionWalker = definitionWalker;
723
717
  }
724
718
  }
725
719
 
@@ -966,6 +960,34 @@ class ComponentContext {
966
960
  }
967
961
  }
968
962
 
963
+ class CustomActionController {
964
+ constructor(configuration, state) {
965
+ this.configuration = configuration;
966
+ this.state = state;
967
+ }
968
+ trigger(action, step, sequence) {
969
+ const handler = this.configuration.customActionHandler;
970
+ if (!handler) {
971
+ console.warn(`Custom action handler is not defined (action type: ${action.type})`);
972
+ return;
973
+ }
974
+ const context = {
975
+ notifyStepNameChanged: (stepId) => this.notifyStepChanged(DefinitionChangeType.stepNameChanged, stepId),
976
+ notifyStepPropertiesChanged: (stepId) => this.notifyStepChanged(DefinitionChangeType.stepPropertyChanged, stepId),
977
+ notifyStepInserted: (stepId) => this.notifyStepChanged(DefinitionChangeType.stepInserted, stepId),
978
+ notifyStepMoved: (stepId) => this.notifyStepChanged(DefinitionChangeType.stepMoved, stepId),
979
+ notifyStepDeleted: (stepId) => this.notifyStepChanged(DefinitionChangeType.stepDeleted, stepId)
980
+ };
981
+ handler(action, step, sequence, context);
982
+ }
983
+ notifyStepChanged(changeType, stepId) {
984
+ if (!stepId) {
985
+ throw new Error('Step id is empty');
986
+ }
987
+ this.state.notifyDefinitionChanged(changeType, stepId);
988
+ }
989
+ }
990
+
969
991
  class EditorView {
970
992
  static create(parent) {
971
993
  return new EditorView(parent);
@@ -993,7 +1015,7 @@ class EditorView {
993
1015
  }
994
1016
 
995
1017
  class Editor {
996
- static create(parent, api, stepEditorClassName, stepEditorProvider, rootEditorClassName, rootEditorProvider) {
1018
+ static create(parent, api, stepEditorClassName, stepEditorProvider, rootEditorClassName, rootEditorProvider, customSelectedStepIdProvider) {
997
1019
  const view = EditorView.create(parent);
998
1020
  function render(step) {
999
1021
  const definition = api.getDefinition();
@@ -1011,7 +1033,7 @@ class Editor {
1011
1033
  }
1012
1034
  view.setContent(content, className);
1013
1035
  }
1014
- const renderer = api.runRenderer(step => render(step));
1036
+ const renderer = api.runRenderer(step => render(step), customSelectedStepIdProvider);
1015
1037
  return new Editor(view, renderer);
1016
1038
  }
1017
1039
  constructor(view, renderer) {
@@ -2079,11 +2101,73 @@ class StepDuplicator {
2079
2101
  }
2080
2102
  }
2081
2103
 
2082
- class DefinitionModifier {
2083
- constructor(definitionWalker, state, configuration) {
2104
+ class FolderPathDefinitionModifierDependency {
2105
+ constructor(state, definitionWalker) {
2106
+ this.state = state;
2107
+ this.definitionWalker = definitionWalker;
2108
+ }
2109
+ update() {
2110
+ for (let index = 0; index < this.state.folderPath.length; index++) {
2111
+ const stepId = this.state.folderPath[index];
2112
+ const found = this.definitionWalker.findById(this.state.definition, stepId);
2113
+ if (!found) {
2114
+ // We need to update path if any folder is deleted.
2115
+ const newPath = this.state.folderPath.slice(0, index);
2116
+ this.state.setFolderPath(newPath);
2117
+ break;
2118
+ }
2119
+ }
2120
+ }
2121
+ }
2122
+
2123
+ class SelectedStepIdDefinitionModifierDependency {
2124
+ constructor(state, definitionWalker) {
2125
+ this.state = state;
2126
+ this.definitionWalker = definitionWalker;
2127
+ }
2128
+ update() {
2129
+ if (this.state.selectedStepId) {
2130
+ const found = this.definitionWalker.findById(this.state.definition, this.state.selectedStepId);
2131
+ if (!found) {
2132
+ // We need to unselect step when it's deleted.
2133
+ this.state.setSelectedStepId(null);
2134
+ }
2135
+ }
2136
+ }
2137
+ }
2138
+
2139
+ class StateModifier {
2140
+ static create(definitionWalker, state, configuration) {
2141
+ const dependencies = [];
2142
+ dependencies.push(new SelectedStepIdDefinitionModifierDependency(state, definitionWalker));
2143
+ dependencies.push(new FolderPathDefinitionModifierDependency(state, definitionWalker));
2144
+ return new StateModifier(definitionWalker, state, configuration, dependencies);
2145
+ }
2146
+ constructor(definitionWalker, state, configuration, dependencies) {
2084
2147
  this.definitionWalker = definitionWalker;
2085
2148
  this.state = state;
2086
2149
  this.configuration = configuration;
2150
+ this.dependencies = dependencies;
2151
+ }
2152
+ addDependency(dependency) {
2153
+ this.dependencies.push(dependency);
2154
+ }
2155
+ isSelectable(step, parentSequence) {
2156
+ return this.configuration.steps.isSelectable ? this.configuration.steps.isSelectable(step, parentSequence) : true;
2157
+ }
2158
+ trySelectStep(step, parentSequence) {
2159
+ if (this.isSelectable(step, parentSequence)) {
2160
+ this.state.setSelectedStepId(step.id);
2161
+ }
2162
+ }
2163
+ trySelectStepById(stepId) {
2164
+ if (this.configuration.steps.isSelectable) {
2165
+ const result = this.definitionWalker.getParentSequence(this.state.definition, stepId);
2166
+ this.trySelectStep(result.step, result.parentSequence);
2167
+ }
2168
+ else {
2169
+ this.state.setSelectedStepId(stepId);
2170
+ }
2087
2171
  }
2088
2172
  isDeletable(stepId) {
2089
2173
  if (this.configuration.steps.isDeletable) {
@@ -2102,7 +2186,7 @@ class DefinitionModifier {
2102
2186
  }
2103
2187
  SequenceModifier.deleteStep(result.step, result.parentSequence);
2104
2188
  this.state.notifyDefinitionChanged(DefinitionChangeType.stepDeleted, result.step.id);
2105
- this.updateDependantFields();
2189
+ this.updateDependencies();
2106
2190
  return true;
2107
2191
  }
2108
2192
  tryInsert(step, targetSequence, targetIndex) {
@@ -2115,7 +2199,7 @@ class DefinitionModifier {
2115
2199
  SequenceModifier.insertStep(step, targetSequence, targetIndex);
2116
2200
  this.state.notifyDefinitionChanged(DefinitionChangeType.stepInserted, step.id);
2117
2201
  if (!this.configuration.steps.isAutoSelectDisabled) {
2118
- this.state.setSelectedStepId(step.id);
2202
+ this.trySelectStepById(step.id);
2119
2203
  }
2120
2204
  return true;
2121
2205
  }
@@ -2136,7 +2220,7 @@ class DefinitionModifier {
2136
2220
  apply();
2137
2221
  this.state.notifyDefinitionChanged(DefinitionChangeType.stepMoved, step.id);
2138
2222
  if (!this.configuration.steps.isAutoSelectDisabled) {
2139
- this.state.setSelectedStepId(step.id);
2223
+ this.trySelectStep(step, targetSequence);
2140
2224
  }
2141
2225
  return true;
2142
2226
  }
@@ -2155,26 +2239,10 @@ class DefinitionModifier {
2155
2239
  throw new Error('Definition is empty');
2156
2240
  }
2157
2241
  this.state.setDefinition(definition);
2158
- this.updateDependantFields();
2242
+ this.updateDependencies();
2159
2243
  }
2160
- updateDependantFields() {
2161
- if (this.state.selectedStepId) {
2162
- const found = this.definitionWalker.findById(this.state.definition, this.state.selectedStepId);
2163
- if (!found) {
2164
- // We need to unselect step when it's deleted.
2165
- this.state.setSelectedStepId(null);
2166
- }
2167
- }
2168
- for (let index = 0; index < this.state.folderPath.length; index++) {
2169
- const stepId = this.state.folderPath[index];
2170
- const found = this.definitionWalker.findById(this.state.definition, stepId);
2171
- if (!found) {
2172
- // We need to update path if any folder is deleted.
2173
- const newPath = this.state.folderPath.slice(0, index);
2174
- this.state.setFolderPath(newPath);
2175
- break;
2176
- }
2177
- }
2244
+ updateDependencies() {
2245
+ this.dependencies.forEach(dependency => dependency.update());
2178
2246
  }
2179
2247
  }
2180
2248
 
@@ -2261,7 +2329,7 @@ class DesignerState {
2261
2329
  }
2262
2330
 
2263
2331
  class HistoryController {
2264
- static create(initialStack, state, definitionModifier, configuration) {
2332
+ static create(initialStack, state, stateModifier, configuration) {
2265
2333
  if (!configuration.undoStackSize || configuration.undoStackSize < 1) {
2266
2334
  throw new Error('Invalid undo stack size');
2267
2335
  }
@@ -2269,7 +2337,7 @@ class HistoryController {
2269
2337
  index: 0,
2270
2338
  items: []
2271
2339
  };
2272
- const controller = new HistoryController(stack, state, definitionModifier, configuration.undoStackSize);
2340
+ const controller = new HistoryController(stack, state, stateModifier, configuration.undoStackSize);
2273
2341
  if (!initialStack) {
2274
2342
  controller.rememberCurrent(DefinitionChangeType.rootReplaced, null);
2275
2343
  }
@@ -2280,10 +2348,10 @@ class HistoryController {
2280
2348
  });
2281
2349
  return controller;
2282
2350
  }
2283
- constructor(stack, state, definitionModifier, stackSize) {
2351
+ constructor(stack, state, stateModifier, stackSize) {
2284
2352
  this.stack = stack;
2285
2353
  this.state = state;
2286
- this.definitionModifier = definitionModifier;
2354
+ this.stateModifier = stateModifier;
2287
2355
  this.stackSize = stackSize;
2288
2356
  }
2289
2357
  canUndo() {
@@ -2335,7 +2403,7 @@ class HistoryController {
2335
2403
  }
2336
2404
  commit() {
2337
2405
  const definition = ObjectCloner.deepClone(this.stack.items[this.stack.index - 1].definition);
2338
- this.definitionModifier.replaceDefinition(definition);
2406
+ this.stateModifier.replaceDefinition(definition);
2339
2407
  }
2340
2408
  }
2341
2409
  function areItemsEqual(item, changeType, stepId) {
@@ -2402,27 +2470,29 @@ class DesignerContext {
2402
2470
  const state = new DesignerState(definition, isReadonly, isToolboxCollapsed, isEditorCollapsed);
2403
2471
  const workspaceController = new WorkspaceControllerWrapper();
2404
2472
  const behaviorController = new BehaviorController();
2473
+ const customActionController = new CustomActionController(configuration, state);
2405
2474
  const stepExtensionResolver = StepExtensionResolver.create(services);
2406
2475
  const definitionWalker = (_c = configuration.definitionWalker) !== null && _c !== void 0 ? _c : new DefinitionWalker();
2407
- const definitionModifier = new DefinitionModifier(definitionWalker, state, configuration);
2476
+ const stateModifier = StateModifier.create(definitionWalker, state, configuration);
2408
2477
  let historyController = undefined;
2409
2478
  if (configuration.undoStackSize) {
2410
- historyController = HistoryController.create(configuration.undoStack, state, definitionModifier, configuration);
2479
+ historyController = HistoryController.create(configuration.undoStack, state, stateModifier, configuration);
2411
2480
  }
2412
2481
  const componentContext = ComponentContext.create(configuration.steps, configuration.validator, state, stepExtensionResolver, services);
2413
- return new DesignerContext(theme, state, configuration, services, componentContext, definitionWalker, definitionModifier, layoutController, workspaceController, behaviorController, historyController);
2482
+ return new DesignerContext(theme, state, configuration, services, componentContext, definitionWalker, stateModifier, layoutController, workspaceController, behaviorController, customActionController, historyController);
2414
2483
  }
2415
- constructor(theme, state, configuration, services, componentContext, definitionWalker, definitionModifier, layoutController, workspaceController, behaviorController, historyController) {
2484
+ constructor(theme, state, configuration, services, componentContext, definitionWalker, stateModifier, layoutController, workspaceController, behaviorController, customActionController, historyController) {
2416
2485
  this.theme = theme;
2417
2486
  this.state = state;
2418
2487
  this.configuration = configuration;
2419
2488
  this.services = services;
2420
2489
  this.componentContext = componentContext;
2421
2490
  this.definitionWalker = definitionWalker;
2422
- this.definitionModifier = definitionModifier;
2491
+ this.stateModifier = stateModifier;
2423
2492
  this.layoutController = layoutController;
2424
2493
  this.workspaceController = workspaceController;
2425
2494
  this.behaviorController = behaviorController;
2495
+ this.customActionController = customActionController;
2426
2496
  this.historyController = historyController;
2427
2497
  }
2428
2498
  setWorkspaceController(controller) {
@@ -2568,18 +2638,24 @@ class WorkspaceView {
2568
2638
  }
2569
2639
 
2570
2640
  class MoveViewportBehavior {
2571
- static create(state, resetSelectedStep) {
2572
- return new MoveViewportBehavior(state.viewport.position, resetSelectedStep, state);
2641
+ static create(resetSelectedStep, context) {
2642
+ return new MoveViewportBehavior(context.state.viewport.position, resetSelectedStep, context.state, context.stateModifier);
2573
2643
  }
2574
- constructor(startPosition, resetSelectedStep, state) {
2644
+ constructor(startPosition, resetSelectedStep, state, stateModifier) {
2575
2645
  this.startPosition = startPosition;
2576
2646
  this.resetSelectedStep = resetSelectedStep;
2577
2647
  this.state = state;
2648
+ this.stateModifier = stateModifier;
2578
2649
  }
2579
2650
  onStart() {
2580
2651
  if (this.resetSelectedStep) {
2581
- const stepId = this.state.tryGetLastStepIdFromFolderPath();
2582
- this.state.setSelectedStepId(stepId);
2652
+ const stepIdOrNull = this.state.tryGetLastStepIdFromFolderPath();
2653
+ if (stepIdOrNull) {
2654
+ this.stateModifier.trySelectStepById(stepIdOrNull);
2655
+ }
2656
+ else {
2657
+ this.state.setSelectedStepId(null);
2658
+ }
2583
2659
  }
2584
2660
  }
2585
2661
  onMove(delta) {
@@ -2597,14 +2673,15 @@ class SelectStepBehavior {
2597
2673
  static create(pressedStepComponent, isMiddleButton, context) {
2598
2674
  const isDragDisabled = isMiddleButton ||
2599
2675
  context.state.isDragDisabled ||
2600
- !context.definitionModifier.isDraggable(pressedStepComponent.step, pressedStepComponent.parentSequence);
2601
- return new SelectStepBehavior(pressedStepComponent, isDragDisabled, context, context.state);
2676
+ !context.stateModifier.isDraggable(pressedStepComponent.step, pressedStepComponent.parentSequence);
2677
+ return new SelectStepBehavior(pressedStepComponent, isDragDisabled, context.state, context.stateModifier, context);
2602
2678
  }
2603
- constructor(pressedStepComponent, isDragDisabled, context, state) {
2679
+ constructor(pressedStepComponent, isDragDisabled, state, stateModifier, context) {
2604
2680
  this.pressedStepComponent = pressedStepComponent;
2605
2681
  this.isDragDisabled = isDragDisabled;
2606
- this.context = context;
2607
2682
  this.state = state;
2683
+ this.stateModifier = stateModifier;
2684
+ this.context = context;
2608
2685
  }
2609
2686
  onStart() {
2610
2687
  // Nothing to do.
@@ -2617,13 +2694,13 @@ class SelectStepBehavior {
2617
2694
  return DragStepBehavior.create(this.context, this.pressedStepComponent.step, this.pressedStepComponent);
2618
2695
  }
2619
2696
  else {
2620
- return MoveViewportBehavior.create(this.state, false);
2697
+ return MoveViewportBehavior.create(false, this.context);
2621
2698
  }
2622
2699
  }
2623
2700
  }
2624
2701
  onEnd(interrupt) {
2625
2702
  if (!interrupt) {
2626
- this.state.setSelectedStepId(this.pressedStepComponent.step.id);
2703
+ this.stateModifier.trySelectStep(this.pressedStepComponent.step, this.pressedStepComponent.parentSequence);
2627
2704
  }
2628
2705
  }
2629
2706
  }
@@ -2670,54 +2747,32 @@ class OpenFolderPressingBehaviorHandler {
2670
2747
  }
2671
2748
 
2672
2749
  class TriggerCustomActionPressingBehaviorHandler {
2673
- constructor(command, designerContext) {
2750
+ constructor(command, customActionController) {
2674
2751
  this.command = command;
2675
- this.designerContext = designerContext;
2752
+ this.customActionController = customActionController;
2676
2753
  }
2677
2754
  handle() {
2678
- const customActionHandler = this.designerContext.configuration.customActionHandler;
2679
- if (!customActionHandler) {
2680
- console.warn(`Custom action handler is not defined (action type: ${this.command.action.type})`);
2681
- return;
2682
- }
2683
- const context = this.createContext();
2684
- customActionHandler(this.command.action, this.command.step, this.command.sequence, context);
2685
- }
2686
- createContext() {
2687
- return {
2688
- notifyStepNameChanged: (stepId) => this.notifyStepChanged(DefinitionChangeType.stepNameChanged, stepId),
2689
- notifyStepPropertiesChanged: (stepId) => this.notifyStepChanged(DefinitionChangeType.stepPropertyChanged, stepId),
2690
- notifyStepInserted: (stepId) => this.notifyStepChanged(DefinitionChangeType.stepInserted, stepId),
2691
- notifyStepMoved: (stepId) => this.notifyStepChanged(DefinitionChangeType.stepMoved, stepId),
2692
- notifyStepDeleted: (stepId) => this.notifyStepChanged(DefinitionChangeType.stepDeleted, stepId)
2693
- };
2694
- }
2695
- notifyStepChanged(changeType, stepId) {
2696
- if (!stepId) {
2697
- throw new Error('Step id is empty');
2698
- }
2699
- this.designerContext.state.notifyDefinitionChanged(changeType, stepId);
2755
+ this.customActionController.trigger(this.command.action, this.command.step, this.command.sequence);
2700
2756
  }
2701
2757
  }
2702
2758
 
2703
2759
  class ClickBehaviorResolver {
2704
- constructor(designerContext, state) {
2705
- this.designerContext = designerContext;
2706
- this.state = state;
2760
+ constructor(context) {
2761
+ this.context = context;
2707
2762
  }
2708
2763
  resolve(commandOrNull, element, isMiddleButton) {
2709
2764
  if (!commandOrNull) {
2710
- return MoveViewportBehavior.create(this.state, !isMiddleButton);
2765
+ return MoveViewportBehavior.create(!isMiddleButton, this.context);
2711
2766
  }
2712
2767
  switch (commandOrNull.type) {
2713
2768
  case ClickCommandType.selectStep:
2714
- return SelectStepBehavior.create(commandOrNull.component, isMiddleButton, this.designerContext);
2769
+ return SelectStepBehavior.create(commandOrNull.component, isMiddleButton, this.context);
2715
2770
  case ClickCommandType.rerenderStep:
2716
- return PressingBehavior.create(element, new RerenderStepPressingBehaviorHandler(this.designerContext));
2771
+ return PressingBehavior.create(element, new RerenderStepPressingBehaviorHandler(this.context));
2717
2772
  case ClickCommandType.openFolder:
2718
- return PressingBehavior.create(element, new OpenFolderPressingBehaviorHandler(commandOrNull, this.designerContext));
2773
+ return PressingBehavior.create(element, new OpenFolderPressingBehaviorHandler(commandOrNull, this.context));
2719
2774
  case ClickCommandType.triggerCustomAction:
2720
- return PressingBehavior.create(element, new TriggerCustomActionPressingBehaviorHandler(commandOrNull, this.designerContext));
2775
+ return PressingBehavior.create(element, new TriggerCustomActionPressingBehaviorHandler(commandOrNull, this.context.customActionController));
2721
2776
  default:
2722
2777
  throw new Error('Not supported behavior type');
2723
2778
  }
@@ -2744,12 +2799,12 @@ class ContextMenu {
2744
2799
  for (let index = 0; index < items.length; index++) {
2745
2800
  const item = items[index];
2746
2801
  const element = document.createElement('div');
2747
- if (typeof item === 'string') {
2748
- element.className = 'sqd-context-menu-group';
2749
- element.innerText = item;
2802
+ if (item.callback) {
2803
+ element.className = 'sqd-context-menu-item';
2804
+ element.innerText = item.label;
2750
2805
  }
2751
2806
  else {
2752
- element.className = 'sqd-context-menu-item';
2807
+ element.className = 'sqd-context-menu-group';
2753
2808
  element.innerText = item.label;
2754
2809
  }
2755
2810
  elements.push(element);
@@ -2790,7 +2845,7 @@ class ContextMenu {
2790
2845
  const index = this.findIndex(e.target);
2791
2846
  if (index !== null) {
2792
2847
  const item = this.items[index];
2793
- if (typeof item !== 'string') {
2848
+ if (item.callback) {
2794
2849
  item.callback();
2795
2850
  }
2796
2851
  }
@@ -2820,91 +2875,122 @@ class ContextMenu {
2820
2875
  }
2821
2876
  }
2822
2877
 
2878
+ class ContextMenuController {
2879
+ constructor(theme, configuration, itemsBuilder) {
2880
+ this.theme = theme;
2881
+ this.configuration = configuration;
2882
+ this.itemsBuilder = itemsBuilder;
2883
+ }
2884
+ tryOpen(position, commandOrNull) {
2885
+ if (this.configuration.contextMenu === false) {
2886
+ // Context menu is disabled.
2887
+ return;
2888
+ }
2889
+ if (this.current) {
2890
+ this.current.tryDestroy();
2891
+ }
2892
+ const items = this.itemsBuilder.build(commandOrNull);
2893
+ this.current = ContextMenu.create(position, this.theme, items);
2894
+ }
2895
+ destroy() {
2896
+ if (this.current) {
2897
+ this.current.tryDestroy();
2898
+ }
2899
+ }
2900
+ }
2901
+
2823
2902
  class ContextMenuItemsBuilder {
2824
- static build(commandOrNull, viewportApi, definitionModifier, state) {
2903
+ constructor(viewportApi, stateModifier, state, customMenuItemsProvider) {
2904
+ this.viewportApi = viewportApi;
2905
+ this.stateModifier = stateModifier;
2906
+ this.state = state;
2907
+ this.customMenuItemsProvider = customMenuItemsProvider;
2908
+ }
2909
+ build(commandOrNull) {
2825
2910
  const items = [];
2826
2911
  if (commandOrNull && commandOrNull.type === ClickCommandType.selectStep) {
2827
2912
  const ssc = commandOrNull;
2828
2913
  const step = ssc.component.step;
2829
2914
  const parentSequence = ssc.component.parentSequence;
2830
- items.push(step.name);
2831
- if (state.selectedStepId === step.id) {
2832
- items.push({
2833
- label: `Unselect`,
2834
- callback: () => {
2835
- state.setSelectedStepId(null);
2836
- }
2837
- });
2838
- }
2839
- else {
2840
- items.push({
2841
- label: 'Select',
2842
- callback: () => {
2843
- state.setSelectedStepId(step.id);
2844
- }
2845
- });
2915
+ items.push({
2916
+ label: step.name,
2917
+ order: 0
2918
+ });
2919
+ this.tryAppendCustomItems(items, step, parentSequence);
2920
+ if (this.stateModifier.isSelectable(step, parentSequence)) {
2921
+ if (this.state.selectedStepId === step.id) {
2922
+ items.push({
2923
+ label: `Unselect`,
2924
+ order: 10,
2925
+ callback: () => {
2926
+ this.state.setSelectedStepId(null);
2927
+ }
2928
+ });
2929
+ }
2930
+ else {
2931
+ items.push({
2932
+ label: 'Select',
2933
+ order: 20,
2934
+ callback: () => {
2935
+ this.stateModifier.trySelectStepById(step.id);
2936
+ }
2937
+ });
2938
+ }
2846
2939
  }
2847
- if (!state.isReadonly) {
2848
- if (definitionModifier.isDeletable(step.id)) {
2940
+ if (!this.state.isReadonly) {
2941
+ if (this.stateModifier.isDeletable(step.id)) {
2849
2942
  items.push({
2850
2943
  label: 'Delete',
2944
+ order: 30,
2851
2945
  callback: () => {
2852
- definitionModifier.tryDelete(step.id);
2946
+ this.stateModifier.tryDelete(step.id);
2853
2947
  }
2854
2948
  });
2855
2949
  }
2856
- if (definitionModifier.isDuplicable(step, parentSequence)) {
2950
+ if (this.stateModifier.isDuplicable(step, parentSequence)) {
2857
2951
  items.push({
2858
2952
  label: 'Duplicate',
2953
+ order: 40,
2859
2954
  callback: () => {
2860
- definitionModifier.tryDuplicate(step, parentSequence);
2955
+ this.stateModifier.tryDuplicate(step, parentSequence);
2861
2956
  }
2862
2957
  });
2863
2958
  }
2864
2959
  }
2865
2960
  }
2961
+ else {
2962
+ this.tryAppendCustomItems(items, null, this.state.definition.sequence);
2963
+ }
2866
2964
  items.push({
2867
2965
  label: 'Reset view',
2966
+ order: 50,
2868
2967
  callback: () => {
2869
- viewportApi.resetViewport();
2968
+ this.viewportApi.resetViewport();
2870
2969
  }
2871
2970
  });
2971
+ items.sort((a, b) => a.order - b.order);
2872
2972
  return items;
2873
2973
  }
2874
- }
2875
-
2876
- class ContextMenuController {
2877
- constructor(theme, viewportApi, definitionModifier, state, configuration) {
2878
- this.theme = theme;
2879
- this.viewportApi = viewportApi;
2880
- this.definitionModifier = definitionModifier;
2881
- this.state = state;
2882
- this.configuration = configuration;
2883
- }
2884
- tryOpen(position, commandOrNull) {
2885
- if (this.configuration.contextMenu === false) {
2886
- // Context menu is disabled.
2887
- return;
2888
- }
2889
- if (this.last) {
2890
- this.last.tryDestroy();
2891
- }
2892
- const items = ContextMenuItemsBuilder.build(commandOrNull, this.viewportApi, this.definitionModifier, this.state);
2893
- this.last = ContextMenu.create(position, this.theme, items);
2894
- }
2895
- destroy() {
2896
- if (this.last) {
2897
- this.last.tryDestroy();
2974
+ tryAppendCustomItems(items, step, parentSequence) {
2975
+ if (this.customMenuItemsProvider) {
2976
+ const customItems = this.customMenuItemsProvider.getItems(step, parentSequence);
2977
+ for (const customItem of customItems) {
2978
+ items.push(customItem);
2979
+ }
2898
2980
  }
2899
2981
  }
2900
2982
  }
2901
2983
 
2902
2984
  class Workspace {
2903
2985
  static create(parent, designerContext, api) {
2986
+ var _a;
2904
2987
  const view = WorkspaceView.create(parent, designerContext.componentContext);
2905
- const clickBehaviorResolver = new ClickBehaviorResolver(designerContext, designerContext.state);
2988
+ const clickBehaviorResolver = new ClickBehaviorResolver(designerContext);
2906
2989
  const wheelController = designerContext.services.wheelController.create(api.workspace);
2907
- const contextMenuController = new ContextMenuController(designerContext.theme, api.viewport, designerContext.definitionModifier, designerContext.state, designerContext.configuration);
2990
+ const contextMenuItemsBuilder = new ContextMenuItemsBuilder(api.viewport, designerContext.stateModifier, designerContext.state, ((_a = designerContext.services.contextMenu) === null || _a === void 0 ? void 0 : _a.createItemsProvider)
2991
+ ? designerContext.services.contextMenu.createItemsProvider(designerContext.customActionController)
2992
+ : undefined);
2993
+ const contextMenuController = new ContextMenuController(designerContext.theme, designerContext.configuration, contextMenuItemsBuilder);
2908
2994
  const workspace = new Workspace(view, designerContext.definitionWalker, designerContext.state, designerContext.behaviorController, wheelController, contextMenuController, clickBehaviorResolver, api.viewport, designerContext.services);
2909
2995
  setTimeout(() => {
2910
2996
  workspace.updateRootComponent();
@@ -3392,7 +3478,7 @@ class SmartEditorView {
3392
3478
  if (configuration.globalEditorProvider) {
3393
3479
  throw new Error('globalEditorProvider is renamed to rootEditorProvider');
3394
3480
  }
3395
- const editor = Editor.create(root, api, 'sqd-editor sqd-step-editor', configuration.stepEditorProvider, 'sqd-editor sqd-root-editor', configuration.rootEditorProvider);
3481
+ const editor = Editor.create(root, api, 'sqd-editor sqd-step-editor', configuration.stepEditorProvider, 'sqd-editor sqd-root-editor', configuration.rootEditorProvider, null);
3396
3482
  return new SmartEditorView(root, toggle, editor);
3397
3483
  }
3398
3484
  constructor(root, toggle, editor) {
@@ -4055,7 +4141,7 @@ class ServicesResolver {
4055
4141
  static resolve(extensions, configuration) {
4056
4142
  const services = {};
4057
4143
  merge(services, extensions || []);
4058
- setDefault(services, configuration);
4144
+ setDefaults(services, configuration);
4059
4145
  return services;
4060
4146
  }
4061
4147
  }
@@ -4097,12 +4183,15 @@ function merge(services, extensions) {
4097
4183
  if (ext.sequenceComponent) {
4098
4184
  services.sequenceComponent = ext.sequenceComponent;
4099
4185
  }
4186
+ if (ext.contextMenu) {
4187
+ services.contextMenu = ext.contextMenu;
4188
+ }
4100
4189
  if (ext.daemons) {
4101
4190
  services.daemons = (services.daemons || []).concat(ext.daemons);
4102
4191
  }
4103
4192
  }
4104
4193
  }
4105
- function setDefault(services, configuration) {
4194
+ function setDefaults(services, configuration) {
4106
4195
  if (!services.steps) {
4107
4196
  services.steps = [];
4108
4197
  }
@@ -4210,7 +4299,7 @@ class Designer {
4210
4299
  const designerContext = DesignerContext.create(placeholder, startDefinition, config, services);
4211
4300
  const designerApi = DesignerApi.create(designerContext);
4212
4301
  const view = DesignerView.create(placeholder, designerContext, designerApi);
4213
- const designer = new Designer(view, designerContext.state, designerContext.definitionWalker, designerContext.historyController, designerApi);
4302
+ const designer = new Designer(view, designerContext.state, designerContext.stateModifier, designerContext.definitionWalker, designerContext.historyController, designerApi);
4214
4303
  view.workspace.onRendered.first().then(designer.onReady.forward);
4215
4304
  race(0, designerContext.state.onDefinitionChanged, designerContext.state.onSelectedStepIdChanged).subscribe(([definition, selectedStepId]) => {
4216
4305
  if (definition !== undefined) {
@@ -4225,9 +4314,10 @@ class Designer {
4225
4314
  designerContext.state.onIsEditorCollapsedChanged.subscribe(designer.onIsEditorCollapsedChanged.forward);
4226
4315
  return designer;
4227
4316
  }
4228
- constructor(view, state, walker, historyController, api) {
4317
+ constructor(view, state, stateModifier, walker, historyController, api) {
4229
4318
  this.view = view;
4230
4319
  this.state = state;
4320
+ this.stateModifier = stateModifier;
4231
4321
  this.walker = walker;
4232
4322
  this.historyController = historyController;
4233
4323
  this.api = api;
@@ -4290,7 +4380,7 @@ class Designer {
4290
4380
  * @description Selects a step by the id.
4291
4381
  */
4292
4382
  selectStepById(stepId) {
4293
- this.state.setSelectedStepId(stepId);
4383
+ this.stateModifier.trySelectStepById(stepId);
4294
4384
  }
4295
4385
  /**
4296
4386
  * @returns the current viewport.
@@ -4317,12 +4407,6 @@ class Designer {
4317
4407
  moveViewportToStep(stepId) {
4318
4408
  this.api.viewport.moveViewportToStep(stepId);
4319
4409
  }
4320
- /**
4321
- * @deprecated Use `moveViewportToStep` instead.
4322
- */
4323
- moveViewPortToStep(stepId) {
4324
- this.moveViewportToStep(stepId);
4325
- }
4326
4410
  /**
4327
4411
  * @description Rerender the root component and all its children.
4328
4412
  */
@@ -4432,11 +4516,6 @@ class StepsDesignerExtension {
4432
4516
  constructor(steps) {
4433
4517
  this.steps = steps;
4434
4518
  }
4435
- }
4436
- /**
4437
- * @deprecated Use `StepsDesignerExtension` instead.
4438
- */
4439
- class StepsExtension extends StepsDesignerExtension {
4440
4519
  }
4441
4520
 
4442
- export { Badges, CenteredViewportCalculator, ClassicWheelControllerExtension, ClickCommandType, ComponentContext, ControlBarApi, DefaultSequenceComponent, DefaultSequenceComponentView, DefaultViewportController, DefaultViewportControllerExtension, DefinitionChangeType, Designer, DesignerApi, DesignerContext, DesignerState, Dom, Editor, EditorApi, Icons, InputView, JoinView, KeyboardAction, LabelView, LineGridDesignerExtension, ObjectCloner, OutputView, PathBarApi, PlaceholderDirection, QuantifiedScaleViewportCalculator, RectPlaceholder, RectPlaceholderView, RegionView, ServicesResolver, SimpleEvent, StepComponent, StepExtensionResolver, StepsDesignerExtension, StepsExtension, ToolboxApi, Uid, ValidationErrorBadgeExtension, Vector, WorkspaceApi, createContainerStepComponentViewFactory, createSwitchStepComponentViewFactory, createTaskStepComponentViewFactory, getAbsolutePosition, race };
4521
+ export { Badges, CenteredViewportCalculator, ClassicWheelControllerExtension, ClickCommandType, ComponentContext, ControlBarApi, CustomActionController, DefaultSequenceComponent, DefaultSequenceComponentView, DefaultViewportController, DefaultViewportControllerExtension, DefinitionChangeType, Designer, DesignerApi, DesignerContext, DesignerState, Dom, Editor, EditorApi, Icons, InputView, JoinView, KeyboardAction, LabelView, LineGridDesignerExtension, ObjectCloner, OutputView, PathBarApi, PlaceholderDirection, QuantifiedScaleViewportCalculator, RectPlaceholder, RectPlaceholderView, RegionView, ServicesResolver, SimpleEvent, StepComponent, StepExtensionResolver, StepsDesignerExtension, ToolboxApi, Uid, ValidationErrorBadgeExtension, Vector, WorkspaceApi, createContainerStepComponentViewFactory, createSwitchStepComponentViewFactory, createTaskStepComponentViewFactory, getAbsolutePosition, race };