@atlaskit/editor-plugin-layout 10.3.3 → 10.3.5

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 (62) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/layoutPlugin.js +4 -0
  3. package/dist/cjs/pm-plugins/actions.js +102 -7
  4. package/dist/cjs/pm-plugins/column-resize-divider.js +7 -9
  5. package/dist/cjs/pm-plugins/consts.js +4 -1
  6. package/dist/cjs/pm-plugins/utils/redistribute-proportionally.js +111 -0
  7. package/dist/cjs/ui/LayoutColumnMenu/InsertColumnDropdownItem.js +69 -0
  8. package/dist/cjs/ui/LayoutColumnMenu/VerticalAlignDropdownItem.js +7 -9
  9. package/dist/cjs/ui/LayoutColumnMenu/VerticalAlignNestedMenu.js +11 -10
  10. package/dist/cjs/ui/LayoutColumnMenu/components.js +21 -0
  11. package/dist/cjs/ui/LayoutColumnMenu/index.js +39 -11
  12. package/dist/cjs/ui/LayoutColumnMenu/keys.js +10 -2
  13. package/dist/cjs/ui/LayoutColumnMenu/layoutColumnSelection.js +21 -0
  14. package/dist/cjs/ui/LayoutColumnMenu/useCurrentLayoutColumn.js +20 -0
  15. package/dist/es2019/layoutPlugin.js +5 -1
  16. package/dist/es2019/pm-plugins/actions.js +98 -1
  17. package/dist/es2019/pm-plugins/column-resize-divider.js +8 -9
  18. package/dist/es2019/pm-plugins/consts.js +3 -0
  19. package/dist/es2019/pm-plugins/utils/redistribute-proportionally.js +89 -0
  20. package/dist/es2019/ui/LayoutColumnMenu/InsertColumnDropdownItem.js +64 -0
  21. package/dist/es2019/ui/LayoutColumnMenu/VerticalAlignDropdownItem.js +6 -11
  22. package/dist/es2019/ui/LayoutColumnMenu/VerticalAlignNestedMenu.js +7 -10
  23. package/dist/es2019/ui/LayoutColumnMenu/components.js +22 -1
  24. package/dist/es2019/ui/LayoutColumnMenu/index.js +34 -13
  25. package/dist/es2019/ui/LayoutColumnMenu/keys.js +12 -2
  26. package/dist/es2019/ui/LayoutColumnMenu/layoutColumnSelection.js +9 -0
  27. package/dist/es2019/ui/LayoutColumnMenu/useCurrentLayoutColumn.js +10 -0
  28. package/dist/esm/layoutPlugin.js +5 -1
  29. package/dist/esm/pm-plugins/actions.js +101 -7
  30. package/dist/esm/pm-plugins/column-resize-divider.js +8 -9
  31. package/dist/esm/pm-plugins/consts.js +3 -0
  32. package/dist/esm/pm-plugins/utils/redistribute-proportionally.js +104 -0
  33. package/dist/esm/ui/LayoutColumnMenu/InsertColumnDropdownItem.js +61 -0
  34. package/dist/esm/ui/LayoutColumnMenu/VerticalAlignDropdownItem.js +8 -10
  35. package/dist/esm/ui/LayoutColumnMenu/VerticalAlignNestedMenu.js +9 -9
  36. package/dist/esm/ui/LayoutColumnMenu/components.js +22 -1
  37. package/dist/esm/ui/LayoutColumnMenu/index.js +40 -13
  38. package/dist/esm/ui/LayoutColumnMenu/keys.js +9 -1
  39. package/dist/esm/ui/LayoutColumnMenu/layoutColumnSelection.js +15 -0
  40. package/dist/esm/ui/LayoutColumnMenu/useCurrentLayoutColumn.js +14 -0
  41. package/dist/types/layoutPluginType.d.ts +3 -2
  42. package/dist/types/pm-plugins/actions.d.ts +6 -0
  43. package/dist/types/pm-plugins/consts.d.ts +3 -0
  44. package/dist/types/pm-plugins/utils/redistribute-proportionally.d.ts +1 -0
  45. package/dist/types/ui/LayoutColumnMenu/InsertColumnDropdownItem.d.ts +10 -0
  46. package/dist/types/ui/LayoutColumnMenu/keys.d.ts +2 -0
  47. package/dist/types/ui/LayoutColumnMenu/layoutColumnSelection.d.ts +7 -0
  48. package/dist/types/ui/LayoutColumnMenu/useCurrentLayoutColumn.d.ts +5 -0
  49. package/dist/types-ts4.5/layoutPluginType.d.ts +3 -2
  50. package/dist/types-ts4.5/pm-plugins/actions.d.ts +6 -0
  51. package/dist/types-ts4.5/pm-plugins/consts.d.ts +3 -0
  52. package/dist/types-ts4.5/pm-plugins/utils/redistribute-proportionally.d.ts +1 -0
  53. package/dist/types-ts4.5/ui/LayoutColumnMenu/InsertColumnDropdownItem.d.ts +10 -0
  54. package/dist/types-ts4.5/ui/LayoutColumnMenu/keys.d.ts +2 -0
  55. package/dist/types-ts4.5/ui/LayoutColumnMenu/layoutColumnSelection.d.ts +7 -0
  56. package/dist/types-ts4.5/ui/LayoutColumnMenu/useCurrentLayoutColumn.d.ts +5 -0
  57. package/package.json +5 -5
  58. package/dist/cjs/ui/LayoutColumnMenu/useCurrentLayoutColumnValign.js +0 -22
  59. package/dist/es2019/ui/LayoutColumnMenu/useCurrentLayoutColumnValign.js +0 -14
  60. package/dist/esm/ui/LayoutColumnMenu/useCurrentLayoutColumnValign.js +0 -16
  61. package/dist/types/ui/LayoutColumnMenu/useCurrentLayoutColumnValign.d.ts +0 -11
  62. package/dist/types-ts4.5/ui/LayoutColumnMenu/useCurrentLayoutColumnValign.d.ts +0 -11
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.VERTICAL_ALIGN_TOP_MENU_ITEM = exports.VERTICAL_ALIGN_MIDDLE_MENU_ITEM = exports.VERTICAL_ALIGN_MENU_SECTION_RANK = exports.VERTICAL_ALIGN_MENU_RANK = exports.VERTICAL_ALIGN_MENU = exports.VERTICAL_ALIGN_BOTTOM_MENU_ITEM = exports.LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION = exports.LAYOUT_COLUMN_MENU_SECTION_RANK = exports.LAYOUT_COLUMN_MENU_SECTION = exports.LAYOUT_COLUMN_MENU_RANK = exports.LAYOUT_COLUMN_MENU = exports.DISTRIBUTE_COLUMNS_MENU_ITEM = void 0;
7
+ exports.VERTICAL_ALIGN_TOP_MENU_ITEM = exports.VERTICAL_ALIGN_MIDDLE_MENU_ITEM = exports.VERTICAL_ALIGN_MENU_SECTION_RANK = exports.VERTICAL_ALIGN_MENU_RANK = exports.VERTICAL_ALIGN_MENU = exports.VERTICAL_ALIGN_BOTTOM_MENU_ITEM = exports.LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION = exports.LAYOUT_COLUMN_MENU_SECTION_RANK = exports.LAYOUT_COLUMN_MENU_SECTION = exports.LAYOUT_COLUMN_MENU_RANK = exports.LAYOUT_COLUMN_MENU = exports.INSERT_COLUMN_RIGHT_MENU_ITEM = exports.INSERT_COLUMN_LEFT_MENU_ITEM = exports.DISTRIBUTE_COLUMNS_MENU_ITEM = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  // --- Menu surface ---
10
10
 
