bpmn-js 18.13.0 → 18.13.2

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.
@@ -113,6 +113,10 @@
113
113
  background: var(--shape-drop-allowed-fill-color) !important;
114
114
  }
115
115
 
116
+ .djs-container svg:focus {
117
+ outline-offset: -1px;
118
+ }
119
+
116
120
  /**
117
121
  * outline styles
118
122
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * bpmn-js - bpmn-modeler v18.13.0
2
+ * bpmn-js - bpmn-modeler v18.13.2
3
3
  *
4
4
  * Copyright (c) 2014-present, camunda Services GmbH
5
5
  *
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * Source Code: https://github.com/bpmn-io/bpmn-js
10
10
  *
11
- * Date: 2026-03-04
11
+ * Date: 2026-03-23
12
12
  */
13
13
  (function (global, factory) {
14
14
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
@@ -18,7 +18,7 @@
18
18
 
19
19
  function e$2(e,t){t&&(e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:false,writable:true,configurable:true}}));}
20
20
 
21
- function getDefaultExportFromCjs$2 (x) {
21
+ function getDefaultExportFromCjs$1 (x) {
22
22
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
23
23
  }
24
24
 
@@ -95,7 +95,7 @@
95
95
  }
96
96
 
97
97
  var hatExports = requireHat();
98
- var hat = /*@__PURE__*/getDefaultExportFromCjs$2(hatExports);
98
+ var hat = /*@__PURE__*/getDefaultExportFromCjs$1(hatExports);
99
99
 
100
100
  /**
101
101
  * @typedef { [ number, number ] | [ number, number, number ] } Seed
@@ -956,101 +956,86 @@
956
956
  return result;
957
957
  }
958
958
 
959
- function getDefaultExportFromCjs$1 (x) {
960
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
961
- }
959
+ /* eslint-disable no-multi-assign */
962
960
 
963
- var domify_1;
964
- var hasRequiredDomify;
961
+ const wrapMap = {
962
+ legend: [1, '<fieldset>', '</fieldset>'],
963
+ tr: [2, '<table><tbody>', '</tbody></table>'],
964
+ col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
965
+ _default: [0, '', ''],
966
+ };
965
967
 
