sequential-workflow-designer 0.24.7 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/esm/index.js CHANGED
@@ -669,16 +669,92 @@ class ToolboxDataProvider {
669
669
  }
670
670
  }
671
671
 
672
+ function animate(interval, handler) {
673
+ const iv = setInterval(tick, 15);
674
+ const startTime = Date.now();
675
+ const anim = {
676
+ isAlive: true,
677
+ stop: () => {
678
+ anim.isAlive = false;
679
+ clearInterval(iv);
680
+ }
681
+ };
682
+ function tick() {
683
+ const progress = Math.min((Date.now() - startTime) / interval, 1);
684
+ handler(progress);
685
+ if (progress === 1) {
686
+ anim.stop();
687
+ }
688
+ }
689
+ return anim;
690
+ }
691
+
692
+ class ViewportAnimator {
693
+ constructor(api) {
694
+ this.api = api;
695
+ }
696
+ execute(target) {
697
+ if (this.animation && this.animation.isAlive) {
698
+ this.animation.stop();
699
+ }
700
+ const viewport = this.api.getViewport();
701
+ const startPosition = viewport.position;
702
+ const startScale = viewport.scale;
703
+ const deltaPosition = startPosition.subtract(target.position);
704
+ const deltaScale = startScale - target.scale;
705
+ this.animation = animate(150, progress => {
706
+ const newScale = startScale - deltaScale * progress;
707
+ this.api.setViewport({
708
+ position: startPosition.subtract(deltaPosition.multiplyByScalar(progress)),
709
+ scale: newScale
710
+ });
711
+ });
712
+ }
713
+ }
714
+
715
+ class ZoomByWheelCalculator {
716
+ static calculate(controller, current, canvasPosition, e) {
717
+ if (e.deltaY === 0) {
718
+ return null;
719
+ }
720
+ const nextScale = controller.getNextScale(current.scale, e.deltaY < 0);
721
+ let scale;
722
+ const absDeltaY = Math.abs(e.deltaY);
723
+ if (absDeltaY < controller.smoothDeltaYLimit) {
724
+ const fraction = absDeltaY / controller.smoothDeltaYLimit;
725
+ const step = nextScale.next - nextScale.current;
726
+ scale = current.scale + step * fraction;
727
+ }
728
+ else {
729
+ scale = nextScale.next;
730
+ }
731
+ const mousePoint = new Vector(e.pageX, e.pageY).subtract(canvasPosition);
732
+ // The real point is point on canvas with no scale.
733
+ const mouseRealPoint = mousePoint.divideByScalar(current.scale).subtract(current.position.divideByScalar(current.scale));
734
+ const position = mouseRealPoint.multiplyByScalar(-scale).add(mousePoint);
735
+ return { position, scale };
736
+ }
737
+ }
738
+
672
739
  class ViewportApi {
673
- constructor(workspaceController, viewportController) {
740
+ constructor(workspaceController, viewportController, api) {
674
741
  this.workspaceController = workspaceController;
675
742
  this.viewportController = viewportController;
743
+ this.api = api;
744
+ this.animator = new ViewportAnimator(this.api);
745
+ }
746
+ limitScale(scale) {
747
+ return this.viewportController.limitScale(scale);
676
748
  }
677
749
  resetViewport() {
678
- this.viewportController.setDefault();
750
+ const defaultViewport = this.viewportController.getDefault();
751
+ this.api.setViewport(defaultViewport);
679
752
  }
680
753
  zoom(direction) {
681
- this.viewportController.zoom(direction);
754
+ const viewport = this.viewportController.getZoomed(direction);
755
+ if (viewport) {
756
+ this.api.setViewport(viewport);
757
+ }
682
758
  }
683
759
  moveViewportToStep(stepId) {
684
760
  const component = this.workspaceController.getComponentByStepId(stepId);
@@ -686,7 +762,16 @@ class ViewportApi {
686
762
  const clientPosition = component.view.getClientPosition();
687
763
  const componentPosition = clientPosition.subtract(canvasPosition);
688
764
  const componentSize = new Vector(component.view.width, component.view.height);
689
- this.viewportController.focusOnComponent(componentPosition, componentSize);
765
+ const viewport = this.viewportController.getFocusedOnComponent(componentPosition, componentSize);
766
+ this.animator.execute(viewport);
767
+ }
768
+ handleWheelEvent(e) {
769
+ const viewport = this.api.getViewport();
770
+ const canvasPosition = this.api.getCanvasPosition();
771
+ const newViewport = ZoomByWheelCalculator.calculate(this.viewportController, viewport, canvasPosition, e);
772
+ if (newViewport) {
773
+ this.api.setViewport(newViewport);
774
+ }
690
775
  }
691
776
  }
692
777
 
@@ -725,7 +810,7 @@ class DesignerApi {
725
810
  static create(context) {
726
811
  const workspace = new WorkspaceApi(context.state, context.workspaceController);
727
812
  const viewportController = context.services.viewportController.create(workspace);
728
- const viewport = new ViewportApi(context.workspaceController, viewportController);
813
+ const viewport = new ViewportApi(context.workspaceController, viewportController, workspace);
729
814
  const toolboxDataProvider = new ToolboxDataProvider(context.componentContext.iconProvider, context.i18n, context.configuration.toolbox);
730
815
  return new DesignerApi(context.configuration.shadowRoot, 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, context.i18n);
731
816
  }
@@ -1170,7 +1255,7 @@ class ValidationErrorBadge {
1170
1255
  }
1171
1256
  }
1172
1257
 
1173
- const defaultConfiguration$6 = {
1258
+ const defaultConfiguration$7 = {
1174
1259
  view: {
1175
1260
  size: 22,
1176
1261
  iconSize: 12
@@ -1178,7 +1263,7 @@ const defaultConfiguration$6 = {
1178
1263
  };
1179
1264
  class ValidationErrorBadgeExtension {
1180
1265
  static create(configuration) {
1181
- return new ValidationErrorBadgeExtension(configuration !== null && configuration !== void 0 ? configuration : defaultConfiguration$6);
1266
+ return new ValidationErrorBadgeExtension(configuration !== null && configuration !== void 0 ? configuration : defaultConfiguration$7);
1182
1267
  }
1183
1268
  constructor(configuration) {
1184
1269
  this.configuration = configuration;
@@ -1495,13 +1580,13 @@ class StartStopRootComponentView {
1495
1580
  const x = view.joinX - cfg.size / 2;
1496
1581
  const endY = cfg.size + view.height;
1497
1582
  const iconSize = parentPlaceIndicator ? cfg.folderIconSize : cfg.defaultIconSize;
1498
- const startCircle = createCircle(parentPlaceIndicator ? cfg.folderIconD : cfg.startIconD, cfg.size, iconSize);
1583
+ const startCircle = createCircle('start', parentPlaceIndicator ? cfg.folderIconD : cfg.startIconD, cfg.size, iconSize);
1499
1584
  Dom.translate(startCircle, x, 0);
1500
1585
  g.appendChild(startCircle);
1501
1586
  Dom.translate(view.g, 0, cfg.size);
1502
- const endCircle = createCircle(parentPlaceIndicator ? cfg.folderIconD : cfg.stopIconD, cfg.size, iconSize);
1503
- Dom.translate(endCircle, x, endY);
1504
- g.appendChild(endCircle);
1587
+ const stopCircle = createCircle('stop', parentPlaceIndicator ? cfg.folderIconD : cfg.stopIconD, cfg.size, iconSize);
1588
+ Dom.translate(stopCircle, x, endY);
1589
+ g.appendChild(stopCircle);
1505
1590
  let startPlaceholder = null;
1506
1591
  let endPlaceholder = null;
1507
1592
  if (parentPlaceIndicator) {
@@ -1529,7 +1614,10 @@ class StartStopRootComponentView {
1529
1614
  (_a = this.g.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(this.g);
1530
1615
  }
1531
1616
  }
1532
- function createCircle(d, size, iconSize) {
1617
+ function createCircle(classSuffix, d, size, iconSize) {
1618
+ const g = Dom.svg('g', {
1619
+ class: 'sqd-root-start-stop-' + classSuffix
1620
+ });
1533
1621
  const r = size / 2;
1534
1622
  const circle = Dom.svg('circle', {
1535
1623
  class: 'sqd-root-start-stop-circle',
@@ -1537,7 +1625,6 @@ function createCircle(d, size, iconSize) {
1537
1625
  cy: r,
1538
1626
  r: r
1539
1627
  });
1540
- const g = Dom.svg('g');
1541
1628
  g.appendChild(circle);
1542
1629
  const offset = (size - iconSize) / 2;
1543
1630
  const icon = Icons.appendPath(g, 'sqd-root-start-stop-icon', d, iconSize);
@@ -1572,7 +1659,7 @@ class StartStopRootComponent {
1572
1659
  }
1573
1660
  }
1574
1661
 
1575
- const defaultConfiguration$5 = {
1662
+ const defaultConfiguration$6 = {
1576
1663
  view: {
1577
1664
  size: 30,
1578
1665
  defaultIconSize: 22,
@@ -1584,7 +1671,7 @@ const defaultConfiguration$5 = {
1584
1671
  };
1585
1672
  class StartStopRootComponentExtension {
1586
1673
  static create(configuration) {
1587
- return new StartStopRootComponentExtension(configuration !== null && configuration !== void 0 ? configuration : defaultConfiguration$5);
1674
+ return new StartStopRootComponentExtension(configuration !== null && configuration !== void 0 ? configuration : defaultConfiguration$6);
1588
1675
  }
1589
1676
  constructor(configuration) {
1590
1677
  this.configuration = configuration;
@@ -1818,15 +1905,15 @@ const createTaskStepComponentViewFactory = (isInterrupted, cfg) => (parentElemen
1818
1905
  };
1819
1906
 
1820
1907
  class CenteredViewportCalculator {
1821
- static center(margin, canvasSize, rootComponentSize) {
1908
+ static center(padding, canvasSize, rootComponentSize) {
1822
1909
  if (canvasSize.x === 0 || canvasSize.y === 0) {
1823
1910
  return {
1824
1911
  position: new Vector(0, 0),
1825
1912
  scale: 1
1826
1913
  };
1827
1914
  }
1828
- const canvasSafeWidth = Math.max(canvasSize.x - margin * 2, 0);
1829
- const canvasSafeHeight = Math.max(canvasSize.y - margin * 2, 0);
1915
+ const canvasSafeWidth = Math.max(canvasSize.x - padding * 2, 0);
1916
+ const canvasSafeHeight = Math.max(canvasSize.y - padding * 2, 0);
1830
1917
  const scale = Math.min(Math.min(canvasSafeWidth / rootComponentSize.x, canvasSafeHeight / rootComponentSize.y), 1);
1831
1918
  const width = rootComponentSize.x * scale;
1832
1919
  const height = rootComponentSize.y * scale;
@@ -1837,7 +1924,7 @@ class CenteredViewportCalculator {
1837
1924
  scale
1838
1925
  };
1839
1926
  }
1840
- static focusOnComponent(canvasSize, viewport, componentPosition, componentSize) {
1927
+ static getFocusedOnComponent(canvasSize, viewport, componentPosition, componentSize) {
1841
1928
  const realPosition = viewport.position.divideByScalar(viewport.scale).subtract(componentPosition.divideByScalar(viewport.scale));
1842
1929
  const componentOffset = componentSize.divideByScalar(2);
1843
1930
  const position = realPosition.add(canvasSize.divideByScalar(2)).subtract(componentOffset);
@@ -1845,6 +1932,24 @@ class CenteredViewportCalculator {
1845
1932
  }
1846
1933
  }
1847
1934
 
1935
+ class ClassicWheelController {
1936
+ static create(api) {
1937
+ return new ClassicWheelController(api);
1938
+ }
1939
+ constructor(api) {
1940
+ this.api = api;
1941
+ }
1942
+ onWheel(e) {
1943
+ this.api.handleWheelEvent(e);
1944
+ }
1945
+ }
1946
+
1947
+ class ClassicWheelControllerExtension {
1948
+ constructor() {
1949
+ this.create = ClassicWheelController.create;
1950
+ }
1951
+ }
1952
+
1848
1953
  class NextQuantifiedNumber {
1849
1954
  constructor(values) {
1850
1955
  this.values = values;
@@ -1871,142 +1976,68 @@ class NextQuantifiedNumber {
1871
1976
  next: this.values[index]
1872
1977
  };
1873
1978
  }
1874
- }
1875
-
1876
- const SCALES = [0.06, 0.08, 0.1, 0.12, 0.16, 0.2, 0.26, 0.32, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1];
1877
- const MAX_DELTA_Y$1 = 16;
1878
- const quantifiedScale = new NextQuantifiedNumber(SCALES);
1879
- class QuantifiedScaleViewportCalculator {
1880
- static zoom(current, direction) {
1881
- const nextScale = quantifiedScale.next(current.scale, direction);
1882
- return {
1883
- position: current.position,
1884
- scale: nextScale.next
1885
- };
1886
- }
1887
- static zoomByWheel(current, e, canvasPosition) {
1888
- if (e.deltaY === 0) {
1889
- return null;
1890
- }
1891
- const nextScale = quantifiedScale.next(current.scale, e.deltaY < 0);
1892
- let scale;
1893
- const absDeltaY = Math.abs(e.deltaY);
1894
- if (absDeltaY < MAX_DELTA_Y$1) {
1895
- const fraction = absDeltaY / MAX_DELTA_Y$1;
1896
- const step = nextScale.next - nextScale.current;
1897
- scale = current.scale + step * fraction;
1898
- }
1899
- else {
1900
- scale = nextScale.next;
1901
- }
1902
- const mousePoint = new Vector(e.pageX, e.pageY).subtract(canvasPosition);
1903
- // The real point is point on canvas with no scale.
1904
- const mouseRealPoint = mousePoint.divideByScalar(current.scale).subtract(current.position.divideByScalar(current.scale));
1905
- const position = mouseRealPoint.multiplyByScalar(-scale).add(mousePoint);
1906
- return { position, scale };
1979
+ limit(scale) {
1980
+ const min = this.values[0];
1981
+ const max = this.values[this.values.length - 1];
1982
+ return Math.min(Math.max(scale, min), max);
1907
1983
  }
1908
1984
  }
1909
1985
 
1910
- class ClassicWheelController {
1911
- static create(api) {
1912
- return new ClassicWheelController(api);
1913
- }
1914
- constructor(api) {
1915
- this.api = api;
1916
- }
1917
- onWheel(e) {
1918
- const viewport = this.api.getViewport();
1919
- const canvasPosition = this.api.getCanvasPosition();
1920
- const newViewport = QuantifiedScaleViewportCalculator.zoomByWheel(viewport, e, canvasPosition);
1921
- if (newViewport) {
1922
- this.api.setViewport(newViewport);
1923
- }
1924
- }
1925
- }
1926
-
1927
- class ClassicWheelControllerExtension {
1928
- constructor() {
1929
- this.create = ClassicWheelController.create;
1930
- }
1931
- }
1932
-
1933
- function animate(interval, handler) {
1934
- const iv = setInterval(tick, 15);
1935
- const startTime = Date.now();
1936
- const anim = {
1937
- isAlive: true,
1938
- stop: () => {
1939
- anim.isAlive = false;
1940
- clearInterval(iv);
1941
- }
1942
- };
1943
- function tick() {
1944
- const progress = Math.min((Date.now() - startTime) / interval, 1);
1945
- handler(progress);
1946
- if (progress === 1) {
1947
- anim.stop();
1948
- }
1949
- }
1950
- return anim;
1951
- }
1952
-
1953
- class ViewportAnimator {
1954
- constructor(api) {
1955
- this.api = api;
1956
- }
1957
- execute(target) {
1958
- if (this.animation && this.animation.isAlive) {
1959
- this.animation.stop();
1960
- }
1961
- const viewport = this.api.getViewport();
1962
- const startPosition = viewport.position;
1963
- const startScale = viewport.scale;
1964
- const deltaPosition = startPosition.subtract(target.position);
1965
- const deltaScale = startScale - target.scale;
1966
- this.animation = animate(150, progress => {
1967
- const newScale = startScale - deltaScale * progress;
1968
- this.api.setViewport({
1969
- position: startPosition.subtract(deltaPosition.multiplyByScalar(progress)),
1970
- scale: newScale
1971
- });
1972
- });
1973
- }
1974
- }
1975
-
1976
- const CENTER_MARGIN = 10;
1986
+ const defaultConfiguration$5 = {
1987
+ scales: [0.06, 0.08, 0.1, 0.12, 0.16, 0.2, 0.26, 0.32, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1],
1988
+ smoothDeltaYLimit: 16,
1989
+ padding: 10
1990
+ };
1977
1991
  class DefaultViewportController {
1978
- static create(api) {
1979
- return new DefaultViewportController(api);
1992
+ static create(api, configuration) {
1993
+ const config = configuration !== null && configuration !== void 0 ? configuration : defaultConfiguration$5;
1994
+ const nqn = new NextQuantifiedNumber(config.scales);
1995
+ return new DefaultViewportController(config.smoothDeltaYLimit, nqn, api, config.padding);
1980
1996
  }
1981
- constructor(api) {
1997
+ constructor(smoothDeltaYLimit, nqn, api, padding) {
1998
+ this.smoothDeltaYLimit = smoothDeltaYLimit;
1999
+ this.nqn = nqn;
1982
2000
  this.api = api;
1983
- this.animator = new ViewportAnimator(this.api);
2001
+ this.padding = padding;
1984
2002
  }
1985
- setDefault() {
2003
+ getDefault() {
1986
2004
  const rootComponentSize = this.api.getRootComponentSize();
1987
2005
  const canvasSize = this.api.getCanvasSize();
1988
- const target = CenteredViewportCalculator.center(CENTER_MARGIN, canvasSize, rootComponentSize);
1989
- this.api.setViewport(target);
2006
+ return CenteredViewportCalculator.center(this.padding, canvasSize, rootComponentSize);
1990
2007
  }
1991
- zoom(direction) {
1992
- const viewport = this.api.getViewport();
1993
- const target = QuantifiedScaleViewportCalculator.zoom(viewport, direction);
1994
- this.api.setViewport(target);
2008
+ getZoomed(direction) {
2009
+ const current = this.api.getViewport();
2010
+ const nextScale = this.nqn.next(current.scale, direction);
2011
+ if (nextScale) {
2012
+ return {
2013
+ position: current.position,
2014
+ scale: nextScale.next
2015
+ };
2016
+ }
2017
+ return null;
1995
2018
  }
1996
- focusOnComponent(componentPosition, componentSize) {
2019
+ getFocusedOnComponent(componentPosition, componentSize) {
1997
2020
  const viewport = this.api.getViewport();
1998
2021
  const canvasSize = this.api.getCanvasSize();
1999
- const target = CenteredViewportCalculator.focusOnComponent(canvasSize, viewport, componentPosition, componentSize);
2000
- this.animateTo(target);
2022
+ return CenteredViewportCalculator.getFocusedOnComponent(canvasSize, viewport, componentPosition, componentSize);
2001
2023
  }
2002
- animateTo(viewport) {
2003
- this.animator.execute(viewport);
2024
+ getNextScale(scale, direction) {
2025
+ return this.nqn.next(scale, direction);
2026
+ }
2027
+ limitScale(scale) {
2028
+ return this.nqn.limit(scale);
2004
2029
  }
2005
2030
  }
2006
2031
 
2007
2032
  class DefaultViewportControllerExtension {
2008
- constructor() {
2009
- this.create = DefaultViewportController.create;
2033
+ static create(configuration) {
2034
+ return new DefaultViewportControllerExtension(configuration);
2035
+ }
2036
+ constructor(configuration) {
2037
+ this.configuration = configuration;
2038
+ }
2039
+ create(api) {
2040
+ return DefaultViewportController.create(api, this.configuration);
2010
2041
  }
2011
2042
  }
2012
2043
 
@@ -2166,10 +2197,26 @@ function readTouchPosition(e) {
2166
2197
  return new Vector(touch.pageX, touch.pageY);
2167
2198
  }
2168
2199
  throw new Error('Unknown touch position');
2200
+ }
2201
+ function calculateFingerDistance(e) {
2202
+ if (e.touches.length === 2) {
2203
+ const t0 = e.touches[0];
2204
+ const t1 = e.touches[1];
2205
+ return Math.hypot(t0.clientX - t1.clientX, t0.clientY - t1.clientY);
2206
+ }
2207
+ throw new Error('Cannot calculate finger distance');
2208
+ }
2209
+ function readFingerCenterPoint(e) {
2210
+ if (e.touches.length === 2) {
2211
+ const t0 = e.touches[0];
2212
+ const t1 = e.touches[1];
2213
+ return new Vector((t0.pageX + t1.pageX) / 2, (t0.pageY + t1.pageY) / 2);
2214
+ }
2215
+ throw new Error('Cannot calculate finger center point');
2169
2216
  }
2170
2217
 
2171
- const notInitializedError = 'State is not initialized';
2172
- const nonPassiveOptions = {
2218
+ const notInitializedError$1 = 'State is not initialized';
2219
+ const nonPassiveOptions$1 = {
2173
2220
  passive: false
2174
2221
  };
2175
2222
  class BehaviorController {
@@ -2199,7 +2246,7 @@ class BehaviorController {
2199
2246
  e.preventDefault();
2200
2247
  e.stopPropagation();
2201
2248
  if (!this.state) {
2202
- throw new Error(notInitializedError);
2249
+ throw new Error(notInitializedError$1);
2203
2250
  }
2204
2251
  const position = (_a = this.state.lastPosition) !== null && _a !== void 0 ? _a : this.state.startPosition;
2205
2252
  const element = this.dom.elementFromPoint(position.x, position.y);
@@ -2230,21 +2277,21 @@ class BehaviorController {
2230
2277
  }
2231
2278
  bind(target) {
2232
2279
  target.addEventListener('mousemove', this.onMouseMove, false);
2233
- target.addEventListener('touchmove', this.onTouchMove, nonPassiveOptions);
2280
+ target.addEventListener('touchmove', this.onTouchMove, nonPassiveOptions$1);
2234
2281
  target.addEventListener('mouseup', this.onMouseUp, false);
2235
- target.addEventListener('touchend', this.onTouchEnd, nonPassiveOptions);
2236
- target.addEventListener('touchstart', this.onTouchStart, nonPassiveOptions);
2282
+ target.addEventListener('touchend', this.onTouchEnd, nonPassiveOptions$1);
2283
+ target.addEventListener('touchstart', this.onTouchStart, nonPassiveOptions$1);
2237
2284
  }
2238
2285
  unbind(target) {
2239
2286
  target.removeEventListener('mousemove', this.onMouseMove, false);
2240
- target.removeEventListener('touchmove', this.onTouchMove, nonPassiveOptions);
2287
+ target.removeEventListener('touchmove', this.onTouchMove, nonPassiveOptions$1);
2241
2288
  target.removeEventListener('mouseup', this.onMouseUp, false);
2242
- target.removeEventListener('touchend', this.onTouchEnd, nonPassiveOptions);
2243
- target.removeEventListener('touchstart', this.onTouchStart, nonPassiveOptions);
2289
+ target.removeEventListener('touchend', this.onTouchEnd, nonPassiveOptions$1);
2290
+ target.removeEventListener('touchstart', this.onTouchStart, nonPassiveOptions$1);
2244
2291
  }
2245
2292
  move(position) {
2246
2293
  if (!this.state) {
2247
- throw new Error(notInitializedError);
2294
+ throw new Error(notInitializedError$1);
2248
2295
  }
2249
2296
  this.state.lastPosition = position;
2250
2297
  const delta = this.state.startPosition.subtract(position);
@@ -2258,7 +2305,7 @@ class BehaviorController {
2258
2305
  }
2259
2306
  stop(interrupt, element) {
2260
2307
  if (!this.state) {
2261
- throw new Error(notInitializedError);
2308
+ throw new Error(notInitializedError$1);
2262
2309
  }
2263
2310
  if (this.shadowRoot) {
2264
2311
  this.unbind(this.shadowRoot);
@@ -2833,20 +2880,26 @@ class WorkspaceView {
2833
2880
  getCanvasSize() {
2834
2881
  return new Vector(this.canvas.clientWidth, this.canvas.clientHeight);
2835
2882
  }
2836
- bindClick(handler) {
2883
+ bindMouseDown(handler) {
2837
2884
  this.canvas.addEventListener('mousedown', e => {
2838
2885
  e.preventDefault();
2839
2886
  handler(readMousePosition(e), e.target, e.button, e.altKey);
2840
2887
  }, false);
2888
+ }
2889
+ bindTouchStart(clickHandler, pinchToZoomHandler) {
2841
2890
  this.canvas.addEventListener('touchstart', e => {
2842
2891
  var _a;
2843
2892
  e.preventDefault();
2893
+ if (e.touches.length === 2) {
2894
+ pinchToZoomHandler(calculateFingerDistance(e), readFingerCenterPoint(e));
2895
+ return;
2896
+ }
2844
2897
  const clientPosition = readTouchClientPosition(e);
2845
2898
  const dom = (_a = this.shadowRoot) !== null && _a !== void 0 ? _a : document;
2846
2899
  const element = dom.elementFromPoint(clientPosition.x, clientPosition.y);
2847
2900
  if (element) {
2848
2901
  const position = readTouchPosition(e);
2849
- handler(position, element, 0, false);
2902
+ clickHandler(position, element, 0, false);
2850
2903
  }
2851
2904
  }, listenerOptions$1);
2852
2905
  }
@@ -3223,17 +3276,96 @@ class ContextMenuItemsBuilder {
3223
3276
  }
3224
3277
  }
3225
3278
 
3279
+ const nonPassiveOptions = {
3280
+ passive: false
3281
+ };
3282
+ const notInitializedError = 'State is not initialized';
3283
+ class PinchToZoomController {
3284
+ static create(workspaceApi, viewportApi, shadowRoot) {
3285
+ return new PinchToZoomController(workspaceApi, viewportApi, shadowRoot);
3286
+ }
3287
+ constructor(workspaceApi, viewportApi, shadowRoot) {
3288
+ this.workspaceApi = workspaceApi;
3289
+ this.viewportApi = viewportApi;
3290
+ this.shadowRoot = shadowRoot;
3291
+ this.state = null;
3292
+ this.onTouchMove = (e) => {
3293
+ e.preventDefault();
3294
+ if (!this.state) {
3295
+ throw new Error(notInitializedError);
3296
+ }
3297
+ const touchEvent = e;
3298
+ const distance = calculateFingerDistance(touchEvent);
3299
+ const centerPoint = readFingerCenterPoint(touchEvent);
3300
+ const deltaCenterPoint = centerPoint.subtract(this.state.lastCenterPoint);
3301
+ const scale = this.viewportApi.limitScale(this.state.startScale * (distance / this.state.startDistance));
3302
+ const zoomPoint = centerPoint.subtract(this.state.canvasPosition);
3303
+ const zoomRealPoint = zoomPoint
3304
+ .divideByScalar(this.state.lastViewport.scale)
3305
+ .subtract(this.state.lastViewport.position.divideByScalar(this.state.lastViewport.scale));
3306
+ const position = zoomRealPoint
3307
+ .multiplyByScalar(-scale)
3308
+ .add(zoomPoint)
3309
+ .add(deltaCenterPoint.divideByScalar(this.state.lastViewport.scale));
3310
+ const newViewport = {
3311
+ position,
3312
+ scale
3313
+ };
3314
+ this.workspaceApi.setViewport(newViewport);
3315
+ this.state.lastCenterPoint = centerPoint;
3316
+ this.state.lastViewport = newViewport;
3317
+ };
3318
+ this.onTouchEnd = (e) => {
3319
+ e.preventDefault();
3320
+ if (!this.state) {
3321
+ throw new Error(notInitializedError);
3322
+ }
3323
+ if (this.shadowRoot) {
3324
+ this.unbind(this.shadowRoot);
3325
+ }
3326
+ this.unbind(window);
3327
+ this.state = null;
3328
+ };
3329
+ }
3330
+ start(startDistance, centerPoint) {
3331
+ if (this.state) {
3332
+ throw new Error(`State is already initialized`);
3333
+ }
3334
+ if (this.shadowRoot) {
3335
+ this.bind(this.shadowRoot);
3336
+ }
3337
+ this.bind(window);
3338
+ const viewport = this.workspaceApi.getViewport();
3339
+ this.state = {
3340
+ canvasPosition: this.workspaceApi.getCanvasPosition(),
3341
+ startScale: viewport.scale,
3342
+ startDistance,
3343
+ lastViewport: viewport,
3344
+ lastCenterPoint: centerPoint
3345
+ };
3346
+ }
3347
+ bind(target) {
3348
+ target.addEventListener('touchmove', this.onTouchMove, nonPassiveOptions);
3349
+ target.addEventListener('touchend', this.onTouchEnd, nonPassiveOptions);
3350
+ }
3351
+ unbind(target) {
3352
+ target.removeEventListener('touchmove', this.onTouchMove, nonPassiveOptions);
3353
+ target.removeEventListener('touchend', this.onTouchEnd, nonPassiveOptions);
3354
+ }
3355
+ }
3356
+
3226
3357
  class Workspace {
3227
3358
  static create(parent, designerContext, api) {
3228
3359
  var _a;
3229
3360
  const view = WorkspaceView.create(parent, designerContext.componentContext);
3230
3361
  const clickBehaviorResolver = new ClickBehaviorResolver(designerContext);
3231
- const wheelController = designerContext.services.wheelController.create(api.workspace);
3362
+ const wheelController = designerContext.services.wheelController.create(api.viewport, api.workspace);
3363
+ const pinchToZoomController = PinchToZoomController.create(api.workspace, api.viewport, api.shadowRoot);
3232
3364
  const contextMenuItemsBuilder = new ContextMenuItemsBuilder(api.viewport, api.i18n, designerContext.stateModifier, designerContext.state, ((_a = designerContext.services.contextMenu) === null || _a === void 0 ? void 0 : _a.createItemsProvider)
3233
3365
  ? designerContext.services.contextMenu.createItemsProvider(designerContext.customActionController)
3234
3366
  : undefined);
3235
3367
  const contextMenuController = new ContextMenuController(designerContext.theme, designerContext.configuration, contextMenuItemsBuilder);
3236
- const workspace = new Workspace(view, designerContext.definitionWalker, designerContext.state, designerContext.behaviorController, wheelController, contextMenuController, clickBehaviorResolver, api.viewport, designerContext.services);
3368
+ const workspace = new Workspace(view, designerContext.definitionWalker, designerContext.state, designerContext.behaviorController, wheelController, pinchToZoomController, contextMenuController, clickBehaviorResolver, api.viewport, designerContext.services);
3237
3369
  setTimeout(() => {
3238
3370
  workspace.updateRootComponent();
3239
3371
  api.viewport.resetViewport();
@@ -3243,17 +3375,19 @@ class Workspace {
3243
3375
  race(0, designerContext.state.onDefinitionChanged, designerContext.state.onSelectedStepIdChanged, designerContext.state.onFolderPathChanged).subscribe(r => {
3244
3376
  workspace.onStateChanged(r[0], r[1], r[2]);
3245
3377
  });
3246
- view.bindClick(workspace.onClick);
3378
+ view.bindMouseDown(workspace.onClick);
3379
+ view.bindTouchStart(workspace.onClick, workspace.onPinchToZoom);
3247
3380
  view.bindWheel(workspace.onWheel);
3248
3381
  view.bindContextMenu(workspace.onContextMenu);
3249
3382
  return workspace;
3250
3383
  }
3251
- constructor(view, definitionWalker, state, behaviorController, wheelController, contextMenuController, clickBehaviorResolver, viewportApi, services) {
3384
+ constructor(view, definitionWalker, state, behaviorController, wheelController, pinchToZoomController, contextMenuController, clickBehaviorResolver, viewportApi, services) {
3252
3385
  this.view = view;
3253
3386
  this.definitionWalker = definitionWalker;
3254
3387
  this.state = state;
3255
3388
  this.behaviorController = behaviorController;
3256
3389
  this.wheelController = wheelController;
3390
+ this.pinchToZoomController = pinchToZoomController;
3257
3391
  this.contextMenuController = contextMenuController;
3258
3392
  this.clickBehaviorResolver = clickBehaviorResolver;
3259
3393
  this.viewportApi = viewportApi;
@@ -3272,6 +3406,9 @@ class Workspace {
3272
3406
  this.behaviorController.start(position, behavior);
3273
3407
  }
3274
3408
  };
3409
+ this.onPinchToZoom = (distance, centerPoint) => {
3410
+ this.pinchToZoomController.start(distance, centerPoint);
3411
+ };
3275
3412
  this.onWheel = (e) => {
3276
3413
  e.preventDefault();
3277
3414
  e.stopPropagation();
@@ -4395,7 +4532,7 @@ function setDefaults(services, configuration) {
4395
4532
  services.regionComponentView = new DefaultRegionComponentViewExtension();
4396
4533
  }
4397
4534
  if (!services.viewportController) {
4398
- services.viewportController = new DefaultViewportControllerExtension();
4535
+ services.viewportController = DefaultViewportControllerExtension.create();
4399
4536
  }
4400
4537
  if (!services.grid) {
4401
4538
  services.grid = LineGridExtension.create();
@@ -4686,4 +4823,4 @@ class StepsDesignerExtension {
4686
4823
  }
4687
4824
  }
4688
4825
 
4689
- export { Badges, CenteredViewportCalculator, ClassicWheelControllerExtension, ClickCommandType, ComponentContext, ComponentDom, ControlBarApi, CustomActionController, DefaultRegionComponentViewExtension, DefaultRegionView, 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, ServicesResolver, SimpleEvent, StartStopRootComponentExtension, StepComponent, StepExtensionResolver, StepsDesignerExtension, ToolboxApi, Uid, ValidationErrorBadgeExtension, Vector, WorkspaceApi, createContainerStepComponentViewFactory, createSwitchStepComponentViewFactory, createTaskStepComponentViewFactory, getAbsolutePosition, race };
4826
+ export { Badges, CenteredViewportCalculator, ClassicWheelControllerExtension, ClickCommandType, ComponentContext, ComponentDom, ControlBarApi, CustomActionController, DefaultRegionComponentViewExtension, DefaultRegionView, DefaultSequenceComponent, DefaultSequenceComponentView, DefaultViewportController, DefaultViewportControllerExtension, DefinitionChangeType, Designer, DesignerApi, DesignerContext, DesignerState, Dom, Editor, EditorApi, Icons, InputView, JoinView, KeyboardAction, LabelView, LineGridDesignerExtension, ObjectCloner, OutputView, PathBarApi, PlaceholderDirection, RectPlaceholder, RectPlaceholderView, ServicesResolver, SimpleEvent, StartStopRootComponentExtension, StepComponent, StepExtensionResolver, StepsDesignerExtension, ToolboxApi, Uid, ValidationErrorBadgeExtension, Vector, ViewportApi, WorkspaceApi, createContainerStepComponentViewFactory, createSwitchStepComponentViewFactory, createTaskStepComponentViewFactory, getAbsolutePosition, race };