@atlaskit/editor-common 112.18.1 → 112.18.3
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 +16 -0
- package/dist/cjs/extensibility/Extension/Extension/index.js +1 -2
- package/dist/cjs/extensibility/ExtensionNodeWrapper.js +2 -0
- package/dist/cjs/extensibility/extensionNodeView.js +112 -1
- package/dist/cjs/monitoring/error.js +1 -1
- package/dist/cjs/react-node-view/index.js +6 -3
- package/dist/cjs/ui/DropList/index.js +1 -1
- package/dist/es2019/extensibility/Extension/Extension/index.js +2 -3
- package/dist/es2019/extensibility/ExtensionNodeWrapper.js +2 -0
- package/dist/es2019/extensibility/extensionNodeView.js +100 -0
- package/dist/es2019/monitoring/error.js +1 -1
- package/dist/es2019/react-node-view/index.js +4 -2
- package/dist/es2019/ui/DropList/index.js +1 -1
- package/dist/esm/extensibility/Extension/Extension/index.js +2 -3
- package/dist/esm/extensibility/ExtensionNodeWrapper.js +2 -0
- package/dist/esm/extensibility/extensionNodeView.js +112 -1
- package/dist/esm/monitoring/error.js +1 -1
- package/dist/esm/react-node-view/index.js +6 -3
- package/dist/esm/ui/DropList/index.js +1 -1
- package/dist/types/analytics/types/ai-streaming.d.ts +6 -0
- package/dist/types/extensibility/extensionNodeView.d.ts +30 -1
- package/dist/types/react-node-view/index.d.ts +1 -1
- package/dist/types-ts4.5/analytics/types/ai-streaming.d.ts +6 -0
- package/dist/types-ts4.5/extensibility/extensionNodeView.d.ts +30 -1
- package/dist/types-ts4.5/react-node-view/index.d.ts +1 -1
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @atlaskit/editor-common
|
|
2
2
|
|
|
3
|
+
## 112.18.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`0a265af52321f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/0a265af52321f) -
|
|
8
|
+
Clean up stale feature flag platform_editor_extension_styles, keeping the enabled code path
|
|
9
|
+
- [`3f798d9934a76`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/3f798d9934a76) -
|
|
10
|
+
[ux] EDITOR-5487 skip react portal initial render when hydration for toc extension node view
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
|
|
13
|
+
## 112.18.2
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Updated dependencies
|
|
18
|
+
|
|
3
19
|
## 112.18.1
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
|
@@ -143,7 +143,6 @@ function ExtensionWithPluginState(props) {
|
|
|
143
143
|
setIsNodeHovered(didHover);
|
|
144
144
|
}
|
|
145
145
|
};
|
|
146
|
-
var extensionContentStyles = (0, _expValEquals.expValEquals)('platform_editor_extension_styles', 'isEnabled', true) ? _styles2.extensionContent : _styles2.content;
|
|
147
146
|
return (0, _react2.jsx)(_react.Fragment, null, !showLegacyContentHeader && showMacroInteractionDesignUpdates && !isLivePageViewMode && (0, _react2.jsx)(_Lozenge.default, {
|
|
148
147
|
isNodeSelected: isNodeSelected,
|
|
149
148
|
isNodeHovered: isNodeHovered,
|
|
@@ -218,7 +217,7 @@ function ExtensionWithPluginState(props) {
|
|
|
218
217
|
"data-testid": "extension-content"
|
|
219
218
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766
|
|
220
219
|
,
|
|
221
|
-
css:
|
|
220
|
+
css: _styles2.extensionContent
|
|
222
221
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
|
|
223
222
|
,
|
|
224
223
|
className: contentClassNames
|
|
@@ -78,7 +78,9 @@ var ExtensionNodeWrapper = exports.ExtensionNodeWrapper = function ExtensionNode
|
|
|
78
78
|
relative: showMacroInteractionDesignUpdates
|
|
79
79
|
});
|
|
80
80
|
return (0, _react2.jsx)("span", {
|
|
81
|
+
"data-testId": "extension-node-wrapper"
|
|
81
82
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
|
|
83
|
+
,
|
|
82
84
|
className: wrapperClassNames,
|
|
83
85
|
css: [styles, (0, _expValEquals.expValEquals)('cc_editor_ttvc_release_bundle_one', 'extensionHoverRefactor', true) && hoverStyles]
|
|
84
86
|
}, children, nodeType === 'inlineExtension' && _whitespace.ZERO_WIDTH_SPACE);
|
|
@@ -12,9 +12,11 @@ var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime
|
|
|
12
12
|
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
|
|
13
13
|
var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));
|
|
14
14
|
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
|
|
15
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
15
16
|
var _react = _interopRequireDefault(require("react"));
|
|
16
17
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
17
18
|
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
19
|
+
var _coreUtils = require("../core-utils");
|
|
18
20
|
var _reactNodeView = _interopRequireDefault(require("../react-node-view"));
|
|
19
21
|
var _Extension = require("./Extension");
|
|
20
22
|
var _ExtensionNodeWrapper = require("./ExtensionNodeWrapper");
|
|
@@ -28,8 +30,23 @@ function _superPropGet(t, o, e, r) { var p = (0, _get2.default)((0, _getPrototyp
|
|
|
28
30
|
// project whilst investigating block nodes. We will revisit the Extension node view there too.
|
|
29
31
|
var ExtensionNode = exports.ExtensionNode = /*#__PURE__*/function (_ReactNodeView) {
|
|
30
32
|
function ExtensionNode() {
|
|
33
|
+
var _this;
|
|
31
34
|
(0, _classCallCheck2.default)(this, ExtensionNode);
|
|
32
|
-
|
|
35
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
36
|
+
args[_key] = arguments[_key];
|
|
37
|
+
}
|
|
38
|
+
_this = _callSuper(this, ExtensionNode, [].concat(args));
|
|
39
|
+
/**
|
|
40
|
+
* Track whether we found and are reusing SSR'd DOM.
|
|
41
|
+
* When true, we skip React Portal rendering on first init to preserve SSR content.
|
|
42
|
+
*/
|
|
43
|
+
(0, _defineProperty2.default)(_this, "didReuseSsrDom", false);
|
|
44
|
+
/**
|
|
45
|
+
* Track whether this is the first init call.
|
|
46
|
+
* SSR content preservation only happens on the very first init.
|
|
47
|
+
*/
|
|
48
|
+
(0, _defineProperty2.default)(_this, "isFirstInit", true);
|
|
49
|
+
return _this;
|
|
33
50
|
}
|
|
34
51
|
(0, _inherits2.default)(ExtensionNode, _ReactNodeView);
|
|
35
52
|
return (0, _createClass2.default)(ExtensionNode, [{
|
|
@@ -47,6 +64,15 @@ var ExtensionNode = exports.ExtensionNode = /*#__PURE__*/function (_ReactNodeVie
|
|
|
47
64
|
key: "createDomRef",
|
|
48
65
|
value: function createDomRef() {
|
|
49
66
|
if (!(0, _platformFeatureFlags.fg)('confluence_connect_macro_preset_height')) {
|
|
67
|
+
// Try to reuse SSR'd DOM node on first init only
|
|
68
|
+
// This preserves SSR content and avoids TTVC mutations during hydration
|
|
69
|
+
if (!(0, _coreUtils.isSSR)() && this.isFirstInit && this.node.type.name === 'extension' && this.node.attrs.extensionKey === 'toc' && (0, _expValEquals.expValEquals)('platform_editor_hydration_skip_react_portal', 'isEnabled', true)) {
|
|
70
|
+
var ssrElement = this.findSSRElement();
|
|
71
|
+
if (ssrElement) {
|
|
72
|
+
this.didReuseSsrDom = true;
|
|
73
|
+
return ssrElement;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
50
76
|
return _superPropGet(ExtensionNode, "createDomRef", this, 3)([]);
|
|
51
77
|
}
|
|
52
78
|
if (!this.node.isInline) {
|
|
@@ -62,6 +88,83 @@ var ExtensionNode = exports.ExtensionNode = /*#__PURE__*/function (_ReactNodeVie
|
|
|
62
88
|
return htmlElement;
|
|
63
89
|
}
|
|
64
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Cache for SSR element lookup to avoid repeated DOM queries.
|
|
93
|
+
* undefined = not yet searched, null = searched but not found, HTMLElement = found
|
|
94
|
+
*/
|
|
95
|
+
}, {
|
|
96
|
+
key: "findSSRElement",
|
|
97
|
+
value:
|
|
98
|
+
/**
|
|
99
|
+
* Attempts to find an existing SSR'd DOM element for this extension node by extensionKey and localId
|
|
100
|
+
* which should uniquely identify the
|
|
101
|
+
* extension node within the editor content.
|
|
102
|
+
*
|
|
103
|
+
* @returns The SSR'd element if found, otherwise null
|
|
104
|
+
*/
|
|
105
|
+
function findSSRElement() {
|
|
106
|
+
if (this.cachedSsrElement !== undefined) {
|
|
107
|
+
return this.cachedSsrElement || null;
|
|
108
|
+
}
|
|
109
|
+
var extensionKey = this.node.attrs.extensionKey;
|
|
110
|
+
var localId = this.node.attrs.localId;
|
|
111
|
+
var editorDom = this.view.dom;
|
|
112
|
+
if (extensionKey && localId) {
|
|
113
|
+
var selector = "[extensionkey=\"".concat(extensionKey, "\"][localid=\"").concat(localId, "\"]");
|
|
114
|
+
var element = editorDom.querySelector(selector);
|
|
115
|
+
if (element && element instanceof HTMLElement) {
|
|
116
|
+
this.cachedSsrElement = element;
|
|
117
|
+
return element;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
this.cachedSsrElement = null;
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Override init() to skip React Portal rendering on first init if we're reusing SSR'd DOM.
|
|
126
|
+
* This preserves the SSR content without React unnecessarily re-rendering it.
|
|
127
|
+
*/
|
|
128
|
+
}, {
|
|
129
|
+
key: "init",
|
|
130
|
+
value: function init() {
|
|
131
|
+
if (!(0, _expValEquals.expValEquals)('platform_editor_hydration_skip_react_portal', 'isEnabled', true)) {
|
|
132
|
+
_superPropGet(ExtensionNode, "init", this, 3)([]);
|
|
133
|
+
} else {
|
|
134
|
+
if (!(0, _coreUtils.isSSR)() && this.node.type.name === 'extension' && this.node.attrs.extensionKey === 'toc') {
|
|
135
|
+
var ssrElement = this.findSSRElement();
|
|
136
|
+
var shouldSkipInitRender = ssrElement !== null;
|
|
137
|
+
_superPropGet(ExtensionNode, "init", this, 3)([shouldSkipInitRender]);
|
|
138
|
+
if (shouldSkipInitRender) {
|
|
139
|
+
this.isFirstInit = false;
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
_superPropGet(ExtensionNode, "init", this, 3)([]);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return this;
|
|
146
|
+
}
|
|
147
|
+
}, {
|
|
148
|
+
key: "update",
|
|
149
|
+
value: function update(node, decorations, _innerDecorations) {
|
|
150
|
+
var validUpdate = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : function () {
|
|
151
|
+
return true;
|
|
152
|
+
};
|
|
153
|
+
// Remove extensionNodeWrapper aka span.relative if we previously reused SSR DOM
|
|
154
|
+
// control is back to React afterwards
|
|
155
|
+
if (this.didReuseSsrDom && (0, _expValEquals.expValEquals)('platform_editor_hydration_skip_react_portal', 'isEnabled', true)) {
|
|
156
|
+
var ssrElement = this.findSSRElement();
|
|
157
|
+
if (ssrElement) {
|
|
158
|
+
var extensionNodeWrapper = ssrElement.querySelector('[data-testId="extension-node-wrapper"]');
|
|
159
|
+
if (extensionNodeWrapper) {
|
|
160
|
+
extensionNodeWrapper.remove();
|
|
161
|
+
}
|
|
162
|
+
this.didReuseSsrDom = false;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return _superPropGet(ExtensionNode, "update", this, 3)([node, decorations, _innerDecorations, validUpdate]);
|
|
166
|
+
}
|
|
167
|
+
|
|
65
168
|
/**
|
|
66
169
|
* When interacting with input elements inside an extension's body, the events
|
|
67
170
|
* bubble up to the editor and get handled by it. This almost always gets in the way
|
|
@@ -85,6 +188,9 @@ var ExtensionNode = exports.ExtensionNode = /*#__PURE__*/function (_ReactNodeVie
|
|
|
85
188
|
if (this.node.isInline) {
|
|
86
189
|
return;
|
|
87
190
|
}
|
|
191
|
+
if (this.didReuseSsrDom) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
88
194
|
var contentDomWrapper = document.createElement('div');
|
|
89
195
|
contentDomWrapper.className = "".concat(this.node.type.name, "-content-dom-wrapper");
|
|
90
196
|
var isBodiedExtension = this.node.type.name === 'bodiedExtension';
|
|
@@ -112,6 +218,11 @@ var ExtensionNode = exports.ExtensionNode = /*#__PURE__*/function (_ReactNodeVie
|
|
|
112
218
|
key: "render",
|
|
113
219
|
value: function render(props, forwardRef) {
|
|
114
220
|
var _props$extensionNodeV;
|
|
221
|
+
// If we reused SSR'd DOM on first init, don't render React Portal
|
|
222
|
+
// The SSR content is already perfect and doesn't need re-rendering
|
|
223
|
+
if (this.didReuseSsrDom && this.isFirstInit) {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
115
226
|
return /*#__PURE__*/_react.default.createElement(_ExtensionNodeWrapper.ExtensionNodeWrapper, {
|
|
116
227
|
nodeType: this.node.type.name,
|
|
117
228
|
macroInteractionDesignFeatureFlags: props.macroInteractionDesignFeatureFlags
|
|
@@ -19,7 +19,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
19
19
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
20
20
|
var SENTRY_DSN = 'https://0b10c8e02fb44d8796c047b102c9bee8@o55978.ingest.sentry.io/4505129224110080';
|
|
21
21
|
var packageName = 'editor-common'; // Sentry doesn't accept '/' in its releases https://docs.sentry.io/platforms/javascript/configuration/releases/
|
|
22
|
-
var packageVersion = "112.18.
|
|
22
|
+
var packageVersion = "112.18.2";
|
|
23
23
|
var sanitiseSentryEvents = function sanitiseSentryEvents(data, _hint) {
|
|
24
24
|
// Remove URL as it has UGC
|
|
25
25
|
// Ignored via go/ees007
|
|
@@ -79,6 +79,7 @@ var ReactNodeView = exports.default = /*#__PURE__*/function () {
|
|
|
79
79
|
key: "init",
|
|
80
80
|
value: function init() {
|
|
81
81
|
var _this2 = this;
|
|
82
|
+
var shouldSkipInitRender = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
82
83
|
this.domRef = this.createDomRef();
|
|
83
84
|
this.setDomAttrs(this.node, this.domRef);
|
|
84
85
|
var _ref = this.getContentDOM() || {
|
|
@@ -105,9 +106,11 @@ var ReactNodeView = exports.default = /*#__PURE__*/function () {
|
|
|
105
106
|
trackingEnabled && (0, _utils.startMeasureReactNodeViewRendered)({
|
|
106
107
|
nodeTypeName: this.node.type.name
|
|
107
108
|
});
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
if (!shouldSkipInitRender) {
|
|
110
|
+
this.renderReactComponent(function () {
|
|
111
|
+
return _this2.render(_this2.reactComponentProps, _this2.handleRef);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
111
114
|
trackingEnabled && (0, _utils.stopMeasureReactNodeViewRendered)({
|
|
112
115
|
nodeTypeName: this.node.type.name,
|
|
113
116
|
dispatchAnalyticsEvent: this.dispatchAnalyticsEvent,
|
|
@@ -24,7 +24,7 @@ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.
|
|
|
24
24
|
* @jsx jsx
|
|
25
25
|
*/ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
26
26
|
var packageName = "@atlaskit/editor-common";
|
|
27
|
-
var packageVersion = "112.18.
|
|
27
|
+
var packageVersion = "112.18.2";
|
|
28
28
|
var halfFocusRing = 1;
|
|
29
29
|
var dropOffset = '0, 8';
|
|
30
30
|
var fadeIn = (0, _react2.keyframes)({
|
|
@@ -18,7 +18,7 @@ import { shouldExtensionBreakout } from '../../utils/should-extension-breakout';
|
|
|
18
18
|
import ExtensionLozenge from '../Lozenge';
|
|
19
19
|
import { overlay } from '../styles';
|
|
20
20
|
import { isEmptyBodiedMacro } from './extension-utils';
|
|
21
|
-
import {
|
|
21
|
+
import { contentWrapper, extensionContent, header, overflowWrapperStyles, widerLayoutClassName, wrapperStyleInheritedCursor } from './styles';
|
|
22
22
|
const hoverStyles = css({
|
|
23
23
|
'&:hover': {
|
|
24
24
|
boxShadow: `0 0 0 1px ${"var(--ds-border-input, #8C8F97)"}`
|
|
@@ -143,7 +143,6 @@ function ExtensionWithPluginState(props) {
|
|
|
143
143
|
setIsNodeHovered(didHover);
|
|
144
144
|
}
|
|
145
145
|
};
|
|
146
|
-
const extensionContentStyles = expValEquals('platform_editor_extension_styles', 'isEnabled', true) ? extensionContent : content;
|
|
147
146
|
return jsx(Fragment, null, !showLegacyContentHeader && showMacroInteractionDesignUpdates && !isLivePageViewMode && jsx(ExtensionLozenge, {
|
|
148
147
|
isNodeSelected: isNodeSelected,
|
|
149
148
|
isNodeHovered: isNodeHovered,
|
|
@@ -214,7 +213,7 @@ function ExtensionWithPluginState(props) {
|
|
|
214
213
|
"data-testid": "extension-content"
|
|
215
214
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766
|
|
216
215
|
,
|
|
217
|
-
css:
|
|
216
|
+
css: extensionContent
|
|
218
217
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
|
|
219
218
|
,
|
|
220
219
|
className: contentClassNames
|
|
@@ -72,7 +72,9 @@ export const ExtensionNodeWrapper = ({
|
|
|
72
72
|
relative: showMacroInteractionDesignUpdates
|
|
73
73
|
});
|
|
74
74
|
return jsx("span", {
|
|
75
|
+
"data-testId": "extension-node-wrapper"
|
|
75
76
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
|
|
77
|
+
,
|
|
76
78
|
className: wrapperClassNames,
|
|
77
79
|
css: [styles, expValEquals('cc_editor_ttvc_release_bundle_one', 'extensionHoverRefactor', true) && hoverStyles]
|
|
78
80
|
}, children, nodeType === 'inlineExtension' && ZERO_WIDTH_SPACE);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
1
2
|
import React from 'react';
|
|
2
3
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
3
4
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
5
|
+
import { isSSR } from '../core-utils';
|
|
4
6
|
import ReactNodeView from '../react-node-view';
|
|
5
7
|
import { Extension } from './Extension';
|
|
6
8
|
import { ExtensionNodeWrapper } from './ExtensionNodeWrapper';
|
|
@@ -10,6 +12,19 @@ import { ExtensionNodeWrapper } from './ExtensionNodeWrapper';
|
|
|
10
12
|
// The ReactNodeView api will be visited in the second phase of the selections
|
|
11
13
|
// project whilst investigating block nodes. We will revisit the Extension node view there too.
|
|
12
14
|
export class ExtensionNode extends ReactNodeView {
|
|
15
|
+
constructor(...args) {
|
|
16
|
+
super(...args);
|
|
17
|
+
/**
|
|
18
|
+
* Track whether we found and are reusing SSR'd DOM.
|
|
19
|
+
* When true, we skip React Portal rendering on first init to preserve SSR content.
|
|
20
|
+
*/
|
|
21
|
+
_defineProperty(this, "didReuseSsrDom", false);
|
|
22
|
+
/**
|
|
23
|
+
* Track whether this is the first init call.
|
|
24
|
+
* SSR content preservation only happens on the very first init.
|
|
25
|
+
*/
|
|
26
|
+
_defineProperty(this, "isFirstInit", true);
|
|
27
|
+
}
|
|
13
28
|
ignoreMutation(mutation) {
|
|
14
29
|
// Extensions can perform async operations that will change the DOM.
|
|
15
30
|
// To avoid having their tree rebuilt, we need to ignore the mutation
|
|
@@ -21,6 +36,15 @@ export class ExtensionNode extends ReactNodeView {
|
|
|
21
36
|
// Reserve height by setting a minimum height for the extension node view element
|
|
22
37
|
createDomRef() {
|
|
23
38
|
if (!fg('confluence_connect_macro_preset_height')) {
|
|
39
|
+
// Try to reuse SSR'd DOM node on first init only
|
|
40
|
+
// This preserves SSR content and avoids TTVC mutations during hydration
|
|
41
|
+
if (!isSSR() && this.isFirstInit && this.node.type.name === 'extension' && this.node.attrs.extensionKey === 'toc' && expValEquals('platform_editor_hydration_skip_react_portal', 'isEnabled', true)) {
|
|
42
|
+
const ssrElement = this.findSSRElement();
|
|
43
|
+
if (ssrElement) {
|
|
44
|
+
this.didReuseSsrDom = true;
|
|
45
|
+
return ssrElement;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
24
48
|
return super.createDomRef();
|
|
25
49
|
}
|
|
26
50
|
if (!this.node.isInline) {
|
|
@@ -36,6 +60,74 @@ export class ExtensionNode extends ReactNodeView {
|
|
|
36
60
|
return htmlElement;
|
|
37
61
|
}
|
|
38
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Cache for SSR element lookup to avoid repeated DOM queries.
|
|
65
|
+
* undefined = not yet searched, null = searched but not found, HTMLElement = found
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Attempts to find an existing SSR'd DOM element for this extension node by extensionKey and localId
|
|
70
|
+
* which should uniquely identify the
|
|
71
|
+
* extension node within the editor content.
|
|
72
|
+
*
|
|
73
|
+
* @returns The SSR'd element if found, otherwise null
|
|
74
|
+
*/
|
|
75
|
+
findSSRElement() {
|
|
76
|
+
if (this.cachedSsrElement !== undefined) {
|
|
77
|
+
return this.cachedSsrElement || null;
|
|
78
|
+
}
|
|
79
|
+
const extensionKey = this.node.attrs.extensionKey;
|
|
80
|
+
const localId = this.node.attrs.localId;
|
|
81
|
+
const editorDom = this.view.dom;
|
|
82
|
+
if (extensionKey && localId) {
|
|
83
|
+
const selector = `[extensionkey="${extensionKey}"][localid="${localId}"]`;
|
|
84
|
+
const element = editorDom.querySelector(selector);
|
|
85
|
+
if (element && element instanceof HTMLElement) {
|
|
86
|
+
this.cachedSsrElement = element;
|
|
87
|
+
return element;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
this.cachedSsrElement = null;
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Override init() to skip React Portal rendering on first init if we're reusing SSR'd DOM.
|
|
96
|
+
* This preserves the SSR content without React unnecessarily re-rendering it.
|
|
97
|
+
*/
|
|
98
|
+
init() {
|
|
99
|
+
if (!expValEquals('platform_editor_hydration_skip_react_portal', 'isEnabled', true)) {
|
|
100
|
+
super.init();
|
|
101
|
+
} else {
|
|
102
|
+
if (!isSSR() && this.node.type.name === 'extension' && this.node.attrs.extensionKey === 'toc') {
|
|
103
|
+
const ssrElement = this.findSSRElement();
|
|
104
|
+
const shouldSkipInitRender = ssrElement !== null;
|
|
105
|
+
super.init(shouldSkipInitRender);
|
|
106
|
+
if (shouldSkipInitRender) {
|
|
107
|
+
this.isFirstInit = false;
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
super.init();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return this;
|
|
114
|
+
}
|
|
115
|
+
update(node, decorations, _innerDecorations, validUpdate = () => true) {
|
|
116
|
+
// Remove extensionNodeWrapper aka span.relative if we previously reused SSR DOM
|
|
117
|
+
// control is back to React afterwards
|
|
118
|
+
if (this.didReuseSsrDom && expValEquals('platform_editor_hydration_skip_react_portal', 'isEnabled', true)) {
|
|
119
|
+
const ssrElement = this.findSSRElement();
|
|
120
|
+
if (ssrElement) {
|
|
121
|
+
const extensionNodeWrapper = ssrElement.querySelector('[data-testId="extension-node-wrapper"]');
|
|
122
|
+
if (extensionNodeWrapper) {
|
|
123
|
+
extensionNodeWrapper.remove();
|
|
124
|
+
}
|
|
125
|
+
this.didReuseSsrDom = false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return super.update(node, decorations, _innerDecorations, validUpdate);
|
|
129
|
+
}
|
|
130
|
+
|
|
39
131
|
/**
|
|
40
132
|
* When interacting with input elements inside an extension's body, the events
|
|
41
133
|
* bubble up to the editor and get handled by it. This almost always gets in the way
|
|
@@ -55,6 +147,9 @@ export class ExtensionNode extends ReactNodeView {
|
|
|
55
147
|
if (this.node.isInline) {
|
|
56
148
|
return;
|
|
57
149
|
}
|
|
150
|
+
if (this.didReuseSsrDom) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
58
153
|
const contentDomWrapper = document.createElement('div');
|
|
59
154
|
contentDomWrapper.className = `${this.node.type.name}-content-dom-wrapper`;
|
|
60
155
|
const isBodiedExtension = this.node.type.name === 'bodiedExtension';
|
|
@@ -80,6 +175,11 @@ export class ExtensionNode extends ReactNodeView {
|
|
|
80
175
|
}
|
|
81
176
|
render(props, forwardRef) {
|
|
82
177
|
var _props$extensionNodeV;
|
|
178
|
+
// If we reused SSR'd DOM on first init, don't render React Portal
|
|
179
|
+
// The SSR content is already perfect and doesn't need re-rendering
|
|
180
|
+
if (this.didReuseSsrDom && this.isFirstInit) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
83
183
|
return /*#__PURE__*/React.createElement(ExtensionNodeWrapper, {
|
|
84
184
|
nodeType: this.node.type.name,
|
|
85
185
|
macroInteractionDesignFeatureFlags: props.macroInteractionDesignFeatureFlags
|
|
@@ -4,7 +4,7 @@ import { isFedRamp } from './environment';
|
|
|
4
4
|
import { normaliseSentryBreadcrumbs, SERIALIZABLE_ATTRIBUTES } from './normalise-sentry-breadcrumbs';
|
|
5
5
|
const SENTRY_DSN = 'https://0b10c8e02fb44d8796c047b102c9bee8@o55978.ingest.sentry.io/4505129224110080';
|
|
6
6
|
const packageName = 'editor-common'; // Sentry doesn't accept '/' in its releases https://docs.sentry.io/platforms/javascript/configuration/releases/
|
|
7
|
-
const packageVersion = "112.18.
|
|
7
|
+
const packageVersion = "112.18.2";
|
|
8
8
|
const sanitiseSentryEvents = (data, _hint) => {
|
|
9
9
|
// Remove URL as it has UGC
|
|
10
10
|
// Ignored via go/ees007
|
|
@@ -51,7 +51,7 @@ export default class ReactNodeView {
|
|
|
51
51
|
* constructor, which leads to some methods being undefined during the
|
|
52
52
|
* first render.
|
|
53
53
|
*/
|
|
54
|
-
init() {
|
|
54
|
+
init(shouldSkipInitRender = false) {
|
|
55
55
|
this.domRef = this.createDomRef();
|
|
56
56
|
this.setDomAttrs(this.node, this.domRef);
|
|
57
57
|
const {
|
|
@@ -80,7 +80,9 @@ export default class ReactNodeView {
|
|
|
80
80
|
trackingEnabled && startMeasureReactNodeViewRendered({
|
|
81
81
|
nodeTypeName: this.node.type.name
|
|
82
82
|
});
|
|
83
|
-
|
|
83
|
+
if (!shouldSkipInitRender) {
|
|
84
|
+
this.renderReactComponent(() => this.render(this.reactComponentProps, this.handleRef));
|
|
85
|
+
}
|
|
84
86
|
trackingEnabled && stopMeasureReactNodeViewRendered({
|
|
85
87
|
nodeTypeName: this.node.type.name,
|
|
86
88
|
dispatchAnalyticsEvent: this.dispatchAnalyticsEvent,
|
|
@@ -14,7 +14,7 @@ import withAnalyticsEvents from '@atlaskit/analytics-next/withAnalyticsEvents';
|
|
|
14
14
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
15
15
|
import Layer from '../Layer';
|
|
16
16
|
const packageName = "@atlaskit/editor-common";
|
|
17
|
-
const packageVersion = "112.18.
|
|
17
|
+
const packageVersion = "112.18.2";
|
|
18
18
|
const halfFocusRing = 1;
|
|
19
19
|
const dropOffset = '0, 8';
|
|
20
20
|
const fadeIn = keyframes({
|
|
@@ -23,7 +23,7 @@ import { shouldExtensionBreakout } from '../../utils/should-extension-breakout';
|
|
|
23
23
|
import ExtensionLozenge from '../Lozenge';
|
|
24
24
|
import { overlay } from '../styles';
|
|
25
25
|
import { isEmptyBodiedMacro } from './extension-utils';
|
|
26
|
-
import {
|
|
26
|
+
import { contentWrapper, extensionContent, header, overflowWrapperStyles, widerLayoutClassName, wrapperStyleInheritedCursor } from './styles';
|
|
27
27
|
var hoverStyles = css({
|
|
28
28
|
'&:hover': {
|
|
29
29
|
boxShadow: "0 0 0 1px ".concat("var(--ds-border-input, #8C8F97)")
|
|
@@ -136,7 +136,6 @@ function ExtensionWithPluginState(props) {
|
|
|
136
136
|
setIsNodeHovered(didHover);
|
|
137
137
|
}
|
|
138
138
|
};
|
|
139
|
-
var extensionContentStyles = expValEquals('platform_editor_extension_styles', 'isEnabled', true) ? extensionContent : content;
|
|
140
139
|
return jsx(Fragment, null, !showLegacyContentHeader && showMacroInteractionDesignUpdates && !isLivePageViewMode && jsx(ExtensionLozenge, {
|
|
141
140
|
isNodeSelected: isNodeSelected,
|
|
142
141
|
isNodeHovered: isNodeHovered,
|
|
@@ -211,7 +210,7 @@ function ExtensionWithPluginState(props) {
|
|
|
211
210
|
"data-testid": "extension-content"
|
|
212
211
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766
|
|
213
212
|
,
|
|
214
|
-
css:
|
|
213
|
+
css: extensionContent
|
|
215
214
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
|
|
216
215
|
,
|
|
217
216
|
className: contentClassNames
|
|
@@ -70,7 +70,9 @@ export var ExtensionNodeWrapper = function ExtensionNodeWrapper(_ref) {
|
|
|
70
70
|
relative: showMacroInteractionDesignUpdates
|
|
71
71
|
});
|
|
72
72
|
return jsx("span", {
|
|
73
|
+
"data-testId": "extension-node-wrapper"
|
|
73
74
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
|
|
75
|
+
,
|
|
74
76
|
className: wrapperClassNames,
|
|
75
77
|
css: [styles, expValEquals('cc_editor_ttvc_release_bundle_one', 'extensionHoverRefactor', true) && hoverStyles]
|
|
76
78
|
}, children, nodeType === 'inlineExtension' && ZERO_WIDTH_SPACE);
|
|
@@ -4,12 +4,14 @@ import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstruct
|
|
|
4
4
|
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
|
|
5
5
|
import _get from "@babel/runtime/helpers/get";
|
|
6
6
|
import _inherits from "@babel/runtime/helpers/inherits";
|
|
7
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
7
8
|
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
|
|
8
9
|
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
|
|
9
10
|
function _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; }
|
|
10
11
|
import React from 'react';
|
|
11
12
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
12
13
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
14
|
+
import { isSSR } from '../core-utils';
|
|
13
15
|
import ReactNodeView from '../react-node-view';
|
|
14
16
|
import { Extension } from './Extension';
|
|
15
17
|
import { ExtensionNodeWrapper } from './ExtensionNodeWrapper';
|
|
@@ -20,8 +22,23 @@ import { ExtensionNodeWrapper } from './ExtensionNodeWrapper';
|
|
|
20
22
|
// project whilst investigating block nodes. We will revisit the Extension node view there too.
|
|
21
23
|
export var ExtensionNode = /*#__PURE__*/function (_ReactNodeView) {
|
|
22
24
|
function ExtensionNode() {
|
|
25
|
+
var _this;
|
|
23
26
|
_classCallCheck(this, ExtensionNode);
|
|
24
|
-
|
|
27
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
28
|
+
args[_key] = arguments[_key];
|
|
29
|
+
}
|
|
30
|
+
_this = _callSuper(this, ExtensionNode, [].concat(args));
|
|
31
|
+
/**
|
|
32
|
+
* Track whether we found and are reusing SSR'd DOM.
|
|
33
|
+
* When true, we skip React Portal rendering on first init to preserve SSR content.
|
|
34
|
+
*/
|
|
35
|
+
_defineProperty(_this, "didReuseSsrDom", false);
|
|
36
|
+
/**
|
|
37
|
+
* Track whether this is the first init call.
|
|
38
|
+
* SSR content preservation only happens on the very first init.
|
|
39
|
+
*/
|
|
40
|
+
_defineProperty(_this, "isFirstInit", true);
|
|
41
|
+
return _this;
|
|
25
42
|
}
|
|
26
43
|
_inherits(ExtensionNode, _ReactNodeView);
|
|
27
44
|
return _createClass(ExtensionNode, [{
|
|
@@ -39,6 +56,15 @@ export var ExtensionNode = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
39
56
|
key: "createDomRef",
|
|
40
57
|
value: function createDomRef() {
|
|
41
58
|
if (!fg('confluence_connect_macro_preset_height')) {
|
|
59
|
+
// Try to reuse SSR'd DOM node on first init only
|
|
60
|
+
// This preserves SSR content and avoids TTVC mutations during hydration
|
|
61
|
+
if (!isSSR() && this.isFirstInit && this.node.type.name === 'extension' && this.node.attrs.extensionKey === 'toc' && expValEquals('platform_editor_hydration_skip_react_portal', 'isEnabled', true)) {
|
|
62
|
+
var ssrElement = this.findSSRElement();
|
|
63
|
+
if (ssrElement) {
|
|
64
|
+
this.didReuseSsrDom = true;
|
|
65
|
+
return ssrElement;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
42
68
|
return _superPropGet(ExtensionNode, "createDomRef", this, 3)([]);
|
|
43
69
|
}
|
|
44
70
|
if (!this.node.isInline) {
|
|
@@ -54,6 +80,83 @@ export var ExtensionNode = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
54
80
|
return htmlElement;
|
|
55
81
|
}
|
|
56
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Cache for SSR element lookup to avoid repeated DOM queries.
|
|
85
|
+
* undefined = not yet searched, null = searched but not found, HTMLElement = found
|
|
86
|
+
*/
|
|
87
|
+
}, {
|
|
88
|
+
key: "findSSRElement",
|
|
89
|
+
value:
|
|
90
|
+
/**
|
|
91
|
+
* Attempts to find an existing SSR'd DOM element for this extension node by extensionKey and localId
|
|
92
|
+
* which should uniquely identify the
|
|
93
|
+
* extension node within the editor content.
|
|
94
|
+
*
|
|
95
|
+
* @returns The SSR'd element if found, otherwise null
|
|
96
|
+
*/
|
|
97
|
+
function findSSRElement() {
|
|
98
|
+
if (this.cachedSsrElement !== undefined) {
|
|
99
|
+
return this.cachedSsrElement || null;
|
|
100
|
+
}
|
|
101
|
+
var extensionKey = this.node.attrs.extensionKey;
|
|
102
|
+
var localId = this.node.attrs.localId;
|
|
103
|
+
var editorDom = this.view.dom;
|
|
104
|
+
if (extensionKey && localId) {
|
|
105
|
+
var selector = "[extensionkey=\"".concat(extensionKey, "\"][localid=\"").concat(localId, "\"]");
|
|
106
|
+
var element = editorDom.querySelector(selector);
|
|
107
|
+
if (element && element instanceof HTMLElement) {
|
|
108
|
+
this.cachedSsrElement = element;
|
|
109
|
+
return element;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
this.cachedSsrElement = null;
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Override init() to skip React Portal rendering on first init if we're reusing SSR'd DOM.
|
|
118
|
+
* This preserves the SSR content without React unnecessarily re-rendering it.
|
|
119
|
+
*/
|
|
120
|
+
}, {
|
|
121
|
+
key: "init",
|
|
122
|
+
value: function init() {
|
|
123
|
+
if (!expValEquals('platform_editor_hydration_skip_react_portal', 'isEnabled', true)) {
|
|
124
|
+
_superPropGet(ExtensionNode, "init", this, 3)([]);
|
|
125
|
+
} else {
|
|
126
|
+
if (!isSSR() && this.node.type.name === 'extension' && this.node.attrs.extensionKey === 'toc') {
|
|
127
|
+
var ssrElement = this.findSSRElement();
|
|
128
|
+
var shouldSkipInitRender = ssrElement !== null;
|
|
129
|
+
_superPropGet(ExtensionNode, "init", this, 3)([shouldSkipInitRender]);
|
|
130
|
+
if (shouldSkipInitRender) {
|
|
131
|
+
this.isFirstInit = false;
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
_superPropGet(ExtensionNode, "init", this, 3)([]);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return this;
|
|
138
|
+
}
|
|
139
|
+
}, {
|
|
140
|
+
key: "update",
|
|
141
|
+
value: function update(node, decorations, _innerDecorations) {
|
|
142
|
+
var validUpdate = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : function () {
|
|
143
|
+
return true;
|
|
144
|
+
};
|
|
145
|
+
// Remove extensionNodeWrapper aka span.relative if we previously reused SSR DOM
|
|
146
|
+
// control is back to React afterwards
|
|
147
|
+
if (this.didReuseSsrDom && expValEquals('platform_editor_hydration_skip_react_portal', 'isEnabled', true)) {
|
|
148
|
+
var ssrElement = this.findSSRElement();
|
|
149
|
+
if (ssrElement) {
|
|
150
|
+
var extensionNodeWrapper = ssrElement.querySelector('[data-testId="extension-node-wrapper"]');
|
|
151
|
+
if (extensionNodeWrapper) {
|
|
152
|
+
extensionNodeWrapper.remove();
|
|
153
|
+
}
|
|
154
|
+
this.didReuseSsrDom = false;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return _superPropGet(ExtensionNode, "update", this, 3)([node, decorations, _innerDecorations, validUpdate]);
|
|
158
|
+
}
|
|
159
|
+
|
|
57
160
|
/**
|
|
58
161
|
* When interacting with input elements inside an extension's body, the events
|
|
59
162
|
* bubble up to the editor and get handled by it. This almost always gets in the way
|
|
@@ -77,6 +180,9 @@ export var ExtensionNode = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
77
180
|
if (this.node.isInline) {
|
|
78
181
|
return;
|
|
79
182
|
}
|
|
183
|
+
if (this.didReuseSsrDom) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
80
186
|
var contentDomWrapper = document.createElement('div');
|
|
81
187
|
contentDomWrapper.className = "".concat(this.node.type.name, "-content-dom-wrapper");
|
|
82
188
|
var isBodiedExtension = this.node.type.name === 'bodiedExtension';
|
|
@@ -104,6 +210,11 @@ export var ExtensionNode = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
104
210
|
key: "render",
|
|
105
211
|
value: function render(props, forwardRef) {
|
|
106
212
|
var _props$extensionNodeV;
|
|
213
|
+
// If we reused SSR'd DOM on first init, don't render React Portal
|
|
214
|
+
// The SSR content is already perfect and doesn't need re-rendering
|
|
215
|
+
if (this.didReuseSsrDom && this.isFirstInit) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
107
218
|
return /*#__PURE__*/React.createElement(ExtensionNodeWrapper, {
|
|
108
219
|
nodeType: this.node.type.name,
|
|
109
220
|
macroInteractionDesignFeatureFlags: props.macroInteractionDesignFeatureFlags
|
|
@@ -10,7 +10,7 @@ import { isFedRamp } from './environment';
|
|
|
10
10
|
import { normaliseSentryBreadcrumbs, SERIALIZABLE_ATTRIBUTES } from './normalise-sentry-breadcrumbs';
|
|
11
11
|
var SENTRY_DSN = 'https://0b10c8e02fb44d8796c047b102c9bee8@o55978.ingest.sentry.io/4505129224110080';
|
|
12
12
|
var packageName = 'editor-common'; // Sentry doesn't accept '/' in its releases https://docs.sentry.io/platforms/javascript/configuration/releases/
|
|
13
|
-
var packageVersion = "112.18.
|
|
13
|
+
var packageVersion = "112.18.2";
|
|
14
14
|
var sanitiseSentryEvents = function sanitiseSentryEvents(data, _hint) {
|
|
15
15
|
// Remove URL as it has UGC
|
|
16
16
|
// Ignored via go/ees007
|
|
@@ -61,6 +61,7 @@ var ReactNodeView = /*#__PURE__*/function () {
|
|
|
61
61
|
key: "init",
|
|
62
62
|
value: function init() {
|
|
63
63
|
var _this2 = this;
|
|
64
|
+
var shouldSkipInitRender = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
64
65
|
this.domRef = this.createDomRef();
|
|
65
66
|
this.setDomAttrs(this.node, this.domRef);
|
|
66
67
|
var _ref = this.getContentDOM() || {
|
|
@@ -87,9 +88,11 @@ var ReactNodeView = /*#__PURE__*/function () {
|
|
|
87
88
|
trackingEnabled && startMeasureReactNodeViewRendered({
|
|
88
89
|
nodeTypeName: this.node.type.name
|
|
89
90
|
});
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
if (!shouldSkipInitRender) {
|
|
92
|
+
this.renderReactComponent(function () {
|
|
93
|
+
return _this2.render(_this2.reactComponentProps, _this2.handleRef);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
93
96
|
trackingEnabled && stopMeasureReactNodeViewRendered({
|
|
94
97
|
nodeTypeName: this.node.type.name,
|
|
95
98
|
dispatchAnalyticsEvent: this.dispatchAnalyticsEvent,
|
|
@@ -21,7 +21,7 @@ import withAnalyticsEvents from '@atlaskit/analytics-next/withAnalyticsEvents';
|
|
|
21
21
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
22
22
|
import Layer from '../Layer';
|
|
23
23
|
var packageName = "@atlaskit/editor-common";
|
|
24
|
-
var packageVersion = "112.18.
|
|
24
|
+
var packageVersion = "112.18.2";
|
|
25
25
|
var halfFocusRing = 1;
|
|
26
26
|
var dropOffset = '0, 8';
|
|
27
27
|
var fadeIn = keyframes({
|
|
@@ -15,11 +15,17 @@ type AIStreamingNoDocChangeAEP = OperationalAEP<ACTION.NO_DOC_CHANGE_FOUND, ACTI
|
|
|
15
15
|
}>;
|
|
16
16
|
type AIStreamingInvalidCommandAEP = OperationalAEP<ACTION.INVALID_COMMAND_FOUND, ACTION_SUBJECT.AI_STREAMING, ACTION_SUBJECT_ID.EXPERIENCE_APPLICATION, {
|
|
17
17
|
ancestors?: string[];
|
|
18
|
+
anchorNodeType?: string;
|
|
19
|
+
destinationParentNodeType?: string;
|
|
18
20
|
errorMessage?: string;
|
|
19
21
|
errorStack?: string;
|
|
20
22
|
fragments?: string[];
|
|
23
|
+
parentNodeType?: string;
|
|
21
24
|
repaired: boolean;
|
|
25
|
+
sourceNodeType?: string;
|
|
26
|
+
sourceParentNodeType?: string;
|
|
22
27
|
success: boolean;
|
|
28
|
+
validationReason?: string;
|
|
23
29
|
}>;
|
|
24
30
|
type AIStreamingUpdateStreamError = OperationalAEP<ACTION.ERRORED, ACTION_SUBJECT.AI_STREAMING, ACTION_SUBJECT_ID.UPDATE_STREAM, {
|
|
25
31
|
docSize: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ADFEntity } from '@atlaskit/adf-utils/types';
|
|
3
3
|
import type { Node as PmNode } from '@atlaskit/editor-prosemirror/model';
|
|
4
|
-
import type { EditorView, NodeView } from '@atlaskit/editor-prosemirror/view';
|
|
4
|
+
import type { Decoration, DecorationSource, EditorView, NodeView } from '@atlaskit/editor-prosemirror/view';
|
|
5
5
|
import type { EventDispatcher } from '../event-dispatcher';
|
|
6
6
|
import type { ExtensionHandlers } from '../extensions';
|
|
7
7
|
import type { PortalProviderAPI } from '../portal';
|
|
@@ -25,11 +25,40 @@ interface ReactExtensionNodeProps {
|
|
|
25
25
|
showUpdatedLivePages1PBodiedExtensionUI?: (node: ADFEntity) => boolean;
|
|
26
26
|
}
|
|
27
27
|
export declare class ExtensionNode<AdditionalParams = unknown> extends ReactNodeView<ReactExtensionNodeProps & AdditionalParams> {
|
|
28
|
+
/**
|
|
29
|
+
* Track whether we found and are reusing SSR'd DOM.
|
|
30
|
+
* When true, we skip React Portal rendering on first init to preserve SSR content.
|
|
31
|
+
*/
|
|
32
|
+
private didReuseSsrDom;
|
|
33
|
+
/**
|
|
34
|
+
* Track whether this is the first init call.
|
|
35
|
+
* SSR content preservation only happens on the very first init.
|
|
36
|
+
*/
|
|
37
|
+
private isFirstInit;
|
|
28
38
|
ignoreMutation(mutation: MutationRecord | {
|
|
29
39
|
target: Node;
|
|
30
40
|
type: 'selection';
|
|
31
41
|
}): boolean;
|
|
32
42
|
createDomRef(): HTMLElement;
|
|
43
|
+
/**
|
|
44
|
+
* Cache for SSR element lookup to avoid repeated DOM queries.
|
|
45
|
+
* undefined = not yet searched, null = searched but not found, HTMLElement = found
|
|
46
|
+
*/
|
|
47
|
+
private cachedSsrElement;
|
|
48
|
+
/**
|
|
49
|
+
* Attempts to find an existing SSR'd DOM element for this extension node by extensionKey and localId
|
|
50
|
+
* which should uniquely identify the
|
|
51
|
+
* extension node within the editor content.
|
|
52
|
+
*
|
|
53
|
+
* @returns The SSR'd element if found, otherwise null
|
|
54
|
+
*/
|
|
55
|
+
private findSSRElement;
|
|
56
|
+
/**
|
|
57
|
+
* Override init() to skip React Portal rendering on first init if we're reusing SSR'd DOM.
|
|
58
|
+
* This preserves the SSR content without React unnecessarily re-rendering it.
|
|
59
|
+
*/
|
|
60
|
+
init(): this;
|
|
61
|
+
update(node: PmNode, decorations: ReadonlyArray<Decoration>, _innerDecorations?: DecorationSource, validUpdate?: (currentNode: PmNode, newNode: PmNode) => boolean): boolean;
|
|
33
62
|
/**
|
|
34
63
|
* When interacting with input elements inside an extension's body, the events
|
|
35
64
|
* bubble up to the editor and get handled by it. This almost always gets in the way
|
|
@@ -32,7 +32,7 @@ export default class ReactNodeView<P = ReactComponentProps> implements NodeView
|
|
|
32
32
|
* constructor, which leads to some methods being undefined during the
|
|
33
33
|
* first render.
|
|
34
34
|
*/
|
|
35
|
-
init(): this;
|
|
35
|
+
init(shouldSkipInitRender?: boolean): this;
|
|
36
36
|
private renderReactComponent;
|
|
37
37
|
createDomRef(): HTMLElement;
|
|
38
38
|
getContentDOM(): {
|
|
@@ -15,11 +15,17 @@ type AIStreamingNoDocChangeAEP = OperationalAEP<ACTION.NO_DOC_CHANGE_FOUND, ACTI
|
|
|
15
15
|
}>;
|
|
16
16
|
type AIStreamingInvalidCommandAEP = OperationalAEP<ACTION.INVALID_COMMAND_FOUND, ACTION_SUBJECT.AI_STREAMING, ACTION_SUBJECT_ID.EXPERIENCE_APPLICATION, {
|
|
17
17
|
ancestors?: string[];
|
|
18
|
+
anchorNodeType?: string;
|
|
19
|
+
destinationParentNodeType?: string;
|
|
18
20
|
errorMessage?: string;
|
|
19
21
|
errorStack?: string;
|
|
20
22
|
fragments?: string[];
|
|
23
|
+
parentNodeType?: string;
|
|
21
24
|
repaired: boolean;
|
|
25
|
+
sourceNodeType?: string;
|
|
26
|
+
sourceParentNodeType?: string;
|
|
22
27
|
success: boolean;
|
|
28
|
+
validationReason?: string;
|
|
23
29
|
}>;
|
|
24
30
|
type AIStreamingUpdateStreamError = OperationalAEP<ACTION.ERRORED, ACTION_SUBJECT.AI_STREAMING, ACTION_SUBJECT_ID.UPDATE_STREAM, {
|
|
25
31
|
docSize: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ADFEntity } from '@atlaskit/adf-utils/types';
|
|
3
3
|
import type { Node as PmNode } from '@atlaskit/editor-prosemirror/model';
|
|
4
|
-
import type { EditorView, NodeView } from '@atlaskit/editor-prosemirror/view';
|
|
4
|
+
import type { Decoration, DecorationSource, EditorView, NodeView } from '@atlaskit/editor-prosemirror/view';
|
|
5
5
|
import type { EventDispatcher } from '../event-dispatcher';
|
|
6
6
|
import type { ExtensionHandlers } from '../extensions';
|
|
7
7
|
import type { PortalProviderAPI } from '../portal';
|
|
@@ -25,11 +25,40 @@ interface ReactExtensionNodeProps {
|
|
|
25
25
|
showUpdatedLivePages1PBodiedExtensionUI?: (node: ADFEntity) => boolean;
|
|
26
26
|
}
|
|
27
27
|
export declare class ExtensionNode<AdditionalParams = unknown> extends ReactNodeView<ReactExtensionNodeProps & AdditionalParams> {
|
|
28
|
+
/**
|
|
29
|
+
* Track whether we found and are reusing SSR'd DOM.
|
|
30
|
+
* When true, we skip React Portal rendering on first init to preserve SSR content.
|
|
31
|
+
*/
|
|
32
|
+
private didReuseSsrDom;
|
|
33
|
+
/**
|
|
34
|
+
* Track whether this is the first init call.
|
|
35
|
+
* SSR content preservation only happens on the very first init.
|
|
36
|
+
*/
|
|
37
|
+
private isFirstInit;
|
|
28
38
|
ignoreMutation(mutation: MutationRecord | {
|
|
29
39
|
target: Node;
|
|
30
40
|
type: 'selection';
|
|
31
41
|
}): boolean;
|
|
32
42
|
createDomRef(): HTMLElement;
|
|
43
|
+
/**
|
|
44
|
+
* Cache for SSR element lookup to avoid repeated DOM queries.
|
|
45
|
+
* undefined = not yet searched, null = searched but not found, HTMLElement = found
|
|
46
|
+
*/
|
|
47
|
+
private cachedSsrElement;
|
|
48
|
+
/**
|
|
49
|
+
* Attempts to find an existing SSR'd DOM element for this extension node by extensionKey and localId
|
|
50
|
+
* which should uniquely identify the
|
|
51
|
+
* extension node within the editor content.
|
|
52
|
+
*
|
|
53
|
+
* @returns The SSR'd element if found, otherwise null
|
|
54
|
+
*/
|
|
55
|
+
private findSSRElement;
|
|
56
|
+
/**
|
|
57
|
+
* Override init() to skip React Portal rendering on first init if we're reusing SSR'd DOM.
|
|
58
|
+
* This preserves the SSR content without React unnecessarily re-rendering it.
|
|
59
|
+
*/
|
|
60
|
+
init(): this;
|
|
61
|
+
update(node: PmNode, decorations: ReadonlyArray<Decoration>, _innerDecorations?: DecorationSource, validUpdate?: (currentNode: PmNode, newNode: PmNode) => boolean): boolean;
|
|
33
62
|
/**
|
|
34
63
|
* When interacting with input elements inside an extension's body, the events
|
|
35
64
|
* bubble up to the editor and get handled by it. This almost always gets in the way
|
|
@@ -32,7 +32,7 @@ export default class ReactNodeView<P = ReactComponentProps> implements NodeView
|
|
|
32
32
|
* constructor, which leads to some methods being undefined during the
|
|
33
33
|
* first render.
|
|
34
34
|
*/
|
|
35
|
-
init(): this;
|
|
35
|
+
init(shouldSkipInitRender?: boolean): this;
|
|
36
36
|
private renderReactComponent;
|
|
37
37
|
createDomRef(): HTMLElement;
|
|
38
38
|
getContentDOM(): {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-common",
|
|
3
|
-
"version": "112.18.
|
|
3
|
+
"version": "112.18.3",
|
|
4
4
|
"description": "A package that contains common classes and components for editor and renderer",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
"@atlaskit/analytics-listeners": "^10.0.0",
|
|
37
37
|
"@atlaskit/analytics-namespaced-context": "^7.2.0",
|
|
38
38
|
"@atlaskit/analytics-next": "^11.2.0",
|
|
39
|
-
"@atlaskit/atlassian-context": "^0.
|
|
39
|
+
"@atlaskit/atlassian-context": "^0.8.0",
|
|
40
40
|
"@atlaskit/browser-apis": "^0.0.1",
|
|
41
|
-
"@atlaskit/button": "^23.
|
|
41
|
+
"@atlaskit/button": "^23.11.0",
|
|
42
42
|
"@atlaskit/codemod-utils": "^4.2.0",
|
|
43
43
|
"@atlaskit/css": "^0.19.0",
|
|
44
44
|
"@atlaskit/custom-steps": "^0.16.0",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"@atlaskit/emoji": "^69.10.0",
|
|
54
54
|
"@atlaskit/icon": "^34.0.0",
|
|
55
55
|
"@atlaskit/icon-object": "^7.5.0",
|
|
56
|
-
"@atlaskit/link": "^3.
|
|
56
|
+
"@atlaskit/link": "^3.4.0",
|
|
57
57
|
"@atlaskit/link-datasource": "^4.34.0",
|
|
58
58
|
"@atlaskit/link-picker": "^4.2.0",
|
|
59
59
|
"@atlaskit/media-card": "^79.16.0",
|
|
@@ -70,16 +70,16 @@
|
|
|
70
70
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
71
71
|
"@atlaskit/platform-feature-flags-react": "^0.4.0",
|
|
72
72
|
"@atlaskit/primitives": "^18.1.0",
|
|
73
|
-
"@atlaskit/profilecard": "^24.
|
|
73
|
+
"@atlaskit/profilecard": "^24.48.0",
|
|
74
74
|
"@atlaskit/prosemirror-history": "^0.2.0",
|
|
75
75
|
"@atlaskit/react-ufo": "^5.11.0",
|
|
76
76
|
"@atlaskit/section-message": "^8.12.0",
|
|
77
77
|
"@atlaskit/smart-card": "^43.31.0",
|
|
78
78
|
"@atlaskit/smart-user-picker": "^9.2.0",
|
|
79
|
-
"@atlaskit/spinner": "^19.
|
|
79
|
+
"@atlaskit/spinner": "^19.1.0",
|
|
80
80
|
"@atlaskit/task-decision": "^19.3.0",
|
|
81
|
-
"@atlaskit/textfield": "^8.
|
|
82
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
81
|
+
"@atlaskit/textfield": "^8.3.0",
|
|
82
|
+
"@atlaskit/tmp-editor-statsig": "^55.0.0",
|
|
83
83
|
"@atlaskit/tokens": "^11.4.0",
|
|
84
84
|
"@atlaskit/tooltip": "^21.1.0",
|
|
85
85
|
"@atlaskit/width-detector": "^5.0.0",
|