@nguyentc21/react-native-tooltip
Version:
Simple tooltip for React native app
260 lines • 7.92 kB
JavaScript
export const BORDER_SPACE_SIZE = 5;
export const PADDING_SPACE_SIZE = 5;
export const SAFE_CARET_PADDING_SIZE_RATIO = 0.8;
export const RATIO = 1.414;
export const getCaretWidth = caretSize => caretSize * RATIO;
export const getDiffCaretPosition = (caretSize, caretWidth) => (caretWidth - caretSize) * 0.5;
export const getFitData = args => {
const {
targetContentLayout,
tooltipContentLayout,
dimension,
caretSize,
safeAreaInsets
} = args;
const {
height: tooltipHeight,
width: tooltipWidth
} = tooltipContentLayout;
const caretWidth = getCaretWidth(caretSize);
const maxContentHeight = tooltipHeight + caretWidth + PADDING_SPACE_SIZE + BORDER_SPACE_SIZE;
const maxContentWidth = tooltipWidth + caretWidth + PADDING_SPACE_SIZE + BORDER_SPACE_SIZE;
const isFitTop = targetContentLayout.pageY > maxContentHeight + safeAreaInsets.top;
const isFitBottom = dimension.height - targetContentLayout.pageY > maxContentHeight + safeAreaInsets.bottom;
const isFitLeft = targetContentLayout.pageX > maxContentWidth + safeAreaInsets.left;
const isFitRight = dimension.width - targetContentLayout.pageX > maxContentWidth + safeAreaInsets.right;
return {
isFitTop,
isFitBottom,
isFitLeft,
isFitRight
};
};
export const getTheFinalPlacement = args => {
const {
placement,
forcePlacement,
targetContentLayout,
tooltipContentLayout,
dimension,
caretSize,
safeAreaInsets
} = args;
if (!!forcePlacement) return placement;
const {
isFitTop,
isFitBottom,
isFitLeft,
isFitRight
} = getFitData({
targetContentLayout,
tooltipContentLayout,
dimension,
caretSize,
safeAreaInsets
});
let _finalPlacement = placement;
switch (placement) {
case 'top':
if (!isFitTop && isFitBottom) _finalPlacement = 'bottom';
break;
case 'bottom':
if (!isFitBottom && isFitTop) _finalPlacement = 'top';
break;
case 'left':
if (!isFitLeft && isFitRight) _finalPlacement = 'right';
break;
case 'right':
if (!isFitRight && isFitLeft) _finalPlacement = 'left';
break;
default:
break;
}
return _finalPlacement;
};
const getLimitScreenPosition = args => {
const {
dimension,
safeAreaInsets
} = args;
const minPositionTop = BORDER_SPACE_SIZE + safeAreaInsets.top;
const maxPositionTop = dimension.height - (BORDER_SPACE_SIZE + safeAreaInsets.bottom);
const minPositionLeft = BORDER_SPACE_SIZE + safeAreaInsets.left;
const maxPositionLeft = dimension.width - (BORDER_SPACE_SIZE + safeAreaInsets.right);
return {
minTop: minPositionTop,
maxTop: maxPositionTop,
minLeft: minPositionLeft,
maxLeft: maxPositionLeft
};
};
export const getLimitTooltipPosition = args => {
const {
dimension,
tooltipContentLayout,
safeAreaInsets
} = args;
const limitScreenPosition = getLimitScreenPosition({
dimension,
safeAreaInsets
});
return {
...limitScreenPosition,
maxTop: limitScreenPosition.maxTop - tooltipContentLayout.height,
maxLeft: limitScreenPosition.maxLeft - tooltipContentLayout.width
};
};
export const getLimitCaretPosition = args => {
const {
dimension,
caretSize,
safeAreaInsets
} = args;
const caretWidth = getCaretWidth(caretSize);
const diffCaretPosision = getDiffCaretPosition(caretSize, caretWidth);
const limitScreenPosition = getLimitScreenPosition({
dimension,
safeAreaInsets
});
const safeCaretPaddingSize = caretWidth * SAFE_CARET_PADDING_SIZE_RATIO;
return {
minTop: limitScreenPosition.minTop + diffCaretPosision + safeCaretPaddingSize,
maxTop: limitScreenPosition.maxTop - caretWidth + diffCaretPosision - safeCaretPaddingSize,
minLeft: limitScreenPosition.minLeft + diffCaretPosision + safeCaretPaddingSize,
maxLeft: limitScreenPosition.maxLeft - caretWidth + diffCaretPosision - safeCaretPaddingSize
};
};
export const getTooltipPosition = args => {
const {
dimension,
tooltipContentLayout,
targetContentLayout,
caretSize = 0,
placement,
safeAreaInsets
} = args;
const caretWidth = getCaretWidth(caretSize);
const {
height: tooltipHeight,
width: tooltipWidth
} = tooltipContentLayout;
const {
height: targetHeight,
width: targetWidth
} = targetContentLayout;
let top = targetContentLayout.pageY,
left = targetContentLayout.pageX;
switch (placement) {
case 'top':
top = top - (tooltipHeight + caretWidth * 0.5 + PADDING_SPACE_SIZE);
left = left - tooltipWidth * 0.5 + targetWidth * 0.5;
break;
case 'bottom':
top = top + (targetHeight + caretWidth * 0.5 + PADDING_SPACE_SIZE);
left = left - tooltipWidth * 0.5 + targetWidth * 0.5;
break;
case 'left':
top = top - tooltipHeight * 0.5 + targetHeight * 0.5;
left = left - (tooltipWidth + caretWidth * 0.5 + PADDING_SPACE_SIZE);
break;
case 'right':
top = top - tooltipHeight * 0.5 + targetHeight * 0.5;
left = left + (targetWidth + caretWidth * 0.5 + PADDING_SPACE_SIZE);
break;
default:
break;
}
const limitTooltipPosition = getLimitTooltipPosition({
dimension,
tooltipContentLayout,
safeAreaInsets
});
if (top > limitTooltipPosition.maxTop) {
top = limitTooltipPosition.maxTop;
}
if (top < limitTooltipPosition.minTop) {
top = limitTooltipPosition.minTop;
}
if (left > limitTooltipPosition.maxLeft) {
left = limitTooltipPosition.maxLeft;
}
if (left < limitTooltipPosition.minLeft) {
left = limitTooltipPosition.minLeft;
}
return {
top,
left
};
};
export const getCaretPosition = args => {
const {
dimension,
targetContentLayout,
caretSize,
placement,
safeAreaInsets
} = args;
const {
height: targetHeight,
width: targetWidth
} = targetContentLayout;
const caretWidth = getCaretWidth(caretSize);
const diffCaretPosision = getDiffCaretPosition(caretSize, caretWidth);
let caretTop = targetContentLayout.pageY + diffCaretPosision,
caretLeft = targetContentLayout.pageX + diffCaretPosision,
hidden = false;
switch (placement) {
case 'top':
caretTop = caretTop - caretWidth - PADDING_SPACE_SIZE;
caretLeft = caretLeft + (targetWidth * 0.5 - caretWidth * 0.5);
break;
case 'bottom':
caretTop = caretTop + targetHeight + PADDING_SPACE_SIZE;
caretLeft = caretLeft + (targetWidth * 0.5 - caretWidth * 0.5);
break;
case 'left':
caretTop = caretTop + targetHeight * 0.5 - caretWidth * 0.5;
caretLeft = caretLeft - caretWidth - PADDING_SPACE_SIZE;
break;
case 'right':
caretTop = caretTop + targetHeight * 0.5 - caretWidth * 0.5;
caretLeft = caretLeft + targetWidth + PADDING_SPACE_SIZE;
break;
default:
break;
}
const limitCaretPosition = getLimitCaretPosition({
dimension,
caretSize,
safeAreaInsets
});
if (caretTop > limitCaretPosition.maxTop || caretTop < limitCaretPosition.minTop || caretLeft > limitCaretPosition.maxLeft || caretLeft < limitCaretPosition.minLeft) {
hidden = true;
}
return {
top: caretTop,
left: caretLeft,
hidden
};
};
export const checkIsXInsideY = (xMeasure, yMeasure, padding = 0) => {
const {
pageX: x_pageX,
pageY: x_pageY,
width: x_width,
height: x_height
} = xMeasure;
const {
pageX: y_pageX,
pageY: y_pageY,
width: y_width,
height: y_height
} = yMeasure;
const x_minPageX = y_pageX - x_width * 0.5 + padding;
const x_maxPageX = y_pageX + y_width - x_width * 0.5 - padding;
const x_minPageY = y_pageY - x_height * 0.5 + padding;
const x_maxPageY = y_pageY + y_height - x_height * 0.5 - padding;
if (x_pageX >= x_minPageX && x_pageX <= x_maxPageX && x_pageY >= x_minPageY && x_pageY <= x_maxPageY) return true;
return false;
};
//# sourceMappingURL=functions.js.map