hooks.ts
TLDR
This file, hooks.ts
, contains a single exported function called useMeasurePunchouts
which is used to calculate the dimensions and positions of certain elements on the screen. The function takes in an array of element IDs, an array of additional dependencies, and an optional offset as input, and returns an object representing the dimensions and positions of the elements.
Methods (if applicable)
None
Classes (if applicable)
None
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {useLayoutEffect, useMemo, useState} from 'react'
import throttle from 'lodash/throttle'
import useElementAvailable from './useElementAvailable'
import {TutorialTourTipPunchout} from './tutorial_tour_tip_backdrop'
type PunchoutOffset = {
x: number
y: number
width: number
height: number
}
export function useMeasurePunchouts(elementIds: string[], additionalDeps: any[], offset?: PunchoutOffset): TutorialTourTipPunchout | null | undefined {
const elementsAvailable = useElementAvailable(elementIds)
const [size, setSize] = useState<DOMRect>()
const updateSize = throttle(() => {
setSize(document.getElementById('root')?.getBoundingClientRect())
}, 100)
useLayoutEffect(() => {
window.addEventListener('resize', updateSize)
return () =>
window.removeEventListener('resize', updateSize)
}, [])
const channelPunchout = useMemo(() => {
let minX = Number.MAX_SAFE_INTEGER
let minY = Number.MAX_SAFE_INTEGER
let maxX = Number.MIN_SAFE_INTEGER
let maxY = Number.MIN_SAFE_INTEGER
for (let i = 0; i < elementIds.length; i++) {
const rectangle = document.querySelector(elementIds[i])?.getBoundingClientRect()
if (!rectangle) {
return null
}
if (rectangle.x < minX) {
minX = rectangle.x
}
if (rectangle.y < minY) {
minY = rectangle.y
}
if (rectangle.x + rectangle.width > maxX) {
maxX = rectangle.x + rectangle.width
}
if (rectangle.y + rectangle.height > maxY) {
maxY = rectangle.y + rectangle.height
}
}
return {
x: `${minX + (offset ? offset.x : 0)}px`,
y: `${minY + (offset ? offset.y : 0)}px`,
width: `${(maxX - minX) + (offset ? offset.width : 0)}px`,
height: `${(maxY - minY) + (offset ? offset.height : 0)}px`,
}
}, [...elementIds, ...additionalDeps, size, elementsAvailable])
return channelPunchout
}