react-lightning-design-system
Version:
Salesforce Lightning Design System components built with React
388 lines (385 loc) • 19.3 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.AutoAlign = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _react = _interopRequireWildcard(require("react"));
var _classnames = _interopRequireDefault(require("classnames"));
var _reactRelativePortal = _interopRequireDefault(require("react-relative-portal"));
var _ComponentSettings = require("./ComponentSettings");
var _hooks = require("./hooks");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function delay(ms) {
return new Promise(function (resolve) {
setTimeout(resolve, ms);
});
}
function getViewportRect() {
var _ref = window || {},
_ref$innerHeight = _ref.innerHeight,
height = _ref$innerHeight === void 0 ? Infinity : _ref$innerHeight,
_ref$innerWidth = _ref.innerWidth,
width = _ref$innerWidth === void 0 ? Infinity : _ref$innerWidth;
return {
top: 0,
left: 0,
width: width,
height: height
};
}
function calcAlignmentRect(target, rect, alignment) {
var _alignment = (0, _slicedToArray2["default"])(alignment, 2),
firstAlign = _alignment[0],
secondAlign = _alignment[1];
return _objectSpread(_objectSpread({}, rect), {}, {
top: firstAlign === 'top-absolute' || secondAlign === 'top-absolute' ? 0 : firstAlign === 'bottom-absolute' || secondAlign === 'bottom-absolute' ? getViewportRect().height - rect.height : firstAlign === 'top' ? target.top + target.height : firstAlign === 'bottom' ? target.top - rect.height : secondAlign === 'top' ? target.top : secondAlign === 'bottom' ? target.top + target.height - rect.height :
// valign middle
target.top + (target.height - rect.height) * 0.5,
left: firstAlign === 'left-absolute' || secondAlign === 'left-absolute' ? 0 : firstAlign === 'right-absolute' || secondAlign === 'right-absolute' ? getViewportRect().width - rect.width : firstAlign === 'left' ? target.left + target.width : firstAlign === 'right' ? target.left - rect.width : secondAlign === 'left' ? target.left : secondAlign === 'right' ? target.left + target.width - rect.width :
// halign center
target.left + (target.width - rect.width) * 0.5
});
}
function hasViewportIntersection(_ref2) {
var top = _ref2.top,
left = _ref2.left,
width = _ref2.width,
height = _ref2.height;
var _getViewportRect = getViewportRect(),
viewportWidth = _getViewportRect.width,
viewportHeight = _getViewportRect.height;
return top < 0 || top + height > viewportHeight || left < 0 || left + width > viewportWidth;
}
function isEqualRect(aRect, bRect) {
if (aRect === bRect) {
return true;
}
if (!aRect || !bRect) {
return false;
}
return aRect.top === bRect.top && aRect.left === bRect.left && aRect.width === bRect.width && aRect.height === bRect.height;
}
function getCenterPoint(rect) {
return {
x: rect.left + 0.5 * rect.width,
y: rect.top + 0.5 * rect.height
};
}
function getPreferAlignment(rect) {
if (!rect) {
return {
v: 'top',
h: 'left'
};
}
var _getCenterPoint = getCenterPoint(rect),
rx = _getCenterPoint.x,
ry = _getCenterPoint.y;
var _getCenterPoint2 = getCenterPoint(getViewportRect()),
vx = _getCenterPoint2.x,
vy = _getCenterPoint2.y;
return {
h: rx < vx ? 'left' : 'right',
v: ry < vy ? 'top' : 'bottom'
};
}
function throttle(func, ms) {
var last = 0;
return function () {
var now = Date.now();
if (last + ms < now) {
func.apply(void 0, arguments);
last = now;
}
};
}
function ignoreFirstCall(func) {
var called = false;
return function () {
if (called) {
func.apply(void 0, arguments);
}
called = true;
};
}
function removeAbsoluteAlign(alignment) {
return alignment.map(function (a) {
return a.replace(/-absolute$/, '');
});
}
function getPossibleAlignments(alignmentStyle, align, target) {
var _getPreferAlignment = getPreferAlignment(target),
h = _getPreferAlignment.h,
v = _getPreferAlignment.v;
var alignments = [['top', 'left'], ['top', 'right'], ['top'], ['bottom', 'left'], ['bottom', 'right'], ['bottom'], ['left', 'top'], ['left', 'bottom'], ['left'], ['right', 'top'], ['right', 'bottom'], ['right'], ['top', "".concat(h, "-absolute")], ['bottom', "".concat(h, "-absolute")], ['left', "".concat(v, "-absolute")], ['right', "".concat(v, "-absolute")], ["".concat(v, "-absolute"), 'left'], ["".concat(v, "-absolute"), 'right'], ["".concat(h, "-absolute"), 'top'], ["".concat(h, "-absolute"), 'bottom'], ["".concat(v, "-absolute")], ["".concat(h, "-absolute")], ["".concat(v, "-absolute"), "".concat(h, "-absolute")]];
return alignments.filter(function (_ref3) {
var _ref4 = (0, _slicedToArray2["default"])(_ref3, 2),
firstAlign = _ref4[0],
secondAlign = _ref4[1];
return !align || firstAlign === align || secondAlign === align;
}).filter(function (_ref5) {
var _ref6 = (0, _slicedToArray2["default"])(_ref5, 2),
firstAlign = _ref6[0],
secondAlign = _ref6[1];
return alignmentStyle === 'menu' ? secondAlign && /^(top|bottom)/.test(firstAlign) : true;
});
}
var EMPTY_RECT = {
top: 0,
left: 0,
width: 0,
height: 0
};
/**
*
*/
function useAutoAlign(props) {
var _rootNodeRect$top, _rootNodeRect$left;
var triggerSelector = props.triggerSelector,
alignmentStyle = props.alignmentStyle,
align = props.align,
alignment_ = props.alignment;
var pidRef = (0, _react.useRef)(null);
var elRef = (0, _react.useRef)(null);
var autoAlignContentRef = (0, _react.useRef)(null);
var _useControlledValue = (0, _hooks.useControlledValue)(alignment_, getPossibleAlignments(alignmentStyle, align)[0]),
_useControlledValue2 = (0, _slicedToArray2["default"])(_useControlledValue, 2),
alignment = _useControlledValue2[0],
setAlignment = _useControlledValue2[1];
var _useState = (0, _react.useState)(),
_useState2 = (0, _slicedToArray2["default"])(_useState, 2),
rootNodeRect = _useState2[0],
setRootNodeRect = _useState2[1];
var _useState3 = (0, _react.useState)(),
_useState4 = (0, _slicedToArray2["default"])(_useState3, 2),
triggerNodeRect = _useState4[0],
setTriggerNodeRect = _useState4[1];
var updateAlignment = (0, _hooks.useEventCallback)(function () {
var _elRef$current$getBou, _elRef$current, _autoAlignContentRef$, _autoAlignContentRef$2;
var newTriggerNodeRect = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : EMPTY_RECT;
var newRootNodeRect = (_elRef$current$getBou = (_elRef$current = elRef.current) === null || _elRef$current === void 0 ? void 0 : _elRef$current.getBoundingClientRect()) !== null && _elRef$current$getBou !== void 0 ? _elRef$current$getBou : EMPTY_RECT;
var _ref7 = (_autoAlignContentRef$ = (_autoAlignContentRef$2 = autoAlignContentRef.current) === null || _autoAlignContentRef$2 === void 0 ? void 0 : _autoAlignContentRef$2.getBoundingClientRect()) !== null && _autoAlignContentRef$ !== void 0 ? _autoAlignContentRef$ : EMPTY_RECT,
contentRectWidth = _ref7.width,
contentRectHeight = _ref7.height;
var newAlignment = null;
var possibleAlignments = getPossibleAlignments(alignmentStyle, align, newTriggerNodeRect);
var _iterator = _createForOfIteratorHelper(possibleAlignments),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var possibleAlignment = _step.value;
var aRect = calcAlignmentRect(newTriggerNodeRect, {
width: contentRectWidth,
height: contentRectHeight
}, possibleAlignment);
if (!hasViewportIntersection(aRect)) {
newAlignment = possibleAlignment;
break;
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
if (!newAlignment) {
newAlignment = possibleAlignments[possibleAlignments.length - 1];
}
if (newAlignment[0] !== alignment[0] || newAlignment[1] !== alignment[1]) {
setAlignment(newAlignment);
setTriggerNodeRect(newTriggerNodeRect);
setRootNodeRect(newRootNodeRect);
} else if (!triggerNodeRect || newTriggerNodeRect.width !== triggerNodeRect.width || newTriggerNodeRect.height !== triggerNodeRect.height || /absolute$/.test(alignment[0]) || /absolute$/.test(alignment[1] || '')) {
setTriggerNodeRect(newTriggerNodeRect);
setRootNodeRect(newRootNodeRect);
}
});
var recalcAlignment = (0, _hooks.useEventCallback)(function () {
var el = elRef.current;
if (el) {
var _ref8, _el$matches;
var matches = // eslint-disable-next-line @typescript-eslint/unbound-method
(_ref8 = (_el$matches = el.matches) !== null && _el$matches !== void 0 ? _el$matches : el.matchesSelector) !== null && _ref8 !== void 0 ? _ref8 : el.msMatchesSelector;
var triggerEl = el;
try {
while (triggerEl) {
if (matches.call(triggerEl, triggerSelector)) {
break;
}
triggerEl = triggerEl.parentElement;
}
} catch (e) {
triggerEl = null;
}
if (triggerEl) {
var _triggerEl$getBoundin = triggerEl.getBoundingClientRect(),
_top = _triggerEl$getBoundin.top,
_left = _triggerEl$getBoundin.left,
width = _triggerEl$getBoundin.width,
height = _triggerEl$getBoundin.height;
if (!isEqualRect(triggerNodeRect, {
top: _top,
left: _left,
width: width,
height: height
})) {
updateAlignment({
top: _top,
left: _left,
width: width,
height: height
});
} else {
updateAlignment(triggerNodeRect);
}
} else {
updateAlignment(triggerNodeRect);
}
}
});
var requestRecalcAlignment = (0, _react.useMemo)(function () {
return throttle( /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() {
var _pidRef$current;
var pid, _i, _arr, ms;
return _regenerator["default"].wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
pid = ((_pidRef$current = pidRef.current) !== null && _pidRef$current !== void 0 ? _pidRef$current : 0) + 1;
pidRef.current = pid;
_i = 0, _arr = [0, 300, 400, 300, 200];
case 3:
if (!(_i < _arr.length)) {
_context.next = 13;
break;
}
ms = _arr[_i];
_context.next = 7;
return delay(ms);
case 7:
if (!(pidRef.current !== pid)) {
_context.next = 9;
break;
}
return _context.abrupt("return");
case 9:
recalcAlignment();
case 10:
_i++;
_context.next = 3;
break;
case 13:
pidRef.current = 0;
case 14:
case "end":
return _context.stop();
}
}, _callee);
})), 100);
}, [recalcAlignment]);
var onScroll = (0, _react.useMemo)(function () {
return ignoreFirstCall(requestRecalcAlignment);
}, [requestRecalcAlignment]);
var elRefCallback = (0, _react.useCallback)(function (el) {
if (el) {
elRef.current = el;
requestRecalcAlignment();
}
}, [requestRecalcAlignment]);
(0, _react.useEffect)(function () {
return function () {
pidRef.current = null;
};
}, []);
var _calcAlignmentRect = calcAlignmentRect(triggerNodeRect !== null && triggerNodeRect !== void 0 ? triggerNodeRect : EMPTY_RECT, rootNodeRect !== null && rootNodeRect !== void 0 ? rootNodeRect : EMPTY_RECT, alignment),
top = _calcAlignmentRect.top,
left_ = _calcAlignmentRect.left;
var left = left_;
if ((alignment[0] === 'top' || alignment[0] === 'bottom') && !alignment[1]) {
var _triggerNodeRect$left, _triggerNodeRect$widt;
left = ((_triggerNodeRect$left = triggerNodeRect === null || triggerNodeRect === void 0 ? void 0 : triggerNodeRect.left) !== null && _triggerNodeRect$left !== void 0 ? _triggerNodeRect$left : 0) + ((_triggerNodeRect$widt = triggerNodeRect === null || triggerNodeRect === void 0 ? void 0 : triggerNodeRect.width) !== null && _triggerNodeRect$widt !== void 0 ? _triggerNodeRect$widt : 0) * 0.5;
}
var offsetTop = top - ((_rootNodeRect$top = rootNodeRect === null || rootNodeRect === void 0 ? void 0 : rootNodeRect.top) !== null && _rootNodeRect$top !== void 0 ? _rootNodeRect$top : 0);
var offsetLeft = left - ((_rootNodeRect$left = rootNodeRect === null || rootNodeRect === void 0 ? void 0 : rootNodeRect.left) !== null && _rootNodeRect$left !== void 0 ? _rootNodeRect$left : 0);
var returnAlignment = (0, _react.useMemo)(function () {
return removeAbsoluteAlign(alignment);
}, [alignment]);
return {
initialized: triggerNodeRect != null,
alignment: returnAlignment,
offsetTop: offsetTop,
offsetLeft: offsetLeft,
onScroll: onScroll,
elRef: elRefCallback,
autoAlignContentRef: autoAlignContentRef
};
}
/**
*
*/
var AutoAlign = exports.AutoAlign = function AutoAlign(props) {
var preventPortalize = props.preventPortalize,
additionalPortalClassName = props.portalClassName,
_props$portalStyle = props.portalStyle,
additionalPortalStyle = _props$portalStyle === void 0 ? {} : _props$portalStyle,
_props$offsetX = props.offsetX,
offsetX = _props$offsetX === void 0 ? 0 : _props$offsetX,
_props$offsetY = props.offsetY,
offsetY = _props$offsetY === void 0 ? 0 : _props$offsetY,
children = props.children;
var _useAutoAlign = useAutoAlign(props),
initialized = _useAutoAlign.initialized,
alignment = _useAutoAlign.alignment,
offsetLeft = _useAutoAlign.offsetLeft,
offsetTop = _useAutoAlign.offsetTop,
onScroll = _useAutoAlign.onScroll,
elRef = _useAutoAlign.elRef,
autoAlignContentRef = _useAutoAlign.autoAlignContentRef;
var compSettings = (0, _react.useContext)(_ComponentSettings.ComponentSettingsContext);
var _compSettings$portalC = compSettings.portalClassName,
portalClassName = _compSettings$portalC === void 0 ? 'slds-scope' : _compSettings$portalC,
_compSettings$portalS = compSettings.portalStyle,
portalStyle = _compSettings$portalS === void 0 ? {
position: 'absolute',
top: 0,
left: 0,
right: 0
} : _compSettings$portalS;
var adjustedOffsetLeft = offsetLeft + offsetX;
var adjustedOffsetTop = offsetTop + offsetY;
if (typeof children !== 'function') {
return /*#__PURE__*/_react["default"].isValidElement(children) ? children : /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, children);
}
var content = children({
alignment: alignment,
autoAlignContentRef: autoAlignContentRef
});
return preventPortalize || process.env.NODE_ENV === 'test' ? content : /*#__PURE__*/_react["default"].createElement("div", {
ref: elRef
}, /*#__PURE__*/_react["default"].createElement(_reactRelativePortal["default"], {
fullWidth: true,
top: adjustedOffsetTop,
left: adjustedOffsetLeft,
right: -adjustedOffsetLeft,
onScroll: onScroll,
component: "div",
className: (0, _classnames["default"])(portalClassName, additionalPortalClassName),
style: _objectSpread(_objectSpread({}, portalStyle), additionalPortalStyle)
}, /*#__PURE__*/_react["default"].createElement(_ComponentSettings.ComponentSettingsContext.Provider, {
value: compSettings
}, initialized ? content : /*#__PURE__*/_react["default"].createElement("div", {
className: "slds-hidden"
}, content))));
};
//# sourceMappingURL=AutoAlign.js.map