@atlaskit/editor-common 112.18.2 → 112.18.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 +22 -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/link/LinkPicker/HyperlinkAddToolbar/HyperlinkAddToolbar.js +2 -6
- package/dist/cjs/monitoring/error.js +1 -1
- package/dist/cjs/node-anchor/node-anchor-provider.js +6 -12
- 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/link/LinkPicker/HyperlinkAddToolbar/HyperlinkAddToolbar.js +3 -6
- package/dist/es2019/monitoring/error.js +1 -1
- package/dist/es2019/node-anchor/node-anchor-provider.js +6 -12
- 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/link/LinkPicker/HyperlinkAddToolbar/HyperlinkAddToolbar.js +3 -7
- package/dist/esm/monitoring/error.js +1 -1
- package/dist/esm/node-anchor/node-anchor-provider.js +6 -12
- 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-autocomplete-events.d.ts +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-autocomplete-events.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 +4 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @atlaskit/editor-common
|
|
2
2
|
|
|
3
|
+
## 112.18.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`d1a0ee6dbcefd`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/d1a0ee6dbcefd) -
|
|
8
|
+
Clean up feature gate platform_editor_native_anchor_patch_2
|
|
9
|
+
- [`8ebeaa8fb64ac`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/8ebeaa8fb64ac) -
|
|
10
|
+
Remove stale feature flag platform_editor_link_picker_width_fix (final value: true)
|
|
11
|
+
- [`fb317c7b6ef38`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/fb317c7b6ef38) -
|
|
12
|
+
Add Autocomplete Conclusion user flow
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
|
|
15
|
+
## 112.18.3
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- [`0a265af52321f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/0a265af52321f) -
|
|
20
|
+
Clean up stale feature flag platform_editor_extension_styles, keeping the enabled code path
|
|
21
|
+
- [`3f798d9934a76`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/3f798d9934a76) -
|
|
22
|
+
[ux] EDITOR-5487 skip react portal initial render when hydration for toc extension node view
|
|
23
|
+
- Updated dependencies
|
|
24
|
+
|
|
3
25
|
## 112.18.2
|
|
4
26
|
|
|
5
27
|
### 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
|
|
@@ -26,7 +26,6 @@ var _adfSchema = require("@atlaskit/adf-schema");
|
|
|
26
26
|
var _withAnalyticsEvents = _interopRequireDefault(require("@atlaskit/analytics-next/withAnalyticsEvents"));
|
|
27
27
|
var _ = _interopRequireDefault(require("@atlaskit/icon-object/glyph/page/16"));
|
|
28
28
|
var _crossCircle = _interopRequireDefault(require("@atlaskit/icon/core/cross-circle"));
|
|
29
|
-
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
30
29
|
var _primitives = require("@atlaskit/primitives");
|
|
31
30
|
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
32
31
|
var _tooltip = _interopRequireDefault(require("@atlaskit/tooltip"));
|
|
@@ -876,9 +875,7 @@ var HyperlinkLinkAddToolbar = exports.HyperlinkLinkAddToolbar = /*#__PURE__*/fun
|
|
|
876
875
|
selectedIndex = _this$state1.selectedIndex,
|
|
877
876
|
displayUrl = _this$state1.displayUrl,
|
|
878
877
|
displayText = _this$state1.displayText;
|
|
879
|
-
var
|
|
880
|
-
formatMessage = _this$props6.intl.formatMessage,
|
|
881
|
-
activityProvider = _this$props6.activityProvider;
|
|
878
|
+
var formatMessage = this.props.intl.formatMessage;
|
|
882
879
|
var formatClearLinkText = formatMessage(messages.clearLink);
|
|
883
880
|
var screenReaderDescriptionId = 'search-recent-links-field-description';
|
|
884
881
|
var linkSearchListId = 'hyperlink-search-list';
|
|
@@ -890,7 +887,6 @@ var HyperlinkLinkAddToolbar = exports.HyperlinkLinkAddToolbar = /*#__PURE__*/fun
|
|
|
890
887
|
// as the Aria design pattern for combobox does not work in this case
|
|
891
888
|
// for details: https://a11y-internal.atlassian.net/browse/AK-740
|
|
892
889
|
var screenReaderText = browser.safari && this.getScreenReaderText();
|
|
893
|
-
var containerWidth = (0, _platformFeatureFlags.fg)('platform_editor_link_picker_width_fix') ? _ToolbarComponents.narrowContainerWidth : !!activityProvider && _ToolbarComponents.containerWithProvider;
|
|
894
890
|
var hyperlinkElement = (0, _react2.jsx)("div", {
|
|
895
891
|
"aria-label": formatMessage(messages.hyperlinkAriaLabel)
|
|
896
892
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
|
|
@@ -899,7 +895,7 @@ var HyperlinkLinkAddToolbar = exports.HyperlinkLinkAddToolbar = /*#__PURE__*/fun
|
|
|
899
895
|
"data-testid": "hyperlink-add-toolbar"
|
|
900
896
|
}, (0, _react2.jsx)("div", {
|
|
901
897
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766
|
|
902
|
-
css: [_ToolbarComponents.container,
|
|
898
|
+
css: [_ToolbarComponents.container, _ToolbarComponents.narrowContainerWidth, containerPadding],
|
|
903
899
|
ref: this.wrapperRef
|
|
904
900
|
}, (0, _react2.jsx)("label", {
|
|
905
901
|
htmlFor: linkSearchInputId,
|
|
@@ -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.3";
|
|
23
23
|
var sanitiseSentryEvents = function sanitiseSentryEvents(data, _hint) {
|
|
24
24
|
// Remove URL as it has UGC
|
|
25
25
|
// Ignored via go/ees007
|
|
@@ -8,7 +8,6 @@ exports.getNodeIdProvider = exports.NodeAnchorProvider = void 0;
|
|
|
8
8
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
9
9
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
10
10
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
11
|
-
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
12
11
|
var _expVal = require("@atlaskit/tmp-editor-statsig/expVal");
|
|
13
12
|
var _utils = require("../utils");
|
|
14
13
|
var _dynamicBitArray = require("./dynamic-bit-array");
|
|
@@ -199,16 +198,11 @@ var isLimitedModeEnabled = function isLimitedModeEnabled(editorView) {
|
|
|
199
198
|
// This allows access to the node ids anywhere.
|
|
200
199
|
var getNodeIdProvider = exports.getNodeIdProvider = function getNodeIdProvider(editorView) {
|
|
201
200
|
if (!nodeIdProviderMap.has(editorView)) {
|
|
202
|
-
if
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
var _provider = new NodeAnchorProvider(limitedMode, isEmptyDoc);
|
|
208
|
-
nodeIdProviderMap.set(editorView, _provider);
|
|
209
|
-
return _provider;
|
|
210
|
-
}
|
|
211
|
-
var provider = new NodeAnchorProvider();
|
|
201
|
+
// if the limited mode flag is on, enable limited mode based on the threshold
|
|
202
|
+
// only for the first time
|
|
203
|
+
var limitedMode = isLimitedModeEnabled(editorView);
|
|
204
|
+
var isEmptyDoc = (0, _utils.isEmptyDocument)(editorView.state.doc);
|
|
205
|
+
var provider = new NodeAnchorProvider(limitedMode, isEmptyDoc);
|
|
212
206
|
nodeIdProviderMap.set(editorView, provider);
|
|
213
207
|
return provider;
|
|
214
208
|
}
|
|
@@ -217,7 +211,7 @@ var getNodeIdProvider = exports.getNodeIdProvider = function getNodeIdProvider(e
|
|
|
217
211
|
// in some cases we need to re-check limited mode state
|
|
218
212
|
// Confluence editor can start with an empty doc and then load content later
|
|
219
213
|
// so we need to check first time from an empty doc to a non-empty doc
|
|
220
|
-
if (nodeIdProvider.isEmptyDoc() && !(0, _utils.isEmptyDocument)(editorView.state.doc)
|
|
214
|
+
if (nodeIdProvider.isEmptyDoc() && !(0, _utils.isEmptyDocument)(editorView.state.doc)) {
|
|
221
215
|
// set empty doc to false regardless of limited mode state
|
|
222
216
|
nodeIdProvider.setEmptyDoc(false);
|
|
223
217
|
if (!nodeIdProvider.isLimitedMode() && isLimitedModeEnabled(editorView)) {
|
|
@@ -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.3";
|
|
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
|
|
@@ -17,7 +17,6 @@ import { isSafeUrl } from '@atlaskit/adf-schema';
|
|
|
17
17
|
import withAnalyticsEvents from '@atlaskit/analytics-next/withAnalyticsEvents';
|
|
18
18
|
import Page16Icon from '@atlaskit/icon-object/glyph/page/16';
|
|
19
19
|
import CrossCircleIcon from '@atlaskit/icon/core/cross-circle';
|
|
20
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
21
20
|
// eslint-disable-next-line @atlaskit/design-system/no-emotion-primitives -- to be migrated to @atlaskit/primitives/compiled – go/akcss
|
|
22
21
|
import { Pressable, xcss } from '@atlaskit/primitives';
|
|
23
22
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
@@ -27,7 +26,7 @@ import { Announcer, PanelTextInput } from '../../../ui';
|
|
|
27
26
|
import { normalizeUrl } from '../../../utils';
|
|
28
27
|
import { browser as browserLegacy, getBrowserInfo } from '../../../utils/browser';
|
|
29
28
|
import LinkSearchList from '../../LinkSearch/LinkSearchList';
|
|
30
|
-
import { container,
|
|
29
|
+
import { container, narrowContainerWidth, inputWrapper } from '../../LinkSearch/ToolbarComponents';
|
|
31
30
|
import { transformTimeStamp } from '../../LinkSearch/transformTimeStamp';
|
|
32
31
|
import { filterUniqueItems, mapContentTypeToIcon, sha1, wordCount } from './utils';
|
|
33
32
|
|
|
@@ -729,8 +728,7 @@ export class HyperlinkLinkAddToolbar extends PureComponent {
|
|
|
729
728
|
const {
|
|
730
729
|
intl: {
|
|
731
730
|
formatMessage
|
|
732
|
-
}
|
|
733
|
-
activityProvider
|
|
731
|
+
}
|
|
734
732
|
} = this.props;
|
|
735
733
|
const formatClearLinkText = formatMessage(messages.clearLink);
|
|
736
734
|
const screenReaderDescriptionId = 'search-recent-links-field-description';
|
|
@@ -743,7 +741,6 @@ export class HyperlinkLinkAddToolbar extends PureComponent {
|
|
|
743
741
|
// as the Aria design pattern for combobox does not work in this case
|
|
744
742
|
// for details: https://a11y-internal.atlassian.net/browse/AK-740
|
|
745
743
|
const screenReaderText = browser.safari && this.getScreenReaderText();
|
|
746
|
-
const containerWidth = fg('platform_editor_link_picker_width_fix') ? narrowContainerWidth : !!activityProvider && containerWithProvider;
|
|
747
744
|
const hyperlinkElement = jsx("div", {
|
|
748
745
|
"aria-label": formatMessage(messages.hyperlinkAriaLabel)
|
|
749
746
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
|
|
@@ -752,7 +749,7 @@ export class HyperlinkLinkAddToolbar extends PureComponent {
|
|
|
752
749
|
"data-testid": "hyperlink-add-toolbar"
|
|
753
750
|
}, jsx("div", {
|
|
754
751
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766
|
|
755
|
-
css: [container,
|
|
752
|
+
css: [container, narrowContainerWidth, containerPadding],
|
|
756
753
|
ref: this.wrapperRef
|
|
757
754
|
}, jsx("label", {
|
|
758
755
|
htmlFor: linkSearchInputId,
|
|
@@ -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.3";
|
|
8
8
|
const sanitiseSentryEvents = (data, _hint) => {
|
|
9
9
|
// Remove URL as it has UGC
|
|
10
10
|
// Ignored via go/ees007
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
3
2
|
import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
|
|
4
3
|
import { isEmptyDocument } from '../utils';
|
|
5
4
|
import { DynamicBitArray } from './dynamic-bit-array';
|
|
@@ -173,16 +172,11 @@ const isLimitedModeEnabled = editorView => {
|
|
|
173
172
|
// This allows access to the node ids anywhere.
|
|
174
173
|
export const getNodeIdProvider = editorView => {
|
|
175
174
|
if (!nodeIdProviderMap.has(editorView)) {
|
|
176
|
-
if
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const provider = new NodeAnchorProvider(limitedMode, isEmptyDoc);
|
|
182
|
-
nodeIdProviderMap.set(editorView, provider);
|
|
183
|
-
return provider;
|
|
184
|
-
}
|
|
185
|
-
const provider = new NodeAnchorProvider();
|
|
175
|
+
// if the limited mode flag is on, enable limited mode based on the threshold
|
|
176
|
+
// only for the first time
|
|
177
|
+
const limitedMode = isLimitedModeEnabled(editorView);
|
|
178
|
+
const isEmptyDoc = isEmptyDocument(editorView.state.doc);
|
|
179
|
+
const provider = new NodeAnchorProvider(limitedMode, isEmptyDoc);
|
|
186
180
|
nodeIdProviderMap.set(editorView, provider);
|
|
187
181
|
return provider;
|
|
188
182
|
}
|
|
@@ -191,7 +185,7 @@ export const getNodeIdProvider = editorView => {
|
|
|
191
185
|
// in some cases we need to re-check limited mode state
|
|
192
186
|
// Confluence editor can start with an empty doc and then load content later
|
|
193
187
|
// so we need to check first time from an empty doc to a non-empty doc
|
|
194
|
-
if (nodeIdProvider.isEmptyDoc() && !isEmptyDocument(editorView.state.doc)
|
|
188
|
+
if (nodeIdProvider.isEmptyDoc() && !isEmptyDocument(editorView.state.doc)) {
|
|
195
189
|
// set empty doc to false regardless of limited mode state
|
|
196
190
|
nodeIdProvider.setEmptyDoc(false);
|
|
197
191
|
if (!nodeIdProvider.isLimitedMode() && isLimitedModeEnabled(editorView)) {
|
|
@@ -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.3";
|
|
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
|
|
@@ -28,7 +28,6 @@ import { isSafeUrl } from '@atlaskit/adf-schema';
|
|
|
28
28
|
import withAnalyticsEvents from '@atlaskit/analytics-next/withAnalyticsEvents';
|
|
29
29
|
import Page16Icon from '@atlaskit/icon-object/glyph/page/16';
|
|
30
30
|
import CrossCircleIcon from '@atlaskit/icon/core/cross-circle';
|
|
31
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
32
31
|
// eslint-disable-next-line @atlaskit/design-system/no-emotion-primitives -- to be migrated to @atlaskit/primitives/compiled – go/akcss
|
|
33
32
|
import { Pressable, xcss } from '@atlaskit/primitives';
|
|
34
33
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
@@ -38,7 +37,7 @@ import { Announcer, PanelTextInput } from '../../../ui';
|
|
|
38
37
|
import { normalizeUrl } from '../../../utils';
|
|
39
38
|
import { browser as browserLegacy, getBrowserInfo } from '../../../utils/browser';
|
|
40
39
|
import LinkSearchList from '../../LinkSearch/LinkSearchList';
|
|
41
|
-
import { container,
|
|
40
|
+
import { container, narrowContainerWidth, inputWrapper } from '../../LinkSearch/ToolbarComponents';
|
|
42
41
|
import { transformTimeStamp } from '../../LinkSearch/transformTimeStamp';
|
|
43
42
|
import { filterUniqueItems, mapContentTypeToIcon, sha1, wordCount } from './utils';
|
|
44
43
|
|
|
@@ -873,9 +872,7 @@ export var HyperlinkLinkAddToolbar = /*#__PURE__*/function (_PureComponent) {
|
|
|
873
872
|
selectedIndex = _this$state1.selectedIndex,
|
|
874
873
|
displayUrl = _this$state1.displayUrl,
|
|
875
874
|
displayText = _this$state1.displayText;
|
|
876
|
-
var
|
|
877
|
-
formatMessage = _this$props6.intl.formatMessage,
|
|
878
|
-
activityProvider = _this$props6.activityProvider;
|
|
875
|
+
var formatMessage = this.props.intl.formatMessage;
|
|
879
876
|
var formatClearLinkText = formatMessage(messages.clearLink);
|
|
880
877
|
var screenReaderDescriptionId = 'search-recent-links-field-description';
|
|
881
878
|
var linkSearchListId = 'hyperlink-search-list';
|
|
@@ -887,7 +884,6 @@ export var HyperlinkLinkAddToolbar = /*#__PURE__*/function (_PureComponent) {
|
|
|
887
884
|
// as the Aria design pattern for combobox does not work in this case
|
|
888
885
|
// for details: https://a11y-internal.atlassian.net/browse/AK-740
|
|
889
886
|
var screenReaderText = browser.safari && this.getScreenReaderText();
|
|
890
|
-
var containerWidth = fg('platform_editor_link_picker_width_fix') ? narrowContainerWidth : !!activityProvider && containerWithProvider;
|
|
891
887
|
var hyperlinkElement = jsx("div", {
|
|
892
888
|
"aria-label": formatMessage(messages.hyperlinkAriaLabel)
|
|
893
889
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
|
|
@@ -896,7 +892,7 @@ export var HyperlinkLinkAddToolbar = /*#__PURE__*/function (_PureComponent) {
|
|
|
896
892
|
"data-testid": "hyperlink-add-toolbar"
|
|
897
893
|
}, jsx("div", {
|
|
898
894
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766
|
|
899
|
-
css: [container,
|
|
895
|
+
css: [container, narrowContainerWidth, containerPadding],
|
|
900
896
|
ref: this.wrapperRef
|
|
901
897
|
}, jsx("label", {
|
|
902
898
|
htmlFor: linkSearchInputId,
|
|
@@ -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.3";
|
|
14
14
|
var sanitiseSentryEvents = function sanitiseSentryEvents(data, _hint) {
|
|
15
15
|
// Remove URL as it has UGC
|
|
16
16
|
// Ignored via go/ees007
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
2
2
|
import _createClass from "@babel/runtime/helpers/createClass";
|
|
3
3
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
4
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
5
4
|
import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
|
|
6
5
|
import { isEmptyDocument } from '../utils';
|
|
7
6
|
import { DynamicBitArray } from './dynamic-bit-array';
|
|
@@ -193,16 +192,11 @@ var isLimitedModeEnabled = function isLimitedModeEnabled(editorView) {
|
|
|
193
192
|
// This allows access to the node ids anywhere.
|
|
194
193
|
export var getNodeIdProvider = function getNodeIdProvider(editorView) {
|
|
195
194
|
if (!nodeIdProviderMap.has(editorView)) {
|
|
196
|
-
if
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
var _provider = new NodeAnchorProvider(limitedMode, isEmptyDoc);
|
|
202
|
-
nodeIdProviderMap.set(editorView, _provider);
|
|
203
|
-
return _provider;
|
|
204
|
-
}
|
|
205
|
-
var provider = new NodeAnchorProvider();
|
|
195
|
+
// if the limited mode flag is on, enable limited mode based on the threshold
|
|
196
|
+
// only for the first time
|
|
197
|
+
var limitedMode = isLimitedModeEnabled(editorView);
|
|
198
|
+
var isEmptyDoc = isEmptyDocument(editorView.state.doc);
|
|
199
|
+
var provider = new NodeAnchorProvider(limitedMode, isEmptyDoc);
|
|
206
200
|
nodeIdProviderMap.set(editorView, provider);
|
|
207
201
|
return provider;
|
|
208
202
|
}
|
|
@@ -211,7 +205,7 @@ export var getNodeIdProvider = function getNodeIdProvider(editorView) {
|
|
|
211
205
|
// in some cases we need to re-check limited mode state
|
|
212
206
|
// Confluence editor can start with an empty doc and then load content later
|
|
213
207
|
// so we need to check first time from an empty doc to a non-empty doc
|
|
214
|
-
if (nodeIdProvider.isEmptyDoc() && !isEmptyDocument(editorView.state.doc)
|
|
208
|
+
if (nodeIdProvider.isEmptyDoc() && !isEmptyDocument(editorView.state.doc)) {
|
|
215
209
|
// set empty doc to false regardless of limited mode state
|
|
216
210
|
nodeIdProvider.setEmptyDoc(false);
|
|
217
211
|
if (!nodeIdProvider.isLimitedMode() && isLimitedModeEnabled(editorView)) {
|
|
@@ -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.3";
|
|
25
25
|
var halfFocusRing = 1;
|
|
26
26
|
var dropOffset = '0, 8';
|
|
27
27
|
var fadeIn = keyframes({
|
|
@@ -6,6 +6,6 @@ type AiAutocompleteInvokedAEP = TrackAEP<ACTION.INVOKED, ACTION_SUBJECT.AI_AUTOC
|
|
|
6
6
|
type AiAutocompleteViewedAEP = TrackAEP<ACTION.SUGGESTION_VIEWED, ACTION_SUBJECT.AI_AUTOCOMPLETE, undefined, undefined, undefined>;
|
|
7
7
|
type AiAutocompleteAcceptedAEP = TrackAEP<ACTION.SUGGESTION_INSERTED, ACTION_SUBJECT.AI_AUTOCOMPLETE, undefined, undefined, undefined>;
|
|
8
8
|
type AiAutocompleteRejectedAEP = TrackAEP<ACTION.SUGGESTION_DISMISSED, ACTION_SUBJECT.AI_AUTOCOMPLETE, undefined, undefined, undefined>;
|
|
9
|
-
export type TriggerType = 'summary-heading' | 'summary-first-lines' | 'summary-panel' | 'cmd+shift+space';
|
|
9
|
+
export type TriggerType = 'summary-heading' | 'summary-first-lines' | 'summary-panel' | 'conclusion-heading' | 'conclusion-last-lines' | 'cmd+shift+space';
|
|
10
10
|
export type AiAutocompleteEventPayload = AiAutocompleteInvokedAEP | AiAutocompleteViewedAEP | AiAutocompleteAcceptedAEP | AiAutocompleteRejectedAEP;
|
|
11
11
|
export {};
|
|
@@ -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(): {
|
|
@@ -6,6 +6,6 @@ type AiAutocompleteInvokedAEP = TrackAEP<ACTION.INVOKED, ACTION_SUBJECT.AI_AUTOC
|
|
|
6
6
|
type AiAutocompleteViewedAEP = TrackAEP<ACTION.SUGGESTION_VIEWED, ACTION_SUBJECT.AI_AUTOCOMPLETE, undefined, undefined, undefined>;
|
|
7
7
|
type AiAutocompleteAcceptedAEP = TrackAEP<ACTION.SUGGESTION_INSERTED, ACTION_SUBJECT.AI_AUTOCOMPLETE, undefined, undefined, undefined>;
|
|
8
8
|
type AiAutocompleteRejectedAEP = TrackAEP<ACTION.SUGGESTION_DISMISSED, ACTION_SUBJECT.AI_AUTOCOMPLETE, undefined, undefined, undefined>;
|
|
9
|
-
export type TriggerType = 'summary-heading' | 'summary-first-lines' | 'summary-panel' | 'cmd+shift+space';
|
|
9
|
+
export type TriggerType = 'summary-heading' | 'summary-first-lines' | 'summary-panel' | 'conclusion-heading' | 'conclusion-last-lines' | 'cmd+shift+space';
|
|
10
10
|
export type AiAutocompleteEventPayload = AiAutocompleteInvokedAEP | AiAutocompleteViewedAEP | AiAutocompleteAcceptedAEP | AiAutocompleteRejectedAEP;
|
|
11
11
|
export {};
|
|
@@ -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.4",
|
|
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/"
|
|
@@ -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.49.0",
|
|
74
74
|
"@atlaskit/prosemirror-history": "^0.2.0",
|
|
75
|
-
"@atlaskit/react-ufo": "^5.
|
|
75
|
+
"@atlaskit/react-ufo": "^5.12.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
79
|
"@atlaskit/spinner": "^19.1.0",
|
|
80
80
|
"@atlaskit/task-decision": "^19.3.0",
|
|
81
81
|
"@atlaskit/textfield": "^8.3.0",
|
|
82
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
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",
|
|
@@ -214,9 +214,6 @@
|
|
|
214
214
|
"p2m-drop-down-motion": {
|
|
215
215
|
"type": "boolean"
|
|
216
216
|
},
|
|
217
|
-
"platform_editor_link_picker_width_fix": {
|
|
218
|
-
"type": "boolean"
|
|
219
|
-
},
|
|
220
217
|
"platform_editor_content_mode_button_mvp": {
|
|
221
218
|
"type": "boolean"
|
|
222
219
|
},
|
|
@@ -253,9 +250,6 @@
|
|
|
253
250
|
"platform_editor_ally_remove_role_tabpanel": {
|
|
254
251
|
"type": "boolean"
|
|
255
252
|
},
|
|
256
|
-
"platform_editor_native_anchor_patch_2": {
|
|
257
|
-
"type": "boolean"
|
|
258
|
-
},
|
|
259
253
|
"platform_forge_ui_support_images_in_adfrenderer": {
|
|
260
254
|
"type": "boolean"
|
|
261
255
|
},
|