@smart-react-components/ui
Version:
SRC UI includes React and Styled components.
214 lines (203 loc) • 7.61 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateCSSTransitionClasses = exports.calculatePosition = void 0;
const types_1 = require("../types");
const dom_1 = require("./dom");
/**
* Calculates the box and arrow position based on X axis.
*/
const calculatePositionBasedOnXAxis = (triggerRect, boxRect, headerRect, pos, space, windowWidth, windowHeight) => {
var _a;
const [arrowWidth, arrowHeight] = getArrowSize(pos);
let left;
let arrowLeft;
let overflow;
if (pos === types_1.Position.RIGHT) {
left = triggerRect.left + triggerRect.width + space + arrowWidth;
overflow = Math.abs(Math.min(windowWidth - (left + boxRect.width), 0));
arrowLeft = (arrowWidth - 2) * -1;
}
else {
left = triggerRect.left - (boxRect.width + arrowWidth + space);
overflow = Math.abs(Math.min(left, 0));
arrowLeft = boxRect.width - 2;
}
const top = headerRect
? (triggerRect.top + (triggerRect.height / 2) - (headerRect.height + (arrowHeight / 2)))
: (triggerRect.top + (triggerRect.height / 2) - (boxRect.height / 2));
const arrowTop = (_a = headerRect === null || headerRect === void 0 ? void 0 : headerRect.height) !== null && _a !== void 0 ? _a : ((boxRect.height - arrowHeight) / 2);
const isArrowInHeader = headerRect && arrowTop + (arrowHeight * 2) < headerRect.height;
if (top < 0) {
overflow += Math.abs(top);
}
else {
overflow += Math.abs(Math.min(windowHeight - (top + boxRect.height), 0));
}
return {
arrowStyle: `
left: ${arrowLeft}px;
top: ${arrowTop}px;
`,
isArrowInHeader,
overflow,
pos,
style: `
left: ${left}px;
top: ${top}px;
`,
};
};
/**
* Calculates the box and arrow position based on Y axis.
*/
const calculatePositionBasedOnYAxis = (triggerRect, boxRect, headerRect, pos, space, windowWidth, windowHeight) => {
const [arrowWidth, arrowHeight] = getArrowSize(pos);
let arrowTop;
let top;
let overflow;
if (pos === types_1.Position.TOP) {
top = triggerRect.top - (boxRect.height + arrowHeight + space);
overflow = Math.abs(Math.min(top, 0));
arrowTop = boxRect.height - 1;
}
else {
top = triggerRect.top + triggerRect.height + space + arrowHeight;
overflow = Math.abs(Math.min(windowHeight - (top + boxRect.height), 0));
arrowTop = (arrowHeight - 1) * -1;
}
const left = (triggerRect.left) + (triggerRect.width / 2) - (boxRect.width / 2);
const arrowLeft = (boxRect.width / 2) - (arrowWidth / 2);
if (left < 0) {
overflow += Math.abs(left);
}
else {
overflow += Math.abs(Math.min(windowWidth - (left + boxRect.width), 0));
}
return {
arrowStyle: `
left: ${arrowLeft}px;
top: ${arrowTop}px;
`,
isArrowInHeader: headerRect && pos === types_1.Position.BOTTOM,
overflow,
pos,
style: `
left: ${left}px;
top: ${top}px;
`,
};
};
/**
* Calculates the box and arrow position.
*/
const calculatePosition = (triggerEl, boxEl, headerEl, arrowEl, position, space) => {
if (!boxEl) {
return;
}
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
const triggerRect = Object.assign(Object.assign({}, triggerEl.getBoundingClientRect()), (0, dom_1.calculateShownPart)(triggerEl));
if (triggerRect.width <= 0 || triggerRect.height <= 0) {
boxEl.setAttribute('style', 'pointer-events: none; visibility: hidden;');
return;
}
boxEl.removeAttribute('style');
const boxRect = boxEl.getBoundingClientRect();
const headerRect = headerEl === null || headerEl === void 0 ? void 0 : headerEl.getBoundingClientRect();
let result;
for (let i = 0, p; i < 4; i++) {
switch (i) {
case 0:
p = position;
break;
case 1:
case 3:
if (p & (types_1.Position.LEFT | types_1.Position.TOP)) {
p <<= 1;
}
else {
p >>= 1;
}
break;
case 2:
if (p & (types_1.Position.LEFT | types_1.Position.RIGHT)) {
p = types_1.Position.TOP;
}
else {
p = types_1.Position.LEFT;
}
break;
}
const r = p & (types_1.Position.LEFT | types_1.Position.RIGHT)
? calculatePositionBasedOnXAxis(triggerRect, boxRect, headerRect, p, space, windowWidth, windowHeight)
: calculatePositionBasedOnYAxis(triggerRect, boxRect, headerRect, p, space, windowWidth, windowHeight);
if (!result || r.overflow < result.overflow) {
result = r;
}
if (result.overflow === 0) {
break;
}
}
boxEl.setAttribute('style', result.style);
boxEl.setAttribute('data-src-position', String(result.pos));
arrowEl.setAttribute('style', result.arrowStyle);
arrowEl.setAttribute('viewBox', getArrowViewBox(result.pos));
arrowEl.setAttribute('data-src-position', String(result.pos));
arrowEl.setAttribute('data-arrow-header', String(result.isArrowInHeader));
};
exports.calculatePosition = calculatePosition;
/**
* Generates CSS transition classes.
*/
const generateCSSTransitionClasses = (key, duration) => `
&.src-${key}-show-active,
&.src-${key}-hide-active {
transition: ${duration}ms 0s ease-in-out;
transition-property: transform, opacity;
}
&.src-${key}-show {
opacity: 0;
&[data-src-position="${types_1.Position.LEFT}"] { transform: translateX(-30px); }
&[data-src-position="${types_1.Position.RIGHT}"] { transform: translateX(30px); }
&[data-src-position="${types_1.Position.TOP}"] { transform: translateY(-30px); }
&[data-src-position="${types_1.Position.BOTTOM}"] { transform: translateY(-30px); }
}
&.src-${key}-show-active {
opacity: 1;
&[data-src-position="${types_1.Position.LEFT}"],
&[data-src-position="${types_1.Position.RIGHT}"] {
transform: translateX(0);
}
&[data-src-position="${types_1.Position.TOP}"],
&[data-src-position="${types_1.Position.BOTTOM}"] {
transform: translateY(0);
}
}
&.src-${key}-hide {
opacity: 1;
&[data-src-position="${types_1.Position.LEFT}"],
&[data-src-position="${types_1.Position.RIGHT}"] {
transform: translateX(0);
}
&[data-src-position="${types_1.Position.TOP}"],
&[data-src-position="${types_1.Position.BOTTOM}"] {
transform: translateY(0);
}
}
&.src-${key}-hide-active {
opacity: 0;
&[data-src-position="${types_1.Position.LEFT}"] { transform: translateX(-30px); }
&[data-src-position="${types_1.Position.RIGHT}"] { transform: translateX(30px); }
&[data-src-position="${types_1.Position.TOP}"] { transform: translateY(-30px); }
&[data-src-position="${types_1.Position.BOTTOM}"] { transform: translateY(-30px); }
}
`;
exports.generateCSSTransitionClasses = generateCSSTransitionClasses;
/**
* Returns width and height attributes depending on position
*/
const getArrowSize = (position) => position & (types_1.Position.LEFT | types_1.Position.RIGHT) ? [10, 15] : [15, 10];
/**
* Returns viewBox attribute depending on position
*/
const getArrowViewBox = (position) => position & (types_1.Position.LEFT | types_1.Position.RIGHT) ? '0 0 252.8 378.5' : '0 0 377.3 251.9';
;