@atlaskit/editor-plugin-show-diff 8.1.13 → 8.3.0
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 +19 -0
- package/dist/cjs/pm-plugins/main.js +20 -7
- package/dist/cjs/pm-plugins/scrollToDiff.js +121 -0
- package/dist/es2019/pm-plugins/main.js +19 -6
- package/dist/es2019/pm-plugins/scrollToDiff.js +115 -0
- package/dist/esm/pm-plugins/main.js +19 -6
- package/dist/esm/pm-plugins/scrollToDiff.js +115 -0
- package/dist/types/pm-plugins/main.d.ts +5 -0
- package/dist/types/pm-plugins/scrollToDiff.d.ts +15 -0
- package/dist/types/showDiffPluginType.d.ts +5 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +5 -0
- package/dist/types-ts4.5/pm-plugins/scrollToDiff.d.ts +15 -0
- package/dist/types-ts4.5/showDiffPluginType.d.ts +5 -0
- package/package.json +4 -4
- package/dist/cjs/pm-plugins/scrollToActiveDecoration.js +0 -72
- package/dist/es2019/pm-plugins/scrollToActiveDecoration.js +0 -66
- package/dist/esm/pm-plugins/scrollToActiveDecoration.js +0 -66
- package/dist/types/pm-plugins/scrollToActiveDecoration.d.ts +0 -7
- package/dist/types-ts4.5/pm-plugins/scrollToActiveDecoration.d.ts +0 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-show-diff
|
|
2
2
|
|
|
3
|
+
## 8.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`1b208e1f7d8f7`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/1b208e1f7d8f7) -
|
|
8
|
+
[ux] Adds the entry point for ai image generation to the media insert picker plugin as a new tab.
|
|
9
|
+
This feature is fully behind an experiment gate.
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
|
|
15
|
+
## 8.2.0
|
|
16
|
+
|
|
17
|
+
### Minor Changes
|
|
18
|
+
|
|
19
|
+
- [`439f373a73aa2`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/439f373a73aa2) -
|
|
20
|
+
EDITOR-6620: Add an option to scroll the diff into view.
|
|
21
|
+
|
|
3
22
|
## 8.1.13
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
|
@@ -17,7 +17,7 @@ var _calculateDiffDecorations = require("./calculateDiff/calculateDiffDecoration
|
|
|
17
17
|
var _enforceCustomStepRegisters = require("./enforceCustomStepRegisters");
|
|
18
18
|
var _getScrollableDecorations = require("./getScrollableDecorations");
|
|
19
19
|
var _NodeViewSerializer = require("./NodeViewSerializer");
|
|
20
|
-
var
|
|
20
|
+
var _scrollToDiff = require("./scrollToDiff");
|
|
21
21
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
22
22
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
23
23
|
var showDiffPluginKey = exports.showDiffPluginKey = new _state2.PluginKey('showDiffPlugin');
|
|
@@ -154,27 +154,40 @@ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl,
|
|
|
154
154
|
originalDoc: (0, _processRawValue.processRawValue)(view.state.schema, config.originalDoc)
|
|
155
155
|
}));
|
|
156
156
|
}
|
|
157
|
+
var pluginState = showDiffPluginKey.getState(view.state);
|
|
158
|
+
|
|
159
|
+
// Scroll to the first decoration when scrollIntoView was requested
|
|
160
|
+
if (pluginState !== null && pluginState !== void 0 && pluginState.scrollIntoView && (0, _expValEquals.expValEquals)('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
|
|
161
|
+
var _cancelPendingScrollT, _pluginState$decorati;
|
|
162
|
+
(_cancelPendingScrollT = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT === void 0 || _cancelPendingScrollT();
|
|
163
|
+
var allDecorations = ((_pluginState$decorati = pluginState.decorations) === null || _pluginState$decorati === void 0 ? void 0 : _pluginState$decorati.find()) || [];
|
|
164
|
+
cancelPendingScrollToDecoration = (0, _scrollToDiff.scrollToFirstDecoration)(view, allDecorations);
|
|
165
|
+
|
|
166
|
+
// Reset the flag so we don't scroll again on subsequent updates
|
|
167
|
+
view.dispatch(view.state.tr.setMeta(showDiffPluginKey, {
|
|
168
|
+
scrollIntoView: false
|
|
169
|
+
}));
|
|
170
|
+
}
|
|
157
171
|
|
|
158
172
|
// Check for any potential scroll side-effects
|
|
159
173
|
if ((0, _platformFeatureFlags.fg)('platform_editor_show_diff_scroll_navigation')) {
|
|
160
|
-
var pluginState = showDiffPluginKey.getState(view.state);
|
|
161
174
|
var activeIndexChanged = (pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex) !== undefined && pluginState.activeIndex !== previousActiveIndex;
|
|
162
175
|
previousActiveIndex = pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex;
|
|
163
176
|
if ((pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex) !== undefined && activeIndexChanged) {
|
|
164
|
-
var
|
|
165
|
-
(
|
|
177
|
+
var _cancelPendingScrollT2, _api$expand;
|
|
178
|
+
(_cancelPendingScrollT2 = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT2 === void 0 || _cancelPendingScrollT2();
|
|
166
179
|
var scrollableDecorations = (0, _getScrollableDecorations.getScrollableDecorations)(pluginState.decorations, view.state.doc);
|
|
167
180
|
var activeDecoration = scrollableDecorations[pluginState.activeIndex];
|
|
168
181
|
if (activeDecoration && api !== null && api !== void 0 && (_api$expand = api.expand) !== null && _api$expand !== void 0 && (_api$expand = _api$expand.commands) !== null && _api$expand !== void 0 && _api$expand.toggleExpandRange && (0, _platformFeatureFlags.fg)('platform_editor_show_diff_scroll_navigation')) {
|
|
169
182
|
api === null || api === void 0 || api.core.actions.execute(api.expand.commands.toggleExpandRange(activeDecoration.from, activeDecoration.to, true));
|
|
170
183
|
}
|
|
171
|
-
cancelPendingScrollToDecoration = (0,
|
|
184
|
+
cancelPendingScrollToDecoration = (0, _scrollToDiff.scrollToActiveDecoration)(view, scrollableDecorations, pluginState.activeIndex);
|
|
172
185
|
}
|
|
173
186
|
}
|
|
174
187
|
},
|
|
175
188
|
destroy: function destroy() {
|
|
176
|
-
var
|
|
177
|
-
(
|
|
189
|
+
var _cancelPendingScrollT3;
|
|
190
|
+
(_cancelPendingScrollT3 = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT3 === void 0 || _cancelPendingScrollT3();
|
|
178
191
|
cancelPendingScrollToDecoration = null;
|
|
179
192
|
}
|
|
180
193
|
};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.scrollToFirstDecoration = exports.scrollToActiveDecoration = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Extra space above the scrolled-to element so it does not sit flush under the
|
|
9
|
+
* viewport edge (helps with sticky table headers, toolbars, etc.).
|
|
10
|
+
*
|
|
11
|
+
* Implemented with `scroll-margin-top` so we still use the browser’s native
|
|
12
|
+
* `scrollIntoView`, which scrolls every relevant scrollport (nested containers
|
|
13
|
+
* and the window). A single manual `scrollTop` on one ancestor often misses
|
|
14
|
+
* outer scroll or mis-identifies the active scroll container.
|
|
15
|
+
*/
|
|
16
|
+
var SCROLL_TOP_MARGIN_PX = 100;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Checks if element is not visible in the viewport, accounting
|
|
20
|
+
* for the scroll margin offset used during scrolling.
|
|
21
|
+
*/
|
|
22
|
+
function shouldScrollIntoView(element) {
|
|
23
|
+
var rect = element.getBoundingClientRect();
|
|
24
|
+
var viewportHeight = window.innerHeight || document.documentElement.clientHeight;
|
|
25
|
+
return !(rect.top >= SCROLL_TOP_MARGIN_PX && rect.bottom <= viewportHeight);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Returns the resolved HTMLElement for a given DOM node, walking up to the
|
|
30
|
+
* parent element if the node itself is not an Element (e.g. a text node).
|
|
31
|
+
*/
|
|
32
|
+
function scrollToSelection(node) {
|
|
33
|
+
var element = node instanceof Element ? node : (node === null || node === void 0 ? void 0 : node.parentElement) instanceof Element ? node.parentElement : null;
|
|
34
|
+
if (!(element instanceof HTMLElement)) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// scroll-margin is included in scroll-into-view math; it does not change layout.
|
|
39
|
+
var previousScrollMarginTop = element.style.scrollMarginTop;
|
|
40
|
+
element.style.scrollMarginTop = "".concat(SCROLL_TOP_MARGIN_PX, "px");
|
|
41
|
+
try {
|
|
42
|
+
element.scrollIntoView({
|
|
43
|
+
behavior: 'smooth',
|
|
44
|
+
block: 'start'
|
|
45
|
+
});
|
|
46
|
+
} finally {
|
|
47
|
+
element.style.scrollMarginTop = previousScrollMarginTop;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Schedules scrolling to the first diff decoration after the next frame.
|
|
53
|
+
* Unlike `scrollToActiveDecoration`, this does not require an active index —
|
|
54
|
+
* it simply scrolls to bring the first decoration into view.
|
|
55
|
+
*
|
|
56
|
+
* @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
|
|
57
|
+
*/
|
|
58
|
+
var scrollToFirstDecoration = exports.scrollToFirstDecoration = function scrollToFirstDecoration(view, decorations) {
|
|
59
|
+
var decoration = decorations[0];
|
|
60
|
+
if (!decoration) {
|
|
61
|
+
return function () {};
|
|
62
|
+
}
|
|
63
|
+
var rafId = requestAnimationFrame(function () {
|
|
64
|
+
var _decoration$spec, _decoration$type;
|
|
65
|
+
rafId = null;
|
|
66
|
+
// @ts-expect-error - decoration.type is not typed public API
|
|
67
|
+
if ((_decoration$spec = decoration.spec) !== null && _decoration$spec !== void 0 && (_decoration$spec = _decoration$spec.key) !== null && _decoration$spec !== void 0 && _decoration$spec.startsWith('diff-widget') && decoration !== null && decoration !== void 0 && (_decoration$type = decoration.type) !== null && _decoration$type !== void 0 && _decoration$type.toDOM) {
|
|
68
|
+
// @ts-expect-error - decoration.type is not typed public API
|
|
69
|
+
var widgetDom = decoration.type.toDOM;
|
|
70
|
+
if (shouldScrollIntoView(widgetDom)) {
|
|
71
|
+
scrollToSelection(widgetDom);
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
var _view$domAtPos;
|
|
75
|
+
var targetNode = view.nodeDOM(decoration === null || decoration === void 0 ? void 0 : decoration.from);
|
|
76
|
+
var node = targetNode instanceof Element ? targetNode : (_view$domAtPos = view.domAtPos(decoration === null || decoration === void 0 ? void 0 : decoration.from)) === null || _view$domAtPos === void 0 ? void 0 : _view$domAtPos.node;
|
|
77
|
+
if (node instanceof HTMLElement && shouldScrollIntoView(node)) {
|
|
78
|
+
scrollToSelection(node);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
return function () {
|
|
83
|
+
if (rafId !== null) {
|
|
84
|
+
cancelAnimationFrame(rafId);
|
|
85
|
+
rafId = null;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Schedules scrolling to the decoration at the given index after the next frame.
|
|
92
|
+
*
|
|
93
|
+
* @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
|
|
94
|
+
*/
|
|
95
|
+
var scrollToActiveDecoration = exports.scrollToActiveDecoration = function scrollToActiveDecoration(view, decorations, activeIndex) {
|
|
96
|
+
var decoration = decorations[activeIndex];
|
|
97
|
+
if (!decoration) {
|
|
98
|
+
return function () {};
|
|
99
|
+
}
|
|
100
|
+
var rafId = requestAnimationFrame(function () {
|
|
101
|
+
var _decoration$spec2;
|
|
102
|
+
rafId = null;
|
|
103
|
+
if (((_decoration$spec2 = decoration.spec) === null || _decoration$spec2 === void 0 ? void 0 : _decoration$spec2.key) === 'diff-widget-active') {
|
|
104
|
+
var _decoration$type2;
|
|
105
|
+
// @ts-expect-error - decoration.type is not typed public API
|
|
106
|
+
var widgetDom = decoration === null || decoration === void 0 || (_decoration$type2 = decoration.type) === null || _decoration$type2 === void 0 ? void 0 : _decoration$type2.toDOM;
|
|
107
|
+
scrollToSelection(widgetDom);
|
|
108
|
+
} else {
|
|
109
|
+
var _view$domAtPos2;
|
|
110
|
+
var targetNode = view.nodeDOM(decoration === null || decoration === void 0 ? void 0 : decoration.from);
|
|
111
|
+
var node = targetNode instanceof Element ? targetNode : (_view$domAtPos2 = view.domAtPos(decoration === null || decoration === void 0 ? void 0 : decoration.from)) === null || _view$domAtPos2 === void 0 ? void 0 : _view$domAtPos2.node;
|
|
112
|
+
scrollToSelection(node);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
return function () {
|
|
116
|
+
if (rafId !== null) {
|
|
117
|
+
cancelAnimationFrame(rafId);
|
|
118
|
+
rafId = null;
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
};
|
|
@@ -9,7 +9,7 @@ import { calculateDiffDecorations } from './calculateDiff/calculateDiffDecoratio
|
|
|
9
9
|
import { enforceCustomStepRegisters } from './enforceCustomStepRegisters';
|
|
10
10
|
import { getScrollableDecorations } from './getScrollableDecorations';
|
|
11
11
|
import { NodeViewSerializer } from './NodeViewSerializer';
|
|
12
|
-
import { scrollToActiveDecoration } from './
|
|
12
|
+
import { scrollToActiveDecoration, scrollToFirstDecoration } from './scrollToDiff';
|
|
13
13
|
export const showDiffPluginKey = new PluginKey('showDiffPlugin');
|
|
14
14
|
export const createPlugin = (config, getIntl, api) => {
|
|
15
15
|
if (fg('platform_editor_show_diff_equality_fallback')) {
|
|
@@ -159,15 +159,28 @@ export const createPlugin = (config, getIntl, api) => {
|
|
|
159
159
|
originalDoc: processRawValue(view.state.schema, config.originalDoc)
|
|
160
160
|
}));
|
|
161
161
|
}
|
|
162
|
+
const pluginState = showDiffPluginKey.getState(view.state);
|
|
163
|
+
|
|
164
|
+
// Scroll to the first decoration when scrollIntoView was requested
|
|
165
|
+
if (pluginState !== null && pluginState !== void 0 && pluginState.scrollIntoView && expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
|
|
166
|
+
var _cancelPendingScrollT, _pluginState$decorati;
|
|
167
|
+
(_cancelPendingScrollT = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT === void 0 ? void 0 : _cancelPendingScrollT();
|
|
168
|
+
const allDecorations = ((_pluginState$decorati = pluginState.decorations) === null || _pluginState$decorati === void 0 ? void 0 : _pluginState$decorati.find()) || [];
|
|
169
|
+
cancelPendingScrollToDecoration = scrollToFirstDecoration(view, allDecorations);
|
|
170
|
+
|
|
171
|
+
// Reset the flag so we don't scroll again on subsequent updates
|
|
172
|
+
view.dispatch(view.state.tr.setMeta(showDiffPluginKey, {
|
|
173
|
+
scrollIntoView: false
|
|
174
|
+
}));
|
|
175
|
+
}
|
|
162
176
|
|
|
163
177
|
// Check for any potential scroll side-effects
|
|
164
178
|
if (fg('platform_editor_show_diff_scroll_navigation')) {
|
|
165
|
-
const pluginState = showDiffPluginKey.getState(view.state);
|
|
166
179
|
const activeIndexChanged = (pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex) !== undefined && pluginState.activeIndex !== previousActiveIndex;
|
|
167
180
|
previousActiveIndex = pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex;
|
|
168
181
|
if ((pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex) !== undefined && activeIndexChanged) {
|
|
169
|
-
var
|
|
170
|
-
(
|
|
182
|
+
var _cancelPendingScrollT2, _api$expand, _api$expand$commands;
|
|
183
|
+
(_cancelPendingScrollT2 = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT2 === void 0 ? void 0 : _cancelPendingScrollT2();
|
|
171
184
|
const scrollableDecorations = getScrollableDecorations(pluginState.decorations, view.state.doc);
|
|
172
185
|
const activeDecoration = scrollableDecorations[pluginState.activeIndex];
|
|
173
186
|
if (activeDecoration && api !== null && api !== void 0 && (_api$expand = api.expand) !== null && _api$expand !== void 0 && (_api$expand$commands = _api$expand.commands) !== null && _api$expand$commands !== void 0 && _api$expand$commands.toggleExpandRange && fg('platform_editor_show_diff_scroll_navigation')) {
|
|
@@ -178,8 +191,8 @@ export const createPlugin = (config, getIntl, api) => {
|
|
|
178
191
|
}
|
|
179
192
|
},
|
|
180
193
|
destroy() {
|
|
181
|
-
var
|
|
182
|
-
(
|
|
194
|
+
var _cancelPendingScrollT3;
|
|
195
|
+
(_cancelPendingScrollT3 = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT3 === void 0 ? void 0 : _cancelPendingScrollT3();
|
|
183
196
|
cancelPendingScrollToDecoration = null;
|
|
184
197
|
}
|
|
185
198
|
};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extra space above the scrolled-to element so it does not sit flush under the
|
|
3
|
+
* viewport edge (helps with sticky table headers, toolbars, etc.).
|
|
4
|
+
*
|
|
5
|
+
* Implemented with `scroll-margin-top` so we still use the browser’s native
|
|
6
|
+
* `scrollIntoView`, which scrolls every relevant scrollport (nested containers
|
|
7
|
+
* and the window). A single manual `scrollTop` on one ancestor often misses
|
|
8
|
+
* outer scroll or mis-identifies the active scroll container.
|
|
9
|
+
*/
|
|
10
|
+
const SCROLL_TOP_MARGIN_PX = 100;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Checks if element is not visible in the viewport, accounting
|
|
14
|
+
* for the scroll margin offset used during scrolling.
|
|
15
|
+
*/
|
|
16
|
+
function shouldScrollIntoView(element) {
|
|
17
|
+
const rect = element.getBoundingClientRect();
|
|
18
|
+
const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
|
|
19
|
+
return !(rect.top >= SCROLL_TOP_MARGIN_PX && rect.bottom <= viewportHeight);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Returns the resolved HTMLElement for a given DOM node, walking up to the
|
|
24
|
+
* parent element if the node itself is not an Element (e.g. a text node).
|
|
25
|
+
*/
|
|
26
|
+
function scrollToSelection(node) {
|
|
27
|
+
const element = node instanceof Element ? node : (node === null || node === void 0 ? void 0 : node.parentElement) instanceof Element ? node.parentElement : null;
|
|
28
|
+
if (!(element instanceof HTMLElement)) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// scroll-margin is included in scroll-into-view math; it does not change layout.
|
|
33
|
+
const previousScrollMarginTop = element.style.scrollMarginTop;
|
|
34
|
+
element.style.scrollMarginTop = `${SCROLL_TOP_MARGIN_PX}px`;
|
|
35
|
+
try {
|
|
36
|
+
element.scrollIntoView({
|
|
37
|
+
behavior: 'smooth',
|
|
38
|
+
block: 'start'
|
|
39
|
+
});
|
|
40
|
+
} finally {
|
|
41
|
+
element.style.scrollMarginTop = previousScrollMarginTop;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Schedules scrolling to the first diff decoration after the next frame.
|
|
47
|
+
* Unlike `scrollToActiveDecoration`, this does not require an active index —
|
|
48
|
+
* it simply scrolls to bring the first decoration into view.
|
|
49
|
+
*
|
|
50
|
+
* @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
|
|
51
|
+
*/
|
|
52
|
+
export const scrollToFirstDecoration = (view, decorations) => {
|
|
53
|
+
const decoration = decorations[0];
|
|
54
|
+
if (!decoration) {
|
|
55
|
+
return () => {};
|
|
56
|
+
}
|
|
57
|
+
let rafId = requestAnimationFrame(() => {
|
|
58
|
+
var _decoration$spec, _decoration$spec$key, _decoration$type;
|
|
59
|
+
rafId = null;
|
|
60
|
+
// @ts-expect-error - decoration.type is not typed public API
|
|
61
|
+
if ((_decoration$spec = decoration.spec) !== null && _decoration$spec !== void 0 && (_decoration$spec$key = _decoration$spec.key) !== null && _decoration$spec$key !== void 0 && _decoration$spec$key.startsWith('diff-widget') && decoration !== null && decoration !== void 0 && (_decoration$type = decoration.type) !== null && _decoration$type !== void 0 && _decoration$type.toDOM) {
|
|
62
|
+
// @ts-expect-error - decoration.type is not typed public API
|
|
63
|
+
const widgetDom = decoration.type.toDOM;
|
|
64
|
+
if (shouldScrollIntoView(widgetDom)) {
|
|
65
|
+
scrollToSelection(widgetDom);
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
var _view$domAtPos;
|
|
69
|
+
const targetNode = view.nodeDOM(decoration === null || decoration === void 0 ? void 0 : decoration.from);
|
|
70
|
+
const node = targetNode instanceof Element ? targetNode : (_view$domAtPos = view.domAtPos(decoration === null || decoration === void 0 ? void 0 : decoration.from)) === null || _view$domAtPos === void 0 ? void 0 : _view$domAtPos.node;
|
|
71
|
+
if (node instanceof HTMLElement && shouldScrollIntoView(node)) {
|
|
72
|
+
scrollToSelection(node);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return () => {
|
|
77
|
+
if (rafId !== null) {
|
|
78
|
+
cancelAnimationFrame(rafId);
|
|
79
|
+
rafId = null;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Schedules scrolling to the decoration at the given index after the next frame.
|
|
86
|
+
*
|
|
87
|
+
* @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
|
|
88
|
+
*/
|
|
89
|
+
export const scrollToActiveDecoration = (view, decorations, activeIndex) => {
|
|
90
|
+
const decoration = decorations[activeIndex];
|
|
91
|
+
if (!decoration) {
|
|
92
|
+
return () => {};
|
|
93
|
+
}
|
|
94
|
+
let rafId = requestAnimationFrame(() => {
|
|
95
|
+
var _decoration$spec2;
|
|
96
|
+
rafId = null;
|
|
97
|
+
if (((_decoration$spec2 = decoration.spec) === null || _decoration$spec2 === void 0 ? void 0 : _decoration$spec2.key) === 'diff-widget-active') {
|
|
98
|
+
var _decoration$type2;
|
|
99
|
+
// @ts-expect-error - decoration.type is not typed public API
|
|
100
|
+
const widgetDom = decoration === null || decoration === void 0 ? void 0 : (_decoration$type2 = decoration.type) === null || _decoration$type2 === void 0 ? void 0 : _decoration$type2.toDOM;
|
|
101
|
+
scrollToSelection(widgetDom);
|
|
102
|
+
} else {
|
|
103
|
+
var _view$domAtPos2;
|
|
104
|
+
const targetNode = view.nodeDOM(decoration === null || decoration === void 0 ? void 0 : decoration.from);
|
|
105
|
+
const node = targetNode instanceof Element ? targetNode : (_view$domAtPos2 = view.domAtPos(decoration === null || decoration === void 0 ? void 0 : decoration.from)) === null || _view$domAtPos2 === void 0 ? void 0 : _view$domAtPos2.node;
|
|
106
|
+
scrollToSelection(node);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
return () => {
|
|
110
|
+
if (rafId !== null) {
|
|
111
|
+
cancelAnimationFrame(rafId);
|
|
112
|
+
rafId = null;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
};
|
|
@@ -12,7 +12,7 @@ import { calculateDiffDecorations } from './calculateDiff/calculateDiffDecoratio
|
|
|
12
12
|
import { enforceCustomStepRegisters } from './enforceCustomStepRegisters';
|
|
13
13
|
import { getScrollableDecorations } from './getScrollableDecorations';
|
|
14
14
|
import { NodeViewSerializer } from './NodeViewSerializer';
|
|
15
|
-
import { scrollToActiveDecoration } from './
|
|
15
|
+
import { scrollToActiveDecoration, scrollToFirstDecoration } from './scrollToDiff';
|
|
16
16
|
export var showDiffPluginKey = new PluginKey('showDiffPlugin');
|
|
17
17
|
export var createPlugin = function createPlugin(config, getIntl, api) {
|
|
18
18
|
if (fg('platform_editor_show_diff_equality_fallback')) {
|
|
@@ -147,15 +147,28 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
|
|
|
147
147
|
originalDoc: processRawValue(view.state.schema, config.originalDoc)
|
|
148
148
|
}));
|
|
149
149
|
}
|
|
150
|
+
var pluginState = showDiffPluginKey.getState(view.state);
|
|
151
|
+
|
|
152
|
+
// Scroll to the first decoration when scrollIntoView was requested
|
|
153
|
+
if (pluginState !== null && pluginState !== void 0 && pluginState.scrollIntoView && expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
|
|
154
|
+
var _cancelPendingScrollT, _pluginState$decorati;
|
|
155
|
+
(_cancelPendingScrollT = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT === void 0 || _cancelPendingScrollT();
|
|
156
|
+
var allDecorations = ((_pluginState$decorati = pluginState.decorations) === null || _pluginState$decorati === void 0 ? void 0 : _pluginState$decorati.find()) || [];
|
|
157
|
+
cancelPendingScrollToDecoration = scrollToFirstDecoration(view, allDecorations);
|
|
158
|
+
|
|
159
|
+
// Reset the flag so we don't scroll again on subsequent updates
|
|
160
|
+
view.dispatch(view.state.tr.setMeta(showDiffPluginKey, {
|
|
161
|
+
scrollIntoView: false
|
|
162
|
+
}));
|
|
163
|
+
}
|
|
150
164
|
|
|
151
165
|
// Check for any potential scroll side-effects
|
|
152
166
|
if (fg('platform_editor_show_diff_scroll_navigation')) {
|
|
153
|
-
var pluginState = showDiffPluginKey.getState(view.state);
|
|
154
167
|
var activeIndexChanged = (pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex) !== undefined && pluginState.activeIndex !== previousActiveIndex;
|
|
155
168
|
previousActiveIndex = pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex;
|
|
156
169
|
if ((pluginState === null || pluginState === void 0 ? void 0 : pluginState.activeIndex) !== undefined && activeIndexChanged) {
|
|
157
|
-
var
|
|
158
|
-
(
|
|
170
|
+
var _cancelPendingScrollT2, _api$expand;
|
|
171
|
+
(_cancelPendingScrollT2 = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT2 === void 0 || _cancelPendingScrollT2();
|
|
159
172
|
var scrollableDecorations = getScrollableDecorations(pluginState.decorations, view.state.doc);
|
|
160
173
|
var activeDecoration = scrollableDecorations[pluginState.activeIndex];
|
|
161
174
|
if (activeDecoration && api !== null && api !== void 0 && (_api$expand = api.expand) !== null && _api$expand !== void 0 && (_api$expand = _api$expand.commands) !== null && _api$expand !== void 0 && _api$expand.toggleExpandRange && fg('platform_editor_show_diff_scroll_navigation')) {
|
|
@@ -166,8 +179,8 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
|
|
|
166
179
|
}
|
|
167
180
|
},
|
|
168
181
|
destroy: function destroy() {
|
|
169
|
-
var
|
|
170
|
-
(
|
|
182
|
+
var _cancelPendingScrollT3;
|
|
183
|
+
(_cancelPendingScrollT3 = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT3 === void 0 || _cancelPendingScrollT3();
|
|
171
184
|
cancelPendingScrollToDecoration = null;
|
|
172
185
|
}
|
|
173
186
|
};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extra space above the scrolled-to element so it does not sit flush under the
|
|
3
|
+
* viewport edge (helps with sticky table headers, toolbars, etc.).
|
|
4
|
+
*
|
|
5
|
+
* Implemented with `scroll-margin-top` so we still use the browser’s native
|
|
6
|
+
* `scrollIntoView`, which scrolls every relevant scrollport (nested containers
|
|
7
|
+
* and the window). A single manual `scrollTop` on one ancestor often misses
|
|
8
|
+
* outer scroll or mis-identifies the active scroll container.
|
|
9
|
+
*/
|
|
10
|
+
var SCROLL_TOP_MARGIN_PX = 100;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Checks if element is not visible in the viewport, accounting
|
|
14
|
+
* for the scroll margin offset used during scrolling.
|
|
15
|
+
*/
|
|
16
|
+
function shouldScrollIntoView(element) {
|
|
17
|
+
var rect = element.getBoundingClientRect();
|
|
18
|
+
var viewportHeight = window.innerHeight || document.documentElement.clientHeight;
|
|
19
|
+
return !(rect.top >= SCROLL_TOP_MARGIN_PX && rect.bottom <= viewportHeight);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Returns the resolved HTMLElement for a given DOM node, walking up to the
|
|
24
|
+
* parent element if the node itself is not an Element (e.g. a text node).
|
|
25
|
+
*/
|
|
26
|
+
function scrollToSelection(node) {
|
|
27
|
+
var element = node instanceof Element ? node : (node === null || node === void 0 ? void 0 : node.parentElement) instanceof Element ? node.parentElement : null;
|
|
28
|
+
if (!(element instanceof HTMLElement)) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// scroll-margin is included in scroll-into-view math; it does not change layout.
|
|
33
|
+
var previousScrollMarginTop = element.style.scrollMarginTop;
|
|
34
|
+
element.style.scrollMarginTop = "".concat(SCROLL_TOP_MARGIN_PX, "px");
|
|
35
|
+
try {
|
|
36
|
+
element.scrollIntoView({
|
|
37
|
+
behavior: 'smooth',
|
|
38
|
+
block: 'start'
|
|
39
|
+
});
|
|
40
|
+
} finally {
|
|
41
|
+
element.style.scrollMarginTop = previousScrollMarginTop;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Schedules scrolling to the first diff decoration after the next frame.
|
|
47
|
+
* Unlike `scrollToActiveDecoration`, this does not require an active index —
|
|
48
|
+
* it simply scrolls to bring the first decoration into view.
|
|
49
|
+
*
|
|
50
|
+
* @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
|
|
51
|
+
*/
|
|
52
|
+
export var scrollToFirstDecoration = function scrollToFirstDecoration(view, decorations) {
|
|
53
|
+
var decoration = decorations[0];
|
|
54
|
+
if (!decoration) {
|
|
55
|
+
return function () {};
|
|
56
|
+
}
|
|
57
|
+
var rafId = requestAnimationFrame(function () {
|
|
58
|
+
var _decoration$spec, _decoration$type;
|
|
59
|
+
rafId = null;
|
|
60
|
+
// @ts-expect-error - decoration.type is not typed public API
|
|
61
|
+
if ((_decoration$spec = decoration.spec) !== null && _decoration$spec !== void 0 && (_decoration$spec = _decoration$spec.key) !== null && _decoration$spec !== void 0 && _decoration$spec.startsWith('diff-widget') && decoration !== null && decoration !== void 0 && (_decoration$type = decoration.type) !== null && _decoration$type !== void 0 && _decoration$type.toDOM) {
|
|
62
|
+
// @ts-expect-error - decoration.type is not typed public API
|
|
63
|
+
var widgetDom = decoration.type.toDOM;
|
|
64
|
+
if (shouldScrollIntoView(widgetDom)) {
|
|
65
|
+
scrollToSelection(widgetDom);
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
var _view$domAtPos;
|
|
69
|
+
var targetNode = view.nodeDOM(decoration === null || decoration === void 0 ? void 0 : decoration.from);
|
|
70
|
+
var node = targetNode instanceof Element ? targetNode : (_view$domAtPos = view.domAtPos(decoration === null || decoration === void 0 ? void 0 : decoration.from)) === null || _view$domAtPos === void 0 ? void 0 : _view$domAtPos.node;
|
|
71
|
+
if (node instanceof HTMLElement && shouldScrollIntoView(node)) {
|
|
72
|
+
scrollToSelection(node);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return function () {
|
|
77
|
+
if (rafId !== null) {
|
|
78
|
+
cancelAnimationFrame(rafId);
|
|
79
|
+
rafId = null;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Schedules scrolling to the decoration at the given index after the next frame.
|
|
86
|
+
*
|
|
87
|
+
* @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
|
|
88
|
+
*/
|
|
89
|
+
export var scrollToActiveDecoration = function scrollToActiveDecoration(view, decorations, activeIndex) {
|
|
90
|
+
var decoration = decorations[activeIndex];
|
|
91
|
+
if (!decoration) {
|
|
92
|
+
return function () {};
|
|
93
|
+
}
|
|
94
|
+
var rafId = requestAnimationFrame(function () {
|
|
95
|
+
var _decoration$spec2;
|
|
96
|
+
rafId = null;
|
|
97
|
+
if (((_decoration$spec2 = decoration.spec) === null || _decoration$spec2 === void 0 ? void 0 : _decoration$spec2.key) === 'diff-widget-active') {
|
|
98
|
+
var _decoration$type2;
|
|
99
|
+
// @ts-expect-error - decoration.type is not typed public API
|
|
100
|
+
var widgetDom = decoration === null || decoration === void 0 || (_decoration$type2 = decoration.type) === null || _decoration$type2 === void 0 ? void 0 : _decoration$type2.toDOM;
|
|
101
|
+
scrollToSelection(widgetDom);
|
|
102
|
+
} else {
|
|
103
|
+
var _view$domAtPos2;
|
|
104
|
+
var targetNode = view.nodeDOM(decoration === null || decoration === void 0 ? void 0 : decoration.from);
|
|
105
|
+
var node = targetNode instanceof Element ? targetNode : (_view$domAtPos2 = view.domAtPos(decoration === null || decoration === void 0 ? void 0 : decoration.from)) === null || _view$domAtPos2 === void 0 ? void 0 : _view$domAtPos2.node;
|
|
106
|
+
scrollToSelection(node);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
return function () {
|
|
110
|
+
if (rafId !== null) {
|
|
111
|
+
cancelAnimationFrame(rafId);
|
|
112
|
+
rafId = null;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
};
|
|
@@ -19,6 +19,11 @@ export type ShowDiffPluginState = {
|
|
|
19
19
|
isDisplayingChanges: boolean;
|
|
20
20
|
isInverted?: boolean;
|
|
21
21
|
originalDoc: PMNode | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* When true, the view update handler should scroll to the first decoration
|
|
24
|
+
* and then reset this flag.
|
|
25
|
+
*/
|
|
26
|
+
scrollIntoView?: boolean;
|
|
22
27
|
steps: ProseMirrorStep[];
|
|
23
28
|
};
|
|
24
29
|
export declare const createPlugin: (config: DiffParams | undefined, getIntl: () => IntlShape, api: ExtractInjectionAPI<ShowDiffPlugin> | undefined) => SafePlugin<ShowDiffPluginState>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { EditorView, Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
2
|
+
/**
|
|
3
|
+
* Schedules scrolling to the first diff decoration after the next frame.
|
|
4
|
+
* Unlike `scrollToActiveDecoration`, this does not require an active index —
|
|
5
|
+
* it simply scrolls to bring the first decoration into view.
|
|
6
|
+
*
|
|
7
|
+
* @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
|
|
8
|
+
*/
|
|
9
|
+
export declare const scrollToFirstDecoration: (view: EditorView, decorations: Decoration[]) => (() => void);
|
|
10
|
+
/**
|
|
11
|
+
* Schedules scrolling to the decoration at the given index after the next frame.
|
|
12
|
+
*
|
|
13
|
+
* @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
|
|
14
|
+
*/
|
|
15
|
+
export declare const scrollToActiveDecoration: (view: EditorView, decorations: Decoration[], activeIndex: number) => (() => void);
|
|
@@ -25,6 +25,11 @@ export type PMDiffParams = {
|
|
|
25
25
|
hideDeletedDiffs?: boolean;
|
|
26
26
|
isInverted?: boolean;
|
|
27
27
|
originalDoc: Node;
|
|
28
|
+
/**
|
|
29
|
+
* When true, the editor will scroll to bring the first diff decoration into view
|
|
30
|
+
* after the diff is shown.
|
|
31
|
+
*/
|
|
32
|
+
scrollIntoView?: boolean;
|
|
28
33
|
/**
|
|
29
34
|
* Prosemirror steps. This is used to calculate and show the diff in the editor
|
|
30
35
|
*/
|
|
@@ -19,6 +19,11 @@ export type ShowDiffPluginState = {
|
|
|
19
19
|
isDisplayingChanges: boolean;
|
|
20
20
|
isInverted?: boolean;
|
|
21
21
|
originalDoc: PMNode | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* When true, the view update handler should scroll to the first decoration
|
|
24
|
+
* and then reset this flag.
|
|
25
|
+
*/
|
|
26
|
+
scrollIntoView?: boolean;
|
|
22
27
|
steps: ProseMirrorStep[];
|
|
23
28
|
};
|
|
24
29
|
export declare const createPlugin: (config: DiffParams | undefined, getIntl: () => IntlShape, api: ExtractInjectionAPI<ShowDiffPlugin> | undefined) => SafePlugin<ShowDiffPluginState>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { EditorView, Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
2
|
+
/**
|
|
3
|
+
* Schedules scrolling to the first diff decoration after the next frame.
|
|
4
|
+
* Unlike `scrollToActiveDecoration`, this does not require an active index —
|
|
5
|
+
* it simply scrolls to bring the first decoration into view.
|
|
6
|
+
*
|
|
7
|
+
* @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
|
|
8
|
+
*/
|
|
9
|
+
export declare const scrollToFirstDecoration: (view: EditorView, decorations: Decoration[]) => (() => void);
|
|
10
|
+
/**
|
|
11
|
+
* Schedules scrolling to the decoration at the given index after the next frame.
|
|
12
|
+
*
|
|
13
|
+
* @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
|
|
14
|
+
*/
|
|
15
|
+
export declare const scrollToActiveDecoration: (view: EditorView, decorations: Decoration[], activeIndex: number) => (() => void);
|
|
@@ -25,6 +25,11 @@ export type PMDiffParams = {
|
|
|
25
25
|
hideDeletedDiffs?: boolean;
|
|
26
26
|
isInverted?: boolean;
|
|
27
27
|
originalDoc: Node;
|
|
28
|
+
/**
|
|
29
|
+
* When true, the editor will scroll to bring the first diff decoration into view
|
|
30
|
+
* after the diff is shown.
|
|
31
|
+
*/
|
|
32
|
+
scrollIntoView?: boolean;
|
|
28
33
|
/**
|
|
29
34
|
* Prosemirror steps. This is used to calculate and show the diff in the editor
|
|
30
35
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-show-diff",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.3.0",
|
|
4
4
|
"description": "ShowDiff plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"sideEffects": false,
|
|
29
29
|
"atlaskit:src": "src/index.ts",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@atlaskit/adf-schema": "^52.
|
|
31
|
+
"@atlaskit/adf-schema": "^52.7.0",
|
|
32
32
|
"@atlaskit/custom-steps": "^0.16.0",
|
|
33
33
|
"@atlaskit/editor-plugin-analytics": "^10.0.0",
|
|
34
34
|
"@atlaskit/editor-plugin-expand": "^11.0.0",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"prosemirror-changeset": "^2.3.1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@atlaskit/adf-utils": "^19.
|
|
46
|
+
"@atlaskit/adf-utils": "^19.28.0",
|
|
47
47
|
"@atlaskit/button": "^23.11.0",
|
|
48
48
|
"@atlaskit/css": "^0.19.0",
|
|
49
49
|
"@atlaskit/editor-core": "^219.1.0",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"react-intl": "^6.6.2"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
|
-
"@atlaskit/editor-common": "^114.
|
|
61
|
+
"@atlaskit/editor-common": "^114.14.0",
|
|
62
62
|
"react": "^18.2.0"
|
|
63
63
|
},
|
|
64
64
|
"techstack": {
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.scrollToActiveDecoration = void 0;
|
|
7
|
-
/**
|
|
8
|
-
* Extra space above the scrolled-to element so it does not sit flush under the
|
|
9
|
-
* viewport edge (helps with sticky table headers, toolbars, etc.).
|
|
10
|
-
*
|
|
11
|
-
* Implemented with `scroll-margin-top` so we still use the browser’s native
|
|
12
|
-
* `scrollIntoView`, which scrolls every relevant scrollport (nested containers
|
|
13
|
-
* and the window). A single manual `scrollTop` on one ancestor often misses
|
|
14
|
-
* outer scroll or mis-identifies the active scroll container.
|
|
15
|
-
*/
|
|
16
|
-
var SCROLL_TOP_MARGIN_PX = 100;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Scrolls to the current position/selection of the document. It does the same as scrollIntoView()
|
|
20
|
-
* but without requiring the focus on the editor, thus it can be called at any time.
|
|
21
|
-
*/
|
|
22
|
-
function scrollToSelection(node) {
|
|
23
|
-
var element = node instanceof Element ? node : (node === null || node === void 0 ? void 0 : node.parentElement) instanceof Element ? node.parentElement : null;
|
|
24
|
-
if (!(element instanceof HTMLElement)) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// scroll-margin is included in scroll-into-view math; it does not change layout.
|
|
29
|
-
var previousScrollMarginTop = element.style.scrollMarginTop;
|
|
30
|
-
element.style.scrollMarginTop = "".concat(SCROLL_TOP_MARGIN_PX, "px");
|
|
31
|
-
try {
|
|
32
|
-
element.scrollIntoView({
|
|
33
|
-
behavior: 'smooth',
|
|
34
|
-
block: 'start'
|
|
35
|
-
});
|
|
36
|
-
} finally {
|
|
37
|
-
element.style.scrollMarginTop = previousScrollMarginTop;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Schedules scrolling to the decoration at the given index after the next frame.
|
|
43
|
-
*
|
|
44
|
-
* @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
|
|
45
|
-
*/
|
|
46
|
-
var scrollToActiveDecoration = exports.scrollToActiveDecoration = function scrollToActiveDecoration(view, decorations, activeIndex) {
|
|
47
|
-
var decoration = decorations[activeIndex];
|
|
48
|
-
if (!decoration) {
|
|
49
|
-
return function () {};
|
|
50
|
-
}
|
|
51
|
-
var rafId = requestAnimationFrame(function () {
|
|
52
|
-
var _decoration$spec;
|
|
53
|
-
rafId = null;
|
|
54
|
-
if (((_decoration$spec = decoration.spec) === null || _decoration$spec === void 0 ? void 0 : _decoration$spec.key) === 'diff-widget-active') {
|
|
55
|
-
var _decoration$type;
|
|
56
|
-
// @ts-expect-error - decoration.type is not typed public API
|
|
57
|
-
var widgetDom = decoration === null || decoration === void 0 || (_decoration$type = decoration.type) === null || _decoration$type === void 0 ? void 0 : _decoration$type.toDOM;
|
|
58
|
-
scrollToSelection(widgetDom);
|
|
59
|
-
} else {
|
|
60
|
-
var _view$domAtPos;
|
|
61
|
-
var targetNode = view.nodeDOM(decoration === null || decoration === void 0 ? void 0 : decoration.from);
|
|
62
|
-
var node = targetNode instanceof Element ? targetNode : (_view$domAtPos = view.domAtPos(decoration === null || decoration === void 0 ? void 0 : decoration.from)) === null || _view$domAtPos === void 0 ? void 0 : _view$domAtPos.node;
|
|
63
|
-
scrollToSelection(node);
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
return function () {
|
|
67
|
-
if (rafId !== null) {
|
|
68
|
-
cancelAnimationFrame(rafId);
|
|
69
|
-
rafId = null;
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
};
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extra space above the scrolled-to element so it does not sit flush under the
|
|
3
|
-
* viewport edge (helps with sticky table headers, toolbars, etc.).
|
|
4
|
-
*
|
|
5
|
-
* Implemented with `scroll-margin-top` so we still use the browser’s native
|
|
6
|
-
* `scrollIntoView`, which scrolls every relevant scrollport (nested containers
|
|
7
|
-
* and the window). A single manual `scrollTop` on one ancestor often misses
|
|
8
|
-
* outer scroll or mis-identifies the active scroll container.
|
|
9
|
-
*/
|
|
10
|
-
const SCROLL_TOP_MARGIN_PX = 100;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Scrolls to the current position/selection of the document. It does the same as scrollIntoView()
|
|
14
|
-
* but without requiring the focus on the editor, thus it can be called at any time.
|
|
15
|
-
*/
|
|
16
|
-
function scrollToSelection(node) {
|
|
17
|
-
const element = node instanceof Element ? node : (node === null || node === void 0 ? void 0 : node.parentElement) instanceof Element ? node.parentElement : null;
|
|
18
|
-
if (!(element instanceof HTMLElement)) {
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// scroll-margin is included in scroll-into-view math; it does not change layout.
|
|
23
|
-
const previousScrollMarginTop = element.style.scrollMarginTop;
|
|
24
|
-
element.style.scrollMarginTop = `${SCROLL_TOP_MARGIN_PX}px`;
|
|
25
|
-
try {
|
|
26
|
-
element.scrollIntoView({
|
|
27
|
-
behavior: 'smooth',
|
|
28
|
-
block: 'start'
|
|
29
|
-
});
|
|
30
|
-
} finally {
|
|
31
|
-
element.style.scrollMarginTop = previousScrollMarginTop;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Schedules scrolling to the decoration at the given index after the next frame.
|
|
37
|
-
*
|
|
38
|
-
* @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
|
|
39
|
-
*/
|
|
40
|
-
export const scrollToActiveDecoration = (view, decorations, activeIndex) => {
|
|
41
|
-
const decoration = decorations[activeIndex];
|
|
42
|
-
if (!decoration) {
|
|
43
|
-
return () => {};
|
|
44
|
-
}
|
|
45
|
-
let rafId = requestAnimationFrame(() => {
|
|
46
|
-
var _decoration$spec;
|
|
47
|
-
rafId = null;
|
|
48
|
-
if (((_decoration$spec = decoration.spec) === null || _decoration$spec === void 0 ? void 0 : _decoration$spec.key) === 'diff-widget-active') {
|
|
49
|
-
var _decoration$type;
|
|
50
|
-
// @ts-expect-error - decoration.type is not typed public API
|
|
51
|
-
const widgetDom = decoration === null || decoration === void 0 ? void 0 : (_decoration$type = decoration.type) === null || _decoration$type === void 0 ? void 0 : _decoration$type.toDOM;
|
|
52
|
-
scrollToSelection(widgetDom);
|
|
53
|
-
} else {
|
|
54
|
-
var _view$domAtPos;
|
|
55
|
-
const targetNode = view.nodeDOM(decoration === null || decoration === void 0 ? void 0 : decoration.from);
|
|
56
|
-
const node = targetNode instanceof Element ? targetNode : (_view$domAtPos = view.domAtPos(decoration === null || decoration === void 0 ? void 0 : decoration.from)) === null || _view$domAtPos === void 0 ? void 0 : _view$domAtPos.node;
|
|
57
|
-
scrollToSelection(node);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
return () => {
|
|
61
|
-
if (rafId !== null) {
|
|
62
|
-
cancelAnimationFrame(rafId);
|
|
63
|
-
rafId = null;
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
};
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extra space above the scrolled-to element so it does not sit flush under the
|
|
3
|
-
* viewport edge (helps with sticky table headers, toolbars, etc.).
|
|
4
|
-
*
|
|
5
|
-
* Implemented with `scroll-margin-top` so we still use the browser’s native
|
|
6
|
-
* `scrollIntoView`, which scrolls every relevant scrollport (nested containers
|
|
7
|
-
* and the window). A single manual `scrollTop` on one ancestor often misses
|
|
8
|
-
* outer scroll or mis-identifies the active scroll container.
|
|
9
|
-
*/
|
|
10
|
-
var SCROLL_TOP_MARGIN_PX = 100;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Scrolls to the current position/selection of the document. It does the same as scrollIntoView()
|
|
14
|
-
* but without requiring the focus on the editor, thus it can be called at any time.
|
|
15
|
-
*/
|
|
16
|
-
function scrollToSelection(node) {
|
|
17
|
-
var element = node instanceof Element ? node : (node === null || node === void 0 ? void 0 : node.parentElement) instanceof Element ? node.parentElement : null;
|
|
18
|
-
if (!(element instanceof HTMLElement)) {
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// scroll-margin is included in scroll-into-view math; it does not change layout.
|
|
23
|
-
var previousScrollMarginTop = element.style.scrollMarginTop;
|
|
24
|
-
element.style.scrollMarginTop = "".concat(SCROLL_TOP_MARGIN_PX, "px");
|
|
25
|
-
try {
|
|
26
|
-
element.scrollIntoView({
|
|
27
|
-
behavior: 'smooth',
|
|
28
|
-
block: 'start'
|
|
29
|
-
});
|
|
30
|
-
} finally {
|
|
31
|
-
element.style.scrollMarginTop = previousScrollMarginTop;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Schedules scrolling to the decoration at the given index after the next frame.
|
|
37
|
-
*
|
|
38
|
-
* @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
|
|
39
|
-
*/
|
|
40
|
-
export var scrollToActiveDecoration = function scrollToActiveDecoration(view, decorations, activeIndex) {
|
|
41
|
-
var decoration = decorations[activeIndex];
|
|
42
|
-
if (!decoration) {
|
|
43
|
-
return function () {};
|
|
44
|
-
}
|
|
45
|
-
var rafId = requestAnimationFrame(function () {
|
|
46
|
-
var _decoration$spec;
|
|
47
|
-
rafId = null;
|
|
48
|
-
if (((_decoration$spec = decoration.spec) === null || _decoration$spec === void 0 ? void 0 : _decoration$spec.key) === 'diff-widget-active') {
|
|
49
|
-
var _decoration$type;
|
|
50
|
-
// @ts-expect-error - decoration.type is not typed public API
|
|
51
|
-
var widgetDom = decoration === null || decoration === void 0 || (_decoration$type = decoration.type) === null || _decoration$type === void 0 ? void 0 : _decoration$type.toDOM;
|
|
52
|
-
scrollToSelection(widgetDom);
|
|
53
|
-
} else {
|
|
54
|
-
var _view$domAtPos;
|
|
55
|
-
var targetNode = view.nodeDOM(decoration === null || decoration === void 0 ? void 0 : decoration.from);
|
|
56
|
-
var node = targetNode instanceof Element ? targetNode : (_view$domAtPos = view.domAtPos(decoration === null || decoration === void 0 ? void 0 : decoration.from)) === null || _view$domAtPos === void 0 ? void 0 : _view$domAtPos.node;
|
|
57
|
-
scrollToSelection(node);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
return function () {
|
|
61
|
-
if (rafId !== null) {
|
|
62
|
-
cancelAnimationFrame(rafId);
|
|
63
|
-
rafId = null;
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { EditorView, Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
2
|
-
/**
|
|
3
|
-
* Schedules scrolling to the decoration at the given index after the next frame.
|
|
4
|
-
*
|
|
5
|
-
* @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
|
|
6
|
-
*/
|
|
7
|
-
export declare const scrollToActiveDecoration: (view: EditorView, decorations: Decoration[], activeIndex: number) => (() => void);
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { EditorView, Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
2
|
-
/**
|
|
3
|
-
* Schedules scrolling to the decoration at the given index after the next frame.
|
|
4
|
-
*
|
|
5
|
-
* @returns A function that cancels the scheduled `requestAnimationFrame` if it has not run yet.
|
|
6
|
-
*/
|
|
7
|
-
export declare const scrollToActiveDecoration: (view: EditorView, decorations: Decoration[], activeIndex: number) => (() => void);
|