966
- function requireDomify () {
967
- if (hasRequiredDomify) return domify_1;
968
- hasRequiredDomify = 1;
969
- const wrapMap = {
970
- legend: [1, '<fieldset>', '</fieldset>'],
971
- tr: [2, '<table><tbody>', '</tbody></table>'],
972
- col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
973
- _default: [0, '', ''],
974
- };
968
+ wrapMap.td
969
+ = wrapMap.th = [3, '<table><tbody><tr>', '</tr></tbody></table>'];
975
970
 
976
- wrapMap.td
977
- = wrapMap.th = [3, '<table><tbody><tr>', '</tr></tbody></table>'];
978
-
979
- wrapMap.option
980
- = wrapMap.optgroup = [1, '<select multiple="multiple">', '</select>'];
981
-
982
- wrapMap.thead
983
- = wrapMap.tbody
984
- = wrapMap.colgroup
985
- = wrapMap.caption
986
- = wrapMap.tfoot = [1, '<table>', '</table>'];
987
-
988
- wrapMap.polyline
989
- = wrapMap.ellipse
990
- = wrapMap.polygon
991
- = wrapMap.circle
992
- = wrapMap.text
993
- = wrapMap.line
994
- = wrapMap.path
995
- = wrapMap.rect
996
- = wrapMap.g = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">', '</svg>'];
997
-
998
- function domify(htmlString, document = globalThis.document) {
999
- if (typeof htmlString !== 'string') {
1000
- throw new TypeError('String expected');
1001
- }
1002
-
1003
- // Handle comment nodes
1004
- const commentMatch = /^<!--(.*?)-->$/s.exec(htmlString);
1005
- if (commentMatch) {
1006
- return document.createComment(commentMatch[1]);
1007
- }
1008
-
1009
- const tagName = /<([\w:]+)/.exec(htmlString)?.[1];
1010
-
1011
- if (!tagName) {
1012
- return document.createTextNode(htmlString);
1013
- }
1014
-
1015
- htmlString = htmlString.trim();
1016
-
1017
- // Body support
1018
- if (tagName === 'body') {
1019
- const element = document.createElement('html');
1020
- element.innerHTML = htmlString;
1021
- const {lastChild} = element;
1022
- lastChild.remove();
1023
- return lastChild;
1024
- }
1025
-
1026
- // Wrap map
1027
- let [depth, prefix, suffix] = Object.hasOwn(wrapMap, tagName) ? wrapMap[tagName] : wrapMap._default;
1028
- let element = document.createElement('div');
1029
- element.innerHTML = prefix + htmlString + suffix;
1030
- while (depth--) {
1031
- element = element.lastChild;
1032
- }
1033
-
1034
- // One element
1035
- if (element.firstChild === element.lastChild) {
1036
- const {firstChild} = element;
1037
- firstChild.remove();
1038
- return firstChild;
1039
- }
1040
-
1041
- // Several elements
1042
- const fragment = document.createDocumentFragment();
1043
- fragment.append(...element.childNodes);
1044
-
1045
- return fragment;
971
+ wrapMap.option
972
+ = wrapMap.optgroup = [1, '<select multiple="multiple">', '</select>'];
973
+
974
+ wrapMap.thead
975
+ = wrapMap.tbody
976
+ = wrapMap.colgroup
977
+ = wrapMap.caption
978
+ = wrapMap.tfoot = [1, '<table>', '</table>'];
979
+
980
+ wrapMap.polyline
981
+ = wrapMap.ellipse
982
+ = wrapMap.polygon
983
+ = wrapMap.circle
984
+ = wrapMap.text
985
+ = wrapMap.line
986
+ = wrapMap.path
987
+ = wrapMap.rect
988
+ = wrapMap.g = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">', '</svg>'];
989
+
990
+ function domify(htmlString, document = globalThis.document) {
991
+ if (typeof htmlString !== 'string') {
992
+ throw new TypeError('String expected');
1046
993
  }
1047
994
 
1048
- domify_1 = domify;
1049
- return domify_1;
1050
- }
995
+ // Handle comment nodes
996
+ const commentMatch = /^<!--(.*?)-->$/s.exec(htmlString);
997
+ if (commentMatch) {
998
+ return document.createComment(commentMatch[1]);
999
+ }
1000
+
1001
+ const tagName = /<([\w:]+)/.exec(htmlString)?.[1];
1002
+
1003
+ if (!tagName) {
1004
+ return document.createTextNode(htmlString);
1005
+ }
1006
+
1007
+ htmlString = htmlString.trim();
1008
+
1009
+ // Body support
1010
+ if (tagName === 'body') {
1011
+ const element = document.createElement('html');
1012
+ element.innerHTML = htmlString;
1013
+ const {lastChild} = element;
1014
+ lastChild.remove();
1015
+ return lastChild;
1016
+ }
1017
+
1018
+ // Wrap map
1019
+ let [depth, prefix, suffix] = Object.hasOwn(wrapMap, tagName) ? wrapMap[tagName] : wrapMap._default;
1020
+ let element = document.createElement('div');
1021
+ element.innerHTML = prefix + htmlString + suffix;
1022
+ while (depth--) {
1023
+ element = element.lastChild;
1024
+ }
1025
+
1026
+ // One element
1027
+ if (element.firstChild === element.lastChild) {
1028
+ const {firstChild} = element;
1029
+ firstChild.remove();
1030
+ return firstChild;
1031
+ }
1051
1032
 
1052
- var domifyExports = /*@__PURE__*/ requireDomify();
1053
- var domify = /*@__PURE__*/getDefaultExportFromCjs$1(domifyExports);
1033
+ // Several elements
1034
+ const fragment = document.createDocumentFragment();
1035
+ fragment.append(...element.childNodes);
1036
+
1037
+ return fragment;
1038
+ }
1054
1039
 
1055
1040
  function _mergeNamespaces$1(n, m) {
1056
1041
  m.forEach(function (e) {
@@ -27827,7 +27812,7 @@
27827
27812
  * @typedef {import('./PopupMenuProvider').PopupMenuEmptyPlaceholderProvider | import('./PopupMenuProvider').PopupMenuEmptyPlaceholder} PopupMenuEmptyPlaceholder
27828
27813
  * @typedef {import('./PopupMenuProvider').PopupMenuGroup} PopupMenuGroup
27829
27814
  *
27830
- * @typedef {import('../search/search').default} search
27815
+ * @typedef {import('../search/search').default} searchFn
27831
27816
  *
27832
27817
  * @typedef {import('../../util/Types').Point} Point
27833
27818
  */
@@ -27847,7 +27832,7 @@
27847
27832
  * @param {boolean} [props.search]
27848
27833
  * @param {PopupMenuEmptyPlaceholder} [props.emptyPlaceholder]
27849
27834
  * @param {number} [props.width]
27850
- * @param {search} props.searchFn
27835
+ * @param {searchFn} props.searchFn
27851
27836
  */
27852
27837
  function PopupMenuComponent(props) {
27853
27838
  const {
@@ -27898,23 +27883,21 @@
27898
27883
  }).map(({ item }) => item);
27899
27884
  }, [ searchable ]);
27900
27885
 
27901
- const [ entries, setEntries ] = p(filterEntries(originalEntries, searchValue));
27886
+ const entries = q(() => filterEntries(originalEntries, searchValue), [ originalEntries, searchValue, filterEntries ]);
27902
27887
  const [ selectedEntry, setSelectedEntry ] = p(entries[0]);
27903
27888
 
27904
- const groupedEntries = q(() => groupEntries(entries), [ entries ]);
27905
-
27906
- const updateEntries = x((newEntries) => {
27907
-
27908
- // always select first
27909
- setSelectedEntry(newEntries[0]);
27889
+ const groupedEntries = q(() => {
27890
+ if (searchValue.trim()) {
27891
+ return entries.length ? [ { id: 'default', entries } ] : [];
27892
+ }
27910
27893
 
27911
- setEntries(newEntries);
27912
- }, [ setEntries, setSelectedEntry ]);
27894
+ return groupEntries(entries);
27895
+ }, [ entries, searchValue ]);
27913
27896
 
27914
- // filter entries on search value change
27897
+ // always select first entry when filtered entries change
27915
27898
  _(() => {
27916
- updateEntries(filterEntries(originalEntries, searchValue));
27917
- }, [ searchValue, originalEntries ]);
27899
+ setSelectedEntry(entries[0]);
27900
+ }, [ entries ]);
27918
27901
 