@@ -34,6 +34,14 @@ var VERTICAL_ALIGN_MENU = exports.VERTICAL_ALIGN_MENU = {
34
34
 
35
35
  // --- Items ---
36
36
 
37
+ var INSERT_COLUMN_LEFT_MENU_ITEM = exports.INSERT_COLUMN_LEFT_MENU_ITEM = {
38
+ type: 'menu-item',
39
+ key: 'layout-column-menu-insert-left-item'
40
+ };
41
+ var INSERT_COLUMN_RIGHT_MENU_ITEM = exports.INSERT_COLUMN_RIGHT_MENU_ITEM = {
42
+ type: 'menu-item',
43
+ key: 'layout-column-menu-insert-right-item'
44
+ };
37
45
  var DISTRIBUTE_COLUMNS_MENU_ITEM = exports.DISTRIBUTE_COLUMNS_MENU_ITEM = {
38
46
  type: 'menu-item',
39
47
  key: 'layout-column-menu-distribute-columns-item'
@@ -53,6 +61,6 @@ var VERTICAL_ALIGN_BOTTOM_MENU_ITEM = exports.VERTICAL_ALIGN_BOTTOM_MENU_ITEM =
53
61
 
54
62
  // --- Item ranks within sections ---
55
63
 
56
- var LAYOUT_COLUMN_MENU_SECTION_RANK = exports.LAYOUT_COLUMN_MENU_SECTION_RANK = (0, _defineProperty2.default)((0, _defineProperty2.default)({}, DISTRIBUTE_COLUMNS_MENU_ITEM.key, 100), VERTICAL_ALIGN_MENU.key, 200);
64
+ var LAYOUT_COLUMN_MENU_SECTION_RANK = exports.LAYOUT_COLUMN_MENU_SECTION_RANK = (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, VERTICAL_ALIGN_MENU.key, 100), INSERT_COLUMN_LEFT_MENU_ITEM.key, 200), INSERT_COLUMN_RIGHT_MENU_ITEM.key, 300), DISTRIBUTE_COLUMNS_MENU_ITEM.key, 400);
57
65
  var VERTICAL_ALIGN_MENU_RANK = exports.VERTICAL_ALIGN_MENU_RANK = (0, _defineProperty2.default)({}, LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION.key, 100);
58
66
  var VERTICAL_ALIGN_MENU_SECTION_RANK = exports.VERTICAL_ALIGN_MENU_SECTION_RANK = (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, VERTICAL_ALIGN_TOP_MENU_ITEM.key, 100), VERTICAL_ALIGN_MIDDLE_MENU_ITEM.key, 200), VERTICAL_ALIGN_BOTTOM_MENU_ITEM.key, 300);
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getLayoutSectionColumnCount = exports.getLayoutSectionAtSelection = exports.getLayoutColumnValign = exports.getLayoutColumnAtSelection = void 0;
7
+ var _state = require("@atlaskit/editor-prosemirror/state");
8
+ var getLayoutColumnAtSelection = exports.getLayoutColumnAtSelection = function getLayoutColumnAtSelection(selection) {
9
+ return selection instanceof _state.NodeSelection && selection.node.type.name === 'layoutColumn' ? selection.node : undefined;
10
+ };
11
+ var getLayoutSectionAtSelection = exports.getLayoutSectionAtSelection = function getLayoutSectionAtSelection(selection) {
12
+ var selectedColumn = getLayoutColumnAtSelection(selection);
13
+ var parent = selectedColumn ? selection === null || selection === void 0 ? void 0 : selection.$from.parent : undefined;
14
+ return (parent === null || parent === void 0 ? void 0 : parent.type.name) === 'layoutSection' ? parent : undefined;
15
+ };
16
+ var getLayoutSectionColumnCount = exports.getLayoutSectionColumnCount = function getLayoutSectionColumnCount(layoutSection) {
17
+ return (layoutSection === null || layoutSection === void 0 ? void 0 : layoutSection.type.name) === 'layoutSection' ? layoutSection.childCount : 0;
18
+ };
19
+ var getLayoutColumnValign = exports.getLayoutColumnValign = function getLayoutColumnValign(layoutColumn) {
20
+ return layoutColumn === null || layoutColumn === void 0 ? void 0 : layoutColumn.attrs.valign;
21
+ };
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useCurrentLayoutSection = exports.useCurrentLayoutColumn = void 0;
7
+ var _hooks = require("@atlaskit/editor-common/hooks");
8
+ var _layoutColumnSelection = require("./layoutColumnSelection");
9
+ var useCurrentLayoutColumn = exports.useCurrentLayoutColumn = function useCurrentLayoutColumn(api) {
10
+ return (0, _hooks.useSharedPluginStateWithSelector)(api, ['selection'], function (states) {
11
+ var _states$selectionStat;
12
+ return (0, _layoutColumnSelection.getLayoutColumnAtSelection)((_states$selectionStat = states.selectionState) === null || _states$selectionStat === void 0 ? void 0 : _states$selectionStat.selection);
13
+ });
14
+ };
15
+ var useCurrentLayoutSection = exports.useCurrentLayoutSection = function useCurrentLayoutSection(api) {
16
+ return (0, _hooks.useSharedPluginStateWithSelector)(api, ['selection'], function (states) {
17
+ var _states$selectionStat2;
18
+ return (0, _layoutColumnSelection.getLayoutSectionAtSelection)((_states$selectionStat2 = states.selectionState) === null || _states$selectionStat2 === void 0 ? void 0 : _states$selectionStat2.selection);
19
+ });
20
+ };
@@ -10,7 +10,7 @@ import { findParentNode } from '@atlaskit/editor-prosemirror/utils';
10
10
  import { fg } from '@atlaskit/platform-feature-flags';
