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