@atlaskit/editor-plugin-block-controls 13.0.4 → 13.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/dist/cjs/blockControlsPlugin.js +23 -0
- package/dist/cjs/editor-commands/move-node.js +42 -3
- package/dist/cjs/pm-plugins/decorations-common.js +3 -1
- package/dist/cjs/pm-plugins/decorations-drop-target-active.js +3 -1
- package/dist/cjs/pm-plugins/utils/validation.js +50 -1
- package/dist/cjs/ui/drag-handle.js +39 -2
- package/dist/cjs/ui/drop-target.js +2 -1
- package/dist/es2019/blockControlsPlugin.js +23 -0
- package/dist/es2019/editor-commands/move-node.js +44 -5
- package/dist/es2019/pm-plugins/decorations-common.js +3 -1
- package/dist/es2019/pm-plugins/decorations-drop-target-active.js +3 -1
- package/dist/es2019/pm-plugins/utils/validation.js +49 -0
- package/dist/es2019/ui/drag-handle.js +39 -2
- package/dist/es2019/ui/drop-target.js +2 -1
- package/dist/esm/blockControlsPlugin.js +23 -0
- package/dist/esm/editor-commands/move-node.js +44 -5
- package/dist/esm/pm-plugins/decorations-common.js +3 -1
- package/dist/esm/pm-plugins/decorations-drop-target-active.js +3 -1
- package/dist/esm/pm-plugins/utils/validation.js +49 -0
- package/dist/esm/ui/drag-handle.js +39 -2
- package/dist/esm/ui/drop-target.js +2 -1
- package/dist/types/pm-plugins/utils/validation.d.ts +10 -2
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-block-controls
|
|
2
2
|
|
|
3
|
+
## 13.0.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`e850980f5a66f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/e850980f5a66f) -
|
|
8
|
+
[EDITOR-6790] Block-controls drag-handle wrapper's background is removed and instead set
|
|
9
|
+
on`::before` on `.pm-table-container.pm-table-sticky` to keep masking the row insert dots when
|
|
10
|
+
legacy sticky header is activated while also not overlapping the column insert button.
|
|
11
|
+
- [`7754772ebfa47`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/7754772ebfa47) -
|
|
12
|
+
Fix table text length calculation for Remix/Improve Writing hero prompts: use
|
|
13
|
+
tableNode.textContent for CellSelection instead of textBetween which only spans anchor/head cell
|
|
14
|
+
range
|
|
15
|
+
- Updated dependencies
|
|
16
|
+
|
|
17
|
+
## 13.0.5
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- [`086e779e3490c`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/086e779e3490c) -
|
|
22
|
+
Add drag and drop support for panel_c1 - allow tables to be dropped into panel_c1, allow panel_c1
|
|
23
|
+
-> panel when dropping in parents that allow panel (e.g., expand, table) via generic transform
|
|
24
|
+
functions for future variants
|
|
25
|
+
- Updated dependencies
|
|
26
|
+
|
|
3
27
|
## 13.0.4
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
|
@@ -10,7 +10,9 @@ var _react = _interopRequireDefault(require("react"));
|
|
|
10
10
|
var _selection = require("@atlaskit/editor-common/selection");
|
|
11
11
|
var _toolbarFlagCheck = require("@atlaskit/editor-common/toolbar-flag-check");
|
|
12
12
|
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
13
|
+
var _cellSelection = require("@atlaskit/editor-tables/cell-selection");
|
|
13
14
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
15
|
+
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
14
16
|
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
|
|
15
17
|
var _handleKeyDownWithPreservedSelection = require("./editor-commands/handle-key-down-with-preserved-selection");
|
|
16
18
|
var _mapPreservedSelection2 = require("./editor-commands/map-preserved-selection");
|
|
@@ -44,6 +46,27 @@ var blockControlsPlugin = exports.blockControlsPlugin = function blockControlsPl
|
|
|
44
46
|
var blockControlsState = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState();
|
|
45
47
|
var preservedSelection = blockControlsState === null || blockControlsState === void 0 ? void 0 : blockControlsState.preservedSelection;
|
|
46
48
|
if (preservedSelection && preservedSelection.from !== preservedSelection.to) {
|
|
49
|
+
// CellSelection covers a table: collect each selected cell's text joined with spaces
|
|
50
|
+
// so that adjacent cells are not fused (e.g. 'hello world' + 'foo' must not
|
|
51
|
+
// become 'hello worldfoo'). Intl.Segmenter word-counting requires correct
|
|
52
|
+
// word boundaries, which raw textContent fusion breaks.
|
|
53
|
+
if (preservedSelection instanceof _cellSelection.CellSelection && (0, _expValEquals.expValEquals)('remix_iw_block_menu_table_calc_fix', 'isEnabled', true)) {
|
|
54
|
+
// Use node(1) to reliably target the table node regardless of $anchorCell depth.
|
|
55
|
+
// node(-1) would return tableRow if $anchorCell is at tableCell depth.
|
|
56
|
+
var tableNode = preservedSelection.$anchorCell.node(1);
|
|
57
|
+
var cellTexts = [];
|
|
58
|
+
if (tableNode) {
|
|
59
|
+
// forEachCell iterates only the selected cells, not all cells in the table.
|
|
60
|
+
preservedSelection.forEachCell(function (cell) {
|
|
61
|
+
cellTexts.push(cell.textContent);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
var _textContent = cellTexts.filter(Boolean).join(' ');
|
|
65
|
+
return {
|
|
66
|
+
textLength: _textContent.length,
|
|
67
|
+
textContent: _textContent
|
|
68
|
+
};
|
|
69
|
+
}
|
|
47
70
|
var from = preservedSelection.from,
|
|
48
71
|
to = preservedSelection.to;
|
|
49
72
|
var textContent = editorView.state.doc.textBetween(from, to, '\n');
|
|
@@ -51,12 +51,23 @@ function transformSourceSlice(nodeCopy, destType) {
|
|
|
51
51
|
var destTypeInTable = (0, _validation.isInsideTable)(destType);
|
|
52
52
|
var destTypeInDocOrLayoutCol = [doc, layoutColumn].includes(destType);
|
|
53
53
|
|
|
54
|
-
//
|
|
55
|
-
|
|
54
|
+
// Only run transformation loop if destination may need node conversions:
|
|
55
|
+
// - Table destinations may need expand → nestedExpand
|
|
56
|
+
// - Doc/layoutColumn destinations may need nestedExpand → expand
|
|
57
|
+
// - When panel_c1 experiment is on:
|
|
58
|
+
// - Expand/table/bodied extension destinations may need panel_c1 → panel downgrade
|
|
59
|
+
// - Doc/layoutColumn destinations may need panel → panel_c1 upgrade
|
|
60
|
+
var needsTransformCheck = destTypeInTable || destTypeInDocOrLayoutCol || (0, _expValEquals.expValEquals)('platform_editor_nest_table_in_panel', 'isEnabled', true);
|
|
61
|
+
if (!needsTransformCheck) {
|
|
56
62
|
return nodeCopy;
|
|
57
63
|
}
|
|
58
64
|
var containsExpand = false;
|
|
59
65
|
var containsNestedExpand = false;
|
|
66
|
+
// Track variant nodes (e.g. panel_c1) and their base forms (e.g. panel).
|
|
67
|
+
// Uses getBaseNodeTypeName to auto-detect variants — new variants only need
|
|
68
|
+
// to be added to variantToBaseNameMap, no changes needed in the detection loop.
|
|
69
|
+
var variantType = null;
|
|
70
|
+
var baseOfVariantType = null;
|
|
60
71
|
for (var i = 0; i < nodeCopy.content.childCount; i++) {
|
|
61
72
|
var node = nodeCopy.content.child(i);
|
|
62
73
|
if (node.type === schema.nodes.expand) {
|
|
@@ -64,7 +75,15 @@ function transformSourceSlice(nodeCopy, destType) {
|
|
|
64
75
|
} else if (node.type === schema.nodes.nestedExpand) {
|
|
65
76
|
containsNestedExpand = true;
|
|
66
77
|
}
|
|
67
|
-
if (
|
|
78
|
+
if ((0, _expValEquals.expValEquals)('platform_editor_nest_table_in_panel', 'isEnabled', true)) {
|
|
79
|
+
var baseName = (0, _nodeTypeUtils.getBaseNodeTypeName)(node.type);
|
|
80
|
+
if (baseName !== node.type.name) {
|
|
81
|
+
variantType = node.type.name;
|
|
82
|
+
} else if (schema.nodes["".concat(baseName, "_c1")]) {
|
|
83
|
+
baseOfVariantType = node.type.name;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (containsExpand && containsNestedExpand && (variantType || baseOfVariantType)) {
|
|
68
87
|
break;
|
|
69
88
|
}
|
|
70
89
|
}
|
|
@@ -73,6 +92,26 @@ function transformSourceSlice(nodeCopy, destType) {
|
|
|
73
92
|
} else if (containsNestedExpand && destTypeInDocOrLayoutCol) {
|
|
74
93
|
return (0, _transforms.transformSliceNestedExpandToExpand)(nodeCopy, schema);
|
|
75
94
|
}
|
|
95
|
+
|
|
96
|
+
// Downgrade variant → base (e.g. panel_c1 → panel) when dest doesn't support the variant
|
|
97
|
+
if (variantType && schema.nodes[variantType]) {
|
|
98
|
+
var destParent = destType.createAndFill();
|
|
99
|
+
if (destParent && !(0, _nodeTypeUtils.isNodeTypeValidChildOf)(variantType, destParent, schema)) {
|
|
100
|
+
var _baseName = (0, _nodeTypeUtils.getBaseNodeTypeName)(schema.nodes[variantType]);
|
|
101
|
+
return (0, _validation.transformSliceNodeType)(nodeCopy, schema, variantType, _baseName);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Upgrade base → variant (e.g. panel → panel_c1) when dest supports the variant
|
|
106
|
+
if (baseOfVariantType) {
|
|
107
|
+
var variantName = "".concat(baseOfVariantType, "_c1");
|
|
108
|
+
if (schema.nodes[variantName]) {
|
|
109
|
+
var _destParent = destType.createAndFill();
|
|
110
|
+
if (_destParent && (0, _nodeTypeUtils.isNodeTypeValidChildOf)(variantName, _destParent, schema)) {
|
|
111
|
+
return (0, _validation.transformSliceNodeType)(nodeCopy, schema, baseOfVariantType, variantName);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
76
115
|
return nodeCopy;
|
|
77
116
|
}
|
|
78
117
|
var nodesSupportDragLayoutColumnInto = ['tableCell', 'tableHeader', 'panel', 'expand', 'nestedExpand'];
|
|
@@ -10,6 +10,7 @@ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/creat
|
|
|
10
10
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
11
11
|
var _reactDom = _interopRequireDefault(require("react-dom"));
|
|
12
12
|
var _uuid = _interopRequireDefault(require("uuid"));
|
|
13
|
+
var _nodeTypeUtils = require("@atlaskit/editor-common/utils/node-type-utils");
|
|
13
14
|
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
14
15
|
var _validation = require("./utils/validation");
|
|
15
16
|
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
@@ -33,7 +34,8 @@ var getSubType = function getSubType(node) {
|
|
|
33
34
|
};
|
|
34
35
|
var getNodeTypeWithLevel = exports.getNodeTypeWithLevel = function getNodeTypeWithLevel(node) {
|
|
35
36
|
var subType = (0, _expValEquals.expValEquals)('platform_editor_small_font_size', 'isEnabled', true) ? getSubType(node) : node.attrs.level ? "-".concat(node.attrs.level) : '';
|
|
36
|
-
|
|
37
|
+
var typeName = (0, _expValEquals.expValEquals)('platform_editor_nest_table_in_panel', 'isEnabled', true) ? (0, _nodeTypeUtils.getBaseNodeTypeName)(node.type) : node.type.name;
|
|
38
|
+
return typeName + subType;
|
|
37
39
|
};
|
|
38
40
|
var ObjHash = /*#__PURE__*/function () {
|
|
39
41
|
function ObjHash() {
|
|
@@ -9,6 +9,7 @@ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers
|
|
|
9
9
|
var _memoizeOne = _interopRequireDefault(require("memoize-one"));
|
|
10
10
|
var _selection = require("@atlaskit/editor-common/selection");
|
|
11
11
|
var _utils = require("@atlaskit/editor-common/utils");
|
|
12
|
+
var _nodeTypeUtils = require("@atlaskit/editor-common/utils/node-type-utils");
|
|
12
13
|
var _utils2 = require("@atlaskit/editor-prosemirror/utils");
|
|
13
14
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
14
15
|
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
@@ -33,7 +34,8 @@ var getContainerNodeTypes = (0, _memoizeOne.default)(function () {
|
|
|
33
34
|
return [].concat(PARENT_WITH_END_DROP_TARGET, (0, _toConsumableArray2.default)((0, _platformFeatureFlags.fg)('confluence_frontend_native_tabs_extension') ? ['multiBodiedExtension'] : []), (0, _toConsumableArray2.default)((0, _experiments.editorExperiment)('platform_synced_block', true) ? ['bodiedSyncBlock'] : []));
|
|
34
35
|
});
|
|
35
36
|
var isContainerNode = function isContainerNode(node) {
|
|
36
|
-
|
|
37
|
+
var nodeName = (0, _expValEquals.expValEquals)('platform_editor_nest_table_in_panel', 'isEnabled', true) ? (0, _nodeTypeUtils.getBaseNodeTypeName)(node.type) : node.type.name;
|
|
38
|
+
return getContainerNodeTypes().includes(nodeName);
|
|
37
39
|
};
|
|
38
40
|
var canMoveNodeOrSliceToPos = exports.canMoveNodeOrSliceToPos = function canMoveNodeOrSliceToPos(state, node, parent, index, $toPos, activeNode) {
|
|
39
41
|
// For deciding to show drop targets or not when multiple nodes are selected
|
|
@@ -7,9 +7,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
exports.canCreateNodeWithContentInsideAnotherNode = void 0;
|
|
8
8
|
exports.canMoveNodeToIndex = canMoveNodeToIndex;
|
|
9
9
|
exports.canMoveSliceToIndex = canMoveSliceToIndex;
|
|
10
|
-
exports.transformSliceExpandToNestedExpand = exports.transformFragmentExpandToNestedExpand = exports.transformExpandToNestedExpand = exports.memoizedTransformExpandToNestedExpand = exports.isNestedExpand = exports.isLayoutColumn = exports.isInsideTable = exports.isInSameLayout = exports.isFontSizeMarkActive = exports.isExpand = exports.isDoc = void 0;
|
|
10
|
+
exports.transformSliceNodeType = exports.transformSliceExpandToNestedExpand = exports.transformFragmentNodeType = exports.transformFragmentExpandToNestedExpand = exports.transformExpandToNestedExpand = exports.memoizedTransformExpandToNestedExpand = exports.isNestedExpand = exports.isLayoutColumn = exports.isInsideTable = exports.isInSameLayout = exports.isFontSizeMarkActive = exports.isExpand = exports.isDoc = void 0;
|
|
11
11
|
var _memoizeOne = _interopRequireDefault(require("memoize-one"));
|
|
12
12
|
var _nesting = require("@atlaskit/editor-common/nesting");
|
|
13
|
+
var _nodeTypeUtils = require("@atlaskit/editor-common/utils/node-type-utils");
|
|
13
14
|
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
14
15
|
var _utils = require("@atlaskit/editor-prosemirror/utils");
|
|
15
16
|
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
@@ -79,6 +80,41 @@ var transformFragmentExpandToNestedExpand = exports.transformFragmentExpandToNes
|
|
|
79
80
|
}
|
|
80
81
|
return _model.Fragment.fromArray(children);
|
|
81
82
|
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Generic fragment transformer — converts all nodes of `fromType` to `toType`,
|
|
86
|
+
* preserving attrs, content, and marks.
|
|
87
|
+
*/
|
|
88
|
+
var transformFragmentNodeType = exports.transformFragmentNodeType = function transformFragmentNodeType(fragment, schema, fromType, toType) {
|
|
89
|
+
var children = [];
|
|
90
|
+
var targetType = schema.nodes[toType];
|
|
91
|
+
if (!targetType) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
fragment.forEach(function (node) {
|
|
96
|
+
if (node.type.name === fromType) {
|
|
97
|
+
children.push(targetType.create(node.attrs, node.content, node.marks));
|
|
98
|
+
} else {
|
|
99
|
+
children.push(node);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
} catch (e) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
return _model.Fragment.fromArray(children);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Generic slice transformer — converts all nodes of `fromType` to `toType`.
|
|
110
|
+
*/
|
|
111
|
+
var transformSliceNodeType = exports.transformSliceNodeType = function transformSliceNodeType(slice, schema, fromType, toType) {
|
|
112
|
+
var fragment = transformFragmentNodeType(slice.content, schema, fromType, toType);
|
|
113
|
+
if (!fragment) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
return new _model.Slice(fragment, slice.openStart, slice.openEnd);
|
|
117
|
+
};
|
|
82
118
|
var transformSliceExpandToNestedExpand = exports.transformSliceExpandToNestedExpand = function transformSliceExpandToNestedExpand(slice) {
|
|
83
119
|
var fragment = transformFragmentExpandToNestedExpand(slice.content);
|
|
84
120
|
if (!fragment) {
|
|
@@ -163,6 +199,19 @@ function canMoveNodeToIndex(destParent, indexIntoParent, srcNode, $destNodePos,
|
|
|
163
199
|
} else if ((isDoc(destParent.type) || isLayoutColumn(destParent.type)) && isNestedExpand(srcNodeType)) {
|
|
164
200
|
srcNodeType = expand;
|
|
165
201
|
}
|
|
202
|
+
|
|
203
|
+
// Downgrade variant node (e.g. panel_c1 → panel) when dest doesn't support it
|
|
204
|
+
if ((0, _expValEquals.expValEquals)('platform_editor_nest_table_in_panel', 'isEnabled', true)) {
|
|
205
|
+
var baseName = (0, _nodeTypeUtils.getBaseNodeTypeName)(srcNodeType);
|
|
206
|
+
if (baseName !== srcNodeType.name && !destParent.canReplaceWith(indexIntoParent, indexIntoParent, srcNodeType)) {
|
|
207
|
+
var baseType = schema.nodes[baseName];
|
|
208
|
+
// Check if the node's content is valid in the base type (e.g. panel with table can't be downgraded)
|
|
209
|
+
if (!baseType || !baseType.validContent(srcNode.content)) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
srcNodeType = baseType;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
166
215
|
return destParent.canReplaceWith(indexIntoParent, indexIntoParent, srcNodeType);
|
|
167
216
|
}
|
|
168
217
|
function canMoveSliceToIndex(slice, sliceFromPos, sliceToPos, destParent, indexIntoParent, $destNodePos, destNode) {
|
|
@@ -82,6 +82,37 @@ var buttonWrapperStyles = (0, _react2.css)({
|
|
|
82
82
|
boxSizing: 'border-box'
|
|
83
83
|
}
|
|
84
84
|
});
|
|
85
|
+
|
|
86
|
+
// EDITOR-6790 - When the `platform_editor_table_col_insert` experiment is enabled,
|
|
87
|
+
// drop the linear-gradient background that paints over the legacy `tr.sticky` table
|
|
88
|
+
// header so the new left-edge column-insert affordance is not visually clipped.
|
|
89
|
+
// Keep all paddings / margins identical to `buttonWrapperStyles` so the drag-handle
|
|
90
|
+
// layout does not shift between the two variants.
|
|
91
|
+
var buttonWrapperStylesNoBackground = (0, _react2.css)({
|
|
92
|
+
display: 'flex',
|
|
93
|
+
justifyContent: 'center',
|
|
94
|
+
alignItems: 'center',
|
|
95
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
|
|
96
|
+
'[data-blocks-drag-handle-container]:has(+ [data-prosemirror-node-name="table"] .pm-table-with-controls tr.sticky) &': {
|
|
97
|
+
marginBottom: "var(--ds-space-negative-200, -16px)",
|
|
98
|
+
paddingBottom: "var(--ds-space-200, 16px)",
|
|
99
|
+
marginTop: "var(--ds-space-negative-400, -32px)",
|
|
100
|
+
paddingTop: "calc(".concat("var(--ds-space-400, 32px)", " - 1px)"),
|
|
101
|
+
marginRight: "var(--ds-space-negative-150, -12px)",
|
|
102
|
+
paddingRight: "var(--ds-space-150, 12px)",
|
|
103
|
+
boxSizing: 'border-box'
|
|
104
|
+
},
|
|
105
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
|
|
106
|
+
'[data-prosemirror-mark-name="breakout"]:has([data-blocks-drag-handle-container]):has(+ [data-prosemirror-node-name="table"] .pm-table-with-controls tr.sticky) &': {
|
|
107
|
+
marginBottom: "var(--ds-space-negative-200, -16px)",
|
|
108
|
+
paddingBottom: "var(--ds-space-200, 16px)",
|
|
109
|
+
marginTop: "var(--ds-space-negative-400, -32px)",
|
|
110
|
+
paddingTop: "calc(".concat("var(--ds-space-400, 32px)", " - 1px)"),
|
|
111
|
+
marginRight: "var(--ds-space-negative-150, -12px)",
|
|
112
|
+
paddingRight: "var(--ds-space-150, 12px)",
|
|
113
|
+
boxSizing: 'border-box'
|
|
114
|
+
}
|
|
115
|
+
});
|
|
85
116
|
var buttonWrapperStylesPatch = (0, _react2.css)({
|
|
86
117
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
|
|
87
118
|
'[data-blocks-drag-handle-container]:has(+ [data-prosemirror-node-name="table"] .pm-table-with-controls [data-number-column="true"] tr.sticky) &': {
|
|
@@ -1092,7 +1123,10 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
|
|
|
1092
1123
|
});
|
|
1093
1124
|
}
|
|
1094
1125
|
}, (0, _react2.jsx)("span", {
|
|
1095
|
-
css: [(0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNodeValue) &&
|
|
1126
|
+
css: [(0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNodeValue) && (
|
|
1127
|
+
// EDITOR-6790 - drop the masking background under the new
|
|
1128
|
+
// column-insert experiment so the left-edge dot is not clipped.
|
|
1129
|
+
(0, _expValEquals.expValEquals)('platform_editor_table_col_insert', 'isEnabled', true) ? buttonWrapperStylesNoBackground : buttonWrapperStyles), buttonWrapperStylesPatch]
|
|
1096
1130
|
}, renderButton()))));
|
|
1097
1131
|
};
|
|
1098
1132
|
var stickyWithoutTooltip = function stickyWithoutTooltip() {
|
|
@@ -1108,7 +1142,10 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
|
|
|
1108
1142
|
}, (0, _react2.jsx)("span", {
|
|
1109
1143
|
css: [tooltipContainerStyles, (0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNodeValue) && tooltipContainerStylesStickyHeaderWithMask, !(0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNodeValue) && tooltipContainerStylesStickyHeaderWithoutMask]
|
|
1110
1144
|
}, (0, _react2.jsx)("span", {
|
|
1111
|
-
css: [(0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNodeValue) &&
|
|
1145
|
+
css: [(0, _dragHandlePositions.shouldMaskNodeControls)(nodeType, isTopLevelNodeValue) && (
|
|
1146
|
+
// EDITOR-6790 - drop the masking background under the new
|
|
1147
|
+
// column-insert experiment so the left-edge dot is not clipped.
|
|
1148
|
+
(0, _expValEquals.expValEquals)('platform_editor_table_col_insert', 'isEnabled', true) ? buttonWrapperStylesNoBackground : buttonWrapperStyles), buttonWrapperStylesPatch]
|
|
1112
1149
|
}, renderButton())));
|
|
1113
1150
|
};
|
|
1114
1151
|
var buttonWithTooltip = function buttonWithTooltip() {
|
|
@@ -11,6 +11,7 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/sli
|
|
|
11
11
|
var _react = require("react");
|
|
12
12
|
var _react2 = require("@emotion/react");
|
|
13
13
|
var _hooks = require("@atlaskit/editor-common/hooks");
|
|
14
|
+
var _nodeTypeUtils = require("@atlaskit/editor-common/utils/node-type-utils");
|
|
14
15
|
var _box = require("@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box");
|
|
15
16
|
var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
|
|
16
17
|
var _constants = require("@atlaskit/theme/constants");
|
|
@@ -232,7 +233,7 @@ var DropTarget = exports.DropTarget = function DropTarget(props) {
|
|
|
232
233
|
};
|
|
233
234
|
var dynamicStyle = (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({
|
|
234
235
|
width: isNestedDropTarget ? 'unset' : '100%'
|
|
235
|
-
}, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_WIDTH, isNestedDropTarget ? '100%' : "".concat(lineLength || DEFAULT_DROP_INDICATOR_WIDTH, "px")), EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN, isNestedDropTarget ? (0, _consts.getNestedNodeLeftPaddingMargin)(parentNode === null || parentNode === void 0 ? void 0 : parentNode.type.name) : '0'), EDITOR_BLOCK_CONTROLS_DROP_TARGET_ZINDEX, _constants.layers.navigation());
|
|
236
|
+
}, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_WIDTH, isNestedDropTarget ? '100%' : "".concat(lineLength || DEFAULT_DROP_INDICATOR_WIDTH, "px")), EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN, isNestedDropTarget ? (0, _expValEquals.expValEquals)('platform_editor_nest_table_in_panel', 'isEnabled', true) && parentNode !== null && parentNode !== void 0 && parentNode.type ? (0, _consts.getNestedNodeLeftPaddingMargin)((0, _nodeTypeUtils.getBaseNodeTypeName)(parentNode.type)) : (0, _consts.getNestedNodeLeftPaddingMargin)(parentNode === null || parentNode === void 0 ? void 0 : parentNode.type.name) : '0'), EDITOR_BLOCK_CONTROLS_DROP_TARGET_ZINDEX, _constants.layers.navigation());
|
|
236
237
|
var isShowInlineDropTarget = (0, _inlineDropTarget.shouldAllowInlineDropTarget)(isNestedDropTarget, nextNode, isSameLayout, activeNode, parentNode);
|
|
237
238
|
return (0, _react2.jsx)(_react.Fragment, null, (0, _react2.jsx)(HoverZone
|
|
238
239
|
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
|
|
@@ -2,7 +2,9 @@ import React from 'react';
|
|
|
2
2
|
import { expandSelectionBounds } from '@atlaskit/editor-common/selection';
|
|
3
3
|
import { areToolbarFlagsEnabled } from '@atlaskit/editor-common/toolbar-flag-check';
|
|
4
4
|
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
5
|
+
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
|
|
5
6
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
7
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
6
8
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
7
9
|
import { handleKeyDownWithPreservedSelection } from './editor-commands/handle-key-down-with-preserved-selection';
|
|
8
10
|
import { mapPreservedSelection } from './editor-commands/map-preserved-selection';
|
|
@@ -35,6 +37,27 @@ export const blockControlsPlugin = ({
|
|
|
35
37
|
const blockControlsState = api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState();
|
|
36
38
|
const preservedSelection = blockControlsState === null || blockControlsState === void 0 ? void 0 : blockControlsState.preservedSelection;
|
|
37
39
|
if (preservedSelection && preservedSelection.from !== preservedSelection.to) {
|
|
40
|
+
// CellSelection covers a table: collect each selected cell's text joined with spaces
|
|
41
|
+
// so that adjacent cells are not fused (e.g. 'hello world' + 'foo' must not
|
|
42
|
+
// become 'hello worldfoo'). Intl.Segmenter word-counting requires correct
|
|
43
|
+
// word boundaries, which raw textContent fusion breaks.
|
|
44
|
+
if (preservedSelection instanceof CellSelection && expValEquals('remix_iw_block_menu_table_calc_fix', 'isEnabled', true)) {
|
|
45
|
+
// Use node(1) to reliably target the table node regardless of $anchorCell depth.
|
|
46
|
+
// node(-1) would return tableRow if $anchorCell is at tableCell depth.
|
|
47
|
+
const tableNode = preservedSelection.$anchorCell.node(1);
|
|
48
|
+
const cellTexts = [];
|
|
49
|
+
if (tableNode) {
|
|
50
|
+
// forEachCell iterates only the selected cells, not all cells in the table.
|
|
51
|
+
preservedSelection.forEachCell(cell => {
|
|
52
|
+
cellTexts.push(cell.textContent);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
const textContent = cellTexts.filter(Boolean).join(' ');
|
|
56
|
+
return {
|
|
57
|
+
textLength: textContent.length,
|
|
58
|
+
textContent
|
|
59
|
+
};
|
|
60
|
+
}
|
|
38
61
|
const {
|
|
39
62
|
from,
|
|
40
63
|
to
|
|
@@ -5,7 +5,7 @@ import { expandSelectionBounds, GapCursorSelection } from '@atlaskit/editor-comm
|
|
|
5
5
|
import { transformSliceNestedExpandToExpand } from '@atlaskit/editor-common/transforms';
|
|
6
6
|
import { DIRECTION } from '@atlaskit/editor-common/types';
|
|
7
7
|
import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
|
|
8
|
-
import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
|
|
8
|
+
import { isNodeTypeValidChildOf, getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
|
|
9
9
|
import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
|
|
10
10
|
import { NodeSelection, Selection } from '@atlaskit/editor-prosemirror/state';
|
|
11
11
|
import { Mapping, StepMap } from '@atlaskit/editor-prosemirror/transform';
|
|
@@ -21,7 +21,7 @@ import { setCursorPositionAtMovedNode } from '../pm-plugins/utils/getSelection';
|
|
|
21
21
|
import { removeFromSource } from '../pm-plugins/utils/remove-from-source';
|
|
22
22
|
import { getSelectedSlicePosition } from '../pm-plugins/utils/selection';
|
|
23
23
|
import { getInsertLayoutStep, updateSelection } from '../pm-plugins/utils/update-selection';
|
|
24
|
-
import { canMoveNodeToIndex, isInsideTable, transformFragmentExpandToNestedExpand, transformSliceExpandToNestedExpand } from '../pm-plugins/utils/validation';
|
|
24
|
+
import { canMoveNodeToIndex, isInsideTable, transformFragmentExpandToNestedExpand, transformSliceExpandToNestedExpand, transformSliceNodeType } from '../pm-plugins/utils/validation';
|
|
25
25
|
import { getPosWhenMoveNodeDown, getPosWhenMoveNodeUp } from './utils/move-node-utils';
|
|
26
26
|
|
|
27
27
|
/**
|
|
@@ -43,12 +43,23 @@ function transformSourceSlice(nodeCopy, destType) {
|
|
|
43
43
|
const destTypeInTable = isInsideTable(destType);
|
|
44
44
|
const destTypeInDocOrLayoutCol = [doc, layoutColumn].includes(destType);
|
|
45
45
|
|
|
46
|
-
//
|
|
47
|
-
|
|
46
|
+
// Only run transformation loop if destination may need node conversions:
|
|
47
|
+
// - Table destinations may need expand → nestedExpand
|
|
48
|
+
// - Doc/layoutColumn destinations may need nestedExpand → expand
|
|
49
|
+
// - When panel_c1 experiment is on:
|
|
50
|
+
// - Expand/table/bodied extension destinations may need panel_c1 → panel downgrade
|
|
51
|
+
// - Doc/layoutColumn destinations may need panel → panel_c1 upgrade
|
|
52
|
+
const needsTransformCheck = destTypeInTable || destTypeInDocOrLayoutCol || expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true);
|
|
53
|
+
if (!needsTransformCheck) {
|
|
48
54
|
return nodeCopy;
|
|
49
55
|
}
|
|
50
56
|
let containsExpand = false;
|
|
51
57
|
let containsNestedExpand = false;
|
|
58
|
+
// Track variant nodes (e.g. panel_c1) and their base forms (e.g. panel).
|
|
59
|
+
// Uses getBaseNodeTypeName to auto-detect variants — new variants only need
|
|
60
|
+
// to be added to variantToBaseNameMap, no changes needed in the detection loop.
|
|
61
|
+
let variantType = null;
|
|
62
|
+
let baseOfVariantType = null;
|
|
52
63
|
for (let i = 0; i < nodeCopy.content.childCount; i++) {
|
|
53
64
|
const node = nodeCopy.content.child(i);
|
|
54
65
|
if (node.type === schema.nodes.expand) {
|
|
@@ -56,7 +67,15 @@ function transformSourceSlice(nodeCopy, destType) {
|
|
|
56
67
|
} else if (node.type === schema.nodes.nestedExpand) {
|
|
57
68
|
containsNestedExpand = true;
|
|
58
69
|
}
|
|
59
|
-
if (
|
|
70
|
+
if (expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true)) {
|
|
71
|
+
const baseName = getBaseNodeTypeName(node.type);
|
|
72
|
+
if (baseName !== node.type.name) {
|
|
73
|
+
variantType = node.type.name;
|
|
74
|
+
} else if (schema.nodes[`${baseName}_c1`]) {
|
|
75
|
+
baseOfVariantType = node.type.name;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (containsExpand && containsNestedExpand && (variantType || baseOfVariantType)) {
|
|
60
79
|
break;
|
|
61
80
|
}
|
|
62
81
|
}
|
|
@@ -65,6 +84,26 @@ function transformSourceSlice(nodeCopy, destType) {
|
|
|
65
84
|
} else if (containsNestedExpand && destTypeInDocOrLayoutCol) {
|
|
66
85
|
return transformSliceNestedExpandToExpand(nodeCopy, schema);
|
|
67
86
|
}
|
|
87
|
+
|
|
88
|
+
// Downgrade variant → base (e.g. panel_c1 → panel) when dest doesn't support the variant
|
|
89
|
+
if (variantType && schema.nodes[variantType]) {
|
|
90
|
+
const destParent = destType.createAndFill();
|
|
91
|
+
if (destParent && !isNodeTypeValidChildOf(variantType, destParent, schema)) {
|
|
92
|
+
const baseName = getBaseNodeTypeName(schema.nodes[variantType]);
|
|
93
|
+
return transformSliceNodeType(nodeCopy, schema, variantType, baseName);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Upgrade base → variant (e.g. panel → panel_c1) when dest supports the variant
|
|
98
|
+
if (baseOfVariantType) {
|
|
99
|
+
const variantName = `${baseOfVariantType}_c1`;
|
|
100
|
+
if (schema.nodes[variantName]) {
|
|
101
|
+
const destParent = destType.createAndFill();
|
|
102
|
+
if (destParent && isNodeTypeValidChildOf(variantName, destParent, schema)) {
|
|
103
|
+
return transformSliceNodeType(nodeCopy, schema, baseOfVariantType, variantName);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
68
107
|
return nodeCopy;
|
|
69
108
|
}
|
|
70
109
|
const nodesSupportDragLayoutColumnInto = ['tableCell', 'tableHeader', 'panel', 'expand', 'nestedExpand'];
|
|
@@ -2,6 +2,7 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
|
2
2
|
import ReactDOM from 'react-dom';
|
|
3
3
|
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
4
4
|
import uuid from 'uuid';
|
|
5
|
+
import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
|
|
5
6
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
6
7
|
import { isFontSizeMarkActive } from './utils/validation';
|
|
7
8
|
export const TYPE_DROP_TARGET_DEC = 'drop-target-decoration';
|
|
@@ -23,7 +24,8 @@ const getSubType = node => {
|
|
|
23
24
|
};
|
|
24
25
|
export const getNodeTypeWithLevel = node => {
|
|
25
26
|
const subType = expValEquals('platform_editor_small_font_size', 'isEnabled', true) ? getSubType(node) : node.attrs.level ? `-${node.attrs.level}` : '';
|
|
26
|
-
|
|
27
|
+
const typeName = expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true) ? getBaseNodeTypeName(node.type) : node.type.name;
|
|
28
|
+
return typeName + subType;
|
|
27
29
|
};
|
|
28
30
|
class ObjHash {
|
|
29
31
|
static getForNode(node) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import memoizeOne from 'memoize-one';
|
|
2
2
|
import { expandSelectionBounds } from '@atlaskit/editor-common/selection';
|
|
3
3
|
import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
|
|
4
|
+
import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
|
|
4
5
|
import { findChildrenByType } from '@atlaskit/editor-prosemirror/utils';
|
|
5
6
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
6
7
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
@@ -24,7 +25,8 @@ const NODE_WITH_NO_PARENT_POS = ['tableCell', 'tableHeader', 'layoutColumn'];
|
|
|
24
25
|
const UNSUPPORTED_LAYOUT_CONTENT = ['syncBlock', 'bodiedSyncBlock'];
|
|
25
26
|
const getContainerNodeTypes = memoizeOne(() => [...PARENT_WITH_END_DROP_TARGET, ...(fg('confluence_frontend_native_tabs_extension') ? ['multiBodiedExtension'] : []), ...(editorExperiment('platform_synced_block', true) ? ['bodiedSyncBlock'] : [])]);
|
|
26
27
|
const isContainerNode = node => {
|
|
27
|
-
|
|
28
|
+
const nodeName = expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true) ? getBaseNodeTypeName(node.type) : node.type.name;
|
|
29
|
+
return getContainerNodeTypes().includes(nodeName);
|
|
28
30
|
};
|
|
29
31
|
export const canMoveNodeOrSliceToPos = (state, node, parent, index, $toPos, activeNode) => {
|
|
30
32
|
// For deciding to show drop targets or not when multiple nodes are selected
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import memoizeOne from 'memoize-one';
|
|
2
2
|
import { getParentOfTypeCount, isNestedTablesSupported } from '@atlaskit/editor-common/nesting';
|
|
3
|
+
import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
|
|
3
4
|
import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
|
|
4
5
|
import { findChildrenByType } from '@atlaskit/editor-prosemirror/utils';
|
|
5
6
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
@@ -69,6 +70,41 @@ export const transformFragmentExpandToNestedExpand = fragment => {
|
|
|
69
70
|
}
|
|
70
71
|
return Fragment.fromArray(children);
|
|
71
72
|
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Generic fragment transformer — converts all nodes of `fromType` to `toType`,
|
|
76
|
+
* preserving attrs, content, and marks.
|
|
77
|
+
*/
|
|
78
|
+
export const transformFragmentNodeType = (fragment, schema, fromType, toType) => {
|
|
79
|
+
const children = [];
|
|
80
|
+
const targetType = schema.nodes[toType];
|
|
81
|
+
if (!targetType) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
fragment.forEach(node => {
|
|
86
|
+
if (node.type.name === fromType) {
|
|
87
|
+
children.push(targetType.create(node.attrs, node.content, node.marks));
|
|
88
|
+
} else {
|
|
89
|
+
children.push(node);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
} catch (e) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
return Fragment.fromArray(children);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Generic slice transformer — converts all nodes of `fromType` to `toType`.
|
|
100
|
+
*/
|
|
101
|
+
export const transformSliceNodeType = (slice, schema, fromType, toType) => {
|
|
102
|
+
const fragment = transformFragmentNodeType(slice.content, schema, fromType, toType);
|
|
103
|
+
if (!fragment) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
return new Slice(fragment, slice.openStart, slice.openEnd);
|
|
107
|
+
};
|
|
72
108
|
export const transformSliceExpandToNestedExpand = slice => {
|
|
73
109
|
const fragment = transformFragmentExpandToNestedExpand(slice.content);
|
|
74
110
|
if (!fragment) {
|
|
@@ -152,6 +188,19 @@ export function canMoveNodeToIndex(destParent, indexIntoParent, srcNode, $destNo
|
|
|
152
188
|
} else if ((isDoc(destParent.type) || isLayoutColumn(destParent.type)) && isNestedExpand(srcNodeType)) {
|
|
153
189
|
srcNodeType = expand;
|
|
154
190
|
}
|
|
191
|
+
|
|
192
|
+
// Downgrade variant node (e.g. panel_c1 → panel) when dest doesn't support it
|
|
193
|
+
if (expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true)) {
|
|
194
|
+
const baseName = getBaseNodeTypeName(srcNodeType);
|
|
195
|
+
if (baseName !== srcNodeType.name && !destParent.canReplaceWith(indexIntoParent, indexIntoParent, srcNodeType)) {
|
|
196
|
+
const baseType = schema.nodes[baseName];
|
|
197
|
+
// Check if the node's content is valid in the base type (e.g. panel with table can't be downgraded)
|
|
198
|
+
if (!baseType || !baseType.validContent(srcNode.content)) {
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
srcNodeType = baseType;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
155
204
|
return destParent.canReplaceWith(indexIntoParent, indexIntoParent, srcNodeType);
|
|
156
205
|
}
|
|
157
206
|
export function canMoveSliceToIndex(slice, sliceFromPos, sliceToPos, destParent, indexIntoParent, $destNodePos, destNode) {
|
|
@@ -73,6 +73,37 @@ const buttonWrapperStyles = css({
|
|
|
73
73
|
boxSizing: 'border-box'
|
|
74
74
|
}
|
|
75
75
|
});
|
|
76
|
+
|
|
77
|
+
// EDITOR-6790 - When the `platform_editor_table_col_insert` experiment is enabled,
|
|
78
|
+
// drop the linear-gradient background that paints over the legacy `tr.sticky` table
|
|
79
|
+
// header so the new left-edge column-insert affordance is not visually clipped.
|
|
80
|
+
// Keep all paddings / margins identical to `buttonWrapperStyles` so the drag-handle
|
|
81
|
+
// layout does not shift between the two variants.
|
|
82
|
+
const buttonWrapperStylesNoBackground = css({
|
|
83
|
+
display: 'flex',
|
|
84
|
+
justifyContent: 'center',
|
|
85
|
+
alignItems: 'center',
|
|
86
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
|
|
87
|
+
'[data-blocks-drag-handle-container]:has(+ [data-prosemirror-node-name="table"] .pm-table-with-controls tr.sticky) &': {
|
|
88
|
+
marginBottom: "var(--ds-space-negative-200, -16px)",
|
|
89
|
+
paddingBottom: "var(--ds-space-200, 16px)",
|
|
90
|
+
marginTop: "var(--ds-space-negative-400, -32px)",
|
|
91
|
+
paddingTop: `calc(${"var(--ds-space-400, 32px)"} - 1px)`,
|
|
92
|
+
marginRight: "var(--ds-space-negative-150, -12px)",
|
|
93
|
+
paddingRight: "var(--ds-space-150, 12px)",
|
|
94
|
+
boxSizing: 'border-box'
|
|
95
|
+
},
|
|
96
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
|
|
97
|
+
'[data-prosemirror-mark-name="breakout"]:has([data-blocks-drag-handle-container]):has(+ [data-prosemirror-node-name="table"] .pm-table-with-controls tr.sticky) &': {
|
|
98
|
+
marginBottom: "var(--ds-space-negative-200, -16px)",
|
|
99
|
+
paddingBottom: "var(--ds-space-200, 16px)",
|
|
100
|
+
marginTop: "var(--ds-space-negative-400, -32px)",
|
|
101
|
+
paddingTop: `calc(${"var(--ds-space-400, 32px)"} - 1px)`,
|
|
102
|
+
marginRight: "var(--ds-space-negative-150, -12px)",
|
|
103
|
+
paddingRight: "var(--ds-space-150, 12px)",
|
|
104
|
+
boxSizing: 'border-box'
|
|
105
|
+
}
|
|
106
|
+
});
|
|
76
107
|
const buttonWrapperStylesPatch = css({
|
|
77
108
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
|
|
78
109
|
'[data-blocks-drag-handle-container]:has(+ [data-prosemirror-node-name="table"] .pm-table-with-controls [data-number-column="true"] tr.sticky) &': {
|
|
@@ -1071,7 +1102,10 @@ export const DragHandle = ({
|
|
|
1071
1102
|
});
|
|
1072
1103
|
}
|
|
1073
1104
|
}, jsx("span", {
|
|
1074
|
-
css: [shouldMaskNodeControls(nodeType, isTopLevelNodeValue) &&
|
|
1105
|
+
css: [shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && (
|
|
1106
|
+
// EDITOR-6790 - drop the masking background under the new
|
|
1107
|
+
// column-insert experiment so the left-edge dot is not clipped.
|
|
1108
|
+
expValEquals('platform_editor_table_col_insert', 'isEnabled', true) ? buttonWrapperStylesNoBackground : buttonWrapperStyles), buttonWrapperStylesPatch]
|
|
1075
1109
|
}, renderButton()))));
|
|
1076
1110
|
const stickyWithoutTooltip = () => jsx(Box
|
|
1077
1111
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
|
|
@@ -1085,7 +1119,10 @@ export const DragHandle = ({
|
|
|
1085
1119
|
}, jsx("span", {
|
|
1086
1120
|
css: [tooltipContainerStyles, shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && tooltipContainerStylesStickyHeaderWithMask, !shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && tooltipContainerStylesStickyHeaderWithoutMask]
|
|
1087
1121
|
}, jsx("span", {
|
|
1088
|
-
css: [shouldMaskNodeControls(nodeType, isTopLevelNodeValue) &&
|
|
1122
|
+
css: [shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && (
|
|
1123
|
+
// EDITOR-6790 - drop the masking background under the new
|
|
1124
|
+
// column-insert experiment so the left-edge dot is not clipped.
|
|
1125
|
+
expValEquals('platform_editor_table_col_insert', 'isEnabled', true) ? buttonWrapperStylesNoBackground : buttonWrapperStyles), buttonWrapperStylesPatch]
|
|
1089
1126
|
}, renderButton())));
|
|
1090
1127
|
const buttonWithTooltip = () => jsx(Tooltip, {
|
|
1091
1128
|
content: tooltipContent,
|
|
@@ -7,6 +7,7 @@ import { Fragment, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
7
7
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports
|
|
8
8
|
import { css, jsx } from '@emotion/react';
|
|
9
9
|
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
10
|
+
import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
|
|
10
11
|
import { DropIndicator } from '@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box';
|
|
11
12
|
import { dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
12
13
|
import { layers } from '@atlaskit/theme/constants';
|
|
@@ -222,7 +223,7 @@ export const DropTarget = props => {
|
|
|
222
223
|
const dynamicStyle = {
|
|
223
224
|
width: isNestedDropTarget ? 'unset' : '100%',
|
|
224
225
|
[EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_WIDTH]: isNestedDropTarget ? '100%' : `${lineLength || DEFAULT_DROP_INDICATOR_WIDTH}px`,
|
|
225
|
-
[EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN]: isNestedDropTarget ? getNestedNodeLeftPaddingMargin(parentNode === null || parentNode === void 0 ? void 0 : parentNode.type.name) : '0',
|
|
226
|
+
[EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN]: isNestedDropTarget ? expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true) && parentNode !== null && parentNode !== void 0 && parentNode.type ? getNestedNodeLeftPaddingMargin(getBaseNodeTypeName(parentNode.type)) : getNestedNodeLeftPaddingMargin(parentNode === null || parentNode === void 0 ? void 0 : parentNode.type.name) : '0',
|
|
226
227
|
[EDITOR_BLOCK_CONTROLS_DROP_TARGET_ZINDEX]: layers.navigation()
|
|
227
228
|
};
|
|
228
229
|
const isShowInlineDropTarget = shouldAllowInlineDropTarget(isNestedDropTarget, nextNode, isSameLayout, activeNode, parentNode);
|
|
@@ -5,7 +5,9 @@ import React from 'react';
|
|
|
5
5
|
import { expandSelectionBounds } from '@atlaskit/editor-common/selection';
|
|
6
6
|
import { areToolbarFlagsEnabled } from '@atlaskit/editor-common/toolbar-flag-check';
|
|
7
7
|
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
8
|
+
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
|
|
8
9
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
10
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
9
11
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
10
12
|
import { handleKeyDownWithPreservedSelection } from './editor-commands/handle-key-down-with-preserved-selection';
|
|
11
13
|
import { mapPreservedSelection as _mapPreservedSelection } from './editor-commands/map-preserved-selection';
|
|
@@ -37,6 +39,27 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
|
|
|
37
39
|
var blockControlsState = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState();
|
|
38
40
|
var preservedSelection = blockControlsState === null || blockControlsState === void 0 ? void 0 : blockControlsState.preservedSelection;
|
|
39
41
|
if (preservedSelection && preservedSelection.from !== preservedSelection.to) {
|
|
42
|
+
// CellSelection covers a table: collect each selected cell's text joined with spaces
|
|
43
|
+
// so that adjacent cells are not fused (e.g. 'hello world' + 'foo' must not
|
|
44
|
+
// become 'hello worldfoo'). Intl.Segmenter word-counting requires correct
|
|
45
|
+
// word boundaries, which raw textContent fusion breaks.
|
|
46
|
+
if (preservedSelection instanceof CellSelection && expValEquals('remix_iw_block_menu_table_calc_fix', 'isEnabled', true)) {
|
|
47
|
+
// Use node(1) to reliably target the table node regardless of $anchorCell depth.
|
|
48
|
+
// node(-1) would return tableRow if $anchorCell is at tableCell depth.
|
|
49
|
+
var tableNode = preservedSelection.$anchorCell.node(1);
|
|
50
|
+
var cellTexts = [];
|
|
51
|
+
if (tableNode) {
|
|
52
|
+
// forEachCell iterates only the selected cells, not all cells in the table.
|
|
53
|
+
preservedSelection.forEachCell(function (cell) {
|
|
54
|
+
cellTexts.push(cell.textContent);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
var _textContent = cellTexts.filter(Boolean).join(' ');
|
|
58
|
+
return {
|
|
59
|
+
textLength: _textContent.length,
|
|
60
|
+
textContent: _textContent
|
|
61
|
+
};
|
|
62
|
+
}
|
|
40
63
|
var from = preservedSelection.from,
|
|
41
64
|
to = preservedSelection.to;
|
|
42
65
|
var textContent = editorView.state.doc.textBetween(from, to, '\n');
|
|
@@ -8,7 +8,7 @@ import { expandSelectionBounds, GapCursorSelection } from '@atlaskit/editor-comm
|
|
|
8
8
|
import { transformSliceNestedExpandToExpand } from '@atlaskit/editor-common/transforms';
|
|
9
9
|
import { DIRECTION } from '@atlaskit/editor-common/types';
|
|
10
10
|
import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
|
|
11
|
-
import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
|
|
11
|
+
import { isNodeTypeValidChildOf, getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
|
|
12
12
|
import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
|
|
13
13
|
import { NodeSelection, Selection } from '@atlaskit/editor-prosemirror/state';
|
|
14
14
|
import { Mapping, StepMap } from '@atlaskit/editor-prosemirror/transform';
|
|
@@ -24,7 +24,7 @@ import { setCursorPositionAtMovedNode } from '../pm-plugins/utils/getSelection';
|
|
|
24
24
|
import { removeFromSource } from '../pm-plugins/utils/remove-from-source';
|
|
25
25
|
import { getSelectedSlicePosition } from '../pm-plugins/utils/selection';
|
|
26
26
|
import { getInsertLayoutStep, updateSelection } from '../pm-plugins/utils/update-selection';
|
|
27
|
-
import { canMoveNodeToIndex, isInsideTable, transformFragmentExpandToNestedExpand, transformSliceExpandToNestedExpand } from '../pm-plugins/utils/validation';
|
|
27
|
+
import { canMoveNodeToIndex, isInsideTable, transformFragmentExpandToNestedExpand, transformSliceExpandToNestedExpand, transformSliceNodeType } from '../pm-plugins/utils/validation';
|
|
28
28
|
import { getPosWhenMoveNodeDown, getPosWhenMoveNodeUp } from './utils/move-node-utils';
|
|
29
29
|
|
|
30
30
|
/**
|
|
@@ -45,12 +45,23 @@ function transformSourceSlice(nodeCopy, destType) {
|
|
|
45
45
|
var destTypeInTable = isInsideTable(destType);
|
|
46
46
|
var destTypeInDocOrLayoutCol = [doc, layoutColumn].includes(destType);
|
|
47
47
|
|
|
48
|
-
//
|
|
49
|
-
|
|
48
|
+
// Only run transformation loop if destination may need node conversions:
|
|
49
|
+
// - Table destinations may need expand → nestedExpand
|
|
50
|
+
// - Doc/layoutColumn destinations may need nestedExpand → expand
|
|
51
|
+
// - When panel_c1 experiment is on:
|
|
52
|
+
// - Expand/table/bodied extension destinations may need panel_c1 → panel downgrade
|
|
53
|
+
// - Doc/layoutColumn destinations may need panel → panel_c1 upgrade
|
|
54
|
+
var needsTransformCheck = destTypeInTable || destTypeInDocOrLayoutCol || expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true);
|
|
55
|
+
if (!needsTransformCheck) {
|
|
50
56
|
return nodeCopy;
|
|
51
57
|
}
|
|
52
58
|
var containsExpand = false;
|
|
53
59
|
var containsNestedExpand = false;
|
|
60
|
+
// Track variant nodes (e.g. panel_c1) and their base forms (e.g. panel).
|
|
61
|
+
// Uses getBaseNodeTypeName to auto-detect variants — new variants only need
|
|
62
|
+
// to be added to variantToBaseNameMap, no changes needed in the detection loop.
|
|
63
|
+
var variantType = null;
|
|
64
|
+
var baseOfVariantType = null;
|
|
54
65
|
for (var i = 0; i < nodeCopy.content.childCount; i++) {
|
|
55
66
|
var node = nodeCopy.content.child(i);
|
|
56
67
|
if (node.type === schema.nodes.expand) {
|
|
@@ -58,7 +69,15 @@ function transformSourceSlice(nodeCopy, destType) {
|
|
|
58
69
|
} else if (node.type === schema.nodes.nestedExpand) {
|
|
59
70
|
containsNestedExpand = true;
|
|
60
71
|
}
|
|
61
|
-
if (
|
|
72
|
+
if (expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true)) {
|
|
73
|
+
var baseName = getBaseNodeTypeName(node.type);
|
|
74
|
+
if (baseName !== node.type.name) {
|
|
75
|
+
variantType = node.type.name;
|
|
76
|
+
} else if (schema.nodes["".concat(baseName, "_c1")]) {
|
|
77
|
+
baseOfVariantType = node.type.name;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (containsExpand && containsNestedExpand && (variantType || baseOfVariantType)) {
|
|
62
81
|
break;
|
|
63
82
|
}
|
|
64
83
|
}
|
|
@@ -67,6 +86,26 @@ function transformSourceSlice(nodeCopy, destType) {
|
|
|
67
86
|
} else if (containsNestedExpand && destTypeInDocOrLayoutCol) {
|
|
68
87
|
return transformSliceNestedExpandToExpand(nodeCopy, schema);
|
|
69
88
|
}
|
|
89
|
+
|
|
90
|
+
// Downgrade variant → base (e.g. panel_c1 → panel) when dest doesn't support the variant
|
|
91
|
+
if (variantType && schema.nodes[variantType]) {
|
|
92
|
+
var destParent = destType.createAndFill();
|
|
93
|
+
if (destParent && !isNodeTypeValidChildOf(variantType, destParent, schema)) {
|
|
94
|
+
var _baseName = getBaseNodeTypeName(schema.nodes[variantType]);
|
|
95
|
+
return transformSliceNodeType(nodeCopy, schema, variantType, _baseName);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Upgrade base → variant (e.g. panel → panel_c1) when dest supports the variant
|
|
100
|
+
if (baseOfVariantType) {
|
|
101
|
+
var variantName = "".concat(baseOfVariantType, "_c1");
|
|
102
|
+
if (schema.nodes[variantName]) {
|
|
103
|
+
var _destParent = destType.createAndFill();
|
|
104
|
+
if (_destParent && isNodeTypeValidChildOf(variantName, _destParent, schema)) {
|
|
105
|
+
return transformSliceNodeType(nodeCopy, schema, baseOfVariantType, variantName);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
70
109
|
return nodeCopy;
|
|
71
110
|
}
|
|
72
111
|
var nodesSupportDragLayoutColumnInto = ['tableCell', 'tableHeader', 'panel', 'expand', 'nestedExpand'];
|
|
@@ -4,6 +4,7 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
|
4
4
|
import ReactDOM from 'react-dom';
|
|
5
5
|
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
6
6
|
import uuid from 'uuid';
|
|
7
|
+
import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
|
|
7
8
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
8
9
|
import { isFontSizeMarkActive } from './utils/validation';
|
|
9
10
|
export var TYPE_DROP_TARGET_DEC = 'drop-target-decoration';
|
|
@@ -25,7 +26,8 @@ var getSubType = function getSubType(node) {
|
|
|
25
26
|
};
|
|
26
27
|
export var getNodeTypeWithLevel = function getNodeTypeWithLevel(node) {
|
|
27
28
|
var subType = expValEquals('platform_editor_small_font_size', 'isEnabled', true) ? getSubType(node) : node.attrs.level ? "-".concat(node.attrs.level) : '';
|
|
28
|
-
|
|
29
|
+
var typeName = expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true) ? getBaseNodeTypeName(node.type) : node.type.name;
|
|
30
|
+
return typeName + subType;
|
|
29
31
|
};
|
|
30
32
|
var ObjHash = /*#__PURE__*/function () {
|
|
31
33
|
function ObjHash() {
|
|
@@ -2,6 +2,7 @@ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
|
2
2
|
import memoizeOne from 'memoize-one';
|
|
3
3
|
import { expandSelectionBounds } from '@atlaskit/editor-common/selection';
|
|
4
4
|
import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
|
|
5
|
+
import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
|
|
5
6
|
import { findChildrenByType } from '@atlaskit/editor-prosemirror/utils';
|
|
6
7
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
7
8
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
@@ -27,7 +28,8 @@ var getContainerNodeTypes = memoizeOne(function () {
|
|
|
27
28
|
return [].concat(PARENT_WITH_END_DROP_TARGET, _toConsumableArray(fg('confluence_frontend_native_tabs_extension') ? ['multiBodiedExtension'] : []), _toConsumableArray(editorExperiment('platform_synced_block', true) ? ['bodiedSyncBlock'] : []));
|
|
28
29
|
});
|
|
29
30
|
var isContainerNode = function isContainerNode(node) {
|
|
30
|
-
|
|
31
|
+
var nodeName = expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true) ? getBaseNodeTypeName(node.type) : node.type.name;
|
|
32
|
+
return getContainerNodeTypes().includes(nodeName);
|
|
31
33
|
};
|
|
32
34
|
export var canMoveNodeOrSliceToPos = function canMoveNodeOrSliceToPos(state, node, parent, index, $toPos, activeNode) {
|
|
33
35
|
// For deciding to show drop targets or not when multiple nodes are selected
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import memoizeOne from 'memoize-one';
|
|
2
2
|
import { getParentOfTypeCount, isNestedTablesSupported } from '@atlaskit/editor-common/nesting';
|
|
3
|
+
import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
|
|
3
4
|
import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
|
|
4
5
|
import { findChildrenByType } from '@atlaskit/editor-prosemirror/utils';
|
|
5
6
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
@@ -69,6 +70,41 @@ export var transformFragmentExpandToNestedExpand = function transformFragmentExp
|
|
|
69
70
|
}
|
|
70
71
|
return Fragment.fromArray(children);
|
|
71
72
|
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Generic fragment transformer — converts all nodes of `fromType` to `toType`,
|
|
76
|
+
* preserving attrs, content, and marks.
|
|
77
|
+
*/
|
|
78
|
+
export var transformFragmentNodeType = function transformFragmentNodeType(fragment, schema, fromType, toType) {
|
|
79
|
+
var children = [];
|
|
80
|
+
var targetType = schema.nodes[toType];
|
|
81
|
+
if (!targetType) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
fragment.forEach(function (node) {
|
|
86
|
+
if (node.type.name === fromType) {
|
|
87
|
+
children.push(targetType.create(node.attrs, node.content, node.marks));
|
|
88
|
+
} else {
|
|
89
|
+
children.push(node);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
} catch (e) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
return Fragment.fromArray(children);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Generic slice transformer — converts all nodes of `fromType` to `toType`.
|
|
100
|
+
*/
|
|
101
|
+
export var transformSliceNodeType = function transformSliceNodeType(slice, schema, fromType, toType) {
|
|
102
|
+
var fragment = transformFragmentNodeType(slice.content, schema, fromType, toType);
|
|
103
|
+
if (!fragment) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
return new Slice(fragment, slice.openStart, slice.openEnd);
|
|
107
|
+
};
|
|
72
108
|
export var transformSliceExpandToNestedExpand = function transformSliceExpandToNestedExpand(slice) {
|
|
73
109
|
var fragment = transformFragmentExpandToNestedExpand(slice.content);
|
|
74
110
|
if (!fragment) {
|
|
@@ -153,6 +189,19 @@ export function canMoveNodeToIndex(destParent, indexIntoParent, srcNode, $destNo
|
|
|
153
189
|
} else if ((isDoc(destParent.type) || isLayoutColumn(destParent.type)) && isNestedExpand(srcNodeType)) {
|
|
154
190
|
srcNodeType = expand;
|
|
155
191
|
}
|
|
192
|
+
|
|
193
|
+
// Downgrade variant node (e.g. panel_c1 → panel) when dest doesn't support it
|
|
194
|
+
if (expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true)) {
|
|
195
|
+
var baseName = getBaseNodeTypeName(srcNodeType);
|
|
196
|
+
if (baseName !== srcNodeType.name && !destParent.canReplaceWith(indexIntoParent, indexIntoParent, srcNodeType)) {
|
|
197
|
+
var baseType = schema.nodes[baseName];
|
|
198
|
+
// Check if the node's content is valid in the base type (e.g. panel with table can't be downgraded)
|
|
199
|
+
if (!baseType || !baseType.validContent(srcNode.content)) {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
srcNodeType = baseType;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
156
205
|
return destParent.canReplaceWith(indexIntoParent, indexIntoParent, srcNodeType);
|
|
157
206
|
}
|
|
158
207
|
export function canMoveSliceToIndex(slice, sliceFromPos, sliceToPos, destParent, indexIntoParent, $destNodePos, destNode) {
|
|
@@ -78,6 +78,37 @@ var buttonWrapperStyles = css({
|
|
|
78
78
|
boxSizing: 'border-box'
|
|
79
79
|
}
|
|
80
80
|
});
|
|
81
|
+
|
|
82
|
+
// EDITOR-6790 - When the `platform_editor_table_col_insert` experiment is enabled,
|
|
83
|
+
// drop the linear-gradient background that paints over the legacy `tr.sticky` table
|
|
84
|
+
// header so the new left-edge column-insert affordance is not visually clipped.
|
|
85
|
+
// Keep all paddings / margins identical to `buttonWrapperStyles` so the drag-handle
|
|
86
|
+
// layout does not shift between the two variants.
|
|
87
|
+
var buttonWrapperStylesNoBackground = css({
|
|
88
|
+
display: 'flex',
|
|
89
|
+
justifyContent: 'center',
|
|
90
|
+
alignItems: 'center',
|
|
91
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
|
|
92
|
+
'[data-blocks-drag-handle-container]:has(+ [data-prosemirror-node-name="table"] .pm-table-with-controls tr.sticky) &': {
|
|
93
|
+
marginBottom: "var(--ds-space-negative-200, -16px)",
|
|
94
|
+
paddingBottom: "var(--ds-space-200, 16px)",
|
|
95
|
+
marginTop: "var(--ds-space-negative-400, -32px)",
|
|
96
|
+
paddingTop: "calc(".concat("var(--ds-space-400, 32px)", " - 1px)"),
|
|
97
|
+
marginRight: "var(--ds-space-negative-150, -12px)",
|
|
98
|
+
paddingRight: "var(--ds-space-150, 12px)",
|
|
99
|
+
boxSizing: 'border-box'
|
|
100
|
+
},
|
|
101
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
|
|
102
|
+
'[data-prosemirror-mark-name="breakout"]:has([data-blocks-drag-handle-container]):has(+ [data-prosemirror-node-name="table"] .pm-table-with-controls tr.sticky) &': {
|
|
103
|
+
marginBottom: "var(--ds-space-negative-200, -16px)",
|
|
104
|
+
paddingBottom: "var(--ds-space-200, 16px)",
|
|
105
|
+
marginTop: "var(--ds-space-negative-400, -32px)",
|
|
106
|
+
paddingTop: "calc(".concat("var(--ds-space-400, 32px)", " - 1px)"),
|
|
107
|
+
marginRight: "var(--ds-space-negative-150, -12px)",
|
|
108
|
+
paddingRight: "var(--ds-space-150, 12px)",
|
|
109
|
+
boxSizing: 'border-box'
|
|
110
|
+
}
|
|
111
|
+
});
|
|
81
112
|
var buttonWrapperStylesPatch = css({
|
|
82
113
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
|
|
83
114
|
'[data-blocks-drag-handle-container]:has(+ [data-prosemirror-node-name="table"] .pm-table-with-controls [data-number-column="true"] tr.sticky) &': {
|
|
@@ -1088,7 +1119,10 @@ export var DragHandle = function DragHandle(_ref) {
|
|
|
1088
1119
|
});
|
|
1089
1120
|
}
|
|
1090
1121
|
}, jsx("span", {
|
|
1091
|
-
css: [shouldMaskNodeControls(nodeType, isTopLevelNodeValue) &&
|
|
1122
|
+
css: [shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && (
|
|
1123
|
+
// EDITOR-6790 - drop the masking background under the new
|
|
1124
|
+
// column-insert experiment so the left-edge dot is not clipped.
|
|
1125
|
+
expValEquals('platform_editor_table_col_insert', 'isEnabled', true) ? buttonWrapperStylesNoBackground : buttonWrapperStyles), buttonWrapperStylesPatch]
|
|
1092
1126
|
}, renderButton()))));
|
|
1093
1127
|
};
|
|
1094
1128
|
var stickyWithoutTooltip = function stickyWithoutTooltip() {
|
|
@@ -1104,7 +1138,10 @@ export var DragHandle = function DragHandle(_ref) {
|
|
|
1104
1138
|
}, jsx("span", {
|
|
1105
1139
|
css: [tooltipContainerStyles, shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && tooltipContainerStylesStickyHeaderWithMask, !shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && tooltipContainerStylesStickyHeaderWithoutMask]
|
|
1106
1140
|
}, jsx("span", {
|
|
1107
|
-
css: [shouldMaskNodeControls(nodeType, isTopLevelNodeValue) &&
|
|
1141
|
+
css: [shouldMaskNodeControls(nodeType, isTopLevelNodeValue) && (
|
|
1142
|
+
// EDITOR-6790 - drop the masking background under the new
|
|
1143
|
+
// column-insert experiment so the left-edge dot is not clipped.
|
|
1144
|
+
expValEquals('platform_editor_table_col_insert', 'isEnabled', true) ? buttonWrapperStylesNoBackground : buttonWrapperStyles), buttonWrapperStylesPatch]
|
|
1108
1145
|
}, renderButton())));
|
|
1109
1146
|
};
|
|
1110
1147
|
var buttonWithTooltip = function buttonWithTooltip() {
|
|
@@ -9,6 +9,7 @@ import { Fragment, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
9
9
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports
|
|
10
10
|
import { css, jsx } from '@emotion/react';
|
|
11
11
|
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
12
|
+
import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
|
|
12
13
|
import { DropIndicator } from '@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box';
|
|
13
14
|
import { dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
14
15
|
import { layers } from '@atlaskit/theme/constants';
|
|
@@ -223,7 +224,7 @@ export var DropTarget = function DropTarget(props) {
|
|
|
223
224
|
};
|
|
224
225
|
var dynamicStyle = _defineProperty(_defineProperty(_defineProperty({
|
|
225
226
|
width: isNestedDropTarget ? 'unset' : '100%'
|
|
226
|
-
}, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_WIDTH, isNestedDropTarget ? '100%' : "".concat(lineLength || DEFAULT_DROP_INDICATOR_WIDTH, "px")), EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN, isNestedDropTarget ? getNestedNodeLeftPaddingMargin(parentNode === null || parentNode === void 0 ? void 0 : parentNode.type.name) : '0'), EDITOR_BLOCK_CONTROLS_DROP_TARGET_ZINDEX, layers.navigation());
|
|
227
|
+
}, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_WIDTH, isNestedDropTarget ? '100%' : "".concat(lineLength || DEFAULT_DROP_INDICATOR_WIDTH, "px")), EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN, isNestedDropTarget ? expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true) && parentNode !== null && parentNode !== void 0 && parentNode.type ? getNestedNodeLeftPaddingMargin(getBaseNodeTypeName(parentNode.type)) : getNestedNodeLeftPaddingMargin(parentNode === null || parentNode === void 0 ? void 0 : parentNode.type.name) : '0'), EDITOR_BLOCK_CONTROLS_DROP_TARGET_ZINDEX, layers.navigation());
|
|
227
228
|
var isShowInlineDropTarget = shouldAllowInlineDropTarget(isNestedDropTarget, nextNode, isSameLayout, activeNode, parentNode);
|
|
228
229
|
return jsx(Fragment, null, jsx(HoverZone
|
|
229
230
|
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { MemoizedFn } from 'memoize-one';
|
|
2
|
-
import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
-
import type { NodeType, Node as PMNode, ResolvedPos } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
import { Fragment, Slice, type Schema, type NodeType, type Node as PMNode, type ResolvedPos } from '@atlaskit/editor-prosemirror/model';
|
|
4
3
|
export declare const isInsideTable: (nodeType: NodeType) => Boolean;
|
|
5
4
|
export declare const isLayoutColumn: (nodeType: NodeType) => Boolean;
|
|
6
5
|
export declare const isDoc: (nodeType: NodeType) => Boolean;
|
|
@@ -17,6 +16,15 @@ export declare const isInSameLayout: ($from: ResolvedPos, $to: ResolvedPos) => b
|
|
|
17
16
|
*/
|
|
18
17
|
export declare const transformExpandToNestedExpand: (expandNode: PMNode) => PMNode | null;
|
|
19
18
|
export declare const transformFragmentExpandToNestedExpand: (fragment: Fragment) => Fragment | null;
|
|
19
|
+
/**
|
|
20
|
+
* Generic fragment transformer — converts all nodes of `fromType` to `toType`,
|
|
21
|
+
* preserving attrs, content, and marks.
|
|
22
|
+
*/
|
|
23
|
+
export declare const transformFragmentNodeType: (fragment: Fragment, schema: Schema, fromType: string, toType: string) => Fragment | null;
|
|
24
|
+
/**
|
|
25
|
+
* Generic slice transformer — converts all nodes of `fromType` to `toType`.
|
|
26
|
+
*/
|
|
27
|
+
export declare const transformSliceNodeType: (slice: Slice, schema: Schema, fromType: string, toType: string) => Slice | null;
|
|
20
28
|
export declare const transformSliceExpandToNestedExpand: (slice: Slice) => Slice | null;
|
|
21
29
|
export declare const memoizedTransformExpandToNestedExpand: MemoizedFn<(node: PMNode) => PMNode | null>;
|
|
22
30
|
export declare const canCreateNodeWithContentInsideAnotherNode: (nodeTypesToCreate: NodeType[], nodeWithTargetFragment: Fragment) => boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-block-controls",
|
|
3
|
-
"version": "13.0.
|
|
3
|
+
"version": "13.0.6",
|
|
4
4
|
"description": "Block controls plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"atlaskit:src": "src/index.ts",
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@atlaskit/browser-apis": "^1.0.0",
|
|
24
|
-
"@atlaskit/button": "^24.
|
|
24
|
+
"@atlaskit/button": "^24.1.0",
|
|
25
25
|
"@atlaskit/editor-plugin-accessibility-utils": "^12.0.0",
|
|
26
26
|
"@atlaskit/editor-plugin-analytics": "^12.0.0",
|
|
27
27
|
"@atlaskit/editor-plugin-editor-disabled": "^12.0.0",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@atlaskit/pragmatic-drag-and-drop-react-drop-indicator": "^4.0.0",
|
|
49
49
|
"@atlaskit/primitives": "^20.0.0",
|
|
50
50
|
"@atlaskit/theme": "^26.0.0",
|
|
51
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
51
|
+
"@atlaskit/tmp-editor-statsig": "^109.1.0",
|
|
52
52
|
"@atlaskit/tokens": "^14.0.0",
|
|
53
53
|
"@atlaskit/tooltip": "^23.0.0",
|
|
54
54
|
"@babel/runtime": "^7.0.0",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"uuid": "^3.1.0"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
|
-
"@atlaskit/editor-common": "^116.
|
|
62
|
+
"@atlaskit/editor-common": "^116.8.0",
|
|
63
63
|
"react": "^18.2.0",
|
|
64
64
|
"react-dom": "^18.2.0",
|
|
65
65
|
"react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
|