diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d9353e..5bafb37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unpublished + +### Fixed + +- Position is once again changed if there's overflow (settings permitted) + +### Changed + +- Added new overflow test and tweaked other tests + ## [1.0.2] - 2024-07-30 [Compare to previous release][comp:1.0.2] diff --git a/eslint.config.mjs b/eslint.config.mjs index 4e8582e..c0c2ca0 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -88,7 +88,7 @@ export default [ 'no-floating-decimal': 'warn', 'no-global-assign': 'warn', 'no-implicit-coercion': 'warn', - 'no-implicit-globals': 'warn', + 'no-implicit-globals': 'off', 'no-implied-eval': 'warn', 'no-invalid-this': 'off', 'no-iterator': 'warn', diff --git a/src/index.ts b/src/index.ts index df53821..999c959 100644 --- a/src/index.ts +++ b/src/index.ts @@ -79,10 +79,10 @@ function position(options: IOptions): PositionData { }, } : options.anchor.getBoundingClientRect(), - originalDisplay = options.target.style.display, - _targetRect = options.target.getBoundingClientRect(); + originalDisplay = options.target.style.display; options.target.style.display = 'block'; + const _targetRect = options.target.getBoundingClientRect(); options.target.style.display = originalDisplay; // Adjust to scrollable regions diff --git a/tests/Helpers.ts b/tests/Helpers.ts index 98d34dd..55cfe01 100644 --- a/tests/Helpers.ts +++ b/tests/Helpers.ts @@ -63,6 +63,7 @@ export class Helper { div.style.height = `${this.targetSize.height}px`; div.style.width = `${this.targetSize.width}px`; div.style.position = 'absolute'; + div.style.display = 'none'; document.body.insertAdjacentElement('beforeend', div); } @@ -70,6 +71,7 @@ export class Helper { tP: CombinedAlignment, my?: CombinedAlignment, at?: CombinedAlignment, + onCollision?: (input: number) => number, ) { let left = 0; @@ -116,18 +118,16 @@ export class Helper { } } - if (this.collision === CollisionHandler.ignore) { - return left; - } - - // Work on collision - return left; + return this.collision !== CollisionHandler.ignore && onCollision + ? onCollision(left) + : left; } getTop( tP: CombinedAlignment, my?: CombinedAlignment, at?: CombinedAlignment, + onCollision?: (input: number) => number, ) { let top = 0; @@ -180,12 +180,9 @@ export class Helper { } } - if (this.collision === CollisionHandler.ignore) { - return top; - } - - // Work on collision - return top; + return this.collision !== CollisionHandler.ignore && onCollision + ? onCollision(top) + : top; } /** @@ -216,16 +213,17 @@ export class Helper { targetEl!.getBoundingClientRect = jest.fn(() => { const top = 0, - left = 0; + left = 0, + hiddenSize = targetEl?.style.display === 'none' ? 0 : null; return { x: left, y: top, - width: this.targetSize.width, - height: this.targetSize.height, + width: hiddenSize ?? this.targetSize.width, + height: hiddenSize ?? this.targetSize.height, top: top, - right: left + this.targetSize.width, - bottom: top + this.targetSize.height, + right: left + (hiddenSize ?? this.targetSize.width), + bottom: top + (hiddenSize ?? this.targetSize.height), left: left, toJSON: () => '{}', }; diff --git a/tests/collision.test.ts b/tests/collision.test.ts new file mode 100644 index 0000000..9217d09 --- /dev/null +++ b/tests/collision.test.ts @@ -0,0 +1,45 @@ +import { CollisionHandler, position } from '../src/index'; +import { allData, Helper, SizeData } from './Helpers'; + +const windowSize: SizeData = { + height: 1000, + width: 1000, + }, + anchorSize: SizeData = { + height: 100, + width: 100, + }, + targetSize: SizeData = { + height: 100, + width: 200, + }, + helper = new Helper(CollisionHandler.bestFit, anchorSize, targetSize), + leftCollision: (input: number) => number = () => 800; + +helper.setupEnvironment(windowSize); + +test('Collision changes the output', () => { + const tP = 'center right', + myA = 'top center', + atA = 'bottom center'; + + helper.setupTest(tP); + + const pData = position({ + ...{ debug: true }, + ...{ + my: myA, + at: atA, + target: document.querySelector('.target')!, + anchor: document.querySelector('.anchor')!, + }, + }) as allData; + + expect({ + left: parseInt(pData.left, 10), + top: parseInt(pData.top, 10), + }).toStrictEqual({ + left: helper.getLeft(tP, myA, atA, leftCollision), + top: helper.getTop(tP, myA, atA), + }); +}); diff --git a/tests/index.test.ts b/tests/index.test.ts index 00e5857..63b0f28 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,5 +1,4 @@ import { CollisionHandler, CombinedAlignment, position } from '../src/index'; -// @ts-ignore import { allData, Helper, SizeData } from './Helpers'; const windowSize: SizeData = { @@ -30,18 +29,16 @@ const windowSize: SizeData = { helper.setupEnvironment(windowSize); describe('HoverPosition (collisions ignored)', () => { - // Add base style - describe.each(positionArray)('Target Position: %s', (tP) => { - describe.each(positionArray)('options.my: %s', (myAlignment) => { - test.each(positionArray)('options.at: %s', (atAlignment) => { + describe.each(positionArray)('options.my: %s', (myPlacement) => { + test.each(positionArray)('options.at: %s', (atPlacement) => { helper.setupTest(tP); const pData = position({ ...{ debug: true }, ...{ - my: myAlignment, - at: atAlignment, + my: myPlacement, + at: atPlacement, target: document.querySelector( '.target', )!, @@ -49,18 +46,13 @@ describe('HoverPosition (collisions ignored)', () => { collision: CollisionHandler.ignore, }, }) as allData; - /* - console.log( - `${tP}|${myAlignment}|${atAlignment}`, - pData, - ); - */ + expect({ left: parseInt(pData.left, 10), top: parseInt(pData.top, 10), }).toStrictEqual({ - left: helper.getLeft(tP, myAlignment, atAlignment), - top: helper.getTop(tP, myAlignment, atAlignment), + left: helper.getLeft(tP, myPlacement, atPlacement), + top: helper.getTop(tP, myPlacement, atPlacement), }); }); }); @@ -68,36 +60,37 @@ describe('HoverPosition (collisions ignored)', () => { }); test('Window scroll adjusts output', () => { + // Set the window scroll position window.scrollX = 50; window.scrollY = 50; - - const tP = 'top left', - myA = 'top center', - atA = 'bottom center'; - - helper.setupTest(tP); + + const targetWindowPosition = 'top left', + myPlacement = 'top center', + atPlacement = 'bottom center'; + + helper.setupTest(targetWindowPosition); const pData = position({ ...{ debug: true }, ...{ - my: myA, - at: atA, - target: document.querySelector( - '.target', - )!, + my: myPlacement, + at: atPlacement, + target: document.querySelector('.target')!, anchor: document.querySelector('.anchor')!, collision: CollisionHandler.ignore, }, }) as allData; - + expect({ left: parseInt(pData.left, 10), top: parseInt(pData.top, 10), }).toStrictEqual({ - left: helper.getLeft(tP, myA, atA) + 50, - top: helper.getTop(tP, myA, atA) + 50, + left: + helper.getLeft(targetWindowPosition, myPlacement, atPlacement) + 50, + top: helper.getTop(targetWindowPosition, myPlacement, atPlacement) + 50, }); - - window.scrollX = 50; - window.scrollY = 50; + + // Reset the window scroll position + window.scrollX = 0; + window.scrollY = 0; });