@atlaskit/editor-plugin-layout 11.0.2 → 11.0.4
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 +15 -0
- package/dist/cjs/layoutPlugin.js +18 -16
- package/dist/cjs/nodeviews/index.js +49 -1
- package/dist/cjs/pm-plugins/column-resize-divider.js +25 -7
- package/dist/cjs/pm-plugins/main.js +2 -2
- package/dist/cjs/pm-plugins/resizing.js +29 -4
- package/dist/cjs/ui/LayoutSSRReactContextsProvider.js +34 -0
- package/dist/es2019/layoutPlugin.js +20 -16
- package/dist/es2019/nodeviews/index.js +49 -1
- package/dist/es2019/pm-plugins/column-resize-divider.js +25 -7
- package/dist/es2019/pm-plugins/main.js +2 -2
- package/dist/es2019/pm-plugins/resizing.js +37 -7
- package/dist/es2019/ui/LayoutSSRReactContextsProvider.js +28 -0
- package/dist/esm/layoutPlugin.js +18 -16
- package/dist/esm/nodeviews/index.js +49 -1
- package/dist/esm/pm-plugins/column-resize-divider.js +25 -7
- package/dist/esm/pm-plugins/main.js +2 -2
- package/dist/esm/pm-plugins/resizing.js +29 -4
- package/dist/esm/ui/LayoutSSRReactContextsProvider.js +27 -0
- package/dist/types/nodeviews/index.d.ts +5 -0
- package/dist/types/pm-plugins/column-resize-divider.d.ts +2 -1
- package/dist/types/pm-plugins/main.d.ts +2 -1
- package/dist/types/pm-plugins/resizing.d.ts +2 -1
- package/dist/types/ui/LayoutSSRReactContextsProvider.d.ts +19 -0
- package/dist/types-ts4.5/nodeviews/index.d.ts +5 -0
- package/dist/types-ts4.5/pm-plugins/column-resize-divider.d.ts +2 -1
- package/dist/types-ts4.5/pm-plugins/main.d.ts +2 -1
- package/dist/types-ts4.5/pm-plugins/resizing.d.ts +2 -1
- package/dist/types-ts4.5/ui/LayoutSSRReactContextsProvider.d.ts +19 -0
- package/package.json +7 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-layout
|
|
2
2
|
|
|
3
|
+
## 11.0.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`1f5c61250d103`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/1f5c61250d103) -
|
|
8
|
+
Updating layout plugin to support ssr streaming
|
|
9
|
+
|
|
10
|
+
## 11.0.3
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- [`795424ce08dae`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/795424ce08dae) -
|
|
15
|
+
Add analytics for layout column resizing
|
|
16
|
+
- Updated dependencies
|
|
17
|
+
|
|
3
18
|
## 11.0.2
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/dist/cjs/layoutPlugin.js
CHANGED
|
@@ -57,7 +57,7 @@ var selectIntoLayoutSection = exports.selectIntoLayoutSection = function selectI
|
|
|
57
57
|
return tr;
|
|
58
58
|
};
|
|
59
59
|
var layoutPlugin = exports.layoutPlugin = function layoutPlugin(_ref) {
|
|
60
|
-
var _api$
|
|
60
|
+
var _api$analytics2, _api$analytics5;
|
|
61
61
|
var _ref$config = _ref.config,
|
|
62
62
|
options = _ref$config === void 0 ? {} : _ref$config,
|
|
63
63
|
api = _ref.api;
|
|
@@ -105,7 +105,8 @@ var layoutPlugin = exports.layoutPlugin = function layoutPlugin(_ref) {
|
|
|
105
105
|
var plugins = [{
|
|
106
106
|
name: 'layout',
|
|
107
107
|
plugin: function plugin() {
|
|
108
|
-
|
|
108
|
+
var _api$analytics;
|
|
109
|
+
return (0, _main.default)(options, api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions);
|
|
109
110
|
}
|
|
110
111
|
}];
|
|
111
112
|
if ((options.editorAppearance === 'full-page' || options.editorAppearance === 'full-width' || options.editorAppearance === 'max' && (0, _experiments.editorExperiment)('platform_editor_layout_column_resize_handle', true)) && api && (0, _experiments.editorExperiment)('advanced_layouts', true)) {
|
|
@@ -113,15 +114,16 @@ var layoutPlugin = exports.layoutPlugin = function layoutPlugin(_ref) {
|
|
|
113
114
|
name: 'layoutResizing',
|
|
114
115
|
plugin: function plugin(_ref2) {
|
|
115
116
|
var portalProviderAPI = _ref2.portalProviderAPI,
|
|
116
|
-
eventDispatcher = _ref2.eventDispatcher
|
|
117
|
-
|
|
117
|
+
eventDispatcher = _ref2.eventDispatcher,
|
|
118
|
+
getIntl = _ref2.getIntl;
|
|
119
|
+
return (0, _resizing.default)(options, api, portalProviderAPI, eventDispatcher, getIntl());
|
|
118
120
|
}
|
|
119
121
|
});
|
|
120
122
|
}
|
|
121
123
|
return plugins;
|
|
122
124
|
},
|
|
123
125
|
actions: {
|
|
124
|
-
insertLayoutColumns: (0, _actions.insertLayoutColumnsWithAnalytics)(api === null || api === void 0 || (_api$
|
|
126
|
+
insertLayoutColumns: (0, _actions.insertLayoutColumnsWithAnalytics)(api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions)
|
|
125
127
|
},
|
|
126
128
|
pluginsOptions: {
|
|
127
129
|
floatingToolbar: function floatingToolbar(state, intl) {
|
|
@@ -143,8 +145,8 @@ var layoutPlugin = exports.layoutPlugin = function layoutPlugin(_ref) {
|
|
|
143
145
|
quickInsert: function quickInsert(_ref3) {
|
|
144
146
|
var formatMessage = _ref3.formatMessage;
|
|
145
147
|
var withInsertLayoutAnalytics = function withInsertLayoutAnalytics(tr, columnCount) {
|
|
146
|
-
var _api$
|
|
147
|
-
api === null || api === void 0 || (_api$
|
|
148
|
+
var _api$analytics3;
|
|
149
|
+
api === null || api === void 0 || (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 || (_api$analytics3 = _api$analytics3.actions) === null || _api$analytics3 === void 0 || _api$analytics3.attachAnalyticsEvent({
|
|
148
150
|
action: _analytics.ACTION.INSERTED,
|
|
149
151
|
actionSubject: _analytics.ACTION_SUBJECT.DOCUMENT,
|
|
150
152
|
actionSubjectId: _analytics.ACTION_SUBJECT_ID.LAYOUT,
|
|
@@ -340,9 +342,9 @@ var layoutPlugin = exports.layoutPlugin = function layoutPlugin(_ref) {
|
|
|
340
342
|
return /*#__PURE__*/_react.default.createElement(_quickInsert.IconLayout, null);
|
|
341
343
|
},
|
|
342
344
|
action: function action(insert, state) {
|
|
343
|
-
var _api$
|
|
345
|
+
var _api$analytics4;
|
|
344
346
|
var tr = insert((0, _actions.createDefaultLayoutSection)(state));
|
|
345
|
-
api === null || api === void 0 || (_api$
|
|
347
|
+
api === null || api === void 0 || (_api$analytics4 = api.analytics) === null || _api$analytics4 === void 0 || (_api$analytics4 = _api$analytics4.actions) === null || _api$analytics4 === void 0 || _api$analytics4.attachAnalyticsEvent({
|
|
346
348
|
action: _analytics.ACTION.INSERTED,
|
|
347
349
|
actionSubject: _analytics.ACTION_SUBJECT.DOCUMENT,
|
|
348
350
|
actionSubjectId: _analytics.ACTION_SUBJECT_ID.LAYOUT,
|
|
@@ -377,18 +379,18 @@ var layoutPlugin = exports.layoutPlugin = function layoutPlugin(_ref) {
|
|
|
377
379
|
return _pluginKey.pluginKey.getState(editorState);
|
|
378
380
|
},
|
|
379
381
|
commands: {
|
|
380
|
-
deleteLayoutColumn: (0, _actions.deleteLayoutColumn)(api === null || api === void 0 || (_api$
|
|
382
|
+
deleteLayoutColumn: (0, _actions.deleteLayoutColumn)(api === null || api === void 0 || (_api$analytics5 = api.analytics) === null || _api$analytics5 === void 0 ? void 0 : _api$analytics5.actions, api),
|
|
381
383
|
distributeLayoutColumns: function distributeLayoutColumns(options) {
|
|
382
|
-
var _api$
|
|
383
|
-
return (0, _actions.distributeLayoutColumns)(api === null || api === void 0 || (_api$
|
|
384
|
+
var _api$analytics6;
|
|
385
|
+
return (0, _actions.distributeLayoutColumns)(api === null || api === void 0 || (_api$analytics6 = api.analytics) === null || _api$analytics6 === void 0 ? void 0 : _api$analytics6.actions, api)(options);
|
|
384
386
|
},
|
|
385
387
|
insertLayoutColumn: function insertLayoutColumn(side) {
|
|
386
|
-
var _api$
|
|
387
|
-
return (0, _actions.insertLayoutColumn)(side, api === null || api === void 0 || (_api$
|
|
388
|
+
var _api$analytics7;
|
|
389
|
+
return (0, _actions.insertLayoutColumn)(side, api === null || api === void 0 || (_api$analytics7 = api.analytics) === null || _api$analytics7 === void 0 ? void 0 : _api$analytics7.actions, api);
|
|
388
390
|
},
|
|
389
391
|
setLayoutColumnValign: function setLayoutColumnValign(valign) {
|
|
390
|
-
var _api$
|
|
391
|
-
return (0, _actions.setLayoutColumnValign)(valign, api === null || api === void 0 || (_api$
|
|
392
|
+
var _api$analytics8;
|
|
393
|
+
return (0, _actions.setLayoutColumnValign)(valign, api === null || api === void 0 || (_api$analytics8 = api.analytics) === null || _api$analytics8 === void 0 ? void 0 : _api$analytics8.actions, api);
|
|
392
394
|
},
|
|
393
395
|
toggleLayoutColumnMenu: _actions.toggleLayoutColumnMenu
|
|
394
396
|
}
|
|
@@ -13,8 +13,9 @@ var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/ge
|
|
|
13
13
|
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
|
|
14
14
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
15
15
|
var _react = _interopRequireWildcard(require("react"));
|
|
16
|
+
var _coreUtils = require("@atlaskit/editor-common/core-utils");
|
|
16
17
|
var _hooks = require("@atlaskit/editor-common/hooks");
|
|
17
|
-
var _reactNodeView =
|
|
18
|
+
var _reactNodeView = _interopRequireWildcard(require("@atlaskit/editor-common/react-node-view"));
|
|
18
19
|
var _resizer = require("@atlaskit/editor-common/resizer");
|
|
19
20
|
var _useSharedPluginStateSelector = require("@atlaskit/editor-common/use-shared-plugin-state-selector");
|
|
20
21
|
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
@@ -22,6 +23,7 @@ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
|
22
23
|
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
23
24
|
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
|
|
24
25
|
var _utils = require("../pm-plugins/utils");
|
|
26
|
+
var _LayoutSSRReactContextsProvider = require("../ui/LayoutSSRReactContextsProvider");
|
|
25
27
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
26
28
|
function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); }
|
|
27
29
|
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
|
|
@@ -140,6 +142,7 @@ var LayoutSectionView = exports.LayoutSectionView = /*#__PURE__*/function (_Reac
|
|
|
140
142
|
* @param props.eventDispatcher
|
|
141
143
|
* @param props.pluginInjectionApi
|
|
142
144
|
* @param props.options
|
|
145
|
+
* @param props.intl
|
|
143
146
|
* @example
|
|
144
147
|
*/
|
|
145
148
|
function LayoutSectionView(props) {
|
|
@@ -148,6 +151,7 @@ var LayoutSectionView = exports.LayoutSectionView = /*#__PURE__*/function (_Reac
|
|
|
148
151
|
_this = _callSuper(this, LayoutSectionView, [props.node, props.view, props.getPos, props.portalProviderAPI, props.eventDispatcher, props]);
|
|
149
152
|
_this.isEmpty = isEmptyLayout(_this.node);
|
|
150
153
|
_this.options = props.options;
|
|
154
|
+
_this.intl = props.intl;
|
|
151
155
|
return _this;
|
|
152
156
|
}
|
|
153
157
|
|
|
@@ -160,6 +164,13 @@ var LayoutSectionView = exports.LayoutSectionView = /*#__PURE__*/function (_Reac
|
|
|
160
164
|
return (0, _createClass2.default)(LayoutSectionView, [{
|
|
161
165
|
key: "getContentDOM",
|
|
162
166
|
value: function getContentDOM() {
|
|
167
|
+
// Build the layout DOM via the schema's toDOM spec. This is the same
|
|
168
|
+
// path used in both CSR and SSR — the only SSR-specific concern is
|
|
169
|
+
// re-attaching `contentDOM` (= the `[data-layout-section]` element)
|
|
170
|
+
// after the portal's renderToStaticMarkup + innerHTML write detaches
|
|
171
|
+
// it. We handle that by stamping `data-ssr-content-dom-ref` on the
|
|
172
|
+
// outer container so `ReactNodeView.init()` can find a re-attach
|
|
173
|
+
// target inside `domRef` after the portal write.
|
|
163
174
|
var _ref2 = _model.DOMSerializer.renderSpec(document, toDOM(this.node)),
|
|
164
175
|
container = _ref2.dom,
|
|
165
176
|
contentDOM = _ref2.contentDOM;
|
|
@@ -172,6 +183,20 @@ var LayoutSectionView = exports.LayoutSectionView = /*#__PURE__*/function (_Reac
|
|
|
172
183
|
if ((0, _platformFeatureFlags.fg)('platform_editor_adf_with_localid')) {
|
|
173
184
|
this.layoutDOM.setAttribute('data-local-id', this.node.attrs.localId);
|
|
174
185
|
}
|
|
186
|
+
|
|
187
|
+
// SSR streaming re-attach note:
|
|
188
|
+
// In SSR, `init()` appends `container` into `domRef`; the portal's
|
|
189
|
+
// renderToStaticMarkup + innerHTML write then wipes `domRef`,
|
|
190
|
+
// detaching the entire subtree (with PM-serialized children inside
|
|
191
|
+
// `[data-layout-section]`). React's `render()` emits a
|
|
192
|
+
// `<NodeViewContentHole/>` placeholder inside `domRef`; the SSR
|
|
193
|
+
// re-attach logic in `init()` finds it via `[data-ssr-content-dom-ref]`
|
|
194
|
+
// and calls `_handleRef`, which appends `contentDOMWrapper` (the
|
|
195
|
+
// detached `container`) back inside the placeholder. The end result
|
|
196
|
+
// is `domRef > NodeViewContentHole > layout-section-container >
|
|
197
|
+
// [data-layout-section] > [data-layout-column] children` — the
|
|
198
|
+
// layout DOM contract is preserved.
|
|
199
|
+
|
|
175
200
|
return {
|
|
176
201
|
dom: container,
|
|
177
202
|
contentDOM: contentDOM
|
|
@@ -206,6 +231,29 @@ var LayoutSectionView = exports.LayoutSectionView = /*#__PURE__*/function (_Reac
|
|
|
206
231
|
if (this.layoutDOM) {
|
|
207
232
|
this.layoutDOM.setAttribute('data-empty-layout', Boolean(this.isEmpty).toString());
|
|
208
233
|
}
|
|
234
|
+
|
|
235
|
+
// SSR streaming path: render only a `<NodeViewContentHole/>` placeholder
|
|
236
|
+
// so ReactNodeView.init()'s SSR re-attach logic can find the marker
|
|
237
|
+
// (`data-ssr-content-dom-ref`) and re-append the detached
|
|
238
|
+
// contentDOMWrapper — which is the FULL layout structure
|
|
239
|
+
// (`layout-section-container > [data-layout-section] > children`) built
|
|
240
|
+
// in `getContentDOM` via DOMSerializer.renderSpec. This avoids
|
|
241
|
+
// duplicating layout structure between getContentDOM and render(), which
|
|
242
|
+
// previously caused an extra wrapping div between `[data-layout-section]`
|
|
243
|
+
// and the `[data-layout-column]` children and broke the flex layout.
|
|
244
|
+
//
|
|
245
|
+
// The BreakoutResizer is intentionally omitted in SSR — it relies on
|
|
246
|
+
// browser-only APIs and contributes no useful static markup. The
|
|
247
|
+
// LayoutSSRReactContextsProvider wraps the placeholder to inject the
|
|
248
|
+
// editor's IntlShape, defending against any descendants that call
|
|
249
|
+
// `useIntl()` during renderToStaticMarkup.
|
|
250
|
+
if ((0, _coreUtils.isSSR)() && (0, _coreUtils.isSSRStreaming)()) {
|
|
251
|
+
return /*#__PURE__*/_react.default.createElement(_LayoutSSRReactContextsProvider.LayoutSSRReactContextsProvider, {
|
|
252
|
+
intl: this.intl
|
|
253
|
+
}, /*#__PURE__*/_react.default.createElement(_reactNodeView.NodeViewContentHole, {
|
|
254
|
+
ref: forwardRef
|
|
255
|
+
}));
|
|
256
|
+
}
|
|
209
257
|
if ((0, _expValEquals.expValEquals)('platform_editor_breakout_resizing', 'isEnabled', true)) {
|
|
210
258
|
return null;
|
|
211
259
|
}
|
|
@@ -7,8 +7,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
exports.getColumnDividerDecorations = void 0;
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
9
|
var _bindEventListener = require("bind-event-listener");
|
|
10
|
+
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
10
11
|
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
11
12
|
var _view = require("@atlaskit/editor-prosemirror/view");
|
|
13
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
12
14
|
var _consts = require("./consts");
|
|
13
15
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
14
16
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
@@ -24,7 +26,7 @@ var dragState = null;
|
|
|
24
26
|
* Dispatches a single undoable ProseMirror transaction to commit the final
|
|
25
27
|
* column widths after a drag completes.
|
|
26
28
|
*/
|
|
27
|
-
var dispatchColumnWidths = function dispatchColumnWidths(view, sectionPos, leftColIndex, leftWidth, rightWidth) {
|
|
29
|
+
var dispatchColumnWidths = function dispatchColumnWidths(view, sectionPos, leftColIndex, leftWidth, rightWidth, editorAnalyticsAPI) {
|
|
28
30
|
var state = view.state;
|
|
29
31
|
var sectionNode = state.doc.nodeAt(sectionPos);
|
|
30
32
|
if (!sectionNode) {
|
|
@@ -51,6 +53,21 @@ var dispatchColumnWidths = function dispatchColumnWidths(view, sectionPos, leftC
|
|
|
51
53
|
tr.replaceWith(sectionPos + 1, sectionPos + sectionNode.nodeSize - 1, _model.Fragment.from(newColumns));
|
|
52
54
|
tr.setMeta('layoutColumnResize', true);
|
|
53
55
|
tr.setMeta('scrollIntoView', false);
|
|
56
|
+
if ((0, _platformFeatureFlags.fg)('platform_editor_layout_resize_analytics')) {
|
|
57
|
+
editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent({
|
|
58
|
+
action: _analytics.ACTION.DRAGGED,
|
|
59
|
+
actionSubject: _analytics.ACTION_SUBJECT.DOCUMENT,
|
|
60
|
+
actionSubjectId: _analytics.ACTION_SUBJECT_ID.LAYOUT_COLUMN,
|
|
61
|
+
attributes: {
|
|
62
|
+
columnCount: sectionNode.childCount,
|
|
63
|
+
leftColumnIndex: leftColIndex,
|
|
64
|
+
leftColumnWidth: Number(leftWidth.toFixed(2)),
|
|
65
|
+
rightColumnWidth: Number(rightWidth.toFixed(2)),
|
|
66
|
+
inputMethod: _analytics.INPUT_METHOD.DRAG
|
|
67
|
+
},
|
|
68
|
+
eventType: _analytics.EVENT_TYPE.TRACK
|
|
69
|
+
})(tr);
|
|
70
|
+
}
|
|
54
71
|
view.dispatch(tr);
|
|
55
72
|
};
|
|
56
73
|
|
|
@@ -152,7 +169,8 @@ var onDragEnd = function onDragEnd(clientX) {
|
|
|
152
169
|
rafId = _dragState2.rafId,
|
|
153
170
|
startLeftWidth = _dragState2.startLeftWidth,
|
|
154
171
|
startRightWidth = _dragState2.startRightWidth,
|
|
155
|
-
unbindListeners = _dragState2.unbindListeners
|
|
172
|
+
unbindListeners = _dragState2.unbindListeners,
|
|
173
|
+
editorAnalyticsAPI = _dragState2.editorAnalyticsAPI;
|
|
156
174
|
unbindListeners();
|
|
157
175
|
|
|
158
176
|
// Cancel any pending rAF so a stale frame doesn't write styles after teardown.
|
|
@@ -175,7 +193,7 @@ var onDragEnd = function onDragEnd(clientX) {
|
|
|
175
193
|
leftColEl.style.flexBasis = '';
|
|
176
194
|
rightColEl.style.flexBasis = '';
|
|
177
195
|
if (widths && (widths.leftWidth !== startLeftWidth || widths.rightWidth !== startRightWidth)) {
|
|
178
|
-
dispatchColumnWidths(view, sectionPos, leftColIndex, widths.leftWidth, widths.rightWidth);
|
|
196
|
+
dispatchColumnWidths(view, sectionPos, leftColIndex, widths.leftWidth, widths.rightWidth, editorAnalyticsAPI);
|
|
179
197
|
}
|
|
180
198
|
};
|
|
181
199
|
var onDragMouseUp = function onDragMouseUp(e) {
|
|
@@ -202,8 +220,7 @@ var onDragCancel = function onDragCancel() {
|
|
|
202
220
|
* column DOM elements for zero-overhead visual feedback (no PM transactions).
|
|
203
221
|
* A single undoable PM transaction is dispatched on mouseup to commit the final widths.
|
|
204
222
|
*/
|
|
205
|
-
var createColumnDividerWidget = function createColumnDividerWidget(view, sectionPos, columnIndex
|
|
206
|
-
) {
|
|
223
|
+
var createColumnDividerWidget = function createColumnDividerWidget(view, sectionPos, columnIndex, editorAnalyticsAPI) {
|
|
207
224
|
var ownerDoc = view.dom.ownerDocument;
|
|
208
225
|
|
|
209
226
|
// Outer container: wide transparent hit area for easy grabbing, zero flex footprint
|
|
@@ -298,6 +315,7 @@ var createColumnDividerWidget = function createColumnDividerWidget(view, section
|
|
|
298
315
|
var totalGap = childCount > 1 ? computedGap * (childCount - 1) : 0;
|
|
299
316
|
var columnsWidth = sectionRect.width - dividersWidth - totalGap;
|
|
300
317
|
dragState = {
|
|
318
|
+
editorAnalyticsAPI: editorAnalyticsAPI,
|
|
301
319
|
hasDragged: false,
|
|
302
320
|
lastClientX: e.clientX,
|
|
303
321
|
rafId: null,
|
|
@@ -329,7 +347,7 @@ var createColumnDividerWidget = function createColumnDividerWidget(view, section
|
|
|
329
347
|
* Returns ProseMirror Decoration widgets for column dividers between layout columns.
|
|
330
348
|
* Each divider supports drag-to-resize interaction for the adjacent columns.
|
|
331
349
|
*/
|
|
332
|
-
var getColumnDividerDecorations = exports.getColumnDividerDecorations = function getColumnDividerDecorations(state, view) {
|
|
350
|
+
var getColumnDividerDecorations = exports.getColumnDividerDecorations = function getColumnDividerDecorations(state, view, editorAnalyticsAPI) {
|
|
333
351
|
var decorations = [];
|
|
334
352
|
if (!view) {
|
|
335
353
|
return decorations;
|
|
@@ -345,7 +363,7 @@ var getColumnDividerDecorations = exports.getColumnDividerDecorations = function
|
|
|
345
363
|
var colIndex = index;
|
|
346
364
|
var widgetPos = pos + offset + 1; // position at the start of this column
|
|
347
365
|
decorations.push(_view.Decoration.widget(widgetPos, function () {
|
|
348
|
-
return createColumnDividerWidget(view, sectionPos, colIndex);
|
|
366
|
+
return createColumnDividerWidget(view, sectionPos, colIndex, editorAnalyticsAPI);
|
|
349
367
|
}, {
|
|
350
368
|
side: -1,
|
|
351
369
|
// place before the position
|
|
@@ -102,7 +102,7 @@ var handleDeleteLayoutColumn = function handleDeleteLayoutColumn(state, dispatch
|
|
|
102
102
|
}
|
|
103
103
|
return false;
|
|
104
104
|
};
|
|
105
|
-
var _default = exports.default = function _default(options) {
|
|
105
|
+
var _default = exports.default = function _default(options, editorAnalyticsAPI) {
|
|
106
106
|
// Store a reference to the EditorView so widget decorations can dispatch transactions
|
|
107
107
|
var editorViewRef;
|
|
108
108
|
return new _safePlugin.SafePlugin({
|
|
@@ -152,7 +152,7 @@ var _default = exports.default = function _default(options) {
|
|
|
152
152
|
var layoutState = _pluginKey.pluginKey.getState(state);
|
|
153
153
|
var isLayoutResizingPluginAvailable = _resizing.pluginKey.get(state) !== undefined;
|
|
154
154
|
if ((0, _experiments.editorExperiment)('advanced_layouts', true) && (0, _experiments.editorExperiment)('platform_editor_layout_column_resize_handle', true) && isLayoutResizingPluginAvailable) {
|
|
155
|
-
var dividerDecorations = (0, _columnResizeDivider.getColumnDividerDecorations)(state, editorViewRef);
|
|
155
|
+
var dividerDecorations = (0, _columnResizeDivider.getColumnDividerDecorations)(state, editorViewRef, editorAnalyticsAPI);
|
|
156
156
|
var selectedDecorations = layoutState.pos !== null ? getNodeDecoration(layoutState.pos, state.doc.nodeAt(layoutState.pos)) : [];
|
|
157
157
|
var allDecorations = [].concat((0, _toConsumableArray2.default)(selectedDecorations), (0, _toConsumableArray2.default)(dividerDecorations));
|
|
158
158
|
if (allDecorations.length > 0) {
|
|
@@ -8,6 +8,8 @@ exports.pluginKey = exports.default = void 0;
|
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
9
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
10
10
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
11
|
+
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
|
12
|
+
var _coreUtils = require("@atlaskit/editor-common/core-utils");
|
|
11
13
|
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
12
14
|
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
13
15
|
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
@@ -26,6 +28,28 @@ var pluginKey = exports.pluginKey = new _state.PluginKey('layoutResizingPlugin')
|
|
|
26
28
|
* (e.g. setting flex-basis to give real-time visual feedback without dispatching
|
|
27
29
|
* PM transactions) are not "corrected" back by ProseMirror's DOM reconciliation.
|
|
28
30
|
*/
|
|
31
|
+
var isLayoutElementLike = function isLayoutElementLike(element) {
|
|
32
|
+
if ((0, _coreUtils.isSSR)() && (0, _coreUtils.isSSRStreaming)()) {
|
|
33
|
+
// In SSR environments, `HTMLElement` is undefined globally so a plain
|
|
34
|
+
// `instanceof HTMLElement` check is always `false`. That makes the
|
|
35
|
+
// `DOMSerializer.renderSpec(...)` result get rejected by the guard below and
|
|
36
|
+
// the NodeView falls back to a bare `<div>`, losing every schema-defined
|
|
37
|
+
// attribute (`data-layout-column`, `style="flex-basis:..."`,
|
|
38
|
+
// `data-column-width`, plus the inner `<div data-layout-content="true">`
|
|
39
|
+
// wrapper) and breaking the layout's flex sizing in SSR output.
|
|
40
|
+
//
|
|
41
|
+
// To unblock SSR streaming without changing CSR semantics, we gate the check:
|
|
42
|
+
// - In SSR (and only when `platform_editor_editor_ssr_streaming` is enabled),
|
|
43
|
+
// use a duck-typed check that mirrors `safe-plugin`'s `isHTMLElement`.
|
|
44
|
+
// - Everywhere else, keep the original `instanceof HTMLElement` check exactly
|
|
45
|
+
// as it was so we don't accidentally widen acceptance in CSR.
|
|
46
|
+
if (element === null || element === undefined) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
return (0, _typeof2.default)(element) === 'object' && 'innerHTML' in element && 'style' in element && 'classList' in element;
|
|
50
|
+
}
|
|
51
|
+
return element instanceof HTMLElement;
|
|
52
|
+
};
|
|
29
53
|
var LayoutColumnView = /*#__PURE__*/function () {
|
|
30
54
|
function LayoutColumnView(node, view, getPos) {
|
|
31
55
|
(0, _classCallCheck2.default)(this, LayoutColumnView);
|
|
@@ -43,7 +67,7 @@ var LayoutColumnView = /*#__PURE__*/function () {
|
|
|
43
67
|
var _DOMSerializer$render = _model.DOMSerializer.renderSpec(document, nodeType.spec.toDOM(node)),
|
|
44
68
|
dom = _DOMSerializer$render.dom,
|
|
45
69
|
contentDOM = _DOMSerializer$render.contentDOM;
|
|
46
|
-
if (!(dom
|
|
70
|
+
if (!isLayoutElementLike(dom) || !isLayoutElementLike(contentDOM)) {
|
|
47
71
|
var _fallbackDiv = document.createElement('div');
|
|
48
72
|
this.dom = _fallbackDiv;
|
|
49
73
|
this.contentDOM = _fallbackDiv;
|
|
@@ -71,7 +95,7 @@ var LayoutColumnView = /*#__PURE__*/function () {
|
|
|
71
95
|
}
|
|
72
96
|
}]);
|
|
73
97
|
}();
|
|
74
|
-
var _default = exports.default = function _default(options, pluginInjectionApi, portalProviderAPI, eventDispatcher) {
|
|
98
|
+
var _default = exports.default = function _default(options, pluginInjectionApi, portalProviderAPI, eventDispatcher, intl) {
|
|
75
99
|
return new _safePlugin.SafePlugin({
|
|
76
100
|
key: pluginKey,
|
|
77
101
|
props: {
|
|
@@ -84,10 +108,11 @@ var _default = exports.default = function _default(options, pluginInjectionApi,
|
|
|
84
108
|
portalProviderAPI: portalProviderAPI,
|
|
85
109
|
eventDispatcher: eventDispatcher,
|
|
86
110
|
pluginInjectionApi: pluginInjectionApi,
|
|
87
|
-
options: options
|
|
111
|
+
options: options,
|
|
112
|
+
intl: intl
|
|
88
113
|
}).init();
|
|
89
114
|
}
|
|
90
|
-
}, (0, _experiments.editorExperiment)('platform_editor_layout_column_resize_handle', true) ? {
|
|
115
|
+
}, (0, _experiments.editorExperiment)('platform_editor_layout_column_resize_handle', true) || (0, _coreUtils.isSSR)() && (0, _coreUtils.isSSRStreaming)() ? {
|
|
91
116
|
layoutColumn: function layoutColumn(node, view, getPos) {
|
|
92
117
|
return new LayoutColumnView(node, view, getPos);
|
|
93
118
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.LayoutSSRReactContextsProvider = LayoutSSRReactContextsProvider;
|
|
8
|
+
var _react = _interopRequireDefault(require("react"));
|
|
9
|
+
var _reactIntl = require("react-intl");
|
|
10
|
+
var _coreUtils = require("@atlaskit/editor-common/core-utils");
|
|
11
|
+
/**
|
|
12
|
+
* Wraps the layout section nodeview children with the editor's actual
|
|
13
|
+
* IntlProvider during SSR streaming (renderToStaticMarkup). This ensures any
|
|
14
|
+
* descendants that call `useIntl()` (e.g. `BreakoutResizer`'s ARIA labels)
|
|
15
|
+
* have a valid intl context and do not throw during the static render pass.
|
|
16
|
+
*
|
|
17
|
+
* Outside of SSR streaming this is a no-op passthrough.
|
|
18
|
+
*
|
|
19
|
+
* Follows the same pattern as `MediaSSRReactContextsProvider` and
|
|
20
|
+
* `SyncBlockSSRReactContextsProvider`.
|
|
21
|
+
*/
|
|
22
|
+
function LayoutSSRReactContextsProvider(_ref) {
|
|
23
|
+
var children = _ref.children,
|
|
24
|
+
intl = _ref.intl;
|
|
25
|
+
if (!(0, _coreUtils.isSSRStreaming)() || !(0, _coreUtils.isSSR)()) {
|
|
26
|
+
return children;
|
|
27
|
+
}
|
|
28
|
+
if (!intl) {
|
|
29
|
+
return children;
|
|
30
|
+
}
|
|
31
|
+
return /*#__PURE__*/_react.default.createElement(_reactIntl.RawIntlProvider, {
|
|
32
|
+
value: intl
|
|
33
|
+
}, children);
|
|
34
|
+
}
|
|
@@ -52,7 +52,7 @@ export const layoutPlugin = ({
|
|
|
52
52
|
config: options = {},
|
|
53
53
|
api
|
|
54
54
|
}) => {
|
|
55
|
-
var _api$
|
|
55
|
+
var _api$analytics2, _api$analytics5;
|
|
56
56
|
const allowAdvancedSingleColumnLayout = editorExperiment('advanced_layouts', true) && editorExperiment('single_column_layouts', true, {
|
|
57
57
|
exposure: true
|
|
58
58
|
});
|
|
@@ -96,21 +96,25 @@ export const layoutPlugin = ({
|
|
|
96
96
|
pmPlugins() {
|
|
97
97
|
const plugins = [{
|
|
98
98
|
name: 'layout',
|
|
99
|
-
plugin: () =>
|
|
99
|
+
plugin: () => {
|
|
100
|
+
var _api$analytics;
|
|
101
|
+
return createLayoutPlugin(options, api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions);
|
|
102
|
+
}
|
|
100
103
|
}];
|
|
101
104
|
if ((options.editorAppearance === 'full-page' || options.editorAppearance === 'full-width' || options.editorAppearance === 'max' && editorExperiment('platform_editor_layout_column_resize_handle', true)) && api && editorExperiment('advanced_layouts', true)) {
|
|
102
105
|
plugins.push({
|
|
103
106
|
name: 'layoutResizing',
|
|
104
107
|
plugin: ({
|
|
105
108
|
portalProviderAPI,
|
|
106
|
-
eventDispatcher
|
|
107
|
-
|
|
109
|
+
eventDispatcher,
|
|
110
|
+
getIntl
|
|
111
|
+
}) => createLayoutResizingPlugin(options, api, portalProviderAPI, eventDispatcher, getIntl())
|
|
108
112
|
});
|
|
109
113
|
}
|
|
110
114
|
return plugins;
|
|
111
115
|
},
|
|
112
116
|
actions: {
|
|
113
|
-
insertLayoutColumns: insertLayoutColumnsWithAnalytics(api === null || api === void 0 ? void 0 : (_api$
|
|
117
|
+
insertLayoutColumns: insertLayoutColumnsWithAnalytics(api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions)
|
|
114
118
|
},
|
|
115
119
|
pluginsOptions: {
|
|
116
120
|
floatingToolbar(state, intl) {
|
|
@@ -135,8 +139,8 @@ export const layoutPlugin = ({
|
|
|
135
139
|
formatMessage
|
|
136
140
|
}) => {
|
|
137
141
|
const withInsertLayoutAnalytics = (tr, columnCount) => {
|
|
138
|
-
var _api$
|
|
139
|
-
api === null || api === void 0 ? void 0 : (_api$
|
|
142
|
+
var _api$analytics3, _api$analytics3$actio;
|
|
143
|
+
api === null || api === void 0 ? void 0 : (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : (_api$analytics3$actio = _api$analytics3.actions) === null || _api$analytics3$actio === void 0 ? void 0 : _api$analytics3$actio.attachAnalyticsEvent({
|
|
140
144
|
action: ACTION.INSERTED,
|
|
141
145
|
actionSubject: ACTION_SUBJECT.DOCUMENT,
|
|
142
146
|
actionSubjectId: ACTION_SUBJECT_ID.LAYOUT,
|
|
@@ -311,9 +315,9 @@ export const layoutPlugin = ({
|
|
|
311
315
|
priority: 1100,
|
|
312
316
|
icon: () => /*#__PURE__*/React.createElement(IconLayout, null),
|
|
313
317
|
action(insert, state) {
|
|
314
|
-
var _api$
|
|
318
|
+
var _api$analytics4, _api$analytics4$actio;
|
|
315
319
|
const tr = insert(createDefaultLayoutSection(state));
|
|
316
|
-
api === null || api === void 0 ? void 0 : (_api$
|
|
320
|
+
api === null || api === void 0 ? void 0 : (_api$analytics4 = api.analytics) === null || _api$analytics4 === void 0 ? void 0 : (_api$analytics4$actio = _api$analytics4.actions) === null || _api$analytics4$actio === void 0 ? void 0 : _api$analytics4$actio.attachAnalyticsEvent({
|
|
317
321
|
action: ACTION.INSERTED,
|
|
318
322
|
actionSubject: ACTION_SUBJECT.DOCUMENT,
|
|
319
323
|
actionSubjectId: ACTION_SUBJECT_ID.LAYOUT,
|
|
@@ -349,18 +353,18 @@ export const layoutPlugin = ({
|
|
|
349
353
|
return pluginKey.getState(editorState);
|
|
350
354
|
},
|
|
351
355
|
commands: {
|
|
352
|
-
deleteLayoutColumn: deleteLayoutColumn(api === null || api === void 0 ? void 0 : (_api$
|
|
356
|
+
deleteLayoutColumn: deleteLayoutColumn(api === null || api === void 0 ? void 0 : (_api$analytics5 = api.analytics) === null || _api$analytics5 === void 0 ? void 0 : _api$analytics5.actions, api),
|
|
353
357
|
distributeLayoutColumns: options => {
|
|
354
|
-
var _api$
|
|
355
|
-
return distributeLayoutColumns(api === null || api === void 0 ? void 0 : (_api$
|
|
358
|
+
var _api$analytics6;
|
|
359
|
+
return distributeLayoutColumns(api === null || api === void 0 ? void 0 : (_api$analytics6 = api.analytics) === null || _api$analytics6 === void 0 ? void 0 : _api$analytics6.actions, api)(options);
|
|
356
360
|
},
|
|
357
361
|
insertLayoutColumn: side => {
|
|
358
|
-
var _api$
|
|
359
|
-
return insertLayoutColumn(side, api === null || api === void 0 ? void 0 : (_api$
|
|
362
|
+
var _api$analytics7;
|
|
363
|
+
return insertLayoutColumn(side, api === null || api === void 0 ? void 0 : (_api$analytics7 = api.analytics) === null || _api$analytics7 === void 0 ? void 0 : _api$analytics7.actions, api);
|
|
360
364
|
},
|
|
361
365
|
setLayoutColumnValign: valign => {
|
|
362
|
-
var _api$
|
|
363
|
-
return setLayoutColumnValign(valign, api === null || api === void 0 ? void 0 : (_api$
|
|
366
|
+
var _api$analytics8;
|
|
367
|
+
return setLayoutColumnValign(valign, api === null || api === void 0 ? void 0 : (_api$analytics8 = api.analytics) === null || _api$analytics8 === void 0 ? void 0 : _api$analytics8.actions, api);
|
|
364
368
|
},
|
|
365
369
|
toggleLayoutColumnMenu
|
|
366
370
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useCallback } from 'react';
|
|
2
|
+
import { isSSR, isSSRStreaming } from '@atlaskit/editor-common/core-utils';
|
|
2
3
|
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
3
|
-
import ReactNodeView from '@atlaskit/editor-common/react-node-view';
|
|
4
|
+
import ReactNodeView, { NodeViewContentHole } from '@atlaskit/editor-common/react-node-view';
|
|
4
5
|
import { BreakoutResizer, ignoreResizerMutations } from '@atlaskit/editor-common/resizer';
|
|
5
6
|
import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
|
|
6
7
|
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
@@ -8,6 +9,7 @@ import { fg } from '@atlaskit/platform-feature-flags';
|
|
|
8
9
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
9
10
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
10
11
|
import { selectIntoLayout } from '../pm-plugins/utils';
|
|
12
|
+
import { LayoutSSRReactContextsProvider } from '../ui/LayoutSSRReactContextsProvider';
|
|
11
13
|
const layoutDynamicFullWidthGuidelineOffset = 16;
|
|
12
14
|
const isEmptyParagraph = node => {
|
|
13
15
|
return !!node && node.type.name === 'paragraph' && !node.childCount;
|
|
@@ -122,12 +124,14 @@ export class LayoutSectionView extends ReactNodeView {
|
|
|
122
124
|
* @param props.eventDispatcher
|
|
123
125
|
* @param props.pluginInjectionApi
|
|
124
126
|
* @param props.options
|
|
127
|
+
* @param props.intl
|
|
125
128
|
* @example
|
|
126
129
|
*/
|
|
127
130
|
constructor(props) {
|
|
128
131
|
super(props.node, props.view, props.getPos, props.portalProviderAPI, props.eventDispatcher, props);
|
|
129
132
|
this.isEmpty = isEmptyLayout(this.node);
|
|
130
133
|
this.options = props.options;
|
|
134
|
+
this.intl = props.intl;
|
|
131
135
|
}
|
|
132
136
|
|
|
133
137
|
/**
|
|
@@ -136,6 +140,13 @@ export class LayoutSectionView extends ReactNodeView {
|
|
|
136
140
|
* @returns
|
|
137
141
|
*/
|
|
138
142
|
getContentDOM() {
|
|
143
|
+
// Build the layout DOM via the schema's toDOM spec. This is the same
|
|
144
|
+
// path used in both CSR and SSR — the only SSR-specific concern is
|
|
145
|
+
// re-attaching `contentDOM` (= the `[data-layout-section]` element)
|
|
146
|
+
// after the portal's renderToStaticMarkup + innerHTML write detaches
|
|
147
|
+
// it. We handle that by stamping `data-ssr-content-dom-ref` on the
|
|
148
|
+
// outer container so `ReactNodeView.init()` can find a re-attach
|
|
149
|
+
// target inside `domRef` after the portal write.
|
|
139
150
|
const {
|
|
140
151
|
dom: container,
|
|
141
152
|
contentDOM
|
|
@@ -149,6 +160,20 @@ export class LayoutSectionView extends ReactNodeView {
|
|
|
149
160
|
if (fg('platform_editor_adf_with_localid')) {
|
|
150
161
|
this.layoutDOM.setAttribute('data-local-id', this.node.attrs.localId);
|
|
151
162
|
}
|
|
163
|
+
|
|
164
|
+
// SSR streaming re-attach note:
|
|
165
|
+
// In SSR, `init()` appends `container` into `domRef`; the portal's
|
|
166
|
+
// renderToStaticMarkup + innerHTML write then wipes `domRef`,
|
|
167
|
+
// detaching the entire subtree (with PM-serialized children inside
|
|
168
|
+
// `[data-layout-section]`). React's `render()` emits a
|
|
169
|
+
// `<NodeViewContentHole/>` placeholder inside `domRef`; the SSR
|
|
170
|
+
// re-attach logic in `init()` finds it via `[data-ssr-content-dom-ref]`
|
|
171
|
+
// and calls `_handleRef`, which appends `contentDOMWrapper` (the
|
|
172
|
+
// detached `container`) back inside the placeholder. The end result
|
|
173
|
+
// is `domRef > NodeViewContentHole > layout-section-container >
|
|
174
|
+
// [data-layout-section] > [data-layout-column] children` — the
|
|
175
|
+
// layout DOM contract is preserved.
|
|
176
|
+
|
|
152
177
|
return {
|
|
153
178
|
dom: container,
|
|
154
179
|
contentDOM
|
|
@@ -179,6 +204,29 @@ export class LayoutSectionView extends ReactNodeView {
|
|
|
179
204
|
if (this.layoutDOM) {
|
|
180
205
|
this.layoutDOM.setAttribute('data-empty-layout', Boolean(this.isEmpty).toString());
|
|
181
206
|
}
|
|
207
|
+
|
|
208
|
+
// SSR streaming path: render only a `<NodeViewContentHole/>` placeholder
|
|
209
|
+
// so ReactNodeView.init()'s SSR re-attach logic can find the marker
|
|
210
|
+
// (`data-ssr-content-dom-ref`) and re-append the detached
|
|
211
|
+
// contentDOMWrapper — which is the FULL layout structure
|
|
212
|
+
// (`layout-section-container > [data-layout-section] > children`) built
|
|
213
|
+
// in `getContentDOM` via DOMSerializer.renderSpec. This avoids
|
|
214
|
+
// duplicating layout structure between getContentDOM and render(), which
|
|
215
|
+
// previously caused an extra wrapping div between `[data-layout-section]`
|
|
216
|
+
// and the `[data-layout-column]` children and broke the flex layout.
|
|
217
|
+
//
|
|
218
|
+
// The BreakoutResizer is intentionally omitted in SSR — it relies on
|
|
219
|
+
// browser-only APIs and contributes no useful static markup. The
|
|
220
|
+
// LayoutSSRReactContextsProvider wraps the placeholder to inject the
|
|
221
|
+
// editor's IntlShape, defending against any descendants that call
|
|
222
|
+
// `useIntl()` during renderToStaticMarkup.
|
|
223
|
+
if (isSSR() && isSSRStreaming()) {
|
|
224
|
+
return /*#__PURE__*/React.createElement(LayoutSSRReactContextsProvider, {
|
|
225
|
+
intl: this.intl
|
|
226
|
+
}, /*#__PURE__*/React.createElement(NodeViewContentHole, {
|
|
227
|
+
ref: forwardRef
|
|
228
|
+
}));
|
|
229
|
+
}
|
|
182
230
|
if (expValEquals('platform_editor_breakout_resizing', 'isEnabled', true)) {
|
|
183
231
|
return null;
|
|
184
232
|
}
|