refactor: extract height monitor hook

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Tilman Vatteroth 2023-05-31 20:36:31 +02:00
parent 21b2fb042c
commit 71e5d00f55
3 changed files with 41 additions and 14 deletions

View file

@ -0,0 +1,34 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import useResizeObserver from '@react-hook/resize-observer'
import type { RefObject } from 'react'
import { useEffect, useState } from 'react'
/**
* Monitors the height of the referenced {@link HTMLElement} and executes the callback on change.
*
* @param elementRef The reference that contains the element to watch
* @param onHeightChange The callback that should be executed if the height changes
*/
export const useOnHeightChange = (
elementRef: RefObject<HTMLElement>,
onHeightChange: undefined | ((value: number) => void)
): void => {
const [rendererSize, setRendererSize] = useState<number>(0)
useResizeObserver(elementRef, (entry) => {
setRendererSize(entry.contentRect.height)
})
useEffect(() => {
const value = elementRef.current?.clientHeight
if (value === undefined) {
return
}
setRendererSize(value)
}, [elementRef])
useEffect(() => {
onHeightChange?.(rendererSize + 1)
}, [rendererSize, onHeightChange])
}

View file

@ -11,12 +11,13 @@ import { useCalculateLineMarkerPosition } from '../../../markdown-renderer/hooks
import { useMarkdownExtensions } from '../../../markdown-renderer/hooks/use-markdown-extensions'
import { MarkdownToReact } from '../../../markdown-renderer/markdown-to-react/markdown-to-react'
import { useDocumentSyncScrolling } from '../../hooks/sync-scroll/use-document-sync-scrolling'
import { useOnHeightChange } from '../../hooks/use-on-height-change'
import { RendererType } from '../../window-post-message-communicator/rendering-message'
import type { CommonMarkdownRendererProps, HeightChangeRendererProps } from '../common-markdown-renderer-props'
import { DocumentTocSidebar } from './document-toc-sidebar'
import styles from './markdown-document.module.scss'
import useResizeObserver from '@react-hook/resize-observer'
import React, { useEffect, useMemo, useRef, useState } from 'react'
import React, { useMemo, useRef, useState } from 'react'
export type DocumentMarkdownRendererProps = CommonMarkdownRendererProps & ScrollProps & HeightChangeRendererProps
@ -41,11 +42,7 @@ export const DocumentMarkdownRenderer: React.FC<DocumentMarkdownRendererProps> =
newLinesAreBreaks
}) => {
const rendererRef = useRef<HTMLDivElement | null>(null)
const [rendererSize, setRendererSize] = useState<DOMRectReadOnly>()
useResizeObserver(rendererRef.current, (entry) => {
setRendererSize(entry.contentRect)
})
useEffect(() => onHeightChange?.((rendererSize?.height ?? 0) + 1), [rendererSize, onHeightChange])
useOnHeightChange(rendererRef, onHeightChange)
const internalDocumentRenderPaneRef = useRef<HTMLDivElement>(null)
const [internalDocumentRenderPaneSize, setInternalDocumentRenderPaneSize] = useState<DOMRectReadOnly>()
@ -74,7 +71,7 @@ export const DocumentMarkdownRenderer: React.FC<DocumentMarkdownRendererProps> =
return (
<div
className={`${styles['markdown-document']} vh-100 bg-light`}
className={`${styles['markdown-document']} vh-100`}
ref={internalDocumentRenderPaneRef}
onScroll={onUserScroll}
data-scroll-element={true}

View file

@ -6,10 +6,10 @@
import { cypressId } from '../../../../utils/cypress-attribute'
import { useMarkdownExtensions } from '../../../markdown-renderer/hooks/use-markdown-extensions'
import { MarkdownToReact } from '../../../markdown-renderer/markdown-to-react/markdown-to-react'
import { useOnHeightChange } from '../../hooks/use-on-height-change'
import { RendererType } from '../../window-post-message-communicator/rendering-message'
import type { CommonMarkdownRendererProps, HeightChangeRendererProps } from '../common-markdown-renderer-props'
import useResizeObserver from '@react-hook/resize-observer'
import React, { useEffect, useRef, useState } from 'react'
import React, { useRef } from 'react'
export type SimpleMarkdownRendererProps = CommonMarkdownRendererProps & HeightChangeRendererProps
@ -28,11 +28,7 @@ export const SimpleMarkdownRenderer: React.FC<SimpleMarkdownRendererProps> = ({
newLinesAreBreaks
}) => {
const rendererRef = useRef<HTMLDivElement | null>(null)
const [rendererSize, setRendererSize] = useState<DOMRectReadOnly>()
useResizeObserver(rendererRef.current, (entry) => {
setRendererSize(entry.contentRect)
})
useEffect(() => onHeightChange?.((rendererSize?.height ?? 0) + 1), [rendererSize, onHeightChange])
useOnHeightChange(rendererRef, onHeightChange)
const extensions = useMarkdownExtensions(baseUrl, RendererType.SIMPLE, [])
return (