@atlaskit/editor-plugin-layout 10.7.1 → 10.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/cjs/pm-plugins/actions.js +33 -28
  3. package/dist/cjs/pm-plugins/utils/{redistribute-proportionally.js → layout-column-distribution.js} +39 -3
  4. package/dist/cjs/pm-plugins/utils/layout-column-selection.js +4 -3
  5. package/dist/cjs/ui/LayoutColumnMenu/DistributeColumnsDropdownItem.js +4 -14
  6. package/dist/cjs/ui/LayoutColumnMenu/VerticalAlignDropdownItem.js +2 -1
  7. package/dist/cjs/ui/LayoutColumnMenu/VerticalAlignNestedMenu.js +1 -4
  8. package/dist/cjs/ui/LayoutColumnMenu/components.js +18 -8
  9. package/dist/cjs/ui/LayoutColumnMenu/index.js +3 -36
  10. package/dist/es2019/pm-plugins/actions.js +27 -15
  11. package/dist/es2019/pm-plugins/utils/{redistribute-proportionally.js → layout-column-distribution.js} +34 -1
  12. package/dist/es2019/pm-plugins/utils/layout-column-selection.js +4 -1
  13. package/dist/es2019/ui/LayoutColumnMenu/DistributeColumnsDropdownItem.js +4 -10
  14. package/dist/es2019/ui/LayoutColumnMenu/VerticalAlignDropdownItem.js +2 -1
  15. package/dist/es2019/ui/LayoutColumnMenu/VerticalAlignNestedMenu.js +2 -5
  16. package/dist/es2019/ui/LayoutColumnMenu/components.js +11 -2
  17. package/dist/es2019/ui/LayoutColumnMenu/index.js +5 -33
  18. package/dist/esm/pm-plugins/actions.js +31 -26
  19. package/dist/esm/pm-plugins/utils/{redistribute-proportionally.js → layout-column-distribution.js} +37 -3
  20. package/dist/esm/pm-plugins/utils/layout-column-selection.js +4 -3
  21. package/dist/esm/ui/LayoutColumnMenu/DistributeColumnsDropdownItem.js +4 -14
  22. package/dist/esm/ui/LayoutColumnMenu/VerticalAlignDropdownItem.js +2 -1
  23. package/dist/esm/ui/LayoutColumnMenu/VerticalAlignNestedMenu.js +2 -5
  24. package/dist/esm/ui/LayoutColumnMenu/components.js +16 -8
  25. package/dist/esm/ui/LayoutColumnMenu/index.js +5 -37
  26. package/dist/types/pm-plugins/actions.d.ts +4 -2
  27. package/dist/types/pm-plugins/utils/layout-column-distribution.d.ts +16 -0
  28. package/dist/types/pm-plugins/utils/layout-column-selection.d.ts +1 -1
  29. package/dist/types/ui/LayoutColumnMenu/VerticalAlignDropdownItem.d.ts +4 -6
  30. package/dist/types/ui/LayoutColumnMenu/verticalAlignIcons.d.ts +1 -1
  31. package/dist/types-ts4.5/pm-plugins/actions.d.ts +4 -2
  32. package/dist/types-ts4.5/pm-plugins/utils/layout-column-distribution.d.ts +16 -0
  33. package/dist/types-ts4.5/pm-plugins/utils/layout-column-selection.d.ts +1 -1
  34. package/dist/types-ts4.5/ui/LayoutColumnMenu/VerticalAlignDropdownItem.d.ts +4 -6
  35. package/dist/types-ts4.5/ui/LayoutColumnMenu/verticalAlignIcons.d.ts +1 -1
  36. package/package.json +6 -6
  37. package/dist/types/pm-plugins/utils/redistribute-proportionally.d.ts +0 -2
  38. package/dist/types-ts4.5/pm-plugins/utils/redistribute-proportionally.d.ts +0 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @atlaskit/editor-plugin-layout
2
2
 
3
+ ## 10.8.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`2ad681c18e86f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/2ad681c18e86f) -
8
+ Add layout column menu actions for inserting, deleting, distributing, and aligning columns.
9
+ - Updated dependencies
10
+
11
+ ## 10.8.0
12
+
13
+ ### Minor Changes
14
+
15
+ - [`1c86d46da6101`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/1c86d46da6101) -
16
+ Address layout column alignment follow-up review feedback
17
+
18
+ ### Patch Changes
19
+
20
+ - Updated dependencies
21
+
3
22
  ## 10.7.1
4
23
 
5
24
  ### Patch Changes
@@ -20,8 +20,8 @@ var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equa
20
20
  var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
21
21
  var _consts = require("./consts");
22
22
  var _pluginKey = require("./plugin-key");
23
+ var _layoutColumnDistribution = require("./utils/layout-column-distribution");
23
24
  var _layoutColumnSelection = require("./utils/layout-column-selection");
24
- var _redistributeProportionally = require("./utils/redistribute-proportionally");
25
25
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
26
26
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
27
27
  var ONE_COL_LAYOUTS = exports.ONE_COL_LAYOUTS = ['single'];
