sequential-workflow-designer 0.38.1 → 0.39.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/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  [![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fb4rtaz%2Fsequential-workflow-designer%2Fbadge%3Fref%3Dmain&style=flat-square)](https://actions-badge.atrox.dev/b4rtaz/sequential-workflow-designer/goto?ref=main) [![License: MIT](https://img.shields.io/badge/license-MIT-green?style=flat-square)](/LICENSE) [![View this project on NPM](https://img.shields.io/npm/v/sequential-workflow-designer.svg?style=flat-square)](https://npmjs.org/package/sequential-workflow-designer)
6
6
 
7
- Sequential workflow designer with no external dependencies for web applications. It is written in pure TypeScript and uses SVG for rendering. This designer is not associated with any workflow engine, it is fully generic. You can use it to create any kind of application, from graphical programming languages to workflow builders.
7
+ A sequential workflow designer with no external dependencies for web applications. It is written in pure TypeScript and uses SVG for rendering. This designer is not associated with any workflow engine; it is fully generic. You can use it to create any kind of application, from graphical programming languages to workflow builders.
8
8
 
9
9
  Features:
10
10
 
@@ -70,11 +70,11 @@ Pro:
70
70
 
71
71
  ## 🚀 Installation
72
72
 
73
- To use the designer you should add JS/TS files and CSS files to your project.
73
+ To use the designer, add the JS/TS and CSS files to your project.
74
74
 
75
75
  ### NPM
76
76
 
77
- Install this package by [NPM](https://www.npmjs.com/) command:
77
+ Install this package with the [NPM](https://www.npmjs.com/) command:
78
78
 
79
79
  `npm i sequential-workflow-designer`
80
80
 
@@ -93,7 +93,7 @@ import 'sequential-workflow-designer/css/designer-soft.css';
93
93
  import 'sequential-workflow-designer/css/designer-dark.css';
94
94
  ```
95
95
 
96
- To create the designer write the below code:
96
+ To create the designer, write the code below:
97
97
 
98
98
  ```ts
99
99
  // ...
@@ -102,19 +102,19 @@ Designer.create(placeholder, definition, configuration);
102
102
 
103
103
  ### CDN
104
104
 
105
- Add the below code to your head section in HTML document.
105
+ Add the code below to the head section of your HTML document.
106
106
 
107
107
  ```html
108
108
  <head>
109
109
  ...
110
- <link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.38.1/css/designer.css" rel="stylesheet" />
111
- <link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.38.1/css/designer-light.css" rel="stylesheet" />
112
- <link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.38.1/css/designer-dark.css" rel="stylesheet" />
113
- <script src="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.38.1/dist/index.umd.js"></script>
110
+ <link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.39.0/css/designer.css" rel="stylesheet" />
111
+ <link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.39.0/css/designer-light.css" rel="stylesheet" />
112
+ <link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.39.0/css/designer-dark.css" rel="stylesheet" />
113
+ <script src="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.39.0/dist/index.umd.js"></script>
114
114
  </head>
115
115
  ```
116
116
 
117
- Call the designer by:
117
+ Create the designer with:
118
118
 
119
119
  ```js
120
120
  sequentialWorkflowDesigner.Designer.create(placeholder, definition, configuration);
@@ -122,7 +122,7 @@ sequentialWorkflowDesigner.Designer.create(placeholder, definition, configuratio
122
122
 
123
123
  ## 🎬 Usage
124
124
 
125
- Check [examples](/examples) directory.
125
+ Check the [examples](/examples) directory.
126
126
 
127
127
  ```ts
128
128
  import { Designer } from 'sequential-workflow-designer';
@@ -188,13 +188,13 @@ const configuration = {
188
188
  {
189
189
  name: 'Files',
190
190
  steps: [
191
- // steps for the toolbox's group
191
+ // steps for the toolbox group
192
192
  ],
193
193
  },
194
194
  {
195
195
  name: 'Notification',
196
196
  steps: [
197
- // steps for the toolbox's group
197
+ // steps for the toolbox group
198
198
  ],
199
199
  },
200
200
  ],
package/dist/index.umd.js CHANGED
@@ -203,15 +203,17 @@
203
203
  }
204
204
 
205
205
  class ControlBarApi {
206
- static create(state, historyController, stateModifier) {
207
- const api = new ControlBarApi(state, historyController, stateModifier);
206
+ static create(state, historyController, customActionController, stateModifier, configuration) {
207
+ const api = new ControlBarApi(state, historyController, customActionController, stateModifier, configuration);
208
208
  race(0, state.onIsReadonlyChanged, state.onSelectedStepIdChanged, state.onIsDragDisabledChanged, api.isUndoRedoSupported() ? state.onDefinitionChanged : undefined).subscribe(api.onStateChanged.emit);
209
209
  return api;
210
210
  }
211
- constructor(state, historyController, stateModifier) {
211
+ constructor(state, historyController, customActionController, stateModifier, configuration) {
212
212
  this.state = state;
213
213
  this.historyController = historyController;
214
+ this.customActionController = customActionController;
214
215
  this.stateModifier = stateModifier;
216
+ this.configuration = configuration;
215
217
  this.onStateChanged = new SimpleEvent();
216
218
  }
217
219
  isDragDisabled() {
@@ -258,6 +260,16 @@
258
260
  !this.state.isDragging &&
259
261
  this.stateModifier.isDeletableById(this.state.selectedStepId));
260
262
  }
263
+ getButtons() {
264
+ return typeof this.configuration === 'boolean' ? null : this.configuration.buttons || null;
265
+ }
266
+ triggerButtonClick(id) {
267
+ const action = {
268
+ type: 'controlBarButtonClicked',
269
+ id
270
+ };
271
+ this.customActionController.trigger(action, null, this.state.definition.sequence);
272
+ }
261
273
  }
262
274
 
263
275
  exports.KeyboardAction = void 0;
@@ -1011,7 +1023,7 @@
1011
1023
  const workspace = new WorkspaceApi(context.state, context.definitionWalker, context.workspaceController);
1012
1024
  const viewportController = context.services.viewportController.create(workspace);
1013
1025
  const toolboxDataProvider = new ToolboxDataProvider(context.i18n, context.componentContext.iconProvider, context.configuration.toolbox);
1014
- return new DesignerApi(context.configuration.shadowRoot, ControlBarApi.create(context.state, context.historyController, context.stateModifier), new ToolboxApi(context.state, context, context.behaviorController, toolboxDataProvider, context.uidGenerator), new EditorApi(context.state, context.definitionWalker, context.stateModifier), workspace, new ViewportApi(context.state, context.workspaceController, viewportController), new PathBarApi(context.state, context.definitionWalker), context.definitionWalker, context.i18n);
1026
+ return new DesignerApi(context.configuration.shadowRoot, ControlBarApi.create(context.state, context.historyController, context.customActionController, context.stateModifier, context.configuration.controlBar), new ToolboxApi(context.state, context, context.behaviorController, toolboxDataProvider, context.uidGenerator), new EditorApi(context.state, context.definitionWalker, context.stateModifier), workspace, new ViewportApi(context.state, context.workspaceController, viewportController), new PathBarApi(context.state, context.definitionWalker), context.definitionWalker, context.i18n);
1015
1027
  }
1016
1028
  constructor(shadowRoot, controlBar, toolbox, editor, workspace, viewport, pathBar, definitionWalker, i18n) {
1017
1029
  this.shadowRoot = shadowRoot;
@@ -3973,6 +3985,7 @@
3973
3985
  this.itemsBuilder = itemsBuilder;
3974
3986
  }
3975
3987
  tryOpen(position, commandOrNull) {
3988
+ var _a, _b;
3976
3989
  if (this.configuration.contextMenu === false) {
3977
3990
  // Context menu is disabled.
3978
3991
  return;
@@ -3980,8 +3993,11 @@
3980
3993
  if (this.current) {
3981
3994
  this.current.tryDestroy();
3982
3995
  }
3983
- const items = this.itemsBuilder.build(commandOrNull);
3984
- this.current = ContextMenu.create(this.configuration.shadowRoot, position, this.theme, items);
3996
+ const isResetViewDisabled = this.configuration.contextMenu === true ? false : (_b = (_a = this.configuration.contextMenu) === null || _a === void 0 ? void 0 : _a.isResetViewDisabled) !== null && _b !== void 0 ? _b : false;
3997
+ const items = this.itemsBuilder.build(commandOrNull, isResetViewDisabled);
3998
+ if (items.length > 0) {
3999
+ this.current = ContextMenu.create(this.configuration.shadowRoot, position, this.theme, items);
4000
+ }
3985
4001
  }
3986
4002
  destroy() {
3987
4003
  if (this.current) {
@@ -3999,7 +4015,7 @@
3999
4015
  this.state = state;
4000
4016
  this.customMenuItemsProvider = customMenuItemsProvider;
4001
4017
  }
4002
- build(commandOrNull) {
4018
+ build(commandOrNull, isResetViewDisabled) {
4003
4019
  const items = [];
4004
4020
  if (commandOrNull && commandOrNull.type === exports.ClickCommandType.selectStep) {
4005
4021
  const ssc = commandOrNull;
@@ -4056,13 +4072,15 @@
4056
4072
  const rootSequence = this.workspaceApi.getRootSequence();
4057
4073
  this.tryAppendCustomItems(items, null, rootSequence.sequence);
4058
4074
  }
4059
- items.push({
4060
- label: this.i18n('contextMenu.resetView', 'Reset view'),
4061
- order: 50,
4062
- callback: () => {
4063
- this.viewportApi.resetViewport();
4064
- }
4065
- });
4075
+ if (!isResetViewDisabled) {
4076
+ items.push({
4077
+ label: this.i18n('contextMenu.resetView', 'Reset view'),
4078
+ order: 50,
4079
+ callback: () => {
4080
+ this.viewportApi.resetViewport();
4081
+ }
4082
+ });
4083
+ }
4066
4084
  items.sort((a, b) => a.order - b.order);
4067
4085
  return items;
4068
4086
  }
@@ -4421,7 +4439,7 @@
4421
4439
  }
4422
4440
 
4423
4441
  class ControlBarView {
4424
- static create(parent, isUndoRedoSupported, i18n) {
4442
+ static create(parent, isUndoRedoSupported, buttons, i18n) {
4425
4443
  const root = Dom.element('div', {
4426
4444
  class: 'sqd-control-bar'
4427
4445
  });
@@ -4446,10 +4464,19 @@
4446
4464
  deleteButton.classList.add('sqd-delete');
4447
4465
  deleteButton.classList.add('sqd-hidden');
4448
4466
  root.appendChild(deleteButton);
4467
+ const customButtons = [];
4468
+ if (buttons) {
4469
+ for (const customButton of buttons) {
4470
+ const button = createButton(customButton.iconD, customButton.label);
4471
+ button.setAttribute('data-id', customButton.id);
4472
+ root.appendChild(button);
4473
+ customButtons.push(button);
4474
+ }
4475
+ }
4449
4476
  parent.appendChild(root);
4450
- return new ControlBarView(resetButton, zoomInButton, zoomOutButton, undoButton, redoButton, disableDragButton, deleteButton);
4477
+ return new ControlBarView(resetButton, zoomInButton, zoomOutButton, undoButton, redoButton, disableDragButton, deleteButton, customButtons);
4451
4478
  }
4452
- constructor(resetButton, zoomInButton, zoomOutButton, undoButton, redoButton, disableDragButton, deleteButton) {
4479
+ constructor(resetButton, zoomInButton, zoomOutButton, undoButton, redoButton, disableDragButton, deleteButton, customButtons) {
4453
4480
  this.resetButton = resetButton;
4454
4481
  this.zoomInButton = zoomInButton;
4455
4482
  this.zoomOutButton = zoomOutButton;
@@ -4457,6 +4484,7 @@
4457
4484
  this.redoButton = redoButton;
4458
4485
  this.disableDragButton = disableDragButton;
4459
4486
  this.deleteButton = deleteButton;
4487
+ this.customButtons = customButtons;
4460
4488
  }
4461
4489
  bindResetButtonClick(handler) {
4462
4490
  bindClick(this.resetButton, handler);
@@ -4485,6 +4513,14 @@
4485
4513
  bindDeleteButtonClick(handler) {
4486
4514
  bindClick(this.deleteButton, handler);
4487
4515
  }
4516
+ bindCustomButtonClick(handler) {
4517
+ for (const customButton of this.customButtons) {
4518
+ const id = customButton.getAttribute('data-id');
4519
+ if (id) {
4520
+ bindClick(customButton, () => handler(id));
4521
+ }
4522
+ }
4523
+ }
4488
4524
  setIsDeleteButtonHidden(isHidden) {
4489
4525
  Dom.toggleClass(this.deleteButton, isHidden, 'sqd-hidden');
4490
4526
  }
@@ -4523,17 +4559,21 @@
4523
4559
  class ControlBar {
4524
4560
  static create(parent, api) {
4525
4561
  const isUndoRedoSupported = api.controlBar.isUndoRedoSupported();
4526
- const view = ControlBarView.create(parent, isUndoRedoSupported, api.i18n);
4562
+ const customButtons = api.controlBar.getButtons();
4563
+ const view = ControlBarView.create(parent, isUndoRedoSupported, customButtons, api.i18n);
4527
4564
  const bar = new ControlBar(view, api.controlBar, api.viewport, isUndoRedoSupported);
4528
- view.bindResetButtonClick(() => bar.onResetButtonClicked());
4529
- view.bindZoomInButtonClick(() => bar.onZoomInButtonClicked());
4530
- view.bindZoomOutButtonClick(() => bar.onZoomOutButtonClicked());
4531
- view.bindDisableDragButtonClick(() => bar.onMoveButtonClicked());
4532
- view.bindDeleteButtonClick(() => bar.onDeleteButtonClicked());
4533
- api.controlBar.onStateChanged.subscribe(() => bar.refreshButtons());
4565
+ view.bindResetButtonClick(bar.onResetButtonClicked);
4566
+ view.bindZoomInButtonClick(bar.onZoomInButtonClicked);
4567
+ view.bindZoomOutButtonClick(bar.onZoomOutButtonClicked);
4568
+ view.bindDisableDragButtonClick(bar.onMoveButtonClicked);
4569
+ view.bindDeleteButtonClick(bar.onDeleteButtonClicked);
4570
+ api.controlBar.onStateChanged.subscribe(bar.refreshButtons);
4534
4571
  if (isUndoRedoSupported) {
4535
- view.bindUndoButtonClick(() => bar.onUndoButtonClicked());
4536
- view.bindRedoButtonClick(() => bar.onRedoButtonClicked());
4572
+ view.bindUndoButtonClick(bar.onUndoButtonClicked);
4573
+ view.bindRedoButtonClick(bar.onRedoButtonClicked);
4574
+ }
4575
+ if (customButtons) {
4576
+ view.bindCustomButtonClick(bar.onCustomButtonClicked);
4537
4577
  }
4538
4578
  bar.refreshButtons();
4539
4579
  return bar;
@@ -4543,6 +4583,37 @@
4543
4583
  this.controlBarApi = controlBarApi;
4544
4584
  this.viewportApi = viewportApi;
4545
4585
  this.isUndoRedoSupported = isUndoRedoSupported;
4586
+ this.onResetButtonClicked = () => {
4587
+ this.viewportApi.resetViewport();
4588
+ };
4589
+ this.onZoomInButtonClicked = () => {
4590
+ this.viewportApi.zoom(true);
4591
+ };
4592
+ this.onZoomOutButtonClicked = () => {
4593
+ this.viewportApi.zoom(false);
4594
+ };
4595
+ this.onMoveButtonClicked = () => {
4596
+ this.controlBarApi.toggleIsDragDisabled();
4597
+ };
4598
+ this.onUndoButtonClicked = () => {
4599
+ this.controlBarApi.tryUndo();
4600
+ };
4601
+ this.onRedoButtonClicked = () => {
4602
+ this.controlBarApi.tryRedo();
4603
+ };
4604
+ this.onDeleteButtonClicked = () => {
4605
+ this.controlBarApi.tryDelete();
4606
+ };
4607
+ this.refreshButtons = () => {
4608
+ this.refreshDeleteButtonVisibility();
4609
+ this.refreshIsDragDisabled();
4610
+ if (this.isUndoRedoSupported) {
4611
+ this.refreshUndoRedoAvailability();
4612
+ }
4613
+ };
4614
+ this.onCustomButtonClicked = (id) => {
4615
+ this.controlBarApi.triggerButtonClick(id);
4616
+ };
4546
4617
  }
4547
4618
  updateLayout() {
4548
4619
  //
@@ -4550,34 +4621,6 @@
4550
4621
  destroy() {
4551
4622
  //
4552
4623
  }
4553
- onResetButtonClicked() {
4554
- this.viewportApi.resetViewport();
4555
- }
4556
- onZoomInButtonClicked() {
4557
- this.viewportApi.zoom(true);
4558
- }
4559
- onZoomOutButtonClicked() {
4560
- this.viewportApi.zoom(false);
4561
- }
4562
- onMoveButtonClicked() {
4563
- this.controlBarApi.toggleIsDragDisabled();
4564
- }
4565
- onUndoButtonClicked() {
4566
- this.controlBarApi.tryUndo();
4567
- }
4568
- onRedoButtonClicked() {
4569
- this.controlBarApi.tryRedo();
4570
- }
4571
- onDeleteButtonClicked() {
4572
- this.controlBarApi.tryDelete();
4573
- }
4574
- refreshButtons() {
4575
- this.refreshDeleteButtonVisibility();
4576
- this.refreshIsDragDisabled();
4577
- if (this.isUndoRedoSupported) {
4578
- this.refreshUndoRedoAvailability();
4579
- }
4580
- }
4581
4624
  //
4582
4625
  refreshIsDragDisabled() {
4583
4626
  const isDragDisabled = this.controlBarApi.isDragDisabled();
@@ -5252,8 +5295,8 @@
5252
5295
  /**
5253
5296
  * Creates a designer.
5254
5297
  * @param placeholder Placeholder where the designer will be attached.
5255
- * @param startDefinition Start definition of a flow.
5256
- * @param configuration Designer's configuration.
5298
+ * @param startDefinition Initial definition of the workflow.
5299
+ * @param configuration The designer configuration.
5257
5300
  * @returns An instance of the designer.
5258
5301
  */
5259
5302
  static create(placeholder, startDefinition, configuration) {
@@ -5340,37 +5383,37 @@
5340
5383
  this.onPreferencesChanged = new SimpleEvent();
5341
5384
  }
5342
5385
  /**
5343
- * @returns the current definition of the workflow.
5386
+ * @returns The current definition of the workflow.
5344
5387
  */
5345
5388
  getDefinition() {
5346
5389
  return this.state.definition;
5347
5390
  }
5348
5391
  /**
5349
- * @returns the validation result of the current definition.
5392
+ * @returns The validation result of the current definition.
5350
5393
  */
5351
5394
  isValid() {
5352
5395
  return this.view.workspace.isValid;
5353
5396
  }
5354
5397
  /**
5355
- * @returns the readonly flag.
5398
+ * @returns The read-only flag.
5356
5399
  */
5357
5400
  isReadonly() {
5358
5401
  return this.state.isReadonly;
5359
5402
  }
5360
5403
  /**
5361
- * @description Changes the readonly flag.
5404
+ * @description Changes the read-only flag.
5362
5405
  */
5363
5406
  setIsReadonly(isReadonly) {
5364
5407
  this.state.setIsReadonly(isReadonly);
5365
5408
  }
5366
5409
  /**
5367
- * @returns current selected step id or `null` if nothing is selected.
5410
+ * @returns The currently selected step id, or `null` if nothing is selected.
5368
5411
  */
5369
5412
  getSelectedStepId() {
5370
5413
  return this.state.selectedStepId;
5371
5414
  }
5372
5415
  /**
5373
- * @description Selects a step by the id.
5416
+ * @description Selects a step by id.
5374
5417
  */
5375
5418
  selectStepById(stepId) {
5376
5419
  this.state.setSelectedStepId(stepId);
@@ -5382,7 +5425,7 @@
5382
5425
  this.state.setSelectedStepId(null);
5383
5426
  }
5384
5427
  /**
5385
- * @returns the current viewport.
5428
+ * @returns The current viewport.
5386
5429
  */
5387
5430
  getViewport() {
5388
5431
  return this.state.viewport;
@@ -5401,13 +5444,13 @@
5401
5444
  this.api.viewport.resetViewport();
5402
5445
  }
5403
5446
  /**
5404
- * @description Moves the viewport to the step with the animation.
5447
+ * @description Moves the viewport to the step with animation.
5405
5448
  */
5406
5449
  moveViewportToStep(stepId) {
5407
5450
  this.api.viewport.moveViewportToStep(stepId);
5408
5451
  }
5409
5452
  /**
5410
- * @description Rerender the root component and all its children.
5453
+ * @description Rerenders the root component and all its children.
5411
5454
  */
5412
5455
  updateRootComponent() {
5413
5456
  this.api.workspace.updateRootComponent();
@@ -5426,37 +5469,37 @@
5426
5469
  this.api.workspace.updateBadges();
5427
5470
  }
5428
5471
  /**
5429
- * @returns a flag that indicates whether the toolbox is collapsed.
5472
+ * @returns A flag that indicates whether the toolbox is collapsed.
5430
5473
  */
5431
5474
  isToolboxCollapsed() {
5432
5475
  return this.state.isToolboxCollapsed;
5433
5476
  }
5434
5477
  /**
5435
- * @description Sets a flag that indicates whether the toolbox is collapsed.
5478
+ * @description Sets the flag that indicates whether the toolbox is collapsed.
5436
5479
  */
5437
5480
  setIsToolboxCollapsed(isCollapsed) {
5438
5481
  this.state.setIsToolboxCollapsed(isCollapsed);
5439
5482
  }
5440
5483
  /**
5441
- * @returns a flag that indicates whether the editor is collapsed.
5484
+ * @returns A flag that indicates whether the editor is collapsed.
5442
5485
  */
5443
5486
  isEditorCollapsed() {
5444
5487
  return this.state.isEditorCollapsed;
5445
5488
  }
5446
5489
  /**
5447
- * @returns a flag that indicates whether the step is being dragged.
5490
+ * @returns A flag that indicates whether a step is being dragged.
5448
5491
  */
5449
5492
  isDragging() {
5450
5493
  return this.state.isDragging;
5451
5494
  }
5452
5495
  /**
5453
- * @description Sets a flag that indicates whether the editor is collapsed.
5496
+ * @description Sets the flag that indicates whether the editor is collapsed.
5454
5497
  */
5455
5498
  setIsEditorCollapsed(isCollapsed) {
5456
5499
  this.state.setIsEditorCollapsed(isCollapsed);
5457
5500
  }
5458
5501
  /**
5459
- * @description Dump the undo stack.
5502
+ * @description Dumps the undo stack.
5460
5503
  */
5461
5504
  dumpUndoStack() {
5462
5505
  return this.getHistoryController().dump();
@@ -5476,13 +5519,13 @@
5476
5519
  }
5477
5520
  /**
5478
5521
  * @param needle A step, a sequence or a step id.
5479
- * @returns parent steps and branch names.
5522
+ * @returns Parent steps and branch names.
5480
5523
  */
5481
5524
  getStepParents(needle) {
5482
5525
  return this.walker.getParents(this.state.definition, needle);
5483
5526
  }
5484
5527
  /**
5485
- * @returns the definition walker.
5528
+ * @returns The definition walker.
5486
5529
  */
5487
5530
  getWalker() {
5488
5531
  return this.walker;