import type { Placement } from './StyledAppCue'; /** * Calculates the position of an element based on its placement relative to a reference position. * * @param {Object} params - The parameters for calculating the position. * @param {Object} params.position - The position and size of target element. * @param {number} params.position.pageX - The X coordinate of the target position. * @param {number} params.position.pageY - The Y coordinate of the target position. * @param {number} params.position.width - The width of the reference element. * @param {number} params.position.height - The height of the reference element. * @param {Object} params.contentSize - The size of the App Cue content. * @param {number} params.contentSize.width - The width of the content. * @param {number} params.contentSize.height - The height of the content. * @param {Placement} params.placement - The placement of the content relative to the reference position ('top', 'bottom', 'right', 'left'). * @param {number} params.offset - The offset distance to display an arrow. * * @returns {Object} The calculated position of the App Cue. * @returns {number} return.x - The X coordinate of the App Cue. * @returns {number} return.y - The Y coordinate of the App Cue. */ export const calculatePosition = ({ placement, position, contentSize, offset, windowWidth, }: { position: { pageX: number; pageY: number; width: number; height: number; }; contentSize: { width: number; height: number; }; placement: Placement; offset: number; windowWidth: number; }): { left?: number; top?: number; bottom?: number; right?: number; } => { switch (placement) { case 'top': { return { // The X coordinate is calculated by adding the half of the width of the target element to the X coordinate of the target element. left: position.pageX + (position.width - contentSize.width) / 2, // The Y coordinate is calculated by subtracting the height of the content and the offset from the Y coordinate of the target element top: position.pageY - contentSize.height - offset, }; } case 'bottom': { return { // The X coordinate is calculated by adding the half of the width of the target element to the X coordinate of the target element. left: position.pageX + (position.width - contentSize.width) / 2, // The Y coordinate is calculated by adding the height of the target element and the offset to the Y coordinate of the target element. top: position.pageY + position.height + offset, }; } case 'right': { return { // The X coordinate is calculated by adding the width of the target element and the offset to the X coordinate of the target element. left: position.pageX + position.width + offset, // The Y coordinate is calculated by adding half of the height of the target element to the Y coordinate of the target element. top: position.pageY + (position.height - contentSize.height) / 2, }; } case 'left': { return { // The X coordinate is calculated by subtracting the width of the content and the offset from the X coordinate of the target element. left: position.pageX - contentSize.width - offset, // The Y coordinate is calculated by adding half of the height of the target element to the Y coordinate of the target element. top: position.pageY + (position.height - contentSize.height) / 2, }; } case 'top-left': { return { // The X coordinate is calculated by subtracting the width of the content from the X coordinate of the target element. right: windowWidth - position.pageX - position.width, // The Y coordinate is calculated by subtracting the height of the content and the offset from the Y coordinate of the target element top: position.pageY - contentSize.height - offset, }; } case 'top-right': { return { // The X coordinate is calculated by adding the width of the target element to the X coordinate of the target element. left: position.pageX, // The Y coordinate is calculated by subtracting the height of the content and the offset from the Y coordinate of the target element. top: position.pageY - contentSize.height - offset, }; } case 'bottom-left': { return { // The X coordinate is calculated by subtracting the width of the content from the X coordinate of the target element. right: windowWidth - position.pageX - position.width, // The Y coordinate is calculated by adding the height of the target element and the offset to the Y coordinate of the target element. top: position.pageY + position.height + offset, }; } case 'bottom-right': { return { // The X coordinate is calculated by adding the width of the target element to the X coordinate of the target element. left: position.pageX, // The Y coordinate is calculated by adding the height of the target element and the offset to the Y coordinate of the target element. top: position.pageY + position.height + offset, }; } } }; /** * Calculates the maximum width of the content based on its position, offset, placement, and window width. * * @param {Object} params - The parameters for the calculation. * @param {Object} params.position - The position and dimensions of the target element. * @param {number} params.position.pageX - The X coordinate of the target element. * @param {number} params.position.pageY - The Y coordinate of the target element. * @param {number} params.position.width - The width of the target element. * @param {number} params.position.height - The height of the target element. * @param {number} params.offset - The offset value to display an arrow. * @param {Placement} params.placement - The placement of the content relative to the element. * @param {number} params.windowWidth - The width of the window. * * @returns {number | undefined} The maximum width of the content. */ export const calulateContentMaxWidth = ({ position, offset, placement, windowWidth, }: { position: { pageX: number; pageY: number; width: number; height: number; }; offset: number; placement: Placement; windowWidth: number; }) => { switch (placement) { case 'top': { return undefined; } case 'bottom': { return undefined; } case 'right': { return windowWidth - position.pageX - position.width - offset; } case 'left': { return position.pageX - offset; } case 'top-left': { return position.pageX + position.width; } case 'top-right': { return windowWidth - position.pageX; } case 'bottom-left': { return position.pageX + position.width; } case 'bottom-right': { return windowWidth - position.pageX; } } };