@@ -583,7 +583,7 @@ var insertLayoutColumnAt = function insertLayoutColumnAt(side, editorAnalyticsAP
583
583
  var existingWidths = (0, _utils.mapChildren)(layoutSectionNode, function (column) {
584
584
  return column.attrs.width;
585
585
  });
586
- var redistributedWidths = (0, _redistributeProportionally.redistributeProportionally)(existingWidths, insertIndex, getEffectiveMaxLayoutColumns(), _consts.MIN_LAYOUT_COLUMN_WIDTH_PERCENT);
586
+ var redistributedWidths = (0, _layoutColumnDistribution.redistributeProportionally)(existingWidths, insertIndex, getEffectiveMaxLayoutColumns(), _consts.MIN_LAYOUT_COLUMN_WIDTH_PERCENT);
587
587
  if (redistributedWidths === existingWidths) {
588
588
  return null;
589
589
  }
@@ -687,31 +687,30 @@ var distributeLayoutColumns = exports.distributeLayoutColumns = function distrib
687
687
  return null;
688
688
  }
689
689
  var layoutSectionNode = selectedLayoutColumns.layoutSectionNode,
690
- layoutSectionPos = selectedLayoutColumns.layoutSectionPos,
691
690
  selectedColumnIndices = selectedLayoutColumns.selectedColumnIndices,
692
691
  selectedColumns = selectedLayoutColumns.selectedColumns;
693
692
  var endIndex = selectedColumnIndices[selectedColumnIndices.length - 1];
694
693
  var selectedColumnCount = selectedColumns.length;
695
694
  var totalColumnCount = layoutSectionNode.childCount;
696
-
697
- // Compute equal width for selected columns
698
695
  var existingWidths = (0, _utils.mapChildren)(layoutSectionNode, function (column) {
699
696
  return column.attrs.width;
700
697
  });
701
- var selectedTotal = selectedColumnIndices.reduce(function (sum, idx) {
702
- return sum + existingWidths[idx];
703
- }, 0);
704
- var equalWidth = selectedTotal / selectedColumnCount;
705
-
706
- // Early return if selected columns are already uniformly distributed — avoids spurious undo entry.
707
- if (selectedColumnIndices.every(function (idx) {
708
- return existingWidths[idx] === Number(equalWidth.toFixed(2));
709
- })) {
698
+ var selectedWidths = selectedColumns.map(function (_ref9) {
699
+ var node = _ref9.node;
700
+ return node.attrs.width;
701
+ });
702
+ var distribution = (0, _layoutColumnDistribution.calculateDistribution)(selectedWidths);
703
+ if (!distribution) {
704
+ return null;
705
+ }
706
+ var selectedTotal = distribution.selectedTotal,
707
+ equalWidth = distribution.equalWidth;
708
+ if ((0, _layoutColumnDistribution.isDistributedUniformly)(selectedWidths, distribution)) {
710
709
  return null;
711
710
  }
712
711
 
713
712
  // Build new widths array: selected columns get equal share, unselected unchanged.
714
- // Assign truncated (2dp) equal widths to all selected cols except the last, which absorbs
713
+ // Assign rounded (2dp) equal widths to all selected cols except the last, which absorbs
715
714
  // the rounding remainder so the sum of selected widths equals selectedTotal exactly.
716
715
  var selectedIndexSet = new Set(selectedColumnIndices);
717
716
  var assignedToSelected = 0;
@@ -722,16 +721,22 @@ var distributeLayoutColumns = exports.distributeLayoutColumns = function distrib
722
721
  }
723
722
  selectedAssignedCount += 1;
724
723
  if (selectedAssignedCount < selectedColumnCount) {
725
- var truncated = Number(equalWidth.toFixed(2));
726
- assignedToSelected += truncated;
727
- return truncated;
724
+ assignedToSelected += equalWidth;
725
+ return equalWidth;
728
726
  }
729
727
  // Last selected column: absorb the remainder to avoid drift
730
728
  return Number((selectedTotal - assignedToSelected).toFixed(2));
731
729
  });
732
730
 
733
- // Apply widths via replaceWith (mirroring forceColumnWidths approach)
734
- tr.replaceWith(layoutSectionPos + 1, layoutSectionPos + layoutSectionNode.nodeSize - 1, columnWidth(layoutSectionNode, tr.doc.type.schema, newWidths));
731
+ // Apply widths via setNodeMarkup per selected column — keeps nodes in place (preserves identity, marks, decorations)
732
+ selectedColumns.forEach(function (_ref0, i) {
733
+ var node = _ref0.node,
734
+ pos = _ref0.pos;
735
+ var colIdx = selectedColumnIndices[i];
736
+ tr.setNodeMarkup(pos, node.type, _objectSpread(_objectSpread({}, node.attrs), {}, {
737
+ width: newWidths[colIdx]
738
+ }));
739
+ });
735
740
  editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent({
736
741
  action: _analytics.ACTION.UPDATED,
737
742
  actionSubject: _analytics.ACTION_SUBJECT.DOCUMENT,
@@ -749,11 +754,11 @@ var distributeLayoutColumns = exports.distributeLayoutColumns = function distrib
749
754
  return tr;
750
755
  };
751
756
  };
