|
|
|
@ -5,23 +5,48 @@ |
|
|
|
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|
|
|
*/ |
|
|
|
|
|
|
|
const POSITION_TOP_CENTER = 'top'; |
|
|
|
const POSITION_TOP_LEFT = 'top-left'; |
|
|
|
const POSITION_TOP_RIGHT = 'top-right'; |
|
|
|
const POSITION_BOTTOM_CENTER = 'bottom'; |
|
|
|
export type RelativePosition = |
|
|
|
'bottom-center' | |
|
|
|
'bottom-left' | |
|
|
|
'bottom-right' | |
|
|
|
'left-bottom' | |
|
|
|
'left-center' | |
|
|
|
'left-top' | |
|
|
|
'right-bottom' | |
|
|
|
'right-center' | |
|
|
|
'right-top' | |
|
|
|
'top-center' | |
|
|
|
'top-left' | |
|
|
|
'top-right'; |
|
|
|
|
|
|
|
const POSITION_BOTTOM_CENTER = 'bottom-center'; |
|
|
|
const POSITION_BOTTOM_LEFT = 'bottom-left'; |
|
|
|
const POSITION_BOTTOM_RIGHT = 'bottom-right'; |
|
|
|
const POSITION_LEFT_CENTER = 'left'; |
|
|
|
const POSITION_LEFT_TOP = 'left-top'; |
|
|
|
const POSITION_LEFT_BOTTOM = 'left-bottom'; |
|
|
|
const POSITION_RIGHT_CENTER = 'right'; |
|
|
|
const POSITION_RIGHT_TOP = 'right-top'; |
|
|
|
const POSITION_LEFT_CENTER = 'left-center'; |
|
|
|
const POSITION_LEFT_TOP = 'left-top'; |
|
|
|
const POSITION_RIGHT_BOTTOM = 'right-bottom'; |
|
|
|
const POSITION_RIGHT_CENTER = 'right-center'; |
|
|
|
const POSITION_RIGHT_TOP = 'right-top'; |
|
|
|
const POSITION_TOP_CENTER = 'top-center'; |
|
|
|
const POSITION_TOP_LEFT = 'top-left'; |
|
|
|
const POSITION_TOP_RIGHT = 'top-right'; |
|
|
|
|
|
|
|
export function positionModal(targetRect: DOMRect, modalRect: DOMRect, relativePosition: string, offset: number, fix: boolean, viewportWidth: number, viewportHeight: number): { x: number; y: number } { |
|
|
|
export type PositionResult = { |
|
|
|
x: number; |
|
|
|
y: number; |
|
|
|
xMax: number; |
|
|
|
yMax: number; |
|
|
|
}; |
|
|
|
|
|
|
|
export function positionModal(targetRect: DOMRect, modalRect: DOMRect, relativePosition: RelativePosition, offset: number, fix: boolean, clientWidth: number, clientHeight: number): PositionResult { |
|
|
|
let y = 0; |
|
|
|
let x = 0; |
|
|
|
|
|
|
|
// Available space in x/y direction.
|
|
|
|
let xMax = 0; |
|
|
|
let yMax = 0; |
|
|
|
|
|
|
|
switch (relativePosition) { |
|
|
|
case POSITION_LEFT_TOP: |
|
|
|
case POSITION_RIGHT_TOP: { |
|
|
|
@ -38,11 +63,18 @@ export function positionModal(targetRect: DOMRect, modalRect: DOMRect, relativeP |
|
|
|
case POSITION_BOTTOM_RIGHT: { |
|
|
|
y = targetRect.bottom + offset; |
|
|
|
|
|
|
|
if (fix && y + modalRect.height > viewportHeight) { |
|
|
|
yMax = clientHeight - y; |
|
|
|
// Unset yMax if we have enough space.
|
|
|
|
if (modalRect.height <= yMax) { |
|
|
|
yMax = 0; |
|
|
|
} else if (fix) { |
|
|
|
// Find a position at the other side of the rect (top).
|
|
|
|
const candidate = targetRect.top - modalRect.height - offset; |
|
|
|
|
|
|
|
if (candidate > 0) { |
|
|
|
y = candidate; |
|
|
|
// Reset space to zero (full space), becuase we fix only if we have the space.
|
|
|
|
yMax = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
@ -52,11 +84,18 @@ export function positionModal(targetRect: DOMRect, modalRect: DOMRect, relativeP |
|
|
|
case POSITION_TOP_RIGHT: { |
|
|
|
y = targetRect.top - modalRect.height - offset; |
|
|
|
|
|
|
|
if (fix && y < 0) { |
|
|
|
yMax = targetRect.top - offset; |
|
|
|
// Unset yMax if we have enough space.
|
|
|
|
if (modalRect.height <= yMax) { |
|
|
|
yMax = 0; |
|
|
|
} else if (fix) { |
|
|
|
// Find a position at the other side of the rect (bottom).
|
|
|
|
const candidate = targetRect.bottom + offset; |
|
|
|
|
|
|
|
if (candidate + modalRect.height < viewportHeight) { |
|
|
|
if (candidate + modalRect.height < clientHeight) { |
|
|
|
y = candidate; |
|
|
|
// Reset space to zero (full space), becuase we fix only if we have the space.
|
|
|
|
yMax = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
@ -83,11 +122,18 @@ export function positionModal(targetRect: DOMRect, modalRect: DOMRect, relativeP |
|
|
|
case POSITION_RIGHT_BOTTOM: { |
|
|
|
x = targetRect.right + offset; |
|
|
|
|
|
|
|
if (fix && x + modalRect.width > viewportWidth) { |
|
|
|
xMax = clientWidth - x; |
|
|
|
// Unset xMax if we have enough space.
|
|
|
|
if (modalRect.width <= xMax) { |
|
|
|
xMax = 0; |
|
|
|
} else if (fix) { |
|
|
|
// Find a position at the other side of the rect (left).
|
|
|
|
const candidate = targetRect.left - modalRect.width - offset; |
|
|
|
|
|
|
|
if (candidate > 0) { |
|
|
|
x = candidate; |
|
|
|
// Reset space to zero (full space), becuase we fix only if we have the space.
|
|
|
|
xMax = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
@ -97,11 +143,18 @@ export function positionModal(targetRect: DOMRect, modalRect: DOMRect, relativeP |
|
|
|
case POSITION_LEFT_BOTTOM: { |
|
|
|
x = targetRect.left - modalRect.width - offset; |
|
|
|
|
|
|
|
if (fix && x < 0) { |
|
|
|
xMax = targetRect.left - offset; |
|
|
|
// Unset xMax if we have enough space.
|
|
|
|
if (modalRect.width <= xMax) { |
|
|
|
xMax = 0; |
|
|
|
} else if (fix) { |
|
|
|
// Find a position at the other side of the rect (right).
|
|
|
|
const candidate = targetRect.right + offset; |
|
|
|
|
|
|
|
if (candidate + modalRect.width < viewportWidth) { |
|
|
|
if (candidate + modalRect.width < clientWidth) { |
|
|
|
x = candidate; |
|
|
|
// Reset space to zero (full space), becuase we fix only if we have the space.
|
|
|
|
xMax = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
@ -112,5 +165,5 @@ export function positionModal(targetRect: DOMRect, modalRect: DOMRect, relativeP |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
return { x, y }; |
|
|
|
return { x, y, xMax, yMax }; |
|
|
|
} |
|
|
|
|