UNPKG

@clayui/shared

Version:

ClayShared component

110 lines (108 loc) 3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useOverlayPosition = useOverlayPosition; var _react = require("react"); var _doAlign = require("./doAlign"); var _observeRect = require("./observeRect"); /** * SPDX-FileCopyrightText: © 2022 Liferay, Inc. <https://liferay.com> * SPDX-License-Identifier: BSD-3-Clause */ const ALIGN_INVERSE = { 0: 'TopCenter', 1: 'TopRight', 2: 'RightCenter', 3: 'BottomRight', 4: 'BottomCenter', 5: 'BottomLeft', 6: 'LeftCenter', 7: 'TopLeft', 8: 'RightTop', 9: 'RightBottom', 10: 'LeftTop', 11: 'LeftBottom' }; const ALIGN_MAP = { BottomCenter: ['tc', 'bc'], BottomLeft: ['tl', 'bl'], BottomRight: ['tr', 'br'], LeftBottom: ['br', 'bl'], LeftCenter: ['cr', 'cl'], LeftTop: ['tr', 'tl'], RightBottom: ['bl', 'br'], RightCenter: ['cl', 'cr'], RightTop: ['tl', 'tr'], TopCenter: ['bc', 'tc'], TopLeft: ['bl', 'tl'], TopRight: ['br', 'tr'] }; /** * For backwards compatability, we are creating a util here so that `metal-position` * number values are used in the same manner and result in the same alignment direction. */ const getAlignPoints = val => ALIGN_MAP[ALIGN_INVERSE[val]]; const BOTTOM_OFFSET = [0, 4]; const LEFT_OFFSET = [-4, 0]; const RIGHT_OFFSET = [4, 0]; const TOP_OFFSET = [0, -4]; const OFFSET_MAP = { bctc: TOP_OFFSET, blbr: RIGHT_OFFSET, bltl: TOP_OFFSET, brbl: LEFT_OFFSET, brtr: TOP_OFFSET, clcr: RIGHT_OFFSET, crcl: LEFT_OFFSET, tcbc: BOTTOM_OFFSET, tlbl: BOTTOM_OFFSET, tltr: RIGHT_OFFSET, trbr: BOTTOM_OFFSET, trtl: LEFT_OFFSET }; const useIsomorphicLayoutEffect = typeof window === 'undefined' ? _react.useEffect : _react.useLayoutEffect; const defaultOffset = points => OFFSET_MAP[points.join('')]; function useOverlayPosition(_ref) { let { alignmentByViewport, alignmentPosition = 5, autoBestAlign = true, getOffset = defaultOffset, isOpen, ref, triggerRef } = _ref; let deps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [isOpen]; const alignElement = (0, _react.useCallback)(() => { if (triggerRef.current && ref.current) { let points = alignmentPosition; if (typeof points === 'number') { points = getAlignPoints(points); } (0, _doAlign.doAlign)({ offset: getOffset(points), overflow: { adjustX: autoBestAlign, adjustY: autoBestAlign, alwaysByViewport: alignmentByViewport }, points, sourceElement: ref.current, targetElement: triggerRef.current }); } }, []); useIsomorphicLayoutEffect(() => { if (isOpen && triggerRef.current) { alignElement(); return (0, _observeRect.observeRect)(triggerRef.current, alignElement); } }, deps); useIsomorphicLayoutEffect(() => { if (isOpen && ref.current) { alignElement(); return (0, _observeRect.observeRect)(ref.current, alignElement); } }, deps); }