752
- var toggleLayoutColumnMenu = exports.toggleLayoutColumnMenu = function toggleLayoutColumnMenu(_ref9) {
753
- var anchorPos = _ref9.anchorPos,
754
- isOpen = _ref9.isOpen;
755
- return function (_ref0) {
756
- var tr = _ref0.tr;
757
+ var toggleLayoutColumnMenu = exports.toggleLayoutColumnMenu = function toggleLayoutColumnMenu(_ref1) {
758
+ var anchorPos = _ref1.anchorPos,
759
+ isOpen = _ref1.isOpen;
760
+ return function (_ref10) {
761
+ var tr = _ref10.tr;
757
762
  tr.setMeta('toggleLayoutColumnMenu', {
758
763
  anchorPos: anchorPos,
759
764
  isOpen: isOpen
@@ -763,8 +768,8 @@ var toggleLayoutColumnMenu = exports.toggleLayoutColumnMenu = function toggleLay
763
768
  };
764
769
  };
765
770
  var deleteLayoutColumn = exports.deleteLayoutColumn = function deleteLayoutColumn(editorAnalyticsAPI) {
766
- return function (_ref1) {
767
- var tr = _ref1.tr;
771
+ return function (_ref11) {
772
+ var tr = _ref11.tr;
768
773
  if (!(0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_layout_column_menu', 'isEnabled', true)) {
769
774
  return null;
770
775
  }
@@ -822,7 +827,7 @@ var deleteLayoutColumn = exports.deleteLayoutColumn = function deleteLayoutColum
822
827
  .sort(function (a, b) {
823
828
  return b - a;
824
829
  }).reduce(function (widths, selectedIndex) {
825
- return (0, _redistributeProportionally.redistributeAfterDeletion)(widths, selectedIndex, _consts.MIN_LAYOUT_COLUMN_WIDTH_PERCENT);
830
+ return (0, _layoutColumnDistribution.redistributeAfterDeletion)(widths, selectedIndex, _consts.MIN_LAYOUT_COLUMN_WIDTH_PERCENT);
826
831
  }, existingWidths);
827
832
  var updatedLayoutSectionNode = layoutSectionNode.copy(_model.Fragment.fromArray(remainingColumns));
828
833
  tr.replaceWith(layoutSectionPos + 1, layoutSectionPos + layoutSectionNode.nodeSize - 1, columnWidth(updatedLayoutSectionNode, tr.doc.type.schema, redistributed));
@@ -4,6 +4,8 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
+ exports.calculateDistribution = void 0;
8
+ exports.isDistributedUniformly = isDistributedUniformly;
7
9
  exports.redistributeProportionally = exports.redistributeAfterDeletion = void 0;
8
10
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
11
  var roundLayoutColumnWidth = function roundLayoutColumnWidth(width) {
@@ -14,9 +16,6 @@ var sumWidths = function sumWidths(widths) {
14
16
  return sum + width;
15
17
  }, 0);
16
18
  };
17
- var isValidWidth = function isValidWidth(width) {
18
- return Number.isFinite(width) && width > 0;
19
- };
20
19
  var normaliseWidthsTotal = function normaliseWidthsTotal(widths, totalWidth, minWidth) {
21
20
  var roundedWidths = widths.map(roundLayoutColumnWidth);
22
21
  var remainder = roundLayoutColumnWidth(totalWidth - sumWidths(roundedWidths));
@@ -37,6 +36,9 @@ var normaliseWidthsTotal = function normaliseWidthsTotal(widths, totalWidth, min
37
36
  return index === adjustmentIndex ? adjustedWidth : width;
38
37
  });
39
38
  };
39
+ var isValidWidth = function isValidWidth(width) {
40
+ return Number.isFinite(width) && width > 0;
41
+ };
40
42
  var redistributeWithMinimumWidth = function redistributeWithMinimumWidth(_ref) {
41
43
  var minWidth = _ref.minWidth,
42
44
  totalWidth = _ref.totalWidth,
@@ -81,6 +83,40 @@ var redistributeWithMinimumWidth = function redistributeWithMinimumWidth(_ref) {
81
83
  });
82
84
  return widths;
83
85
  };
86
+
87
+ /**
88
+ * Returns true when the given selected columns already reflect the distribution that
89
+ * `distributeLayoutColumns` would produce — i.e. the first N-1 cols each hold
90
+ * `equalWidth` (rounded to 2 dp) and the last col absorbs the rounding remainder.
91
+ *
92
+ * This mirrors the action's "last col absorbs remainder" logic so that the UI can
93
+ * disable the option when it would be a no-op, avoiding spurious undo entries.
94
+ */
95
+
96
+ var calculateDistribution = exports.calculateDistribution = function calculateDistribution(selectedWidths) {
97
+ var count = selectedWidths.length;
98
+ if (count < 2) {
99
+ return undefined;
100
+ }
101
+ var selectedTotal = sumWidths(selectedWidths);
102
+ var equalWidth = roundLayoutColumnWidth(selectedTotal / count);
103
+ return {
104
+ selectedTotal: selectedTotal,
105
+ equalWidth: equalWidth
106
+ };
107
+ };
108
+ function isDistributedUniformly(selectedWidths) {
109
+ var distribution = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : calculateDistribution(selectedWidths);
110
+ if (!distribution || selectedWidths.length < 2) {
111
+ return false;
112
+ }
113
+ var selectedTotal = distribution.selectedTotal,
114
+ equalWidth = distribution.equalWidth;
115
+ var lastColWidth = roundLayoutColumnWidth(selectedTotal - equalWidth * (selectedWidths.length - 1));
116
+ return selectedWidths.slice(0, -1).every(function (width) {
117
+ return width === equalWidth;
118
+ }) && selectedWidths[selectedWidths.length - 1] === lastColWidth;
119
+ }
84
120
  var redistributeAfterDeletion = exports.redistributeAfterDeletion = function redistributeAfterDeletion(currentWidths, removeIndex, minWidth) {
85
121
  if (currentWidths.length === 0 || removeIndex < 0 || removeIndex >= currentWidths.length || !isValidWidth(minWidth)) {
86
122
  return currentWidths;
@@ -112,7 +112,8 @@ var getLayoutSectionColumnCount = exports.getLayoutSectionColumnCount = function
112
112
  return (layoutSection === null || layoutSection === void 0 ? void 0 : layoutSection.type.name) === 'layoutSection' ? layoutSection.childCount : 0;
113
113
  };
114
114
  var getLayoutColumnValign = exports.getLayoutColumnValign = function getLayoutColumnValign(layoutColumn) {
115
- return layoutColumn === null || layoutColumn === void 0 ? void 0 : layoutColumn.attrs.valign;
115
+ var _ref2;
116
+ return layoutColumn ? (_ref2 = layoutColumn.attrs.valign) !== null && _ref2 !== void 0 ? _ref2 : 'top' : undefined;
116
117
  };
117
118
  var getLayoutColumnMenuAnchorPos = exports.getLayoutColumnMenuAnchorPos = function getLayoutColumnMenuAnchorPos(selection, anchorPosFromHandle) {
118
119
  var _clickedSelectedColum, _selectedLayoutColumn;
@@ -120,8 +121,8 @@ var getLayoutColumnMenuAnchorPos = exports.getLayoutColumnMenuAnchorPos = functi
120
121
  if (!selectedLayoutColumns) {
121
122
  return undefined;
122
123
  }
123
- var clickedSelectedColumn = selectedLayoutColumns.selectedColumns.find(function (_ref2) {
124
- var pos = _ref2.pos;
124
+ var clickedSelectedColumn = selectedLayoutColumns.selectedColumns.find(function (_ref3) {
125
+ var pos = _ref3.pos;
125
126
  return pos === anchorPosFromHandle;
126
127
  });
127
128
  return (_clickedSelectedColum = clickedSelectedColumn === null || clickedSelectedColumn === void 0 ? void 0 : clickedSelectedColumn.pos) !== null && _clickedSelectedColum !== void 0 ? _clickedSelectedColum : (_selectedLayoutColumn = selectedLayoutColumns.selectedColumns[0]) === null || _selectedLayoutColumn === void 0 ? void 0 : _selectedLayoutColumn.pos;
@@ -9,6 +9,7 @@ var _react = _interopRequireWildcard(require("react"));
9
9
  var _reactIntl = require("react-intl");
10
10
  var _messages = require("@atlaskit/editor-common/messages");
11
11
  var _editorToolbar = require("@atlaskit/editor-toolbar");
12
+ var _layoutColumnDistribution = require("../../pm-plugins/utils/layout-column-distribution");
12
13
  var _useSelectedLayoutColumns = require("./useSelectedLayoutColumns");
13
14
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
14
15
  var DistributeColumnsDropdownItem = exports.DistributeColumnsDropdownItem = function DistributeColumnsDropdownItem(_ref) {
@@ -32,9 +33,6 @@ var DistributeColumnsDropdownItem = exports.DistributeColumnsDropdownItem = func
32
33
  return closedTr !== null && closedTr !== void 0 ? closedTr : tr;
33
34
  });
34
35
  }, [api]);
35
-
36
- // Hide when selected columns are already evenly distributed — no-op action.
37
- // Must be before any early return to satisfy rules-of-hooks.
38
36
  var isAlreadyUniform = (0, _react.useMemo)(function () {
39
37
  if (!selectedLayoutColumns || selectedLayoutColumns.selectedColumns.length < 2) {
40
38
  return false;
@@ -42,21 +40,13 @@ var DistributeColumnsDropdownItem = exports.DistributeColumnsDropdownItem = func
42
40
  var selectedWidths = selectedLayoutColumns.selectedColumns.map(function (col) {
43
41
  return col.node.attrs.width;
44
42
  });
45
- var selectedTotal = selectedWidths.reduce(function (sum, w) {
46
- return sum + w;
47
- }, 0);
48
- var equalWidth = Number((selectedTotal / selectedWidths.length).toFixed(2));
49
- return selectedWidths.every(function (w) {
50
- return w === equalWidth;
51
- });
43
+ return (0, _layoutColumnDistribution.isDistributedUniformly)(selectedWidths);
52
44
  }, [selectedLayoutColumns]);
53
45
  if (selectedLayoutColumns === undefined || selectedLayoutColumns.selectedColumns.length < 2) {
54
46
  return null;
55
47
  }
56
- if (isAlreadyUniform) {
57
- return null;
58
- }
59
48
  return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownItem, {
60
- onClick: handleClick
49
+ onClick: handleClick,
50
+ isDisabled: isAlreadyUniform
61
51
  }, formatMessage(_messages.layoutMessages.distributeColumns));
62
52
  };
@@ -35,6 +35,7 @@ var VerticalAlignDropdownItem = exports.VerticalAlignDropdownItem = function Ver
35
35
  size: "small"
36
36
  }),
37
37
  isSelected: isSelected,
38
- onClick: onClick
38
+ onClick: onClick,
39
+ role: "menuitemradio"
39
40
  }, formatMessage(label));
40
41
  };
