draft-js
Version:
A React framework for building text editors.
80 lines (72 loc) • 1.91 kB
Flow
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict-local
* @emails oncall+draft_js
*/
;
const getRangeClientRects = require("./getRangeClientRects");
export type FakeClientRect = {|
left: number,
width: number,
right: number,
top: number,
bottom: number,
height: number,
|};
/**
* Like range.getBoundingClientRect() but normalizes for browser bugs.
*/
function getRangeBoundingClientRect(range: Range): FakeClientRect {
// "Return a DOMRect object describing the smallest rectangle that includes
// the first rectangle in list and all of the remaining rectangles of which
// the height or width is not zero."
// http://www.w3.org/TR/cssom-view/#dom-range-getboundingclientrect
const rects = getRangeClientRects(range);
let top = 0;
let right = 0;
let bottom = 0;
let left = 0;
if (rects.length) {
// If the first rectangle has 0 width, we use the second, this is needed
// because Chrome renders a 0 width rectangle when the selection contains
// a line break.
if (rects.length > 1 && rects[0].width === 0) {
({
top,
right,
bottom,
left
} = rects[1]);
} else {
({
top,
right,
bottom,
left
} = rects[0]);
}
for (let ii = 1; ii < rects.length; ii++) {
const rect = rects[ii];
if (rect.height !== 0 && rect.width !== 0) {
top = Math.min(top, rect.top);
right = Math.max(right, rect.right);
bottom = Math.max(bottom, rect.bottom);
left = Math.min(left, rect.left);
}
}
}
return {
top,
right,
bottom,
left,
width: right - left,
height: bottom - top
};
}
module.exports = getRangeBoundingClientRect;