27919
27902
  // handle keyboard selection
27920
27903
  const keyboardSelect = x(direction => {
@@ -40324,6 +40307,58 @@
40324
40307
  }
40325
40308
  }
40326
40309
 
40310
+ /**
40311
+ * @typedef { import('../model/Types').Element } Element
40312
+ */
40313
+
40314
+ /**
40315
+ * Get text annotations connected to the given element.
40316
+ *
40317
+ * @param {Element} element
40318
+ *
40319
+ * @return { { annotation: Element, association: Element }[] }
40320
+ */
40321
+ function getElementAnnotations(element) {
40322
+ let result = [];
40323
+
40324
+ forEach(element.incoming, (connection) => {
40325
+ if (is(connection, 'bpmn:Association') && is(connection.source, 'bpmn:TextAnnotation')) {
40326
+ result.push({ annotation: connection.source, association: connection });
40327
+ }
40328
+ });
40329
+
40330
+ forEach(element.outgoing, (connection) => {
40331
+ if (is(connection, 'bpmn:Association') && is(connection.target, 'bpmn:TextAnnotation')) {
40332
+ result.push({ annotation: connection.target, association: connection });
40333
+ }
40334
+ });
40335
+
40336
+ return result;
40337
+ }
40338
+
40339
+ /**
40340
+ * Recursively collect text annotations connected to the given elements and their descendants.
40341
+ * De-duplicates by annotation, collecting all associations per annotation.
40342
+ *
40343
+ * @param {Element[]} elements
40344
+ *
40345
+ * @return { { annotation: Element, associations: Element[] }[] }
40346
+ */
40347
+ function collectElementsAnnotations(elements) {
40348
+ const result = new Map();
40349
+
40350
+ forEach(selfAndChildren(elements, true), (element) => {
40351
+ forEach(getElementAnnotations(element), (entry) => {
40352
+ if (!result.has(entry.annotation)) {
40353
+ result.set(entry.annotation, { annotation: entry.annotation, associations: [] });
40354
+ }
40355
+ result.get(entry.annotation).associations.push(entry.association);
40356
+ });
40357
+ });
40358
+
40359
+ return [ ...result.values() ];
40360
+ }
40361
+
40327
40362
  /**
40328
40363
  * @typedef {import('diagram-js/lib/core/Canvas').default} Canvas
40329
40364
  * @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
@@ -40346,7 +40381,6 @@
40346
40381
  y: 160
40347
40382
  };
40348
40383
 
40349
-
40350
40384
  /**
40351
40385
  * Creates bpmndi:BPMNPlane elements and canvas planes when collapsed subprocesses are created.
40352
40386
  *
@@ -40412,17 +40446,26 @@
40412
40446
  }, true);
40413
40447
 
40414
40448
 
40415
- this.postExecuted('shape.create', function(context) {
40416
- var shape = context.shape,
40417
- rootElement = context.newRootElement;
40449
+ this.postExecuted('elements.create', function(context) {
40450
+ var elements = context.elements;
40418
40451
 
40419
- if (!rootElement || !shape.children) {
40420
- return;
40421
- }
40452
+ forEach(elements, function(element) {
40453
+ if (!isCollapsedSubProcess(element)) {
40454
+ return;
40455
+ }
40456
+
40457
+ var rootElement = elementRegistry.get(getPlaneIdFromShape(element));
40458
+
40459
+ if (!rootElement || !element.children || !element.children.length) {
40460
+ return;
40461
+ }
40462
+
40463
+ var children = getSubProcessChildren(element);
40422
40464
 
40423
- self._showRecursively(shape.children);
40465
+ self._showRecursively(children);
40424
40466
 
40425
- self._moveChildrenToShape(shape, rootElement);
40467
+ self._moveChildrenToShape(children, rootElement);
40468
+ });
40426
40469
  }, true);
40427
40470
 
40428
40471
 
@@ -40436,6 +40479,20 @@
40436
40479
  }, true);
40437
40480
 
40438
40481
 
40482
+ // remove annotations connected to elements inside the subprocess
40483
+ this.preExecute('shape.delete', function(context) {
40484
+ var shape = context.shape;
40485
+
40486
+ if (!is(shape, 'bpmn:SubProcess') || !isExpanded(shape)) {
40487
+ return;
40488
+ }
40489
+
40490
+ forEach(collectElementsAnnotations([ shape ]), (entry) => {
40491
+ modeling.removeShape(entry.annotation);
40492
+ });
40493
+ }, true);
40494
+
40495
+
40439
40496
  this.preExecuted('shape.delete', function(context) {
40440
40497
  var shape = context.shape;
40441
40498
  if (!isCollapsedSubProcess(shape)) {
@@ -40641,11 +40698,27 @@
40641
40698
 
40642
40699
  if (!isExpanded(shape)) {
40643
40700
 
40644
- // collapsed
40645
- self._moveChildrenToShape(shape, rootElement);
40701
+ // if an annotation is attached to both the sub-process and elements inside it,
40702
+ // remove the inner associations, keeping only connections at the sub-process level,
40703
+ // since we can't keep both after collapsing
40704
+ self._disconnectSharedAnnotations(shape);
40705
+
40706
+ var children = getSubProcessChildren(shape);
40707
+
40708
+ self._moveChildrenToShape(children, rootElement);
40646
40709
 
40647
40710
  } else {
40648
- self._moveChildrenToShape(rootElement, shape);
40711
+ self._moveChildrenToShape(rootElement.children.slice(), shape);
40712
+
40713
+ // annotations live at process level by design;
40714
+ // move them back from the sub-process to the process root
40715
+ forEach(collectElementsAnnotations(shape.children), (entry) => {
40716
+ modeling.moveShape(entry.annotation, { x: 0, y: 0 }, shape.parent);
40717
+
40718
+ forEach(entry.associations, (association) => {
40719
+ modeling.moveConnection(association, { x: 0, y: 0 }, shape.parent);
40720
+ });
40721
+ });
40649
40722
  }
40650
40723
  }, true);
40651
40724
 
@@ -40715,33 +40788,21 @@
40715
40788
  e$2(SubProcessPlaneBehavior, CommandInterceptor);
40716
40789
 
40717
40790
  /**
40718
- * Moves the child elements from source to target.
40791
+ * Moves the given elements to the target.
40719
40792
  *
40720
40793
  * If the target is a plane, the children are moved to the top left corner.
40721
40794
  * Otherwise, the center of the target is used.
40722
40795
  *
40723
- * @param {Root} source
40796
+ * @param {Element[]} children
40724
40797
  * @param {Root} target
40725
40798
  */