@@ -31,10 +31,7 @@ var VerticalAlignNestedMenu = exports.VerticalAlignNestedMenu = function Vertica
31
31
  }
32
32
  return firstValign;
33
33
  }, [selectedLayoutColumns]);
34
- var TriggerIcon = currentValign ? _verticalAlignIcons.VERTICAL_ALIGN_ICONS[currentValign] : _editorToolbar.LayoutIcon;
35
- if (!selectedLayoutColumns) {
36
- return null;
37
- }
34
+ var TriggerIcon = currentValign ? _verticalAlignIcons.VERTICAL_ALIGN_ICONS[currentValign] : _verticalAlignIcons.VERTICAL_ALIGN_ICONS.top;
38
35
  return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarNestedDropdownMenu, {
39
36
  elemBefore: /*#__PURE__*/_react.default.createElement(TriggerIcon, {
40
37
  label: "",
@@ -1,13 +1,15 @@
1
1
  "use strict";
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof = require("@babel/runtime/helpers/typeof");
4
5
  Object.defineProperty(exports, "__esModule", {
5
6
  value: true
6
7
  });
7
8
  exports.getLayoutColumnMenuComponents = exports.LAYOUT_COLUMN_MENU_FALLBACKS = void 0;
8
9
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
- var _react = _interopRequireDefault(require("react"));
10
+ var _react = _interopRequireWildcard(require("react"));
10
11
  var _messages = require("@atlaskit/editor-common/messages");
12
+ var _uiReact = require("@atlaskit/editor-common/ui-react");
11
13
  var _editorToolbar = require("@atlaskit/editor-toolbar");
12
14
  var _toolbarMenuContainer = require("@atlaskit/editor-toolbar/toolbar-menu-container");
13
15
  var _DeleteColumnDropdownItem = require("./DeleteColumnDropdownItem");
@@ -16,18 +18,26 @@ var _InsertColumnDropdownItem = require("./InsertColumnDropdownItem");
16
18
  var _keys = require("./keys");
17
19
  var _VerticalAlignDropdownItem = require("./VerticalAlignDropdownItem");
18
20
  var _VerticalAlignNestedMenu = require("./VerticalAlignNestedMenu");
21
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
19
22
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
20
23
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
24
+ var LayoutColumnMenuContainer = function LayoutColumnMenuContainer(_ref) {
25
+ var children = _ref.children;
26
+ var setOutsideClickTargetRef = (0, _react.useContext)(_uiReact.OutsideClickTargetRefContext);
27
+ return /*#__PURE__*/_react.default.createElement(_toolbarMenuContainer.ToolbarMenuContainer, {
28
+ ref: setOutsideClickTargetRef
29
+ }, children);
30
+ };
21
31
  var LAYOUT_COLUMN_MENU_FALLBACKS = exports.LAYOUT_COLUMN_MENU_FALLBACKS = {
22
- 'menu-section': function menuSection(_ref) {
23
- var children = _ref.children;
32
+ 'menu-section': function menuSection(_ref2) {
33
+ var children = _ref2.children;
24
34
  return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownItemSection, null, children);
25
35
  }
26
36
  };
27
- var getLayoutColumnMenuComponents = exports.getLayoutColumnMenuComponents = function getLayoutColumnMenuComponents(_ref2) {
28
- var api = _ref2.api;
37
+ var getLayoutColumnMenuComponents = exports.getLayoutColumnMenuComponents = function getLayoutColumnMenuComponents(_ref3) {
38
+ var api = _ref3.api;
29
39
  return [_objectSpread(_objectSpread({}, _keys.LAYOUT_COLUMN_MENU), {}, {
30
- component: _toolbarMenuContainer.ToolbarMenuContainer
40
+ component: LayoutColumnMenuContainer
31
41
  }), _objectSpread(_objectSpread({}, _keys.LAYOUT_COLUMN_MENU_SECTION), {}, {
32
42
  parents: [_objectSpread(_objectSpread({}, _keys.LAYOUT_COLUMN_MENU), {}, {
33
43
  rank: _keys.LAYOUT_COLUMN_MENU_RANK[_keys.LAYOUT_COLUMN_MENU_SECTION.key]
@@ -71,8 +81,8 @@ var getLayoutColumnMenuComponents = exports.getLayoutColumnMenuComponents = func
71
81
  rank: _keys.LAYOUT_COLUMN_MENU_SECTION_RANK[_keys.DELETE_COLUMN_MENU_ITEM.key]
72
82
  })]
73
83
  }), _objectSpread(_objectSpread({}, _keys.VERTICAL_ALIGN_MENU), {}, {
74
- component: function component(_ref3) {
75
- var children = _ref3.children;
84
+ component: function component(_ref4) {
85
+ var children = _ref4.children;
76
86
  return /*#__PURE__*/_react.default.createElement(_VerticalAlignNestedMenu.VerticalAlignNestedMenu, {
77
87
  api: api
78
88
  }, children);
@@ -1,16 +1,13 @@
1
1
  "use strict";
2
2
 
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
3
  var _typeof = require("@babel/runtime/helpers/typeof");
5
4
  Object.defineProperty(exports, "__esModule", {
6
5
  value: true
7
6
  });
8
7
  exports.LayoutColumnMenu = void 0;
9
- var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
8
  var _react = _interopRequireWildcard(require("react"));
11
9
  var _hooks = require("@atlaskit/editor-common/hooks");
12
10
  var _styles = require("@atlaskit/editor-common/styles");
13
- var _toolbar = require("@atlaskit/editor-common/toolbar");
14
11
  var _ui = require("@atlaskit/editor-common/ui");
15
12
  var _uiReact = require("@atlaskit/editor-common/ui-react");
16
13
  var _editorSharedStyles = require("@atlaskit/editor-shared-styles");
@@ -21,8 +18,8 @@ var _components = require("./components");
21
18
  var _keys = require("./keys");
22
19
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
23
20
  var PopupWithListeners = (0, _uiReact.withReactEditorViewOuterListeners)(_ui.Popup);
24
- var FALLBACK_MENU_HEIGHT = 300;
25
21
  var LAYOUT_COLUMN_MENU_POPUP_OFFSET = [0, 4];
22
+ var TOOLBAR_MENU_SELECTOR = '[data-toolbar-component="menu"]';
26
23
 
27
24
  /**
28
25
  * Returns the drag handle button for the selected layout column.
@@ -58,20 +55,6 @@ var LayoutColumnMenu = exports.LayoutColumnMenu = /*#__PURE__*/_react.default.me
58
55
  isLayoutColumnMenuOpen = _useSharedPluginState.isLayoutColumnMenuOpen,
59
56
  layoutColumnMenuAnchorPos = _useSharedPluginState.layoutColumnMenuAnchorPos,
60
57
  selection = _useSharedPluginState.selection;
61
- var setOutsideClickTargetRef = (0, _react.useContext)(_uiReact.OutsideClickTargetRefContext);
62
- var menuRef = (0, _react.useRef)(null);
63
- var popupRef = (0, _react.useRef)(undefined);
64
- var _React$useState = _react.default.useState(FALLBACK_MENU_HEIGHT),
65
- _React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
66
- menuHeight = _React$useState2[0],
67
- setMenuHeight = _React$useState2[1];
68
- (0, _react.useLayoutEffect)(function () {
69
- var _popupRef$current;
70
- if (!isLayoutColumnMenuOpen) {
71
- return;
72
- }
73
- setMenuHeight(((_popupRef$current = popupRef.current) === null || _popupRef$current === void 0 ? void 0 : _popupRef$current.clientHeight) || FALLBACK_MENU_HEIGHT);
74
- }, [isLayoutColumnMenuOpen]);
75
58
  var closeLayoutColumnMenu = (0, _react.useCallback)(function () {
76
59
  var _api$core, _api$layout;
77
60
  api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api === null || api === void 0 || (_api$layout = api.layout) === null || _api$layout === void 0 ? void 0 : _api$layout.commands.toggleLayoutColumnMenu({
@@ -79,11 +62,7 @@ var LayoutColumnMenu = exports.LayoutColumnMenu = /*#__PURE__*/_react.default.me
79
62
  }));
80
63
  }, [api]);
81
64
  var handleClickOutside = (0, _react.useCallback)(function (event) {
82
- var _menuRef$current;
83
- if (event.target instanceof Node && (_menuRef$current = menuRef.current) !== null && _menuRef$current !== void 0 && _menuRef$current.contains(event.target)) {
84
- return;
85
- }
86
- if (event.target instanceof Element && event.target.closest('[data-toolbar-nested-dropdown-menu]')) {
65
+ if (event.target instanceof Element && (event.target.closest(TOOLBAR_MENU_SELECTOR) || event.target.closest('[data-toolbar-nested-dropdown-menu]'))) {
87
66
  return;
88
67
  }
89
68
 
@@ -100,13 +79,6 @@ var LayoutColumnMenu = exports.LayoutColumnMenu = /*#__PURE__*/_react.default.me
100
79
  closeLayoutColumnMenu();
101
80
  }
102
81
  }, [closeLayoutColumnMenu]);
103
- var handleMenuRef = (0, _react.useCallback)(function (el) {
104
- setOutsideClickTargetRef === null || setOutsideClickTargetRef === void 0 || setOutsideClickTargetRef(el);
105
- menuRef.current = el;
106
- if (el) {
107
- popupRef.current = el;
108
- }
109
- }, [setOutsideClickTargetRef]);
110
82
  var components = (_api$uiControlRegistr = api === null || api === void 0 || (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.getComponents(_keys.LAYOUT_COLUMN_MENU.key)) !== null && _api$uiControlRegistr !== void 0 ? _api$uiControlRegistr : [];
111
83
  var target = (0, _react.useMemo)(function () {
112
84
  return isLayoutColumnMenuOpen ? getLayoutColumnMenuTarget(editorView, selection, layoutColumnMenuAnchorPos) : null;
@@ -127,16 +99,11 @@ var LayoutColumnMenu = exports.LayoutColumnMenu = /*#__PURE__*/_react.default.me
127
99
  scrollableElement: scrollableElement,
128
100
  zIndex: _editorSharedStyles.akEditorFloatingOverlapPanelZIndex,
129
101
  alignX: "center",
130
- fitHeight: menuHeight,
131
102
  preventOverflow: true,
132
103
  stick: true,
133
104
  offset: LAYOUT_COLUMN_MENU_POPUP_OFFSET,
134
105
  handleClickOutside: handleClickOutside,
135
106
  handleEscapeKeydown: closeLayoutColumnMenu
136
- }, /*#__PURE__*/_react.default.createElement("div", {
137
- ref: handleMenuRef
138
- }, /*#__PURE__*/_react.default.createElement(_toolbar.EditorToolbarProvider, {
139
- editorView: editorView
140
107
  }, /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownMenuProvider, {
141
108
  isOpen: isLayoutColumnMenuOpen,
142
109
  setIsOpen: handleSetIsOpen
@@ -144,5 +111,5 @@ var LayoutColumnMenu = exports.LayoutColumnMenu = /*#__PURE__*/_react.default.me
144
111
  components: components,
145
112
  fallbacks: _components.LAYOUT_COLUMN_MENU_FALLBACKS,
146
113
  surface: _keys.LAYOUT_COLUMN_MENU
147
- })))));
114
+ })));
148
115
  });
@@ -9,8 +9,8 @@ import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equ
9
9
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
10
10
  import { EVEN_DISTRIBUTED_COL_WIDTHS, MAX_LAYOUT_COLUMNS, MAX_STANDARD_LAYOUT_COLUMNS, MIN_LAYOUT_COLUMN_WIDTH_PERCENT } from './consts';
11
11
  import { pluginKey } from './plugin-key';
12
+ import { calculateDistribution, isDistributedUniformly, redistributeAfterDeletion, redistributeProportionally } from './utils/layout-column-distribution';
12
13
  import { getSelectedLayoutColumns } from './utils/layout-column-selection';
13
- import { redistributeAfterDeletion, redistributeProportionally } from './utils/redistribute-proportionally';
14
14
  export const ONE_COL_LAYOUTS = ['single'];
15
15
  export const TWO_COL_LAYOUTS = ['two_equal', 'two_left_sidebar', 'two_right_sidebar'];
16
16
  export const THREE_COL_LAYOUTS = ['three_equal', 'three_with_sidebars'];
@@ -664,26 +664,30 @@ export const distributeLayoutColumns = (editorAnalyticsAPI, inputMethod = INPUT_
664
664
  }
665
665
  const {
666
666
  layoutSectionNode,
667
- layoutSectionPos,
668
667
  selectedColumnIndices,
669
668
  selectedColumns
670
669
  } = selectedLayoutColumns;
671
670
  const endIndex = selectedColumnIndices[selectedColumnIndices.length - 1];
672
671
  const selectedColumnCount = selectedColumns.length;
673
672
  const totalColumnCount = layoutSectionNode.childCount;
674
-
675
- // Compute equal width for selected columns
676
673
  const existingWidths = mapChildren(layoutSectionNode, column => column.attrs.width);
677
- const selectedTotal = selectedColumnIndices.reduce((sum, idx) => sum + existingWidths[idx], 0);
678
- const equalWidth = selectedTotal / selectedColumnCount;
679
-
680
- // Early return if selected columns are already uniformly distributed — avoids spurious undo entry.
681
- if (selectedColumnIndices.every(idx => existingWidths[idx] === Number(equalWidth.toFixed(2)))) {
674
+ const selectedWidths = selectedColumns.map(({
675
+ node
676
+ }) => node.attrs.width);
677
+ const distribution = calculateDistribution(selectedWidths);
678
+ if (!distribution) {
679
+ return null;
680
+ }
681
+ const {
682
+ selectedTotal,
683
+ equalWidth
684
+ } = distribution;
685
+ if (isDistributedUniformly(selectedWidths, distribution)) {
682
686
  return null;
683
687
  }
684
688
 
685
689
  // Build new widths array: selected columns get equal share, unselected unchanged.
686
- // Assign truncated (2dp) equal widths to all selected cols except the last, which absorbs
690
+ // Assign rounded (2dp) equal widths to all selected cols except the last, which absorbs
687
691
  // the rounding remainder so the sum of selected widths equals selectedTotal exactly.
688
692
  const selectedIndexSet = new Set(selectedColumnIndices);
689
693
  let assignedToSelected = 0;
@@ -694,16 +698,24 @@ export const distributeLayoutColumns = (editorAnalyticsAPI, inputMethod = INPUT_
694
698
  }
695
699
  selectedAssignedCount += 1;
696
700
  if (selectedAssignedCount < selectedColumnCount) {
697
- const truncated = Number(equalWidth.toFixed(2));
698
- assignedToSelected += truncated;
699
- return truncated;
701
+ assignedToSelected += equalWidth;
702
+ return equalWidth;
700
703
  }
701
704
  // Last selected column: absorb the remainder to avoid drift
702
705
  return Number((selectedTotal - assignedToSelected).toFixed(2));
703
706
  });
704
707
 
705
- // Apply widths via replaceWith (mirroring forceColumnWidths approach)
706
- tr.replaceWith(layoutSectionPos + 1, layoutSectionPos + layoutSectionNode.nodeSize - 1, columnWidth(layoutSectionNode, tr.doc.type.schema, newWidths));
708
+ // Apply widths via setNodeMarkup per selected column — keeps nodes in place (preserves identity, marks, decorations)
709
+ selectedColumns.forEach(({
710
+ node,
711
+ pos
712
+ }, i) => {
713
+ const colIdx = selectedColumnIndices[i];
714
+ tr.setNodeMarkup(pos, node.type, {
715
+ ...node.attrs,
716
+ width: newWidths[colIdx]
717
+ });
718
+ });
707
719
  editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 ? void 0 : editorAnalyticsAPI.attachAnalyticsEvent({
708
720
  action: ACTION.UPDATED,
709
721
  actionSubject: ACTION_SUBJECT.DOCUMENT,
@@ -1,6 +1,5 @@
1
1
  const roundLayoutColumnWidth = width => Number(width.toFixed(2));
2
2
  const sumWidths = widths => widths.reduce((sum, width) => sum + width, 0);
3
- const isValidWidth = width => Number.isFinite(width) && width > 0;
4
3
  const normaliseWidthsTotal = (widths, totalWidth, minWidth) => {
5
4
  const roundedWidths = widths.map(roundLayoutColumnWidth);
6
5
  const remainder = roundLayoutColumnWidth(totalWidth - sumWidths(roundedWidths));
@@ -19,6 +18,7 @@ const normaliseWidthsTotal = (widths, totalWidth, minWidth) => {
19
18
  }
20
19
  return roundedWidths.map((width, index) => index === adjustmentIndex ? adjustedWidth : width);
21
20
  };
21
+ const isValidWidth = width => Number.isFinite(width) && width > 0;
22
22
  const redistributeWithMinimumWidth = ({
23
23
  minWidth,
24
24
  totalWidth,
@@ -61,6 +61,39 @@ const redistributeWithMinimumWidth = ({
61
61
  });
62
62
  return widths;
63
63
  };
64
+
65
+ /**
66
+ * Returns true when the given selected columns already reflect the distribution that
67
+ * `distributeLayoutColumns` would produce — i.e. the first N-1 cols each hold
68
+ * `equalWidth` (rounded to 2 dp) and the last col absorbs the rounding remainder.
69
+ *
70
+ * This mirrors the action's "last col absorbs remainder" logic so that the UI can
71
+ * disable the option when it would be a no-op, avoiding spurious undo entries.
72
+ */
73
+
74
+ export const calculateDistribution = selectedWidths => {
75
+ const count = selectedWidths.length;
76
+ if (count < 2) {
77
+ return undefined;
78
+ }
79
+ const selectedTotal = sumWidths(selectedWidths);
80
+ const equalWidth = roundLayoutColumnWidth(selectedTotal / count);
81
+ return {
82
+ selectedTotal,
83
+ equalWidth
84
+ };
85
+ };
86
+ export function isDistributedUniformly(selectedWidths, distribution = calculateDistribution(selectedWidths)) {
87
+ if (!distribution || selectedWidths.length < 2) {
88
+ return false;
89
+ }
90
+ const {
91
+ selectedTotal,
92
+ equalWidth
93
+ } = distribution;
94
+ const lastColWidth = roundLayoutColumnWidth(selectedTotal - equalWidth * (selectedWidths.length - 1));
95
+ return selectedWidths.slice(0, -1).every(width => width === equalWidth) && selectedWidths[selectedWidths.length - 1] === lastColWidth;
96
+ }
64
97
  export const redistributeAfterDeletion = (currentWidths, removeIndex, minWidth) => {
65
98
  if (currentWidths.length === 0 || removeIndex < 0 || removeIndex >= currentWidths.length || !isValidWidth(minWidth)) {
66
99
  return currentWidths;
@@ -104,7 +104,10 @@ export const getSelectedLayoutColumns = selection => {
104
104
  };
105
105
  };
106
106
  export const getLayoutSectionColumnCount = layoutSection => (layoutSection === null || layoutSection === void 0 ? void 0 : layoutSection.type.name) === 'layoutSection' ? layoutSection.childCount : 0;
107
- export const getLayoutColumnValign = layoutColumn => layoutColumn === null || layoutColumn === void 0 ? void 0 : layoutColumn.attrs.valign;
107
+ export const getLayoutColumnValign = layoutColumn => {
108
+ var _ref;
109
+ return layoutColumn ? (_ref = layoutColumn.attrs.valign) !== null && _ref !== void 0 ? _ref : 'top' : undefined;
110
+ };
108
111
  export const getLayoutColumnMenuAnchorPos = (selection, anchorPosFromHandle) => {
109
112
  var _clickedSelectedColum, _selectedLayoutColumn;
110
113
  const selectedLayoutColumns = getSelectedLayoutColumns(selection);