@ckeditor/ckeditor5-utils 39.0.2 → 40.1.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/LICENSE.md +3 -3
- package/package.json +1 -1
- package/src/collection.d.ts +6 -0
- package/src/collection.js +8 -0
- package/src/config.js +5 -4
- package/src/dom/createelement.d.ts +18 -18
- package/src/dom/position.d.ts +5 -2
- package/src/dom/position.js +91 -83
- package/src/dom/rect.d.ts +5 -1
- package/src/dom/rect.js +93 -7
- package/src/index.d.ts +1 -2
- package/src/index.js +1 -2
- package/src/keyboard.js +2 -2
- package/src/splicearray.d.ts +1 -1
- package/src/version.d.ts +1 -1
- package/src/version.js +2 -2
- package/src/dom/getelementsintersectionrect.d.ts +0 -14
- package/src/dom/getelementsintersectionrect.js +0 -43
- package/src/dom/getscrollableancestors.d.ts +0 -14
- package/src/dom/getscrollableancestors.js +0 -28
package/LICENSE.md
CHANGED
|
@@ -2,7 +2,7 @@ Software License Agreement
|
|
|
2
2
|
==========================
|
|
3
3
|
|
|
4
4
|
**CKEditor 5 utilities** – https://github.com/ckeditor/ckeditor5-utils <br>
|
|
5
|
-
Copyright (c) 2003
|
|
5
|
+
Copyright (c) 2003–2023, [CKSource Holding sp. z o.o.](https://cksource.com) All rights reserved.
|
|
6
6
|
|
|
7
7
|
Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html).
|
|
8
8
|
|
|
@@ -13,9 +13,9 @@ Where not otherwise indicated, all CKEditor content is authored by CKSource engi
|
|
|
13
13
|
|
|
14
14
|
The following libraries are included in CKEditor under the [MIT license](https://opensource.org/licenses/MIT):
|
|
15
15
|
|
|
16
|
-
*
|
|
16
|
+
* Lodash - Copyright (c) JS Foundation and other contributors https://js.foundation/. Based on Underscore.js, copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors http://underscorejs.org/.
|
|
17
17
|
|
|
18
18
|
Trademarks
|
|
19
19
|
----------
|
|
20
20
|
|
|
21
|
-
**CKEditor** is a trademark of [CKSource Holding sp. z o.o.](https://cksource.com) All other brand and product names are trademarks, registered trademarks or service marks of their respective holders.
|
|
21
|
+
**CKEditor** is a trademark of [CKSource Holding sp. z o.o.](https://cksource.com) All other brand and product names are trademarks, registered trademarks, or service marks of their respective holders.
|
package/package.json
CHANGED
package/src/collection.d.ts
CHANGED
|
@@ -188,6 +188,12 @@ export default class Collection<T extends Record<string, any>> extends Collectio
|
|
|
188
188
|
* @returns The result of mapping.
|
|
189
189
|
*/
|
|
190
190
|
map<U>(callback: (item: T, index: number) => U, ctx?: any): Array<U>;
|
|
191
|
+
/**
|
|
192
|
+
* Performs the specified action for each item in the collection.
|
|
193
|
+
*
|
|
194
|
+
* @param ctx Context in which the `callback` will be called.
|
|
195
|
+
*/
|
|
196
|
+
forEach(callback: (item: T, index: number) => unknown, ctx?: any): void;
|
|
191
197
|
/**
|
|
192
198
|
* Finds the first item in the collection for which the `callback` returns a true value.
|
|
193
199
|
*
|
package/src/collection.js
CHANGED
|
@@ -198,6 +198,14 @@ export default class Collection extends EmitterMixin() {
|
|
|
198
198
|
map(callback, ctx) {
|
|
199
199
|
return this._items.map(callback, ctx);
|
|
200
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Performs the specified action for each item in the collection.
|
|
203
|
+
*
|
|
204
|
+
* @param ctx Context in which the `callback` will be called.
|
|
205
|
+
*/
|
|
206
|
+
forEach(callback, ctx) {
|
|
207
|
+
this._items.forEach(callback, ctx);
|
|
208
|
+
}
|
|
201
209
|
/**
|
|
202
210
|
* Finds the first item in the collection for which the `callback` returns a true value.
|
|
203
211
|
*
|
package/src/config.js
CHANGED
|
@@ -151,12 +151,13 @@ export default class Config {
|
|
|
151
151
|
* Clones configuration object or value.
|
|
152
152
|
*/
|
|
153
153
|
function cloneConfig(source) {
|
|
154
|
-
return cloneDeepWith(source,
|
|
154
|
+
return cloneDeepWith(source, leaveItemReferences);
|
|
155
155
|
}
|
|
156
156
|
/**
|
|
157
157
|
* A customized function for cloneDeepWith.
|
|
158
|
-
*
|
|
158
|
+
* In case if it's a DOM Element it will leave references to DOM Elements instead of cloning them.
|
|
159
|
+
* If it's a function it will leave reference to actuall function.
|
|
159
160
|
*/
|
|
160
|
-
function
|
|
161
|
-
return isElement(value) ? value : undefined;
|
|
161
|
+
function leaveItemReferences(value) {
|
|
162
|
+
return isElement(value) || typeof value === 'function' ? value : undefined;
|
|
162
163
|
}
|
|
@@ -18,24 +18,6 @@ type SVGElementAttributes = HTMLElementAttributes & {
|
|
|
18
18
|
* Element or elements that will be added to the created element as children. Strings will be automatically turned into Text nodes.
|
|
19
19
|
*/
|
|
20
20
|
type ChildrenElements = Node | string | Iterable<Node | string>;
|
|
21
|
-
/**
|
|
22
|
-
* Creates an HTML element with attributes and children elements.
|
|
23
|
-
*
|
|
24
|
-
* ```ts
|
|
25
|
-
* createElement( document, 'p' ); // <p>
|
|
26
|
-
* createElement( document, 'p', { class: 'foo' } ); // <p class="foo">
|
|
27
|
-
* createElement( document, 'p', null, 'foo' ); // <p>foo</p>
|
|
28
|
-
* createElement( document, 'p', null, [ createElement(...) ] ); // <p><...></p>
|
|
29
|
-
* ```
|
|
30
|
-
*
|
|
31
|
-
* @label HTML_ELEMENT
|
|
32
|
-
* @param doc Document used to create the element.
|
|
33
|
-
* @param name Name of the HTML element.
|
|
34
|
-
* @param attributes Object where keys represent attribute keys and values represent attribute values.
|
|
35
|
-
* @param children Child or any iterable of children. Strings will be automatically turned into Text nodes.
|
|
36
|
-
* @returns HTML element.
|
|
37
|
-
*/
|
|
38
|
-
export default function createElement<T extends keyof HTMLElementTagNameMap>(doc: Document, name: T, attributes?: HTMLElementAttributes, children?: ChildrenElements): HTMLElementTagNameMap[T];
|
|
39
21
|
/**
|
|
40
22
|
* Creates an SVG element with attributes and children elements.
|
|
41
23
|
*
|
|
@@ -54,4 +36,22 @@ export default function createElement<T extends keyof HTMLElementTagNameMap>(doc
|
|
|
54
36
|
* @returns SVG element.
|
|
55
37
|
*/
|
|
56
38
|
export default function createElement<T extends keyof SVGElementTagNameMap>(doc: Document, name: T, attributes: SVGElementAttributes, children?: ChildrenElements): SVGElementTagNameMap[T];
|
|
39
|
+
/**
|
|
40
|
+
* Creates an HTML element with attributes and children elements.
|
|
41
|
+
*
|
|
42
|
+
* ```ts
|
|
43
|
+
* createElement( document, 'p' ); // <p>
|
|
44
|
+
* createElement( document, 'p', { class: 'foo' } ); // <p class="foo">
|
|
45
|
+
* createElement( document, 'p', null, 'foo' ); // <p>foo</p>
|
|
46
|
+
* createElement( document, 'p', null, [ createElement(...) ] ); // <p><...></p>
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @label HTML_ELEMENT
|
|
50
|
+
* @param doc Document used to create the element.
|
|
51
|
+
* @param name Name of the HTML element.
|
|
52
|
+
* @param attributes Object where keys represent attribute keys and values represent attribute values.
|
|
53
|
+
* @param children Child or any iterable of children. Strings will be automatically turned into Text nodes.
|
|
54
|
+
* @returns HTML element.
|
|
55
|
+
*/
|
|
56
|
+
export default function createElement<T extends keyof HTMLElementTagNameMap>(doc: Document, name: T, attributes?: HTMLElementAttributes, children?: ChildrenElements): HTMLElementTagNameMap[T];
|
|
57
57
|
export {};
|
package/src/dom/position.d.ts
CHANGED
|
@@ -8,6 +8,9 @@ import Rect, { type RectSource } from './rect';
|
|
|
8
8
|
* target in the visually most efficient way, taking various restrictions like viewport or limiter geometry
|
|
9
9
|
* into consideration.
|
|
10
10
|
*
|
|
11
|
+
* **Note**: If there are no position coordinates found that meet the requirements (arguments of this helper),
|
|
12
|
+
* `null` is returned.
|
|
13
|
+
*
|
|
11
14
|
* ```ts
|
|
12
15
|
* // The element which is to be positioned.
|
|
13
16
|
* const element = document.body.querySelector( '#toolbar' );
|
|
@@ -68,7 +71,7 @@ import Rect, { type RectSource } from './rect';
|
|
|
68
71
|
*
|
|
69
72
|
* @param options The input data and configuration of the helper.
|
|
70
73
|
*/
|
|
71
|
-
export declare function getOptimalPosition({ element, target, positions, limiter, fitInViewport, viewportOffsetConfig }: Options): Position;
|
|
74
|
+
export declare function getOptimalPosition({ element, target, positions, limiter, fitInViewport, viewportOffsetConfig }: Options): Position | null;
|
|
72
75
|
/**
|
|
73
76
|
* A position object which instances are created and used by the {@link module:utils/dom/position~getOptimalPosition} helper.
|
|
74
77
|
*
|
|
@@ -179,7 +182,7 @@ export interface Options {
|
|
|
179
182
|
* @param viewportRect The rect of the visual browser viewport.
|
|
180
183
|
* @returns When the function returns `null`, it will not be considered by {@link module:utils/dom/position~getOptimalPosition}.
|
|
181
184
|
*/
|
|
182
|
-
export type PositioningFunction = (elementRect: Rect, targetRect: Rect, viewportRect: Rect
|
|
185
|
+
export type PositioningFunction = (elementRect: Rect, targetRect: Rect, viewportRect: Rect, limiterRect?: Rect) => PositioningFunctionResult | null;
|
|
183
186
|
/**
|
|
184
187
|
* The result of {@link module:utils/dom/position~PositioningFunction}.
|
|
185
188
|
*/
|
package/src/dom/position.js
CHANGED
|
@@ -8,14 +8,47 @@
|
|
|
8
8
|
import global from './global';
|
|
9
9
|
import Rect from './rect';
|
|
10
10
|
import getPositionedAncestor from './getpositionedancestor';
|
|
11
|
-
import getBorderWidths from './getborderwidths';
|
|
12
11
|
import { isFunction } from 'lodash-es';
|
|
13
|
-
// @if CK_DEBUG_POSITION // const
|
|
12
|
+
// @if CK_DEBUG_POSITION // const {
|
|
13
|
+
// @if CK_DEBUG_POSITION // default: RectDrawer,
|
|
14
|
+
// @if CK_DEBUG_POSITION // diagonalStylesBlack,
|
|
15
|
+
// @if CK_DEBUG_POSITION // diagonalStylesGreen,
|
|
16
|
+
// @if CK_DEBUG_POSITION // diagonalStylesRed
|
|
17
|
+
// @if CK_DEBUG_POSITION // } = require( '@ckeditor/ckeditor5-utils/tests/_utils/rectdrawer' );
|
|
18
|
+
// @if CK_DEBUG_POSITION // const TARGET_RECT_STYLE = {
|
|
19
|
+
// @if CK_DEBUG_POSITION // outlineWidth: '2px', outlineStyle: 'dashed', outlineColor: 'blue', outlineOffset: '2px'
|
|
20
|
+
// @if CK_DEBUG_POSITION // };
|
|
21
|
+
// @if CK_DEBUG_POSITION // const VISIBLE_TARGET_RECT_STYLE = {
|
|
22
|
+
// @if CK_DEBUG_POSITION // ...diagonalStylesBlack,
|
|
23
|
+
// @if CK_DEBUG_POSITION // opacity: '1',
|
|
24
|
+
// @if CK_DEBUG_POSITION // backgroundColor: '#00000033',
|
|
25
|
+
// @if CK_DEBUG_POSITION // outlineWidth: '2px'
|
|
26
|
+
// @if CK_DEBUG_POSITION // };
|
|
27
|
+
// @if CK_DEBUG_POSITION // const VIEWPORT_RECT_STYLE = {
|
|
28
|
+
// @if CK_DEBUG_POSITION // outlineWidth: '2px',
|
|
29
|
+
// @if CK_DEBUG_POSITION // outlineOffset: '-2px',
|
|
30
|
+
// @if CK_DEBUG_POSITION // outlineStyle: 'solid',
|
|
31
|
+
// @if CK_DEBUG_POSITION // outlineColor: 'red'
|
|
32
|
+
// @if CK_DEBUG_POSITION // };
|
|
33
|
+
// @if CK_DEBUG_POSITION // const VISIBLE_LIMITER_RECT_STYLE = {
|
|
34
|
+
// @if CK_DEBUG_POSITION // ...diagonalStylesGreen,
|
|
35
|
+
// @if CK_DEBUG_POSITION // outlineWidth: '2px',
|
|
36
|
+
// @if CK_DEBUG_POSITION // outlineOffset: '-2px'
|
|
37
|
+
// @if CK_DEBUG_POSITION // };
|
|
38
|
+
// @if CK_DEBUG_POSITION // const ELEMENT_RECT_STYLE = {
|
|
39
|
+
// @if CK_DEBUG_POSITION // outlineWidth: '2px', outlineColor: 'orange', outlineOffset: '-2px'
|
|
40
|
+
// @if CK_DEBUG_POSITION // };
|
|
41
|
+
// @if CK_DEBUG_POSITION // const CHOSEN_POSITION_RECT_STYLE = {
|
|
42
|
+
// @if CK_DEBUG_POSITION // opacity: .5, outlineColor: 'magenta', backgroundColor: 'magenta'
|
|
43
|
+
// @if CK_DEBUG_POSITION // };
|
|
14
44
|
/**
|
|
15
45
|
* Calculates the `position: absolute` coordinates of a given element so it can be positioned with respect to the
|
|
16
46
|
* target in the visually most efficient way, taking various restrictions like viewport or limiter geometry
|
|
17
47
|
* into consideration.
|
|
18
48
|
*
|
|
49
|
+
* **Note**: If there are no position coordinates found that meet the requirements (arguments of this helper),
|
|
50
|
+
* `null` is returned.
|
|
51
|
+
*
|
|
19
52
|
* ```ts
|
|
20
53
|
* // The element which is to be positioned.
|
|
21
54
|
* const element = document.body.querySelector( '#toolbar' );
|
|
@@ -88,32 +121,56 @@ export function getOptimalPosition({ element, target, positions, limiter, fitInV
|
|
|
88
121
|
limiter = limiter();
|
|
89
122
|
}
|
|
90
123
|
const positionedElementAncestor = getPositionedAncestor(element);
|
|
124
|
+
const constrainedViewportRect = getConstrainedViewportRect(viewportOffsetConfig);
|
|
91
125
|
const elementRect = new Rect(element);
|
|
92
|
-
const
|
|
126
|
+
const visibleTargetRect = getVisibleViewportIntersectionRect(target, constrainedViewportRect);
|
|
93
127
|
let bestPosition;
|
|
128
|
+
// @if CK_DEBUG_POSITION // const targetRect = new Rect( target );
|
|
94
129
|
// @if CK_DEBUG_POSITION // RectDrawer.clear();
|
|
95
|
-
// @if CK_DEBUG_POSITION // RectDrawer.draw( targetRect,
|
|
96
|
-
|
|
97
|
-
|
|
130
|
+
// @if CK_DEBUG_POSITION // RectDrawer.draw( targetRect, TARGET_RECT_STYLE, 'Target' );
|
|
131
|
+
// @if CK_DEBUG_POSITION // if ( constrainedViewportRect ) {
|
|
132
|
+
// @if CK_DEBUG_POSITION // RectDrawer.draw( constrainedViewportRect, VIEWPORT_RECT_STYLE, 'Viewport' );
|
|
133
|
+
// @if CK_DEBUG_POSITION // }
|
|
134
|
+
// If the target got cropped by ancestors or went off the screen, positioning does not make any sense.
|
|
135
|
+
if (!visibleTargetRect || !constrainedViewportRect.getIntersection(visibleTargetRect)) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
// @if CK_DEBUG_POSITION // RectDrawer.draw( visibleTargetRect, VISIBLE_TARGET_RECT_STYLE, 'VisTgt' );
|
|
139
|
+
const positionOptions = {
|
|
140
|
+
targetRect: visibleTargetRect,
|
|
141
|
+
elementRect,
|
|
142
|
+
positionedElementAncestor,
|
|
143
|
+
viewportRect: constrainedViewportRect
|
|
144
|
+
};
|
|
98
145
|
// If there are no limits, just grab the very first position and be done with that drama.
|
|
99
146
|
if (!limiter && !fitInViewport) {
|
|
100
147
|
bestPosition = new PositionObject(positions[0], positionOptions);
|
|
101
148
|
}
|
|
102
149
|
else {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
Object.assign(positionOptions, { limiterRect, viewportRect });
|
|
150
|
+
if (limiter) {
|
|
151
|
+
const visibleLimiterRect = getVisibleViewportIntersectionRect(limiter, constrainedViewportRect);
|
|
152
|
+
if (visibleLimiterRect) {
|
|
153
|
+
positionOptions.limiterRect = visibleLimiterRect;
|
|
154
|
+
// @if CK_DEBUG_POSITION // RectDrawer.draw( visibleLimiterRect, VISIBLE_LIMITER_RECT_STYLE, 'VisLim' );
|
|
155
|
+
}
|
|
156
|
+
}
|
|
111
157
|
// If there's no best position found, i.e. when all intersections have no area because
|
|
112
|
-
// rects have no width or height, then just
|
|
113
|
-
bestPosition = getBestPosition(positions, positionOptions)
|
|
158
|
+
// rects have no width or height, then just return `null`
|
|
159
|
+
bestPosition = getBestPosition(positions, positionOptions);
|
|
114
160
|
}
|
|
115
161
|
return bestPosition;
|
|
116
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* Returns intersection of visible source `Rect` with Viewport `Rect`. In case when source `Rect` is not visible
|
|
165
|
+
* or there is no intersection between source `Rect` and Viewport `Rect`, `null` will be returned.
|
|
166
|
+
*/
|
|
167
|
+
function getVisibleViewportIntersectionRect(source, viewportRect) {
|
|
168
|
+
const visibleSourceRect = new Rect(source).getVisible();
|
|
169
|
+
if (!visibleSourceRect) {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
return visibleSourceRect.getIntersection(viewportRect);
|
|
173
|
+
}
|
|
117
174
|
/**
|
|
118
175
|
* Returns a viewport `Rect` shrunk by the viewport offset config from all sides.
|
|
119
176
|
*/
|
|
@@ -145,61 +202,30 @@ function getBestPosition(positions, options) {
|
|
|
145
202
|
// If a such position is found that element is fully contained by the limiter then, obviously,
|
|
146
203
|
// there will be no better one, so finishing.
|
|
147
204
|
if (limiterIntersectionArea === elementRectArea) {
|
|
205
|
+
// @if CK_DEBUG_POSITION // RectDrawer.draw( position._rect, CHOSEN_POSITION_RECT_STYLE, [
|
|
206
|
+
// @if CK_DEBUG_POSITION // position.name,
|
|
207
|
+
// @if CK_DEBUG_POSITION // '100% fit',
|
|
208
|
+
// @if CK_DEBUG_POSITION // ].join( '\n' ) );
|
|
148
209
|
return position;
|
|
149
210
|
}
|
|
150
211
|
// To maximize both viewport and limiter intersection areas we use distance on _viewportIntersectionArea
|
|
151
212
|
// and _limiterIntersectionArea plane (without sqrt because we are looking for max value).
|
|
152
213
|
const fitFactor = viewportIntersectionArea ** 2 + limiterIntersectionArea ** 2;
|
|
214
|
+
// @if CK_DEBUG_POSITION // RectDrawer.draw( position._rect, { opacity: .4 }, [
|
|
215
|
+
// @if CK_DEBUG_POSITION // position.name,
|
|
216
|
+
// @if CK_DEBUG_POSITION // 'Vi=' + Math.round( viewportIntersectionArea ),
|
|
217
|
+
// @if CK_DEBUG_POSITION // 'Li=' + Math.round( limiterIntersectionArea )
|
|
218
|
+
// @if CK_DEBUG_POSITION // ].join( '\n' ) );
|
|
153
219
|
if (fitFactor > maxFitFactor) {
|
|
154
220
|
maxFitFactor = fitFactor;
|
|
155
221
|
bestPosition = position;
|
|
156
222
|
}
|
|
157
223
|
}
|
|
224
|
+
// @if CK_DEBUG_POSITION // if ( bestPosition ) {
|
|
225
|
+
// @if CK_DEBUG_POSITION // RectDrawer.draw( bestPosition._rect, CHOSEN_POSITION_RECT_STYLE );
|
|
226
|
+
// @if CK_DEBUG_POSITION // }
|
|
158
227
|
return bestPosition;
|
|
159
228
|
}
|
|
160
|
-
/**
|
|
161
|
-
* For a given absolute Rect coordinates object and a positioned element ancestor, it updates its
|
|
162
|
-
* coordinates that make up for the position and the scroll of the ancestor.
|
|
163
|
-
*
|
|
164
|
-
* This is necessary because while Rects (and DOMRects) are relative to the browser's viewport, their coordinates
|
|
165
|
-
* are used in real–life to position elements with `position: absolute`, which are scoped by any positioned
|
|
166
|
-
* (and scrollable) ancestors.
|
|
167
|
-
*/
|
|
168
|
-
function shiftRectToCompensatePositionedAncestor(rect, positionedElementAncestor) {
|
|
169
|
-
const ancestorPosition = getRectForAbsolutePositioning(new Rect(positionedElementAncestor));
|
|
170
|
-
const ancestorBorderWidths = getBorderWidths(positionedElementAncestor);
|
|
171
|
-
let moveX = 0;
|
|
172
|
-
let moveY = 0;
|
|
173
|
-
// (https://github.com/ckeditor/ckeditor5-ui-default/issues/126)
|
|
174
|
-
// If there's some positioned ancestor of the panel, then its `Rect` must be taken into
|
|
175
|
-
// consideration. `Rect` is always relative to the viewport while `position: absolute` works
|
|
176
|
-
// with respect to that positioned ancestor.
|
|
177
|
-
moveX -= ancestorPosition.left;
|
|
178
|
-
moveY -= ancestorPosition.top;
|
|
179
|
-
// (https://github.com/ckeditor/ckeditor5-utils/issues/139)
|
|
180
|
-
// If there's some positioned ancestor of the panel, not only its position must be taken into
|
|
181
|
-
// consideration (see above) but also its internal scrolls. Scroll have an impact here because `Rect`
|
|
182
|
-
// is relative to the viewport (it doesn't care about scrolling), while `position: absolute`
|
|
183
|
-
// must compensate that scrolling.
|
|
184
|
-
moveX += positionedElementAncestor.scrollLeft;
|
|
185
|
-
moveY += positionedElementAncestor.scrollTop;
|
|
186
|
-
// (https://github.com/ckeditor/ckeditor5-utils/issues/139)
|
|
187
|
-
// If there's some positioned ancestor of the panel, then its `Rect` includes its CSS `borderWidth`
|
|
188
|
-
// while `position: absolute` positioning does not consider it.
|
|
189
|
-
// E.g. `{ position: absolute, top: 0, left: 0 }` means upper left corner of the element,
|
|
190
|
-
// not upper-left corner of its border.
|
|
191
|
-
moveX -= ancestorBorderWidths.left;
|
|
192
|
-
moveY -= ancestorBorderWidths.top;
|
|
193
|
-
rect.moveBy(moveX, moveY);
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* DOMRect (also Rect) works in a scroll–independent geometry but `position: absolute` doesn't.
|
|
197
|
-
* This function converts Rect to `position: absolute` coordinates.
|
|
198
|
-
*/
|
|
199
|
-
function getRectForAbsolutePositioning(rect) {
|
|
200
|
-
const { scrollX, scrollY } = global.window;
|
|
201
|
-
return rect.clone().moveBy(scrollX, scrollY);
|
|
202
|
-
}
|
|
203
229
|
/**
|
|
204
230
|
* A position class which instances are created and used by the {@link module:utils/dom/position~getOptimalPosition} helper.
|
|
205
231
|
*
|
|
@@ -221,7 +247,7 @@ class PositionObject {
|
|
|
221
247
|
* @param options.positionedElementAncestor Nearest element ancestor element which CSS position is not "static".
|
|
222
248
|
*/
|
|
223
249
|
constructor(positioningFunction, options) {
|
|
224
|
-
const positioningFunctionOutput = positioningFunction(options.targetRect, options.elementRect, options.viewportRect);
|
|
250
|
+
const positioningFunctionOutput = positioningFunction(options.targetRect, options.elementRect, options.viewportRect, options.limiterRect);
|
|
225
251
|
// Nameless position for a function that didn't participate.
|
|
226
252
|
if (!positioningFunctionOutput) {
|
|
227
253
|
return;
|
|
@@ -229,7 +255,7 @@ class PositionObject {
|
|
|
229
255
|
const { left, top, name, config } = positioningFunctionOutput;
|
|
230
256
|
this.name = name;
|
|
231
257
|
this.config = config;
|
|
232
|
-
this.
|
|
258
|
+
this._positioningFunctionCoordinates = { left, top };
|
|
233
259
|
this._options = options;
|
|
234
260
|
}
|
|
235
261
|
/**
|
|
@@ -252,19 +278,7 @@ class PositionObject {
|
|
|
252
278
|
get limiterIntersectionArea() {
|
|
253
279
|
const limiterRect = this._options.limiterRect;
|
|
254
280
|
if (limiterRect) {
|
|
255
|
-
|
|
256
|
-
if (viewportRect) {
|
|
257
|
-
// Consider only the part of the limiter which is visible in the viewport. So the limiter is getting limited.
|
|
258
|
-
const limiterViewportIntersectRect = limiterRect.getIntersection(viewportRect);
|
|
259
|
-
if (limiterViewportIntersectRect) {
|
|
260
|
-
// If the limiter is within the viewport, then check the intersection between that part of the
|
|
261
|
-
// limiter and actual position.
|
|
262
|
-
return limiterViewportIntersectRect.getIntersectionArea(this._rect);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
else {
|
|
266
|
-
return limiterRect.getIntersectionArea(this._rect);
|
|
267
|
-
}
|
|
281
|
+
return limiterRect.getIntersectionArea(this._rect);
|
|
268
282
|
}
|
|
269
283
|
return 0;
|
|
270
284
|
}
|
|
@@ -273,10 +287,7 @@ class PositionObject {
|
|
|
273
287
|
*/
|
|
274
288
|
get viewportIntersectionArea() {
|
|
275
289
|
const viewportRect = this._options.viewportRect;
|
|
276
|
-
|
|
277
|
-
return viewportRect.getIntersectionArea(this._rect);
|
|
278
|
-
}
|
|
279
|
-
return 0;
|
|
290
|
+
return viewportRect.getIntersectionArea(this._rect);
|
|
280
291
|
}
|
|
281
292
|
/**
|
|
282
293
|
* An already positioned element rect. A clone of the element rect passed to the constructor
|
|
@@ -286,7 +297,7 @@ class PositionObject {
|
|
|
286
297
|
if (this._cachedRect) {
|
|
287
298
|
return this._cachedRect;
|
|
288
299
|
}
|
|
289
|
-
this._cachedRect = this._options.elementRect.clone().moveTo(this.
|
|
300
|
+
this._cachedRect = this._options.elementRect.clone().moveTo(this._positioningFunctionCoordinates.left, this._positioningFunctionCoordinates.top);
|
|
290
301
|
return this._cachedRect;
|
|
291
302
|
}
|
|
292
303
|
/**
|
|
@@ -296,10 +307,7 @@ class PositionObject {
|
|
|
296
307
|
if (this._cachedAbsoluteRect) {
|
|
297
308
|
return this._cachedAbsoluteRect;
|
|
298
309
|
}
|
|
299
|
-
this._cachedAbsoluteRect =
|
|
300
|
-
if (this._options.positionedElementAncestor) {
|
|
301
|
-
shiftRectToCompensatePositionedAncestor(this._cachedAbsoluteRect, this._options.positionedElementAncestor);
|
|
302
|
-
}
|
|
310
|
+
this._cachedAbsoluteRect = this._rect.toAbsoluteRect();
|
|
303
311
|
return this._cachedAbsoluteRect;
|
|
304
312
|
}
|
|
305
313
|
}
|
package/src/dom/rect.d.ts
CHANGED
|
@@ -117,7 +117,7 @@ export default class Rect {
|
|
|
117
117
|
*/
|
|
118
118
|
getArea(): number;
|
|
119
119
|
/**
|
|
120
|
-
* Returns a new rect, a part of the original rect, which is actually visible to the user
|
|
120
|
+
* Returns a new rect, a part of the original rect, which is actually visible to the user and is relative to the,`body`,
|
|
121
121
|
* e.g. an original rect cropped by parent element rects which have `overflow` set in CSS
|
|
122
122
|
* other than `"visible"`.
|
|
123
123
|
*
|
|
@@ -150,6 +150,10 @@ export default class Rect {
|
|
|
150
150
|
* @returns `true` if contains, `false` otherwise.
|
|
151
151
|
*/
|
|
152
152
|
contains(anotherRect: Rect): boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Recalculates screen coordinates to coordinates relative to the positioned ancestor offset.
|
|
155
|
+
*/
|
|
156
|
+
toAbsoluteRect(): Rect;
|
|
153
157
|
/**
|
|
154
158
|
* Excludes scrollbars and CSS borders from the rect.
|
|
155
159
|
*
|
package/src/dom/rect.js
CHANGED
|
@@ -9,6 +9,8 @@ import isRange from './isrange';
|
|
|
9
9
|
import isWindow from './iswindow';
|
|
10
10
|
import getBorderWidths from './getborderwidths';
|
|
11
11
|
import isText from './istext';
|
|
12
|
+
import getPositionedAncestor from './getpositionedancestor';
|
|
13
|
+
import global from './global';
|
|
12
14
|
const rectProperties = ['top', 'right', 'bottom', 'left', 'width', 'height'];
|
|
13
15
|
/**
|
|
14
16
|
* A helper class representing a `ClientRect` object, e.g. value returned by
|
|
@@ -141,7 +143,9 @@ export default class Rect {
|
|
|
141
143
|
return null;
|
|
142
144
|
}
|
|
143
145
|
else {
|
|
144
|
-
|
|
146
|
+
const newRect = new Rect(rect);
|
|
147
|
+
newRect._source = this._source;
|
|
148
|
+
return newRect;
|
|
145
149
|
}
|
|
146
150
|
}
|
|
147
151
|
/**
|
|
@@ -165,7 +169,7 @@ export default class Rect {
|
|
|
165
169
|
return this.width * this.height;
|
|
166
170
|
}
|
|
167
171
|
/**
|
|
168
|
-
* Returns a new rect, a part of the original rect, which is actually visible to the user
|
|
172
|
+
* Returns a new rect, a part of the original rect, which is actually visible to the user and is relative to the,`body`,
|
|
169
173
|
* e.g. an original rect cropped by parent element rects which have `overflow` set in CSS
|
|
170
174
|
* other than `"visible"`.
|
|
171
175
|
*
|
|
@@ -193,14 +197,47 @@ export default class Rect {
|
|
|
193
197
|
let absolutelyPositionedChildElement;
|
|
194
198
|
// Check the ancestors all the way up to the <body>.
|
|
195
199
|
while (parent && !isBody(parent)) {
|
|
200
|
+
const isParentOverflowVisible = getElementOverflow(parent) === 'visible';
|
|
196
201
|
if (child instanceof HTMLElement && getElementPosition(child) === 'absolute') {
|
|
197
202
|
absolutelyPositionedChildElement = child;
|
|
198
203
|
}
|
|
204
|
+
const parentElementPosition = getElementPosition(parent);
|
|
199
205
|
// The child will be cropped only if it has `position: absolute` and the parent has `position: relative` + some overflow.
|
|
200
206
|
// Otherwise there's no chance of visual clipping and the parent can be skipped
|
|
201
207
|
// https://github.com/ckeditor/ckeditor5/issues/14107.
|
|
202
|
-
|
|
203
|
-
|
|
208
|
+
//
|
|
209
|
+
// condition: isParentOverflowVisible
|
|
210
|
+
// +---------------------------+
|
|
211
|
+
// | #parent |
|
|
212
|
+
// | (overflow: visible) |
|
|
213
|
+
// | +-----------+---------------+
|
|
214
|
+
// | | child |
|
|
215
|
+
// | +-----------+---------------+
|
|
216
|
+
// +---------------------------+
|
|
217
|
+
//
|
|
218
|
+
// condition: absolutelyPositionedChildElement && parentElementPosition === 'relative' && isParentOverflowVisible
|
|
219
|
+
// +---------------------------+
|
|
220
|
+
// | parent |
|
|
221
|
+
// | (position: relative;) |
|
|
222
|
+
// | (overflow: visible;) |
|
|
223
|
+
// | +-----------+---------------+
|
|
224
|
+
// | | child |
|
|
225
|
+
// | | (position: absolute;) |
|
|
226
|
+
// | +-----------+---------------+
|
|
227
|
+
// +---------------------------+
|
|
228
|
+
//
|
|
229
|
+
// condition: absolutelyPositionedChildElement && parentElementPosition !== 'relative'
|
|
230
|
+
// +---------------------------+
|
|
231
|
+
// | parent |
|
|
232
|
+
// | (position: static;) |
|
|
233
|
+
// | +-----------+---------------+
|
|
234
|
+
// | | child |
|
|
235
|
+
// | | (position: absolute;) |
|
|
236
|
+
// | +-----------+---------------+
|
|
237
|
+
// +---------------------------+
|
|
238
|
+
if (isParentOverflowVisible ||
|
|
239
|
+
absolutelyPositionedChildElement && ((parentElementPosition === 'relative' && isParentOverflowVisible) ||
|
|
240
|
+
parentElementPosition !== 'relative')) {
|
|
204
241
|
child = parent;
|
|
205
242
|
parent = parent.parentNode;
|
|
206
243
|
continue;
|
|
@@ -248,6 +285,20 @@ export default class Rect {
|
|
|
248
285
|
const intersectRect = this.getIntersection(anotherRect);
|
|
249
286
|
return !!(intersectRect && intersectRect.isEqual(anotherRect));
|
|
250
287
|
}
|
|
288
|
+
/**
|
|
289
|
+
* Recalculates screen coordinates to coordinates relative to the positioned ancestor offset.
|
|
290
|
+
*/
|
|
291
|
+
toAbsoluteRect() {
|
|
292
|
+
const { scrollX, scrollY } = global.window;
|
|
293
|
+
const absoluteRect = this.clone().moveBy(scrollX, scrollY);
|
|
294
|
+
if (isDomElement(absoluteRect._source)) {
|
|
295
|
+
const positionedAncestor = getPositionedAncestor(absoluteRect._source);
|
|
296
|
+
if (positionedAncestor) {
|
|
297
|
+
shiftRectToCompensatePositionedAncestor(absoluteRect, positionedAncestor);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return absoluteRect;
|
|
301
|
+
}
|
|
251
302
|
/**
|
|
252
303
|
* Excludes scrollbars and CSS borders from the rect.
|
|
253
304
|
*
|
|
@@ -378,11 +429,46 @@ function isDomElement(value) {
|
|
|
378
429
|
* Returns the value of the `position` style of an `HTMLElement`.
|
|
379
430
|
*/
|
|
380
431
|
function getElementPosition(element) {
|
|
381
|
-
return element.ownerDocument.defaultView.getComputedStyle(element).position;
|
|
432
|
+
return element instanceof HTMLElement ? element.ownerDocument.defaultView.getComputedStyle(element).position : 'static';
|
|
382
433
|
}
|
|
383
434
|
/**
|
|
384
|
-
* Returns the value of the `overflow` style of an `HTMLElement`.
|
|
435
|
+
* Returns the value of the `overflow` style of an `HTMLElement` or a `Range`.
|
|
385
436
|
*/
|
|
386
437
|
function getElementOverflow(element) {
|
|
387
|
-
return element.ownerDocument.defaultView.getComputedStyle(element).overflow;
|
|
438
|
+
return element instanceof HTMLElement ? element.ownerDocument.defaultView.getComputedStyle(element).overflow : 'visible';
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* For a given absolute Rect coordinates object and a positioned element ancestor, it updates its
|
|
442
|
+
* coordinates that make up for the position and the scroll of the ancestor.
|
|
443
|
+
*
|
|
444
|
+
* This is necessary because while Rects (and DOMRects) are relative to the browser's viewport, their coordinates
|
|
445
|
+
* are used in real–life to position elements with `position: absolute`, which are scoped by any positioned
|
|
446
|
+
* (and scrollable) ancestors.
|
|
447
|
+
*/
|
|
448
|
+
function shiftRectToCompensatePositionedAncestor(rect, positionedElementAncestor) {
|
|
449
|
+
const ancestorPosition = new Rect(positionedElementAncestor);
|
|
450
|
+
const ancestorBorderWidths = getBorderWidths(positionedElementAncestor);
|
|
451
|
+
let moveX = 0;
|
|
452
|
+
let moveY = 0;
|
|
453
|
+
// (https://github.com/ckeditor/ckeditor5-ui-default/issues/126)
|
|
454
|
+
// If there's some positioned ancestor of the panel, then its `Rect` must be taken into
|
|
455
|
+
// consideration. `Rect` is always relative to the viewport while `position: absolute` works
|
|
456
|
+
// with respect to that positioned ancestor.
|
|
457
|
+
moveX -= ancestorPosition.left;
|
|
458
|
+
moveY -= ancestorPosition.top;
|
|
459
|
+
// (https://github.com/ckeditor/ckeditor5-utils/issues/139)
|
|
460
|
+
// If there's some positioned ancestor of the panel, not only its position must be taken into
|
|
461
|
+
// consideration (see above) but also its internal scrolls. Scroll have an impact here because `Rect`
|
|
462
|
+
// is relative to the viewport (it doesn't care about scrolling), while `position: absolute`
|
|
463
|
+
// must compensate that scrolling.
|
|
464
|
+
moveX += positionedElementAncestor.scrollLeft;
|
|
465
|
+
moveY += positionedElementAncestor.scrollTop;
|
|
466
|
+
// (https://github.com/ckeditor/ckeditor5-utils/issues/139)
|
|
467
|
+
// If there's some positioned ancestor of the panel, then its `Rect` includes its CSS `borderWidth`
|
|
468
|
+
// while `position: absolute` positioning does not consider it.
|
|
469
|
+
// E.g. `{ position: absolute, top: 0, left: 0 }` means upper left corner of the element,
|
|
470
|
+
// not upper-left corner of its border.
|
|
471
|
+
moveX -= ancestorBorderWidths.left;
|
|
472
|
+
moveY -= ancestorBorderWidths.top;
|
|
473
|
+
rect.moveBy(moveX, moveY);
|
|
388
474
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -25,9 +25,8 @@ export { default as DomEmitterMixin, type DomEmitter } from './dom/emittermixin'
|
|
|
25
25
|
export { default as findClosestScrollableAncestor } from './dom/findclosestscrollableancestor';
|
|
26
26
|
export { default as global } from './dom/global';
|
|
27
27
|
export { default as getAncestors } from './dom/getancestors';
|
|
28
|
-
export { default as getElementsIntersectionRect } from './dom/getelementsintersectionrect';
|
|
29
|
-
export { default as getScrollableAncestors } from './dom/getscrollableancestors';
|
|
30
28
|
export { default as getDataFromElement } from './dom/getdatafromelement';
|
|
29
|
+
export { default as getBorderWidths } from './dom/getborderwidths';
|
|
31
30
|
export { default as isText } from './dom/istext';
|
|
32
31
|
export { default as Rect, type RectSource } from './dom/rect';
|
|
33
32
|
export { default as ResizeObserver } from './dom/resizeobserver';
|
package/src/index.js
CHANGED
|
@@ -24,9 +24,8 @@ export { default as DomEmitterMixin } from './dom/emittermixin';
|
|
|
24
24
|
export { default as findClosestScrollableAncestor } from './dom/findclosestscrollableancestor';
|
|
25
25
|
export { default as global } from './dom/global';
|
|
26
26
|
export { default as getAncestors } from './dom/getancestors';
|
|
27
|
-
export { default as getElementsIntersectionRect } from './dom/getelementsintersectionrect';
|
|
28
|
-
export { default as getScrollableAncestors } from './dom/getscrollableancestors';
|
|
29
27
|
export { default as getDataFromElement } from './dom/getdatafromelement';
|
|
28
|
+
export { default as getBorderWidths } from './dom/getborderwidths';
|
|
30
29
|
export { default as isText } from './dom/istext';
|
|
31
30
|
export { default as Rect } from './dom/rect';
|
|
32
31
|
export { default as ResizeObserver } from './dom/resizeobserver';
|
package/src/keyboard.js
CHANGED
|
@@ -100,7 +100,7 @@ export function parseKeystroke(keystroke) {
|
|
|
100
100
|
*/
|
|
101
101
|
export function getEnvKeystrokeText(keystroke) {
|
|
102
102
|
let keystrokeCode = parseKeystroke(keystroke);
|
|
103
|
-
const modifiersToGlyphs = Object.entries(env.isMac ? modifiersToGlyphsMac : modifiersToGlyphsNonMac);
|
|
103
|
+
const modifiersToGlyphs = Object.entries((env.isMac || env.isiOS) ? modifiersToGlyphsMac : modifiersToGlyphsNonMac);
|
|
104
104
|
const modifiers = modifiersToGlyphs.reduce((modifiers, [name, glyph]) => {
|
|
105
105
|
// Modifier keys are stored as a bit mask so extract those from the keystroke code.
|
|
106
106
|
if ((keystrokeCode & keyCodes[name]) != 0) {
|
|
@@ -161,7 +161,7 @@ function getEnvKeyCode(key) {
|
|
|
161
161
|
return getCode(key.slice(0, -1));
|
|
162
162
|
}
|
|
163
163
|
const code = getCode(key);
|
|
164
|
-
return env.isMac && code == keyCodes.ctrl ? keyCodes.cmd : code;
|
|
164
|
+
return (env.isMac || env.isiOS) && code == keyCodes.ctrl ? keyCodes.cmd : code;
|
|
165
165
|
}
|
|
166
166
|
/**
|
|
167
167
|
* Determines if the provided key code moves the {@link module:engine/model/documentselection~DocumentSelection selection}
|
package/src/splicearray.d.ts
CHANGED
|
@@ -23,4 +23,4 @@
|
|
|
23
23
|
*
|
|
24
24
|
* @returns New spliced array.
|
|
25
25
|
*/
|
|
26
|
-
export default function spliceArray<T>(target:
|
|
26
|
+
export default function spliceArray<T>(target: ReadonlyArray<T>, source: ReadonlyArray<T>, start: number, count: number): Array<T>;
|
package/src/version.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
|
-
declare const version = "
|
|
5
|
+
declare const version = "40.1.0";
|
|
6
6
|
export default version;
|
|
7
7
|
export declare const releaseDate: Date;
|
|
8
8
|
declare global {
|
package/src/version.js
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
* @module utils/version
|
|
7
7
|
*/
|
|
8
8
|
import CKEditorError from './ckeditorerror';
|
|
9
|
-
const version = '
|
|
9
|
+
const version = '40.1.0';
|
|
10
10
|
export default version;
|
|
11
11
|
// The second argument is not a month. It is `monthIndex` and starts from `0`.
|
|
12
|
-
export const releaseDate = new Date(2023,
|
|
12
|
+
export const releaseDate = new Date(2023, 10, 15);
|
|
13
13
|
/* istanbul ignore next -- @preserve */
|
|
14
14
|
if (globalThis.CKEDITOR_VERSION) {
|
|
15
15
|
/**
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
-
*/
|
|
5
|
-
import Rect from './rect';
|
|
6
|
-
/**
|
|
7
|
-
* Calculates the intersection `Rect` of a given set of elements (and/or a `document`).
|
|
8
|
-
* Also, takes into account the viewport top offset configuration.
|
|
9
|
-
*
|
|
10
|
-
* @internal
|
|
11
|
-
* @param elements
|
|
12
|
-
* @param viewportTopOffset
|
|
13
|
-
*/
|
|
14
|
-
export default function getElementsIntersectionRect(elements: Array<HTMLElement | Document>, viewportTopOffset?: number): Rect | null;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* @module utils/dom/getelementsintersectionrect
|
|
7
|
-
*/
|
|
8
|
-
import global from './global';
|
|
9
|
-
import Rect from './rect';
|
|
10
|
-
/**
|
|
11
|
-
* Calculates the intersection `Rect` of a given set of elements (and/or a `document`).
|
|
12
|
-
* Also, takes into account the viewport top offset configuration.
|
|
13
|
-
*
|
|
14
|
-
* @internal
|
|
15
|
-
* @param elements
|
|
16
|
-
* @param viewportTopOffset
|
|
17
|
-
*/
|
|
18
|
-
export default function getElementsIntersectionRect(elements, viewportTopOffset = 0) {
|
|
19
|
-
const elementRects = elements.map(element => {
|
|
20
|
-
// The document (window) is yet another "element", but cropped by the top offset.
|
|
21
|
-
if (element instanceof Document) {
|
|
22
|
-
const windowRect = new Rect(global.window);
|
|
23
|
-
windowRect.top += viewportTopOffset;
|
|
24
|
-
windowRect.height -= viewportTopOffset;
|
|
25
|
-
return windowRect;
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
return new Rect(element);
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
let intersectionRect = elementRects[0];
|
|
32
|
-
// @if CK_DEBUG_GETELEMENTSINTERSECTIONRECT // for ( const rect of elementRects ) {
|
|
33
|
-
// @if CK_DEBUG_GETELEMENTSINTERSECTIONRECT // RectDrawer.draw( rect, {
|
|
34
|
-
// @if CK_DEBUG_GETELEMENTSINTERSECTIONRECT // outlineWidth: '1px', opacity: '.7', outlineStyle: 'dashed'
|
|
35
|
-
// @if CK_DEBUG_GETELEMENTSINTERSECTIONRECT // }, 'Scrollable element' );
|
|
36
|
-
// @if CK_DEBUG_GETELEMENTSINTERSECTIONRECT // }
|
|
37
|
-
for (const rect of elementRects.slice(1)) {
|
|
38
|
-
if (intersectionRect) {
|
|
39
|
-
intersectionRect = intersectionRect.getIntersection(rect);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return intersectionRect;
|
|
43
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* Loops over the given element's ancestors to find all the scrollable elements.
|
|
7
|
-
*
|
|
8
|
-
* **Note**: The `document` is always included in the returned array.
|
|
9
|
-
*
|
|
10
|
-
* @internal
|
|
11
|
-
* @param element
|
|
12
|
-
* @returns An array of scrollable element's ancestors (including the `document`).
|
|
13
|
-
*/
|
|
14
|
-
export default function getScrollableAncestors(element: HTMLElement): Array<HTMLElement | Document>;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* @module utils/dom/getscrollableancestors
|
|
7
|
-
*/
|
|
8
|
-
import global from './global';
|
|
9
|
-
import findClosestScrollableAncestor from './findclosestscrollableancestor';
|
|
10
|
-
/**
|
|
11
|
-
* Loops over the given element's ancestors to find all the scrollable elements.
|
|
12
|
-
*
|
|
13
|
-
* **Note**: The `document` is always included in the returned array.
|
|
14
|
-
*
|
|
15
|
-
* @internal
|
|
16
|
-
* @param element
|
|
17
|
-
* @returns An array of scrollable element's ancestors (including the `document`).
|
|
18
|
-
*/
|
|
19
|
-
export default function getScrollableAncestors(element) {
|
|
20
|
-
const scrollableAncestors = [];
|
|
21
|
-
let scrollableAncestor = findClosestScrollableAncestor(element);
|
|
22
|
-
while (scrollableAncestor && scrollableAncestor !== global.document.body) {
|
|
23
|
-
scrollableAncestors.push(scrollableAncestor);
|
|
24
|
-
scrollableAncestor = findClosestScrollableAncestor(scrollableAncestor);
|
|
25
|
-
}
|
|
26
|
-
scrollableAncestors.push(global.document);
|
|
27
|
-
return scrollableAncestors;
|
|
28
|
-
}
|