40726
- SubProcessPlaneBehavior.prototype._moveChildrenToShape = function(source, target) {
40799
+ SubProcessPlaneBehavior.prototype._moveChildrenToShape = function(children, target) {
40727
40800
  var modeling = this._modeling;
40728
40801
 
40729
- var children = source.children;
40730
- var offset;
40731
-
40732
- if (!children) {
40802
+ if (!children.length) {
40733
40803
  return;
40734
40804
  }
40735
40805
 
40736
- // add external labels that weren't children of sub process
40737
- children = children.concat(children.reduce(function(labels, child) {
40738
- if (child.label && child.label.parent !== source) {
40739
- return labels.concat(child.label);
40740
- }
40741
-
40742
- return labels;
40743
- }, []));
40744
-
40745
40806
  // only change plane if there are no visible children, but don't move them
40746
40807
  var visibleChildren = children.filter(function(child) {
40747
40808
  return !child.hidden;
@@ -40753,6 +40814,7 @@
40753
40814
  }
40754
40815
 
40755
40816
  var childrenBounds = getBBox(visibleChildren);
40817
+ var offset;
40756
40818
 
40757
40819
  // target is a plane
40758
40820
  if (!target.x) {
@@ -40778,6 +40840,32 @@
40778
40840
  modeling.moveElements(children, offset, target, { autoResize: false });
40779
40841
  };
40780
40842
 
40843
+ /**
40844
+ * Remove all associations between inner elements and annotations that are
40845
+ * also connected to the sub-process itself.
40846
+ *
40847
+ * @param {Element} shape
40848
+ */
40849
+ SubProcessPlaneBehavior.prototype._disconnectSharedAnnotations = function(shape) {
40850
+ var modeling = this._modeling;
40851
+
40852
+ var sharedAnnotations = new Set(
40853
+ getElementAnnotations(shape).map((entry) => entry.annotation)
40854
+ );
40855
+
40856
+ if (!sharedAnnotations.size) {
40857
+ return;
40858
+ }
40859
+
40860
+ forEach(collectElementsAnnotations(shape.children), (entry) => {
40861
+ if (sharedAnnotations.has(entry.annotation)) {
40862
+ forEach(entry.associations, (association) => {
40863
+ modeling.removeConnection(association);
40864
+ });
40865
+ }
40866
+ });
40867
+ };
40868
+
40781
40869
  /**
40782
40870
  * Sets `hidden` property on all children of the given shape.
40783
40871
  *
@@ -40892,6 +40980,57 @@
40892
40980
  'elementRegistry'
40893
40981
  ];
40894
40982
 
40983
+ /**
40984
+ * Collect text annotations and their associations connected to the given elements.
40985
+ *
40986
+ * @param {Element[]} elements
40987
+ *
40988
+ * @return {Element[]}
40989
+ */
40990
+ function collectAnnotationElements(elements) {
40991
+ var result = [];
40992
+
40993
+ forEach(collectElementsAnnotations(elements), (entry) => {
40994
+ result.push(entry.annotation);
40995
+ result.push.apply(result, entry.associations);
40996
+ });
40997
+
40998
+ return result;
40999
+ }
41000
+
41001
+ /**
41002
+ * Collect all children of a collapsed subprocess that need to be moved
41003
+ * to or from its plane, including annotations and external labels that
41004
+ * live at the process level by design(ref: https://github.com/camunda/camunda-modeler/issues/5163#issuecomment-3946571271)
41005
+ *
41006
+ * @param {Element} element
41007
+ *
41008
+ * @return {Element[]}
41009
+ */
41010
+ function getSubProcessChildren(element) {
41011
+ return element.children.slice()
41012
+ .concat(collectAnnotationElements(element.children))
41013
+ .concat(getExternalLabels(element));
41014
+ }
41015
+
41016
+ /**
41017
+ * Returns external labels of the given element's children and their descendants
41018
+ * that are not direct children of the element (i.e. parented elsewhere).
41019
+ *
41020
+ * @param {Element} element
41021
+ *
41022
+ * @return {Element[]}
41023
+ */
41024
+ function getExternalLabels(element) {
41025
+ return selfAndChildren(element.children || [], true)
41026
+ .reduce(function(labels, child) {
41027
+ if (child.label && child.label.parent !== element) {
41028
+ labels.push(child.label);
41029
+ }
41030
+ return labels;
41031
+ }, []);
41032
+ }
41033
+
40895
41034
  /**
40896
41035
  * @typedef {import('didi').Injector} Injector
40897
41036
  * @typedef {import('../Modeling').default} Modeling
@@ -41001,7 +41140,6 @@
41001
41140
 
41002
41141
  this.postExecuted('shape.toggleCollapse', 1500, function(context) {
41003
41142
 
41004
- // var shape = context.shape;
41005
41143
  var shape = context.shape;
41006
41144
 
41007
41145
  // only change connections when collapsing
@@ -41032,6 +41170,12 @@
41032
41170
  return;
41033
41171
  }
41034
41172
 
41173
+ // don't reconnect TextAnnotation connections,
41174
+ // since they should stay connected and moved with its element to the subprocess plane
41175
+ if (is(c, 'bpmn:Association') && (is(c.source, 'bpmn:TextAnnotation') || is(c.target, 'bpmn:TextAnnotation'))) {
41176
+ return;
41177
+ }
41178
+
41035
41179
  if (incoming) {
41036
41180
  modeling.reconnectEnd(c, shape, getMid(shape));
41037
41181
  } else {
@@ -44587,6 +44731,21 @@
44587
44731
  }
44588
44732
  });
44589
44733
 
44734
+ eventBus.on('copyPaste.createTree', function(context) {
44735
+ var element = context.element,
44736
+ children = context.children;
44737
+
44738
+ if (!is(element, 'bpmn:SubProcess')) {
44739
+ return;
44740
+ }
44741
+
44742
+ // add TextAnnotations to copy the closure,
44743
+ // since by default they are children of a global process, not subprocess
44744
+ forEach(collectElementsAnnotations(children), (entry) => {
44745
+ children.push(entry.annotation);
44746
+ });
44747
+ });
44748
+
44590
44749
  // resolve references
44591
44750
 
44592
44751
  eventBus.on('copyPaste.pasteElement', LOW_PRIORITY$b, function(context) {
@@ -54713,17 +54872,34 @@
54713
54872
  }
54714
54873
  }
54715
54874
 
54716
- // attached to either top-right, top-left, bottom-right or bottom-left corner
54717
- // and orientation is same on the counter-axis
54875
+ // attached to either top-right, top-left, bottom-right or bottom-left corner,
54876
+ // or strictly above/below or left/right of the target. In the corner case,
54877
+ // the orientation is compared on the counter-axis to decide the layout.
54878
+
54879
+ var verticalAttachOrientation = getVerticalOrientation(attachOrientation),
54880
+ horizontalAttachOrientation = getHorizontalOrientation(attachOrientation),
54881
+ verticalTargetOrientation = getVerticalOrientation(targetOrientation),
54882
+ horizontalTargetOrientation = getHorizontalOrientation(targetOrientation);
54883
+
54884
+ // If the target is strictly above/below (no horizontal orientation)
54885
+ if (verticalTargetOrientation && !horizontalTargetOrientation) {
54886
+ return 'v';
54887
+ }
54888
+
54889
+ // If the target is strictly left/right (no vertical orientation)
54890
+ if (horizontalTargetOrientation && !verticalTargetOrientation) {
54891
+ return 'h';
54892
+ }
54893
+
54718
54894
 
54719
54895
  if (isHorizontal) {
54720
- if (isSame(getVerticalOrientation(attachOrientation), getVerticalOrientation(targetOrientation))) {
54896
+ if (isSame(verticalAttachOrientation, verticalTargetOrientation)) {
54721
54897
  return 'h';
54722
54898
  } else {
54723
54899
  return 'v';
54724
54900
  }
54725
54901
  } else {
54726
- if (isSame(getHorizontalOrientation(attachOrientation), getHorizontalOrientation(targetOrientation))) {
54902
+ if (isSame(horizontalAttachOrientation, horizontalTargetOrientation)) {
54727
54903
  return 'v';
54728
54904
  } else {
54729
54905
  return 'h';