Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions packages/flowtip-core/src/Rect.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ class Rect {
* Convert a rect-like object to a Rect instance. This is useful for
* converting non-serializable ClientRect instances to more standard objects.
*
* @param {object} rect A rect-like object.
* @returns {object} A Rect instance.
* @param {Object} rect A rect-like object.
* @returns {Object} A Rect instance.
*/
static from(rect: RectLike): Rect {
if (rect instanceof Rect) return rect;
Expand All @@ -44,9 +44,9 @@ class Rect {
* If the rects do not intersect in either axis, the returned dimension for
* that axis is negative and represents the distance between the rects.
*
* @param {object} a A rect-like object.
* @param {object} b A rect-like object.
* @returns {object} A Rect instance.
* @param {Object} a A rect-like object.
* @param {Object} b A rect-like object.
* @returns {Object} A Rect instance.
*/
static intersect(a: RectLike, b: RectLike): Rect {
const rectA = Rect.from(a);
Expand All @@ -65,9 +65,9 @@ class Rect {
/**
* Expand (or shrink) the boundaries of a rect.
*
* @param {object} rect A rect-like object.
* @param {Object} rect A rect-like object.
* @param {number} amount Offset to apply to each boundary edge.
* @returns {object} A Rect instance.
* @returns {Object} A Rect instance.
*/
static grow(rect: RectLike, amount: number): Rect {
return new Rect(
Expand All @@ -81,8 +81,8 @@ class Rect {
/**
* Determine if two rect-like objects are equal.
*
* @param {object} [a] A rect-like object.
* @param {object} [b] A rect-like object.
* @param {Object} [a] A rect-like object.
* @param {Object} [b] A rect-like object.
* @returns {boolean} True if rects are equal.
*/
static areEqual(a: ?RectLike, b: ?RectLike): boolean {
Expand All @@ -104,6 +104,16 @@ class Rect {
);
}

/**
* Determine if a rect-like object has valid positive area.
*
* @param {Object} [rect] A rect-like object.
* @returns {boolean} True if the rect has a positive area.
*/
static isValid(rect: RectLike): boolean {
return rect.width >= 0 && rect.height >= 0;
}

constructor(left: number, top: number, width: number, height: number): void {
this.left = left;
this.top = top;
Expand Down
32 changes: 18 additions & 14 deletions packages/flowtip-core/src/flowtip.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ type _Regions = {
};
export type Regions = $Shape<_Regions>;
export type Result = {
bounds: Rect,
target: Rect,
region: Region,
reason: Reason,
rect: Rect,
Expand Down Expand Up @@ -69,7 +71,7 @@ export const END: Align = 'end';
*
* @param {Object} config FlowTip layout config object.
* @param {string} region A region (`top`, `right`, `bottom`, or `left`).
* @returns {object} A rect object.
* @returns {Object} A rect object.
*/
function getRect(config: _Config, region: Region): Rect {
const {target, content, align, offset} = config;
Expand Down Expand Up @@ -113,7 +115,7 @@ function getRect(config: _Config, region: Region): Rect {
*
* @param {Object} config FlowTip layout config object.
* @param {string} region A region (`top`, `right`, `bottom`, or `left`).
* @returns {object} A rect object
* @returns {Object} A rect object
*/
function getOffsetBounds(config: _Config, region: Region): Rect {
const {bounds, edgeOffset, offset} = config;
Expand All @@ -133,8 +135,8 @@ function getOffsetBounds(config: _Config, region: Region): Rect {
*
* @param {Object} config FlowTip layout config object.
* @param {string} region A region (`top`, `right`, `bottom`, or `left`).
* @param {object} offsetBounds A final bounds rect for the current region.
* @param {object} rect A content rect object.
* @param {Object} offsetBounds A final bounds rect for the current region.
* @param {Object} rect A content rect object.
* @returns {number} A new left position for the content rect.
*/
function constrainLeft(
Expand Down Expand Up @@ -170,8 +172,8 @@ function constrainLeft(
*
* @param {Object} config FlowTip layout config object.
* @param {string} region A region (`top`, `right`, `bottom`, or `left`).
* @param {object} offsetBounds A final bounds rect for the current region.
* @param {object} rect A content rect object.
* @param {Object} offsetBounds A final bounds rect for the current region.
* @param {Object} rect A content rect object.
* @returns {number} A new top position for the content rect.
*/
function constrainTop(
Expand Down Expand Up @@ -699,8 +701,8 @@ function getRegion(config: _Config, valid: _Regions): [Region, Reason] {
*
* @param {Object} config FlowTip layout config object.
* @param {string} region A region (`top`, `right`, `bottom`, or `left`).
* @param {object} rect A content rect object.
* @returns {object} A repositioned content rect.
* @param {Object} rect A content rect object.
* @returns {Object} A repositioned content rect.
*/
function constrainRect(config: _Config, region: Region, rect: Rect): Rect {
const offsetBounds = getOffsetBounds(config, region);
Expand All @@ -720,7 +722,7 @@ function constrainRect(config: _Config, region: Region, rect: Rect): Rect {
*
* @param {Object} config FlowTip layout config object.
* @param {string} region A region (`top`, `right`, `bottom`, or `left`).
* @param {object} rect A content rect object.
* @param {Object} rect A content rect object.
* @returns {number} Distance between target and content.
*/
function getOffset(config: _Config, region: Region, rect: Rect): number {
Expand All @@ -742,7 +744,7 @@ function getOffset(config: _Config, region: Region, rect: Rect): number {
* Get the current linear overlap between the content rect and the target rect.
*
* @param {string} region A region (`top`, `right`, `bottom`, or `left`).
* @param {object} intersect The intersection rect of the target and content.
* @param {Object} intersect The intersection rect of the target and content.
* @returns {number} Overlap between target and content.
*/
function getOverlap(region: Region, intersect: Rect): number {
Expand Down Expand Up @@ -791,8 +793,8 @@ function getOverlap(region: Region, intersect: Rect): number {
*

* @param {string} region A region (`top`, `right`, `bottom`, or `left`).
* @param {object} rect A content rect object.
* @param {object} intersect The intersection rect of the target and content.
* @param {Object} rect A content rect object.
* @param {Object} intersect The intersection rect of the target and content.
* @returns {number} Distance to overlap center.
*/
function getCenter(region: Region, rect: Rect, intersect: Rect): number {
Expand Down Expand Up @@ -851,8 +853,8 @@ function defaults(config: Config): _Config {
* Calculate a FlowTip layout result.
*
* @param {Object} config FlowTip layout config object.
* @param {object} config.target A rect representing the target element.
* @param {object} config.content A rect representing the content element.
* @param {Object} config.target A rect representing the target element.
* @param {Object} config.content A rect representing the content element.
* @param {string} [config.region] The default region
* (`top`, `right`, `bottom`, or `left`).
* @param {string} config.disabled Disabled regions
Expand Down Expand Up @@ -884,6 +886,8 @@ function flowtip(config: Config): Result {
const overlapCenter = getCenter(region, rect, intersect);

return {
bounds: finalConfig.bounds,
target: finalConfig.target,
region,
reason,
rect,
Expand Down
7 changes: 4 additions & 3 deletions packages/flowtip-react-dom/__test__/FlowTip.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ describe('FlowTip', () => {
let spy;

beforeEach(() => {
spy = jest.spyOn(FlowTip.prototype, '_handleScroll');
spy = jest.spyOn(FlowTip.prototype, '_updateState');
});

afterEach(() => {
Expand All @@ -71,11 +71,12 @@ describe('FlowTip', () => {
attachTo: document.getElementById('root'),
});

expect(spy).toHaveBeenCalledTimes(0);
const count = spy.mock.calls.length;

window.dispatchEvent(new UIEvent('scroll'));

expect(spy).toHaveBeenCalledTimes(1);
expect(spy).toHaveBeenCalledTimes(count + 1);

wrapper.unmount();
});
});
Expand Down
Loading