11
11
  import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
12
12
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
13
- import { createDefaultLayoutSection, createMultiColumnLayoutSection, insertLayoutColumnsWithAnalytics, setLayoutColumnValign, toggleLayoutColumnMenu } from './pm-plugins/actions';
13
+ import { createDefaultLayoutSection, createMultiColumnLayoutSection, insertLayoutColumn, insertLayoutColumnsWithAnalytics, setLayoutColumnValign, toggleLayoutColumnMenu } from './pm-plugins/actions';
14
14
  import { default as createLayoutPlugin } from './pm-plugins/main';
15
15
  import { pluginKey } from './pm-plugins/plugin-key';
16
16
  import { default as createLayoutResizingPlugin } from './pm-plugins/resizing';
@@ -290,6 +290,10 @@ export const layoutPlugin = ({
290
290
  return pluginKey.getState(editorState);
291
291
  },
292
292
  commands: {
293
+ insertLayoutColumn: side => {
294
+ var _api$analytics4;
295
+ return insertLayoutColumn(side, api === null || api === void 0 ? void 0 : (_api$analytics4 = api.analytics) === null || _api$analytics4 === void 0 ? void 0 : _api$analytics4.actions);
296
+ },
293
297
  setLayoutColumnValign,
294
298
  toggleLayoutColumnMenu
295
299
  }
@@ -7,8 +7,9 @@ import { safeInsert } from '@atlaskit/editor-prosemirror/utils';
7
7
  import { fg } from '@atlaskit/platform-feature-flags';
8
8
  import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
9
9
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
10
- import { EVEN_DISTRIBUTED_COL_WIDTHS } from './consts';
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 { redistributeProportionally } from './utils/redistribute-proportionally';
12
13
  export const ONE_COL_LAYOUTS = ['single'];
13
14
  export const TWO_COL_LAYOUTS = ['two_equal', 'two_left_sidebar', 'two_right_sidebar'];
14
15
  export const THREE_COL_LAYOUTS = ['three_equal', 'three_with_sidebars'];
@@ -526,6 +527,102 @@ const formatLayoutName = layout => {
526
527
  return LAYOUT_TYPE.THREE_WITH_SIDEBARS;
527
528
  }
528
529
  };
