sequential-workflow-designer 0.18.5 → 0.19.1

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,41 @@ class ComponentContext {
966
960
  }
967
961
  }
968
962
 
963
+ class CustomActionController {
964
+ constructor(configuration, state, stateModifier) {
965
+ this.configuration = configuration;
966
+ this.state = state;
967
+ this.stateModifier = stateModifier;
968
+ }
969
+ trigger(action, step, sequence) {
970
+ const handler = this.configuration.customActionHandler;
971
+ if (!handler) {
972
+ console.warn(`Custom action handler is not defined (action type: ${action.type})`);
973
+ return;
974
+ }
975
+ const context = this.createCustomActionHandlerContext();
976
+ handler(action, step, sequence, context);
977
+ }
978
+ createCustomActionHandlerContext() {
979
+ return {
980
+ notifyStepNameChanged: (stepId) => this.notifyStepChanged(DefinitionChangeType.stepNameChanged, stepId, false),
981
+ notifyStepPropertiesChanged: (stepId) => this.notifyStepChanged(DefinitionChangeType.stepPropertyChanged, stepId, false),
982
+ notifyStepInserted: (stepId) => this.notifyStepChanged(DefinitionChangeType.stepInserted, stepId, true),
983
+ notifyStepMoved: (stepId) => this.notifyStepChanged(DefinitionChangeType.stepMoved, stepId, true),
984
+ notifyStepDeleted: (stepId) => this.notifyStepChanged(DefinitionChangeType.stepDeleted, stepId, true)
985
+ };
986
+ }
987
+ notifyStepChanged(changeType, stepId, updateDependencies) {
988
+ if (!stepId) {
989
+ throw new Error('Step id is empty');
990
+ }
991
+ this.state.notifyDefinitionChanged(changeType, stepId);
992
+ if (updateDependencies) {
993
+ this.stateModifier.updateDependencies();
994
+ }
995
+ }
996
+ }
997
+
969
998
  class EditorView {
970
999
  static create(parent) {
971
1000
  return new EditorView(parent);
@@ -993,7 +1022,7 @@ class EditorView {
993
1022
  }
994
1023
 
995
1024
  class Editor {
996
- static create(parent, api, stepEditorClassName, stepEditorProvider, rootEditorClassName, rootEditorProvider) {
1025
+ static create(parent, api, stepEditorClassName, stepEditorProvider, rootEditorClassName, rootEditorProvider, customSelectedStepIdProvider) {
997
1026
  const view = EditorView.create(parent);
998
1027
  function render(step) {
999
1028
  const definition = api.getDefinition();
@@ -1011,7 +1040,7 @@ class Editor {
1011
1040
  }
1012
1041
  view.setContent(content, className);
1013
1042
  }
1014
- const renderer = api.runRenderer(step => render(step));
1043
+ const renderer = api.runRenderer(step => render(step), customSelectedStepIdProvider);
1015
1044
  return new Editor(view, renderer);
1016
1045
  }
1017
1046
  constructor(view, renderer) {
@@ -2079,11 +2108,73 @@ class StepDuplicator {
2079
2108
  }
2080
2109
  }
2081
2110
 
2082
- class DefinitionModifier {
2083
- constructor(definitionWalker, state, configuration) {
2111
+ class FolderPathDefinitionModifierDependency {
2112
+ constructor(state, definitionWalker) {
2113
+ this.state = state;
2114
+ this.definitionWalker = definitionWalker;
2115
+ }
2116
+ update() {
2117
+ for (let index = 0; index < this.state.folderPath.length; index++) {
2118
+ const stepId = this.state.folderPath[index];
2119
+ const found = this.definitionWalker.findById(this.state.definition, stepId);
2120
+ if (!found) {
2121
+ // We need to update path if any folder is deleted.
2122
+ const newPath = this.state.folderPath.slice(0, index);
2123
+ this.state.setFolderPath(newPath);
2124
+ break;
2125
+ }
2126
+ }
2127
+ }
2128
+ }
2129
+
2130
+ class SelectedStepIdDefinitionModifierDependency {
2131
+ constructor(state, definitionWalker) {
2132
+ this.state = state;
2133
+ this.definitionWalker = definitionWalker;
2134
+ }
2135
+ update() {
2136
+ if (this.state.selectedStepId) {
2137
+ const found = this.definitionWalker.findById(this.state.definition, this.state.selectedStepId);
2138
+ if (!found) {
2139
+ // We need to unselect step when it's deleted.
2140
+ this.state.setSelectedStepId(null);
2141
+ }
2142
+ }
2143
+ }
2144
+ }
2145
+
2146
+ class StateModifier {
2147
+ static create(definitionWalker, state, configuration) {
2148
+ const dependencies = [];
2149
+ dependencies.push(new SelectedStepIdDefinitionModifierDependency(state, definitionWalker));
2150
+ dependencies.push(new FolderPathDefinitionModifierDependency(state, definitionWalker));
2151
+ return new StateModifier(definitionWalker, state, configuration, dependencies);
2152
+ }
2153
+ constructor(definitionWalker, state, configuration, dependencies) {
2084
2154
  this.definitionWalker = definitionWalker;
2085
2155
  this.state = state;
2086
2156
  this.configuration = configuration;
2157
+ this.dependencies = dependencies;
2158
+ }
2159
+ addDependency(dependency) {
2160
+ this.dependencies.push(dependency);
2161
+ }
2162
+ isSelectable(step, parentSequence) {
2163
+ return this.configuration.steps.isSelectable ? this.configuration.steps.isSelectable(step, parentSequence) : true;
2164
+ }
2165
+ trySelectStep(step, parentSequence) {
2166
+ if (this.isSelectable(step, parentSequence)) {
2167
+ this.state.setSelectedStepId(step.id);
2168
+ }
2169
+ }
2170
+ trySelectStepById(stepId) {
2171
+ if (this.configuration.steps.isSelectable) {
2172
+ const result = this.definitionWalker.getParentSequence(this.state.definition, stepId);
2173
+ this.trySelectStep(result.step, result.parentSequence);
2174
+ }
2175
+ else {
2176
+ this.state.setSelectedStepId(stepId);
2177
+ }
2087
2178
  }
2088
2179
  isDeletable(stepId) {
2089
2180
  if (this.configuration.steps.isDeletable) {
@@ -2102,7 +2193,7 @@ class DefinitionModifier {
2102
2193
  }
2103
2194
  SequenceModifier.deleteStep(result.step, result.parentSequence);
2104
2195
  this.state.notifyDefinitionChanged(DefinitionChangeType.stepDeleted, result.step.id);
2105
- this.updateDependantFields();
2196
+ this.updateDependencies();
2106
2197
  return true;
2107
2198
  }
2108
2199
  tryInsert(step, targetSequence, targetIndex) {
@@ -2115,7 +2206,7 @@ class DefinitionModifier {
2115
2206
  SequenceModifier.insertStep(step, targetSequence, targetIndex);
2116
2207
  this.state.notifyDefinitionChanged(DefinitionChangeType.stepInserted, step.id);
2117
2208
  if (!this.configuration.steps.isAutoSelectDisabled) {
2118
- this.state.setSelectedStepId(step.id);
2209
+ this.trySelectStepById(step.id);
2119
2210
  }
2120
2211
  return true;
2121
2212
  }
@@ -2136,7 +2227,7 @@ class DefinitionModifier {
2136
2227
  apply();
2137
2228
  this.state.notifyDefinitionChanged(DefinitionChangeType.stepMoved, step.id);
2138
2229
  if (!this.configuration.steps.isAutoSelectDisabled) {
2139
- this.state.setSelectedStepId(step.id);
2230
+ this.trySelectStep(step, targetSequence);
2140
2231
  }
2141
2232
  return true;
2142
2233
  }
@@ -2155,26 +2246,10 @@ class DefinitionModifier {
2155
2246
  throw new Error('Definition is empty');
2156
2247
  }
2157
2248
  this.state.setDefinition(definition);
2158
- this.updateDependantFields();
2249
+ this.updateDependencies();
2159
2250
  }
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
- }
2251
+ updateDependencies() {
2252
+ this.dependencies.forEach(dependency => dependency.update());
2178
2253
  }
2179
2254
  }
2180
2255
 
@@ -2261,7 +2336,7 @@ class DesignerState {
2261
2336
  }
2262
2337
 
2263
2338
  class HistoryController {
2264
- static create(initialStack, state, definitionModifier, configuration) {
2339
+ static create(initialStack, state, stateModifier, configuration) {
2265
2340
  if (!configuration.undoStackSize || configuration.undoStackSize < 1) {
2266
2341
  throw new Error('Invalid undo stack size');
2267
2342
  }
@@ -2269,7 +2344,7 @@ class HistoryController {
2269
2344
  index: 0,
2270
2345
  items: []
2271
2346
  };
2272
- const controller = new HistoryController(stack, state, definitionModifier, configuration.undoStackSize);
2347
+ const controller = new HistoryController(stack, state, stateModifier, configuration.undoStackSize);
2273
2348
  if (!initialStack) {
2274
2349
  controller.rememberCurrent(DefinitionChangeType.rootReplaced, null);
2275
2350
  }
@@ -2280,10 +2355,10 @@ class HistoryController {
2280
2355
  });
2281
2356
  return controller;
2282
2357
  }
2283
- constructor(stack, state, definitionModifier, stackSize) {
2358
+ constructor(stack, state, stateModifier, stackSize) {
2284
2359
  this.stack = stack;
2285
2360
  this.state = state;
2286
- this.definitionModifier = definitionModifier;
2361
+ this.stateModifier = stateModifier;
2287
2362
  this.stackSize = stackSize;
2288
2363
  }
2289
2364
  canUndo() {
@@ -2335,7 +2410,7 @@ class HistoryController {
2335
2410
  }
2336
2411
  commit() {
2337
2412
  const definition = ObjectCloner.deepClone(this.stack.items[this.stack.index - 1].definition);
2338
- this.definitionModifier.replaceDefinition(definition);
2413
+ this.stateModifier.replaceDefinition(definition);
2339
2414
  }
2340
2415
  }
2341
2416
  function areItemsEqual(item, changeType, stepId) {
@@ -2404,25 +2479,27 @@ class DesignerContext {
2404
2479
  const behaviorController = new BehaviorController();
2405
2480
  const stepExtensionResolver = StepExtensionResolver.create(services);
2406
2481
  const definitionWalker = (_c = configuration.definitionWalker) !== null && _c !== void 0 ? _c : new DefinitionWalker();
2407
- const definitionModifier = new DefinitionModifier(definitionWalker, state, configuration);
2482
+ const stateModifier = StateModifier.create(definitionWalker, state, configuration);
2483
+ const customActionController = new CustomActionController(configuration, state, stateModifier);
2408
2484
  let historyController = undefined;
2409
2485
  if (configuration.undoStackSize) {
2410
- historyController = HistoryController.create(configuration.undoStack, state, definitionModifier, configuration);
2486
+ historyController = HistoryController.create(configuration.undoStack, state, stateModifier, configuration);
2411
2487
  }
2412
2488
  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);
2489
+ return new DesignerContext(theme, state, configuration, services, componentContext, definitionWalker, stateModifier, layoutController, workspaceController, behaviorController, customActionController, historyController);
2414
2490
  }
2415
- constructor(theme, state, configuration, services, componentContext, definitionWalker, definitionModifier, layoutController, workspaceController, behaviorController, historyController) {
2491
+ constructor(theme, state, configuration, services, componentContext, definitionWalker, stateModifier, layoutController, workspaceController, behaviorController, customActionController, historyController) {
2416
2492
  this.theme = theme;
2417
2493
  this.state = state;
2418
2494
  this.configuration = configuration;
2419
2495
  this.services = services;
2420
2496
  this.componentContext = componentContext;
2421
2497
  this.definitionWalker = definitionWalker;
2422
- this.definitionModifier = definitionModifier;
2498
+ this.stateModifier = stateModifier;
2423
2499
  this.layoutController = layoutController;
2424
2500
  this.workspaceController = workspaceController;
2425
2501
  this.behaviorController = behaviorController;
2502
+ this.customActionController = customActionController;
2426
2503
  this.historyController = historyController;
2427
2504
  }
2428
2505
  setWorkspaceController(controller) {
@@ -2568,18 +2645,24 @@ class WorkspaceView {
2568
2645
  }
2569
2646
 
2570
2647
  class MoveViewportBehavior {
2571
- static create(state, resetSelectedStep) {
2572
- return new MoveViewportBehavior(state.viewport.position, resetSelectedStep, state);
2648
+ static create(resetSelectedStep, context) {
2649
+ return new MoveViewportBehavior(context.state.viewport.position, resetSelectedStep, context.state, context.stateModifier);
2573
2650
  }
2574
- constructor(startPosition, resetSelectedStep, state) {
2651
+ constructor(startPosition, resetSelectedStep, state, stateModifier) {
2575
2652
  this.startPosition = startPosition;
2576
2653
  this.resetSelectedStep = resetSelectedStep;
2577
2654
  this.state = state;
2655
+ this.stateModifier = stateModifier;
2578
2656
  }
2579
2657
  onStart() {
2580
2658
  if (this.resetSelectedStep) {
2581
- const stepId = this.state.tryGetLastStepIdFromFolderPath();
2582
- this.state.setSelectedStepId(stepId);
2659
+ const stepIdOrNull = this.state.tryGetLastStepIdFromFolderPath();
2660
+ if (stepIdOrNull) {
2661
+ this.stateModifier.trySelectStepById(stepIdOrNull);
2662
+ }
2663
+ else {
2664
+ this.state.setSelectedStepId(null);
2665
+ }
2583
2666
  }
2584
2667
  }
2585
2668
  onMove(delta) {
@@ -2597,14 +2680,15 @@ class SelectStepBehavior {
2597
2680
  static create(pressedStepComponent, isMiddleButton, context) {
2598
2681
  const isDragDisabled = isMiddleButton ||
2599
2682
  context.state.isDragDisabled ||
2600
- !context.definitionModifier.isDraggable(pressedStepComponent.step, pressedStepComponent.parentSequence);
2601
- return new SelectStepBehavior(pressedStepComponent, isDragDisabled, context, context.state);
2683
+ !context.stateModifier.isDraggable(pressedStepComponent.step, pressedStepComponent.parentSequence);
2684
+ return new SelectStepBehavior(pressedStepComponent, isDragDisabled, context.state, context.stateModifier, context);
2602
2685
  }
2603
- constructor(pressedStepComponent, isDragDisabled, context, state) {
2686
+ constructor(pressedStepComponent, isDragDisabled, state, stateModifier, context) {
2604
2687
  this.pressedStepComponent = pressedStepComponent;
2605
2688
  this.isDragDisabled = isDragDisabled;
2606
- this.context = context;
2607
2689
  this.state = state;
2690
+ this.stateModifier = stateModifier;
2691
+ this.context = context;
2608
2692
  }
2609
2693
  onStart() {
2610
2694
  // Nothing to do.
@@ -2617,13 +2701,13 @@ class SelectStepBehavior {
2617
2701
  return DragStepBehavior.create(this.context, this.pressedStepComponent.step, this.pressedStepComponent);
2618
2702
  }
2619
2703
  else {
2620
- return MoveViewportBehavior.create(this.state, false);
2704
+ return MoveViewportBehavior.create(false, this.context);
2621
2705
  }
2622
2706
  }
2623
2707
  }
2624
2708
  onEnd(interrupt) {
2625
2709
  if (!interrupt) {
2626
- this.state.setSelectedStepId(this.pressedStepComponent.step.id);
2710
+ this.stateModifier.trySelectStep(this.pressedStepComponent.step, this.pressedStepComponent.parentSequence);
2627
2711
  }
2628
2712
  }
2629
2713
  }
@@ -2670,54 +2754,32 @@ class OpenFolderPressingBehaviorHandler {
2670
2754
  }
2671
2755
 
2672
2756
  class TriggerCustomActionPressingBehaviorHandler {
2673
- constructor(command, designerContext) {
2757
+ constructor(command, customActionController) {
2674
2758
  this.command = command;
2675
- this.designerContext = designerContext;
2759
+ this.customActionController = customActionController;
2676
2760
  }
2677
2761
  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);
2762
+ this.customActionController.trigger(this.command.action, this.command.step, this.command.sequence);
2700
2763
  }
2701
2764
  }
2702
2765
 
2703
2766
  class ClickBehaviorResolver {
2704
- constructor(designerContext, state) {
2705
- this.designerContext = designerContext;
2706
- this.state = state;
2767
+ constructor(context) {
2768
+ this.context = context;
2707
2769
  }
2708
2770
  resolve(commandOrNull, element, isMiddleButton) {
2709
2771
  if (!commandOrNull) {
2710
- return MoveViewportBehavior.create(this.state, !isMiddleButton);
2772
+ return MoveViewportBehavior.create(!isMiddleButton, this.context);
2711
2773
  }
2712
2774
  switch (commandOrNull.type) {
2713
2775
  case ClickCommandType.selectStep:
2714
- return SelectStepBehavior.create(commandOrNull.component, isMiddleButton, this.designerContext);
2776
+ return SelectStepBehavior.create(commandOrNull.component, isMiddleButton, this.context);
2715
2777
  case ClickCommandType.rerenderStep:
2716
- return PressingBehavior.create(element, new RerenderStepPressingBehaviorHandler(this.designerContext));
2778
+ return PressingBehavior.create(element, new RerenderStepPressingBehaviorHandler(this.context));
2717
2779
  case ClickCommandType.openFolder:
2718
- return PressingBehavior.create(element, new OpenFolderPressingBehaviorHandler(commandOrNull, this.designerContext));
2780
+ return PressingBehavior.create(element, new OpenFolderPressingBehaviorHandler(commandOrNull, this.context));
2719
2781
  case ClickCommandType.triggerCustomAction:
2720
- return PressingBehavior.create(element, new TriggerCustomActionPressingBehaviorHandler(commandOrNull, this.designerContext));
2782
+ return PressingBehavior.create(element, new TriggerCustomActionPressingBehaviorHandler(commandOrNull, this.context.customActionController));
2721
2783
  default:
2722
2784
  throw new Error('Not supported behavior type');
2723
2785
  }
@@ -2744,12 +2806,12 @@ class ContextMenu {
2744
2806
  for (let index = 0; index < items.length; index++) {
2745
2807
  const item = items[index];
2746
2808
  const element = document.createElement('div');
2747
- if (typeof item === 'string') {
2748
- element.className = 'sqd-context-menu-group';
2749
- element.innerText = item;
2809
+ if (item.callback) {
2810
+ element.className = 'sqd-context-menu-item';
2811
+ element.innerText = item.label;
2750
2812
  }
2751
2813
  else {
2752
- element.className = 'sqd-context-menu-item';
2814
+ element.className = 'sqd-context-menu-group';
2753
2815
  element.innerText = item.label;
2754
2816
  }
2755
2817
  elements.push(element);
@@ -2790,7 +2852,7 @@ class ContextMenu {
2790
2852
  const index = this.findIndex(e.target);
2791
2853
  if (index !== null) {
2792
2854
  const item = this.items[index];
2793
- if (typeof item !== 'string') {
2855
+ if (item.callback) {
2794
2856
  item.callback();
2795
2857
  }
2796
2858
  }
@@ -2820,91 +2882,122 @@ class ContextMenu {
2820
2882
  }
2821
2883
  }
2822
2884
 
2885
+ class ContextMenuController {
2886
+ constructor(theme, configuration, itemsBuilder) {
2887
+ this.theme = theme;
2888
+ this.configuration = configuration;
2889
+ this.itemsBuilder = itemsBuilder;
2890
+ }
2891
+ tryOpen(position, commandOrNull) {
2892
+ if (this.configuration.contextMenu === false) {
2893
+ // Context menu is disabled.
2894
+ return;
2895
+ }
2896
+ if (this.current) {
2897
+ this.current.tryDestroy();
2898
+ }
2899
+ const items = this.itemsBuilder.build(commandOrNull);
2900
+ this.current = ContextMenu.create(position, this.theme, items);
2901
+ }
2902
+ destroy() {
2903
+ if (this.current) {
2904
+ this.current.tryDestroy();
2905
+ }
2906
+ }
2907
+ }
2908
+
2823
2909
  class ContextMenuItemsBuilder {
2824
- static build(commandOrNull, viewportApi, definitionModifier, state) {
2910
+ constructor(viewportApi, stateModifier, state, customMenuItemsProvider) {
2911
+ this.viewportApi = viewportApi;
2912
+ this.stateModifier = stateModifier;
2913
+ this.state = state;
2914
+ this.customMenuItemsProvider = customMenuItemsProvider;
2915
+ }
2916
+ build(commandOrNull) {
2825
2917
  const items = [];
2826
2918
  if (commandOrNull && commandOrNull.type === ClickCommandType.selectStep) {
2827
2919
  const ssc = commandOrNull;
2828
2920
  const step = ssc.component.step;
2829
2921
  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
- });
2922
+ items.push({
2923
+ label: step.name,
2924
+ order: 0
2925
+ });
2926
+ this.tryAppendCustomItems(items, step, parentSequence);
2927
+ if (this.stateModifier.isSelectable(step, parentSequence)) {
2928
+ if (this.state.selectedStepId === step.id) {
2929
+ items.push({
2930
+ label: `Unselect`,
2931
+ order: 10,
2932
+ callback: () => {
2933
+ this.state.setSelectedStepId(null);
2934
+ }
2935
+ });
2936
+ }
2937
+ else {
2938
+ items.push({
2939
+ label: 'Select',
2940
+ order: 20,
2941
+ callback: () => {
2942
+ this.stateModifier.trySelectStepById(step.id);
2943
+ }
2944
+ });
2945
+ }
2846
2946
  }
2847
- if (!state.isReadonly) {
2848
- if (definitionModifier.isDeletable(step.id)) {
2947
+ if (!this.state.isReadonly) {
2948
+ if (this.stateModifier.isDeletable(step.id)) {
2849
2949
  items.push({
2850
2950
  label: 'Delete',
2951
+ order: 30,
2851
2952
  callback: () => {
2852
- definitionModifier.tryDelete(step.id);
2953
+ this.stateModifier.tryDelete(step.id);
2853
2954
  }
2854
2955
  });
2855
2956
  }
2856
- if (definitionModifier.isDuplicable(step, parentSequence)) {
2957
+ if (this.stateModifier.isDuplicable(step, parentSequence)) {
2857
2958
  items.push({
2858
2959
  label: 'Duplicate',
2960
+ order: 40,
2859
2961
  callback: () => {
2860
- definitionModifier.tryDuplicate(step, parentSequence);
2962
+ this.stateModifier.tryDuplicate(step, parentSequence);
2861
2963
  }
2862
2964
  });
2863
2965
  }
2864
2966
  }
2865
2967
  }
2968
+ else {
2969
+ this.tryAppendCustomItems(items, null, this.state.definition.sequence);
2970
+ }
2866
2971
  items.push({
2867
2972
  label: 'Reset view',
2973
+ order: 50,
2868
2974
  callback: () => {
2869
- viewportApi.resetViewport();
2975
+ this.viewportApi.resetViewport();
2870
2976
  }
2871
2977
  });
2978
+ items.sort((a, b) => a.order - b.order);
2872
2979
  return items;
2873
2980
  }
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();
2981
+ tryAppendCustomItems(items, step, parentSequence) {
2982
+ if (this.customMenuItemsProvider) {
2983
+ const customItems = this.customMenuItemsProvider.getItems(step, parentSequence);
2984
+ for (const customItem of customItems) {
2985
+ items.push(customItem);
2986
+ }
2898
2987
  }
2899
2988
  }
2900
2989
  }
2901
2990
 
2902
2991
  class Workspace {
2903
2992
  static create(parent, designerContext, api) {
2993
+ var _a;
2904
2994
  const view = WorkspaceView.create(parent, designerContext.componentContext);
2905
- const clickBehaviorResolver = new ClickBehaviorResolver(designerContext, designerContext.state);
2995
+ const clickBehaviorResolver = new ClickBehaviorResolver(designerContext);
2906
2996
  const wheelController = designerContext.services.wheelController.create(api.workspace);
2907
- const contextMenuController = new ContextMenuController(designerContext.theme, api.viewport, designerContext.definitionModifier, designerContext.state, designerContext.configuration);
2997
+ const contextMenuItemsBuilder = new ContextMenuItemsBuilder(api.viewport, designerContext.stateModifier, designerContext.state, ((_a = designerContext.services.contextMenu) === null || _a === void 0 ? void 0 : _a.createItemsProvider)
2998
+ ? designerContext.services.contextMenu.createItemsProvider(designerContext.customActionController)
2999
+ : undefined);
3000
+ const contextMenuController = new ContextMenuController(designerContext.theme, designerContext.configuration, contextMenuItemsBuilder);
2908
3001
  const workspace = new Workspace(view, designerContext.definitionWalker, designerContext.state, designerContext.behaviorController, wheelController, contextMenuController, clickBehaviorResolver, api.viewport, designerContext.services);
2909
3002
  setTimeout(() => {
2910
3003
  workspace.updateRootComponent();
@@ -3392,7 +3485,7 @@ class SmartEditorView {
3392
3485
  if (configuration.globalEditorProvider) {
3393
3486
  throw new Error('globalEditorProvider is renamed to rootEditorProvider');
3394
3487
  }
3395
- const editor = Editor.create(root, api, 'sqd-editor sqd-step-editor', configuration.stepEditorProvider, 'sqd-editor sqd-root-editor', configuration.rootEditorProvider);
3488
+ const editor = Editor.create(root, api, 'sqd-editor sqd-step-editor', configuration.stepEditorProvider, 'sqd-editor sqd-root-editor', configuration.rootEditorProvider, null);
3396
3489
  return new SmartEditorView(root, toggle, editor);
3397
3490
  }
3398
3491
  constructor(root, toggle, editor) {
@@ -4055,7 +4148,7 @@ class ServicesResolver {
4055
4148
  static resolve(extensions, configuration) {
4056
4149
  const services = {};
4057
4150
  merge(services, extensions || []);
4058
- setDefault(services, configuration);
4151
+ setDefaults(services, configuration);
4059
4152
  return services;
4060
4153
  }
4061
4154
  }
@@ -4097,12 +4190,15 @@ function merge(services, extensions) {
4097
4190
  if (ext.sequenceComponent) {
4098
4191
  services.sequenceComponent = ext.sequenceComponent;
4099
4192
  }
4193
+ if (ext.contextMenu) {
4194
+ services.contextMenu = ext.contextMenu;
4195
+ }
4100
4196
  if (ext.daemons) {
4101
4197
  services.daemons = (services.daemons || []).concat(ext.daemons);
4102
4198
  }
4103
4199
  }
4104
4200
  }
4105
- function setDefault(services, configuration) {
4201
+ function setDefaults(services, configuration) {
4106
4202
  if (!services.steps) {
4107
4203
  services.steps = [];
4108
4204
  }
@@ -4210,7 +4306,7 @@ class Designer {
4210
4306
  const designerContext = DesignerContext.create(placeholder, startDefinition, config, services);
4211
4307
  const designerApi = DesignerApi.create(designerContext);
4212
4308
  const view = DesignerView.create(placeholder, designerContext, designerApi);
4213
- const designer = new Designer(view, designerContext.state, designerContext.definitionWalker, designerContext.historyController, designerApi);
4309
+ const designer = new Designer(view, designerContext.state, designerContext.stateModifier, designerContext.definitionWalker, designerContext.historyController, designerApi);
4214
4310
  view.workspace.onRendered.first().then(designer.onReady.forward);
4215
4311
  race(0, designerContext.state.onDefinitionChanged, designerContext.state.onSelectedStepIdChanged).subscribe(([definition, selectedStepId]) => {
4216
4312
  if (definition !== undefined) {
@@ -4225,9 +4321,10 @@ class Designer {
4225
4321
  designerContext.state.onIsEditorCollapsedChanged.subscribe(designer.onIsEditorCollapsedChanged.forward);
4226
4322
  return designer;
4227
4323
  }
4228
- constructor(view, state, walker, historyController, api) {
4324
+ constructor(view, state, stateModifier, walker, historyController, api) {
4229
4325
  this.view = view;
4230
4326
  this.state = state;
4327
+ this.stateModifier = stateModifier;
4231
4328
  this.walker = walker;
4232
4329
  this.historyController = historyController;
4233
4330
  this.api = api;
@@ -4290,7 +4387,7 @@ class Designer {
4290
4387
  * @description Selects a step by the id.
4291
4388
  */
4292
4389
  selectStepById(stepId) {
4293
- this.state.setSelectedStepId(stepId);
4390
+ this.stateModifier.trySelectStepById(stepId);
4294
4391
  }
4295
4392
  /**
4296
4393
  * @returns the current viewport.
@@ -4317,12 +4414,6 @@ class Designer {
4317
4414
  moveViewportToStep(stepId) {
4318
4415
  this.api.viewport.moveViewportToStep(stepId);
4319
4416
  }
4320
- /**
4321
- * @deprecated Use `moveViewportToStep` instead.
4322
- */
4323
- moveViewPortToStep(stepId) {
4324
- this.moveViewportToStep(stepId);
4325
- }
4326
4417
  /**
4327
4418
  * @description Rerender the root component and all its children.
4328
4419
  */
@@ -4432,11 +4523,6 @@ class StepsDesignerExtension {
4432
4523
  constructor(steps) {
4433
4524
  this.steps = steps;
4434
4525
  }
4435
- }
4436
- /**
4437
- * @deprecated Use `StepsDesignerExtension` instead.
4438
- */
4439
- class StepsExtension extends StepsDesignerExtension {
4440
4526
  }
4441
4527
 
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 };
4528
+ 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 };