UNPKG

@clayui/shared

Version:

ClayShared component

104 lines (103 loc) 2.84 kB
/** * SPDX-FileCopyrightText: © 2022 Liferay, Inc. <https://liferay.com> * SPDX-License-Identifier: BSD-3-Clause */ import { useCallback, useEffect, useLayoutEffect } from 'react'; import { doAlign } from "./doAlign.js"; import { observeRect } from "./observeRect.js"; 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' ? useEffect : useLayoutEffect; const defaultOffset = points => OFFSET_MAP[points.join('')]; export 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 = useCallback(() => { if (triggerRef.current && ref.current) { let points = alignmentPosition; if (typeof points === 'number') { points = getAlignPoints(points); } 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 observeRect(triggerRef.current, alignElement); } }, deps); useIsomorphicLayoutEffect(() => { if (isOpen && ref.current) { alignElement(); return observeRect(ref.current, alignElement); } }, deps); }