UNPKG

@mantine/core

Version:

React components library focused on usability, accessibility and developer experience

1 lines 7.81 kB
{"version":3,"file":"use-floating-indicator.cjs","names":["toInt","getEnv"],"sources":["../../../src/components/FloatingIndicator/use-floating-indicator.ts"],"sourcesContent":["import { useEffect, useRef, useState, type RefObject } from 'react';\nimport { useMutationObserverTarget, useTimeout } from '@mantine/hooks';\nimport { getEnv } from '../../core';\nimport { toInt } from '../ScrollArea/utils';\n\nfunction isParent(\n parentElement: HTMLElement | EventTarget | null,\n childElement: HTMLElement | null\n) {\n if (!childElement || !parentElement) {\n return false;\n }\n\n let parent = childElement.parentNode;\n while (parent != null) {\n if (parent === parentElement) {\n return true;\n }\n parent = parent.parentNode;\n }\n return false;\n}\n\ninterface UseFloatingIndicatorInput {\n target: HTMLElement | null | undefined;\n parent: HTMLElement | null | undefined;\n ref: RefObject<HTMLElement | null>;\n displayAfterTransitionEnd?: boolean;\n onTransitionStart?: () => void;\n onTransitionEnd?: () => void;\n}\n\nexport function useFloatingIndicator({\n target,\n parent,\n ref,\n displayAfterTransitionEnd,\n onTransitionStart,\n onTransitionEnd,\n}: UseFloatingIndicatorInput) {\n const transitionTimeout = useRef<number>(-1);\n const previousTarget = useRef<HTMLElement | null | undefined>(target);\n const [initialized, setInitialized] = useState(false);\n\n const [hidden, setHidden] = useState(\n typeof displayAfterTransitionEnd === 'boolean' ? displayAfterTransitionEnd : false\n );\n\n const updatePosition = () => {\n if (!target || !parent || !ref.current) {\n return;\n }\n\n const targetRect = target.getBoundingClientRect();\n const parentRect = parent.getBoundingClientRect();\n\n const targetComputedStyle = window.getComputedStyle(target);\n const parentComputedStyle = window.getComputedStyle(parent);\n\n const borderTopWidth =\n toInt(targetComputedStyle.borderTopWidth) + toInt(parentComputedStyle.borderTopWidth);\n const borderLeftWidth =\n toInt(targetComputedStyle.borderLeftWidth) + toInt(parentComputedStyle.borderLeftWidth);\n\n const position = {\n top: targetRect.top - parentRect.top - borderTopWidth,\n left: targetRect.left - parentRect.left - borderLeftWidth,\n width: targetRect.width,\n height: targetRect.height,\n };\n\n ref.current.style.transform = `translateY(${position.top}px) translateX(${position.left}px)`;\n ref.current.style.width = `${position.width}px`;\n ref.current.style.height = `${position.height}px`;\n };\n\n const updatePositionWithoutAnimation = () => {\n window.clearTimeout(transitionTimeout.current);\n if (ref.current) {\n ref.current.style.transitionDuration = '0ms';\n }\n updatePosition();\n transitionTimeout.current = window.setTimeout(() => {\n if (ref.current) {\n ref.current.style.transitionDuration = '';\n }\n }, 30);\n };\n\n const targetResizeObserver = useRef<ResizeObserver>(null);\n const parentResizeObserver = useRef<ResizeObserver>(null);\n\n useEffect(() => {\n if (initialized && previousTarget.current !== target && onTransitionStart) {\n onTransitionStart();\n }\n\n previousTarget.current = target;\n updatePosition();\n\n if (target) {\n targetResizeObserver.current = new ResizeObserver(updatePositionWithoutAnimation);\n targetResizeObserver.current.observe(target);\n\n if (parent) {\n parentResizeObserver.current = new ResizeObserver(updatePositionWithoutAnimation);\n parentResizeObserver.current.observe(parent);\n }\n\n return () => {\n targetResizeObserver.current?.disconnect();\n parentResizeObserver.current?.disconnect();\n };\n }\n\n return undefined;\n }, [parent, target]);\n\n useEffect(() => {\n if (parent) {\n const handleTransitionEnd = (event: TransitionEvent) => {\n if (isParent(event.target, parent)) {\n updatePositionWithoutAnimation();\n setHidden(false);\n }\n };\n\n parent.addEventListener('transitionend', handleTransitionEnd);\n return () => {\n parent.removeEventListener('transitionend', handleTransitionEnd);\n };\n }\n\n return undefined;\n }, [parent]);\n\n useEffect(() => {\n if (ref.current && onTransitionEnd) {\n const handleIndicatorTransitionEnd = (event: TransitionEvent) => {\n if (event.propertyName === 'transform') {\n onTransitionEnd();\n }\n };\n\n ref.current.addEventListener('transitionend', handleIndicatorTransitionEnd);\n return () => {\n ref.current?.removeEventListener('transitionend', handleIndicatorTransitionEnd);\n };\n }\n\n return undefined;\n }, [onTransitionEnd]);\n\n useTimeout(\n () => {\n // Prevents warning about state update without act\n if (getEnv() !== 'test') {\n setInitialized(true);\n }\n },\n 20,\n { autoInvoke: true }\n );\n\n useMutationObserverTarget(\n (mutations) => {\n mutations.forEach((mutation) => {\n if (mutation.type === 'attributes' && mutation.attributeName === 'dir') {\n updatePositionWithoutAnimation();\n }\n });\n },\n { attributes: true, attributeFilter: ['dir'] },\n () => document.documentElement\n );\n\n return { initialized, hidden };\n}\n"],"mappings":"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"}