530
+ /**
531
+ * Returns the active maximum layout column count for the current advanced layouts experiment state.
532
+ */
533
+ export function getEffectiveMaxLayoutColumns() {
534
+ return editorExperiment('advanced_layouts', true) ? MAX_LAYOUT_COLUMNS : MAX_STANDARD_LAYOUT_COLUMNS;
535
+ }
536
+ const getSelectedLayoutColumnInSection = ({
537
+ doc,
538
+ selection
539
+ }) => {
540
+ const {
541
+ layoutColumn,
542
+ layoutSection
543
+ } = doc.type.schema.nodes;
544
+ if (!(selection instanceof NodeSelection) || selection.node.type !== layoutColumn) {
545
+ return;
546
+ }
547
+ const {
548
+ $from
549
+ } = selection;
550
+ if ($from.parent.type !== layoutSection) {
551
+ return;
552
+ }
553
+ const selectedColumnIndex = $from.index($from.depth);
554
+ const selectedColumnNode = selection.node;
555
+ const selectedColumnPos = selection.from;
556
+ const layoutSectionPos = $from.before($from.depth);
557
+ return {
558
+ layoutSectionNode: $from.parent,
559
+ layoutSectionPos,
560
+ selectedColumnIndex,
561
+ selectedColumnNode,
562
+ selectedColumnPos
563
+ };
564
+ };
565
+ const insertLayoutColumnAt = (side, editorAnalyticsAPI) => ({
566
+ tr
567
+ }) => {
568
+ if (!expValEqualsNoExposure('platform_editor_layout_column_menu', 'isEnabled', true)) {
569
+ return null;
570
+ }
571
+ const selectedColumn = getSelectedLayoutColumnInSection(tr);
572
+ if (!selectedColumn) {
573
+ return null;
574
+ }
575
+ const {
576
+ layoutSectionNode,
577
+ layoutSectionPos,
578
+ selectedColumnIndex
579
+ } = selectedColumn;
580
+ if (layoutSectionNode.childCount >= getEffectiveMaxLayoutColumns()) {
581
+ return null;
582
+ }
583
+ const insertIndex = side === 'left' ? selectedColumnIndex : selectedColumnIndex + 1;
584
+ const existingWidths = mapChildren(layoutSectionNode, column => column.attrs.width);
585
+ const redistributedWidths = redistributeProportionally(existingWidths, insertIndex, getEffectiveMaxLayoutColumns(), MIN_LAYOUT_COLUMN_WIDTH_PERCENT);
586
+ if (redistributedWidths === existingWidths) {
587
+ return null;
588
+ }
589
+ const {
590
+ layoutColumn
591
+ } = tr.doc.type.schema.nodes;
592
+ const newColumn = layoutColumn.createAndFill({
593
+ width: redistributedWidths[insertIndex]
594
+ });
595
+ if (!newColumn) {
596
+ return null;
597
+ }
598
+ const updatedColumns = [];
599
+ layoutSectionNode.forEach((column, _offset, index) => {
600
+ if (index === insertIndex) {
601
+ updatedColumns.push(newColumn);
602
+ }
603
+ updatedColumns.push(column);
604
+ });
605
+ if (insertIndex === layoutSectionNode.childCount) {
606
+ updatedColumns.push(newColumn);
607
+ }
608
+ const updatedLayoutSectionNode = layoutSectionNode.copy(Fragment.fromArray(updatedColumns));
609
+ tr.replaceWith(layoutSectionPos + 1, layoutSectionPos + layoutSectionNode.nodeSize - 1, columnWidth(updatedLayoutSectionNode, tr.doc.type.schema, redistributedWidths));
610
+ editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 ? void 0 : editorAnalyticsAPI.attachAnalyticsEvent({
611
+ action: ACTION.INSERTED,
612
+ actionSubject: ACTION_SUBJECT.DOCUMENT,
613
+ actionSubjectId: ACTION_SUBJECT_ID.LAYOUT_COLUMN,
614
+ attributes: {
615
+ columnCount: redistributedWidths.length,
616
+ inputMethod: INPUT_METHOD.LAYOUT_COLUMN_MENU,
617
+ selectedIndex: selectedColumnIndex,
618
+ side
619
+ },
620
+ eventType: EVENT_TYPE.TRACK
621
+ })(tr);
622
+ tr.setMeta('scrollIntoView', false);
623
+ return tr;
624
+ };
625
+ export const insertLayoutColumn = (side, editorAnalyticsAPI) => insertLayoutColumnAt(side, editorAnalyticsAPI);
529
626
  export const setLayoutColumnValign = valign => ({
530
627
  tr
531
628
  }) => {
@@ -1,14 +1,13 @@
1
1
  import { bind } from 'bind-event-listener';
2
2
  import { Fragment } from '@atlaskit/editor-prosemirror/model';
3
3
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
4
+ import { MIN_LAYOUT_COLUMN_WIDTH_PERCENT } from './consts';
5
+
4
6
  // Class names for the column resize divider widget — must stay in sync with layout.ts in editor-core
5
7
  const layoutColumnDividerClassName = 'layout-column-divider';
6
8
  const layoutColumnDividerRailClassName = 'layout-column-divider-rail';
7
9
  const layoutColumnDividerThumbClassName = 'layout-column-divider-thumb';
8
10
 
9
- // Minimum column width percentage to prevent columns from collapsing
10
- const MIN_COLUMN_WIDTH_PERCENT = 5;
11
-
12
11
  // Module-level drag state so it survives widget DOM recreation during transactions.
13
12
  let dragState = null;
14
13
 
@@ -75,12 +74,12 @@ const calcDragWidths = clientX => {
75
74
  const deltaPercent = deltaX / columnsWidth * 100;
76
75
  let leftWidth = dragState.startLeftWidth + deltaPercent;
77
76
  let rightWidth = dragState.startRightWidth - deltaPercent;
78
- if (leftWidth < MIN_COLUMN_WIDTH_PERCENT) {
79
- leftWidth = MIN_COLUMN_WIDTH_PERCENT;
80
- rightWidth = combinedWidth - MIN_COLUMN_WIDTH_PERCENT;
81
- } else if (rightWidth < MIN_COLUMN_WIDTH_PERCENT) {
82
- rightWidth = MIN_COLUMN_WIDTH_PERCENT;
83
- leftWidth = combinedWidth - MIN_COLUMN_WIDTH_PERCENT;
77
+ if (leftWidth < MIN_LAYOUT_COLUMN_WIDTH_PERCENT) {
78
+ leftWidth = MIN_LAYOUT_COLUMN_WIDTH_PERCENT;
79
+ rightWidth = combinedWidth - MIN_LAYOUT_COLUMN_WIDTH_PERCENT;
80
+ } else if (rightWidth < MIN_LAYOUT_COLUMN_WIDTH_PERCENT) {
81
+ rightWidth = MIN_LAYOUT_COLUMN_WIDTH_PERCENT;
82
+ leftWidth = combinedWidth - MIN_LAYOUT_COLUMN_WIDTH_PERCENT;
84
83
  }
85
84
  return {
86
85
  leftWidth,
@@ -1,3 +1,6 @@
1
+ export const MAX_STANDARD_LAYOUT_COLUMNS = 3;
2
+ export const MAX_LAYOUT_COLUMNS = 5;
3
+ export const MIN_LAYOUT_COLUMN_WIDTH_PERCENT = 5;
1
4
  export const EVEN_DISTRIBUTED_COL_WIDTHS = {
2
5
  1: 100,
3
6
  2: 50,
@@ -0,0 +1,89 @@
1
+ const roundLayoutColumnWidth = width => Number(width.toFixed(2));
2
+ const sumWidths = widths => widths.reduce((sum, width) => sum + width, 0);
3
+ const isValidWidth = width => Number.isFinite(width) && width > 0;
4
+ const normaliseWidthsTotal = (widths, totalWidth, minWidth) => {
5
+ const roundedWidths = widths.map(roundLayoutColumnWidth);
6
+ const remainder = roundLayoutColumnWidth(totalWidth - sumWidths(roundedWidths));
7
+ if (remainder === 0 || roundedWidths.length === 0) {
8
+ return roundedWidths;
9
+ }
10
+ let adjustmentIndex = 0;
11
+ roundedWidths.forEach((width, index) => {
12
+ if (width > roundedWidths[adjustmentIndex]) {
13
+ adjustmentIndex = index;
14
+ }
15
+ });
16
+ const adjustedWidth = roundLayoutColumnWidth(roundedWidths[adjustmentIndex] + remainder);
17
+ if (adjustedWidth < minWidth) {
18
+ return roundedWidths;
19
+ }
20
+ return roundedWidths.map((width, index) => index === adjustmentIndex ? adjustedWidth : width);
21
+ };
22
+ const redistributeWithMinimumWidth = ({
23
+ minWidth,
24
+ totalWidth,
25
+ weights
26
+ }) => {
27
+ if (weights.length * minWidth > totalWidth) {
28
+ return;
29
+ }
30
+ const widths = Array(weights.length).fill(0);
31
+ const clampedIndexes = new Set();
32
+ let remainingWidth = totalWidth;
33
+ let remainingWeight = sumWidths(weights);
34
+ while (clampedIndexes.size < weights.length) {
35
+ const remainingWidthForPass = remainingWidth;
36
+ const remainingWeightForPass = remainingWeight;
37
+ const indexesToClamp = [];
38
+ weights.forEach((weight, index) => {
39
+ if (clampedIndexes.has(index)) {
40
+ return;
41
+ }
42
+ const proportionalWidth = remainingWeightForPass > 0 ? weight / remainingWeightForPass * remainingWidthForPass : 0;
43
+ if (proportionalWidth < minWidth) {
44
+ indexesToClamp.push(index);
45
+ }
46
+ });
47
+ if (indexesToClamp.length === 0) {
48
+ break;
49
+ }
50
+ indexesToClamp.forEach(index => {
51
+ widths[index] = minWidth;
52
+ clampedIndexes.add(index);
53
+ remainingWidth -= minWidth;
54
+ remainingWeight -= weights[index];
55
+ });
56
+ }
57
+ weights.forEach((weight, index) => {
58
+ if (!clampedIndexes.has(index)) {
59
+ widths[index] = remainingWeight > 0 ? weight / remainingWeight * remainingWidth : minWidth;
60
+ }
61
+ });
62
+ return widths;
63
+ };
64
+ export const redistributeProportionally = (currentWidths, insertIndex, maxColumns, minWidth) => {
65
+ if (currentWidths.length === 0 || !Number.isInteger(maxColumns) || maxColumns <= 0 || currentWidths.length >= maxColumns || insertIndex < 0 || insertIndex > currentWidths.length || !isValidWidth(minWidth) || currentWidths.some(width => !isValidWidth(width))) {
66
+ return currentWidths;
67
+ }
68
+ const currentTotalWidth = sumWidths(currentWidths);
69
+ if (!isValidWidth(currentTotalWidth)) {
70
+ return currentWidths;
71
+ }
72
+ const targetTotalWidth = Math.round(currentTotalWidth) === 100 ? 100 : currentTotalWidth;
73
+ const newColumnWidth = Math.max(minWidth, roundLayoutColumnWidth(targetTotalWidth / (currentWidths.length + 1)));
74
+ const existingColumnsTotalWidth = targetTotalWidth - newColumnWidth;
75
+ if (existingColumnsTotalWidth < currentWidths.length * minWidth) {
76
+ return currentWidths;
77
+ }
78
+ const redistributedExistingWidths = redistributeWithMinimumWidth({
79
+ weights: currentWidths,
80
+ totalWidth: existingColumnsTotalWidth,
81
+ minWidth
82
+ });
83
+ if (!redistributedExistingWidths) {
84
+ return currentWidths;
85
+ }
86
+ const nextWidths = [...redistributedExistingWidths];
87
+ nextWidths.splice(insertIndex, 0, newColumnWidth);
88
+ return normaliseWidthsTotal(nextWidths, targetTotalWidth, minWidth);
89
+ };
@@ -0,0 +1,64 @@
1
+ import React, { useCallback } from 'react';
2
+ import { useIntl } from 'react-intl';
3
+ import { layoutMessages } from '@atlaskit/editor-common/messages';
4
+ import { TableColumnAddLeftIcon, TableColumnAddRightIcon, ToolbarDropdownItem } from '@atlaskit/editor-toolbar';
5
+ import { getEffectiveMaxLayoutColumns } from '../../pm-plugins/actions';
6
+ import { getLayoutSectionColumnCount } from './layoutColumnSelection';
7
+ import { useCurrentLayoutColumn, useCurrentLayoutSection } from './useCurrentLayoutColumn';
8
+ const INSERT_COLUMN_OPTIONS = {
9
+ left: {
10
+ Icon: TableColumnAddLeftIcon,
11
+ label: layoutMessages.insertColumnLeft,
12
+ side: 'left'
13
+ },
14
+ right: {
15
+ Icon: TableColumnAddRightIcon,
16
+ label: layoutMessages.insertColumnRight,
17
+ side: 'right'
18
+ }
19
+ };
20
+ export const InsertColumnDropdownItem = ({
21
+ api,
22
+ side
23
+ }) => {
24
+ const {
25
+ formatMessage
26
+ } = useIntl();
27
+ const {
28
+ Icon,
29
+ label
30
+ } = INSERT_COLUMN_OPTIONS[side];
31
+ const currentColumn = useCurrentLayoutColumn(api);
32
+ const currentLayoutSection = useCurrentLayoutSection(api);
33
+ const columnCount = getLayoutSectionColumnCount(currentLayoutSection);
34
+ const maxColumnCount = getEffectiveMaxLayoutColumns();
35
+ const canInsertColumn = currentColumn !== undefined && columnCount < maxColumnCount;
36
+ const onClick = useCallback(() => {
37
+ var _api$layout, _api$core;
38
+ const insertCommand = api === null || api === void 0 ? void 0 : (_api$layout = api.layout) === null || _api$layout === void 0 ? void 0 : _api$layout.commands.insertLayoutColumn(side);
39
+ api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(props => {
40
+ var _api$layout2;
41
+ const tr = insertCommand === null || insertCommand === void 0 ? void 0 : insertCommand(props);
42
+ if (!tr) {
43
+ return tr !== null && tr !== void 0 ? tr : null;
44
+ }
45
+ api === null || api === void 0 ? void 0 : (_api$layout2 = api.layout) === null || _api$layout2 === void 0 ? void 0 : _api$layout2.commands.toggleLayoutColumnMenu({
46
+ isOpen: false
47
+ })({
48
+ tr
49
+ });
50
+ return tr;
51
+ });
52
+ }, [api, side]);
53
+ if (!canInsertColumn) {
54
+ return null;
55
+ }
56
+ return /*#__PURE__*/React.createElement(ToolbarDropdownItem, {
57
+ elemBefore: /*#__PURE__*/React.createElement(Icon, {
58
+ color: "currentColor",
59
+ label: "",
60
+ size: "small"
61
+ }),
62
+ onClick: onClick
63
+ }, formatMessage(label));
64
+ };
@@ -1,7 +1,8 @@
1
- import React, { useCallback } from 'react';
1
+ import React, { useCallback, useMemo } from 'react';
2
2
  import { useIntl } from 'react-intl';
3
3
  import { ToolbarDropdownItem } from '@atlaskit/editor-toolbar';
4
- import { useCurrentLayoutColumnValign } from './useCurrentLayoutColumnValign';
4
+ import { getLayoutColumnValign } from './layoutColumnSelection';
5
+ import { useCurrentLayoutColumn } from './useCurrentLayoutColumn';
5
6
  import { VERTICAL_ALIGN_ICONS } from './verticalAlignIcons';
6
7
  export const VerticalAlignDropdownItem = ({
7
8
  api,
@@ -11,25 +12,19 @@ export const VerticalAlignDropdownItem = ({
11
12
  const {
12
13
  formatMessage
13
14
  } = useIntl();
14
- const {
15
- currentValign,
16
- selectedColumn
17
- } = useCurrentLayoutColumnValign(api);
15
+ const currentColumn = useCurrentLayoutColumn(api);
16
+ const currentValign = useMemo(() => getLayoutColumnValign(currentColumn), [currentColumn]);
18
17
  const Icon = VERTICAL_ALIGN_ICONS[value];
19
18
  const onClick = useCallback(() => {
20
19
  var _api$core, _api$layout;
21
20
  api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(api === null || api === void 0 ? void 0 : (_api$layout = api.layout) === null || _api$layout === void 0 ? void 0 : _api$layout.commands.setLayoutColumnValign(value));
22
21
  }, [api, value]);
23
- if (!selectedColumn) {
24
- return null;
25
- }
26
22
  return /*#__PURE__*/React.createElement(ToolbarDropdownItem, {
27
23
  elemBefore: /*#__PURE__*/React.createElement(Icon, {
28
24
  label: "",
29
25
  size: "small"
30
26
  }),
31
27
  isSelected: currentValign === value,
32
- onClick: onClick,
33
- testId: `layout-column-align-${value}`
28
+ onClick: onClick
34
29
  }, formatMessage(label));
35
30
  };
@@ -1,8 +1,9 @@
1
- import React from 'react';
1
+ import React, { useMemo } from 'react';
2
2
  import { useIntl } from 'react-intl';
3
3
  import { layoutMessages } from '@atlaskit/editor-common/messages';
4
4
  import { LayoutIcon, NestedDropdownRightIcon, ToolbarNestedDropdownMenu } from '@atlaskit/editor-toolbar';
5
- import { useCurrentLayoutColumnValign } from './useCurrentLayoutColumnValign';
5
+ import { getLayoutColumnValign } from './layoutColumnSelection';
6
+ import { useCurrentLayoutColumn } from './useCurrentLayoutColumn';
6
7
  import { VERTICAL_ALIGN_ICONS } from './verticalAlignIcons';
7
8
  export const VerticalAlignNestedMenu = ({
8
9
  api,
@@ -11,12 +12,10 @@ export const VerticalAlignNestedMenu = ({
11
12
  const {
12
13
  formatMessage
13
14
  } = useIntl();
14
- const {
15
- currentValign,
16
- selectedColumn
17
- } = useCurrentLayoutColumnValign(api);
15
+ const currentColumn = useCurrentLayoutColumn(api);
16
+ const currentValign = useMemo(() => getLayoutColumnValign(currentColumn), [currentColumn]);
18
17
  const TriggerIcon = currentValign ? VERTICAL_ALIGN_ICONS[currentValign] : LayoutIcon;
19
- if (!selectedColumn) {
18
+ if (!currentColumn) {
20
19
  return null;
21
20
  }
22
21
  return /*#__PURE__*/React.createElement(ToolbarNestedDropdownMenu, {
@@ -28,8 +27,6 @@ export const VerticalAlignNestedMenu = ({
28
27
  label: "",
29
28
  size: "small"
30
29
  }),
31
- text: formatMessage(layoutMessages.alignColumn),
32
- testId: "layout-column-align-menu",
33
- dropdownTestId: "layout-column-align-dropdown"
30
+ text: formatMessage(layoutMessages.alignColumn)
34
31
  }, children);
35
32
  };
@@ -3,7 +3,8 @@ import { layoutMessages } from '@atlaskit/editor-common/messages';
3
3
  import { ToolbarDropdownItemSection } from '@atlaskit/editor-toolbar';
4
4
  import { ToolbarMenuContainer } from '@atlaskit/editor-toolbar/toolbar-menu-container';
5
5
  import { createDistributeColumnsDropdownItem } from './DistributeColumnsDropdownItem';
6
- import { DISTRIBUTE_COLUMNS_MENU_ITEM, LAYOUT_COLUMN_MENU, LAYOUT_COLUMN_MENU_RANK, LAYOUT_COLUMN_MENU_SECTION, LAYOUT_COLUMN_MENU_SECTION_RANK, LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION, VERTICAL_ALIGN_BOTTOM_MENU_ITEM, VERTICAL_ALIGN_MENU, VERTICAL_ALIGN_MENU_RANK, VERTICAL_ALIGN_MENU_SECTION_RANK, VERTICAL_ALIGN_MIDDLE_MENU_ITEM, VERTICAL_ALIGN_TOP_MENU_ITEM } from './keys';
6
+ import { InsertColumnDropdownItem } from './InsertColumnDropdownItem';
7
+ import { DISTRIBUTE_COLUMNS_MENU_ITEM, INSERT_COLUMN_LEFT_MENU_ITEM, INSERT_COLUMN_RIGHT_MENU_ITEM, LAYOUT_COLUMN_MENU, LAYOUT_COLUMN_MENU_RANK, LAYOUT_COLUMN_MENU_SECTION, LAYOUT_COLUMN_MENU_SECTION_RANK, LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION, VERTICAL_ALIGN_BOTTOM_MENU_ITEM, VERTICAL_ALIGN_MENU, VERTICAL_ALIGN_MENU_RANK, VERTICAL_ALIGN_MENU_SECTION_RANK, VERTICAL_ALIGN_MIDDLE_MENU_ITEM, VERTICAL_ALIGN_TOP_MENU_ITEM } from './keys';
7
8
  import { VerticalAlignDropdownItem } from './VerticalAlignDropdownItem';
8
9
  import { VerticalAlignNestedMenu } from './VerticalAlignNestedMenu';
9
10
  export const LAYOUT_COLUMN_MENU_FALLBACKS = {
@@ -23,6 +24,26 @@ export const getLayoutColumnMenuComponents = ({
23
24
  ...LAYOUT_COLUMN_MENU,
24
25
  rank: LAYOUT_COLUMN_MENU_RANK[LAYOUT_COLUMN_MENU_SECTION.key]
25
26
  }]
27
+ }, {
28
+ ...INSERT_COLUMN_LEFT_MENU_ITEM,
29
+ component: () => /*#__PURE__*/React.createElement(InsertColumnDropdownItem, {
30
+ api: api,
31
+ side: "left"
32
+ }),
33
+ parents: [{
34
+ ...LAYOUT_COLUMN_MENU_SECTION,
35
+ rank: LAYOUT_COLUMN_MENU_SECTION_RANK[INSERT_COLUMN_LEFT_MENU_ITEM.key]
36
+ }]
37
+ }, {
38
+ ...INSERT_COLUMN_RIGHT_MENU_ITEM,
39
+ component: () => /*#__PURE__*/React.createElement(InsertColumnDropdownItem, {
40
+ api: api,
41
+ side: "right"
42
+ }),
43
+ parents: [{
44
+ ...LAYOUT_COLUMN_MENU_SECTION,
45
+ rank: LAYOUT_COLUMN_MENU_SECTION_RANK[INSERT_COLUMN_RIGHT_MENU_ITEM.key]
46
+ }]
26
47
  }, {
27
48
  ...DISTRIBUTE_COLUMNS_MENU_ITEM,
28
49
  component: createDistributeColumnsDropdownItem(api),
@@ -1,25 +1,33 @@
1
- import React, { useCallback, useContext, useEffect, useRef } from 'react';
1
+ import React, { useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef } from 'react';
2
2
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
3
+ import { DRAG_HANDLE_SELECTOR } from '@atlaskit/editor-common/styles';
3
4
  import { EditorToolbarProvider } from '@atlaskit/editor-common/toolbar';
4
5
  import { Popup } from '@atlaskit/editor-common/ui';
5
6
  import { OutsideClickTargetRefContext, withReactEditorViewOuterListeners } from '@atlaskit/editor-common/ui-react';
6
- import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
7
- import { akEditorFloatingPanelZIndex } from '@atlaskit/editor-shared-styles';
7
+ import { akEditorFloatingOverlapPanelZIndex } from '@atlaskit/editor-shared-styles';
8
8
  import { ToolbarDropdownMenuProvider } from '@atlaskit/editor-toolbar';
9
9
  import { SurfaceRenderer } from '@atlaskit/editor-ui-control-model';
10
10
  import { LAYOUT_COLUMN_MENU_FALLBACKS } from './components';
11
11
  import { LAYOUT_COLUMN_MENU } from './keys';
12
+ import { getLayoutColumnAtSelection } from './layoutColumnSelection';
12
13
  const PopupWithListeners = withReactEditorViewOuterListeners(Popup);
13
- const LAYOUT_COLUMN_MENU_POPUP_OFFSET = [0, 10];
14
- const getLayoutColumnMenuTarget = (editorView, selectionAnchorPos) => {
15
- if (selectionAnchorPos === undefined) {
14
+ const FALLBACK_MENU_HEIGHT = 300;
15
+ const LAYOUT_COLUMN_MENU_POPUP_OFFSET = [0, 4];
16
+
17
+ /**
18
+ * Returns the drag handle button for the selected layout column.
19
+ */
20
+ const getLayoutColumnMenuTarget = (editorView, selection) => {
21
+ var _columnDomRef$parentE;
22
+ if (!getLayoutColumnAtSelection(selection) || (selection === null || selection === void 0 ? void 0 : selection.from) === undefined) {
16
23
  return null;
17
24
  }
18
- const selectionNode = editorView.state.doc.nodeAt(selectionAnchorPos);
19
- if ((selectionNode === null || selectionNode === void 0 ? void 0 : selectionNode.type.name) !== 'layoutColumn') {
25
+ const columnDomRef = editorView.nodeDOM(selection.from);
26
+ if (!(columnDomRef instanceof HTMLElement)) {
20
27
  return null;
21
28
  }
22
- return findDomRefAtPos(selectionAnchorPos, editorView.domAtPos.bind(editorView));
29
+ const dragHandleContainer = (_columnDomRef$parentE = columnDomRef.parentElement) === null || _columnDomRef$parentE === void 0 ? void 0 : _columnDomRef$parentE.querySelector(':scope > [data-blocks-drag-handle-container]');
30
+ return dragHandleContainer === null || dragHandleContainer === void 0 ? void 0 : dragHandleContainer.querySelector(DRAG_HANDLE_SELECTOR);
23
31
  };
24
32
  export const LayoutColumnMenu = /*#__PURE__*/React.memo(function LayoutColumnMenu({
25
33
  api,
@@ -41,6 +49,15 @@ export const LayoutColumnMenu = /*#__PURE__*/React.memo(function LayoutColumnMen
41
49
  });
42
50
  const setOutsideClickTargetRef = useContext(OutsideClickTargetRefContext);
43
51
  const menuRef = useRef(null);
52
+ const popupRef = useRef(undefined);
53
+ const [menuHeight, setMenuHeight] = React.useState(FALLBACK_MENU_HEIGHT);
54
+ useLayoutEffect(() => {
55
+ var _popupRef$current;
56
+ if (!isLayoutColumnMenuOpen) {
57
+ return;
58
+ }
59
+ setMenuHeight(((_popupRef$current = popupRef.current) === null || _popupRef$current === void 0 ? void 0 : _popupRef$current.clientHeight) || FALLBACK_MENU_HEIGHT);
60
+ }, [isLayoutColumnMenuOpen]);
44
61
  const closeLayoutColumnMenu = useCallback(() => {
45
62
  var _api$core, _api$layout;
46
63
  api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(api === null || api === void 0 ? void 0 : (_api$layout = api.layout) === null || _api$layout === void 0 ? void 0 : _api$layout.commands.toggleLayoutColumnMenu({
@@ -65,9 +82,12 @@ export const LayoutColumnMenu = /*#__PURE__*/React.memo(function LayoutColumnMen
65
82
  const handleMenuRef = useCallback(el => {
66
83
  setOutsideClickTargetRef === null || setOutsideClickTargetRef === void 0 ? void 0 : setOutsideClickTargetRef(el);
67
84
  menuRef.current = el;
85
+ if (el) {
86
+ popupRef.current = el;
87
+ }
68
88
  }, [setOutsideClickTargetRef]);
69
89
  const components = (_api$uiControlRegistr = api === null || api === void 0 ? void 0 : (_api$uiControlRegistr2 = api.uiControlRegistry) === null || _api$uiControlRegistr2 === void 0 ? void 0 : _api$uiControlRegistr2.actions.getComponents(LAYOUT_COLUMN_MENU.key)) !== null && _api$uiControlRegistr !== void 0 ? _api$uiControlRegistr : [];
70
- const target = isLayoutColumnMenuOpen ? getLayoutColumnMenuTarget(editorView, selection === null || selection === void 0 ? void 0 : selection.from) : null;
90
+ const target = useMemo(() => isLayoutColumnMenuOpen ? getLayoutColumnMenuTarget(editorView, selection) : null, [editorView, isLayoutColumnMenuOpen, selection]);
71
91
  const hasValidTarget = target instanceof HTMLElement;
72
92
  useEffect(() => {
73
93
  if (isLayoutColumnMenuOpen && (!hasValidTarget || components.length === 0)) {
@@ -82,10 +102,11 @@ export const LayoutColumnMenu = /*#__PURE__*/React.memo(function LayoutColumnMen
82
102
  mountTo: mountTo,
83
103
  boundariesElement: boundariesElement,
84
104
  scrollableElement: scrollableElement,
85
- zIndex: akEditorFloatingPanelZIndex,
105
+ zIndex: akEditorFloatingOverlapPanelZIndex,
86
106
  alignX: "center",
87
- alignY: "top",
88
- forcePlacement: true,
107
+ fitHeight: menuHeight,
108
+ preventOverflow: true,
109
+ stick: true,
89
110
  offset: LAYOUT_COLUMN_MENU_POPUP_OFFSET,
90
111
  handleClickOutside: handleClickOutside,
91
112
  handleEscapeKeydown: closeLayoutColumnMenu
@@ -28,6 +28,14 @@ export const VERTICAL_ALIGN_MENU = {
28
28
 
29
29
  // --- Items ---
30
30
 
31
+ export const INSERT_COLUMN_LEFT_MENU_ITEM = {
32
+ type: 'menu-item',
33
+ key: 'layout-column-menu-insert-left-item'
34
+ };
35
+ export const INSERT_COLUMN_RIGHT_MENU_ITEM = {
36
+ type: 'menu-item',
37
+ key: 'layout-column-menu-insert-right-item'
38
+ };
31
39
  export const DISTRIBUTE_COLUMNS_MENU_ITEM = {
32
40
  type: 'menu-item',
33
41
  key: 'layout-column-menu-distribute-columns-item'
@@ -48,8 +56,10 @@ export const VERTICAL_ALIGN_BOTTOM_MENU_ITEM = {
48
56
  // --- Item ranks within sections ---
49
57
 
50
58
  export const LAYOUT_COLUMN_MENU_SECTION_RANK = {
51
- [DISTRIBUTE_COLUMNS_MENU_ITEM.key]: 100,
52
- [VERTICAL_ALIGN_MENU.key]: 200
59
+ [VERTICAL_ALIGN_MENU.key]: 100,
60
+ [INSERT_COLUMN_LEFT_MENU_ITEM.key]: 200,
61
+ [INSERT_COLUMN_RIGHT_MENU_ITEM.key]: 300,
62
+ [DISTRIBUTE_COLUMNS_MENU_ITEM.key]: 400
53
63
  };
54
64
  export const VERTICAL_ALIGN_MENU_RANK = {
55
65
  [LAYOUT_COLUMN_VERTICAL_ALIGN_MENU_SECTION.key]: 100
@@ -0,0 +1,9 @@
1
+ import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
2
+ export const getLayoutColumnAtSelection = selection => selection instanceof NodeSelection && selection.node.type.name === 'layoutColumn' ? selection.node : undefined;
3
+ export const getLayoutSectionAtSelection = selection => {
4
+ const selectedColumn = getLayoutColumnAtSelection(selection);
5
+ const parent = selectedColumn ? selection === null || selection === void 0 ? void 0 : selection.$from.parent : undefined;
6
+ return (parent === null || parent === void 0 ? void 0 : parent.type.name) === 'layoutSection' ? parent : undefined;
7
+ };
8
+ export const getLayoutSectionColumnCount = layoutSection => (layoutSection === null || layoutSection === void 0 ? void 0 : layoutSection.type.name) === 'layoutSection' ? layoutSection.childCount : 0;
9
+ export const getLayoutColumnValign = layoutColumn => layoutColumn === null || layoutColumn === void 0 ? void 0 : layoutColumn.attrs.valign;