@contember/react-utils
Advanced tools
Comparing version 1.2.1 to 1.2.2
import { useRef, useLayoutEffect } from "react"; | ||
import { useOnWindowResize } from "./useOnWindowResize.js"; | ||
import { useReferentiallyStableCallback } from "../referentiallyStable/useReferentiallyStableCallback.js"; | ||
function intendedFlushOfCSSChangesToCauseImmediateReflow(element) { | ||
element.offsetHeight; | ||
} | ||
function addClassName(className, element) { | ||
if (element.classList.contains(className)) { | ||
element.classList.remove(className); | ||
intendedFlushOfCSSChangesToCauseImmediateReflow(element); | ||
} | ||
@@ -16,3 +12,2 @@ } | ||
element.classList.add(className); | ||
intendedFlushOfCSSChangesToCauseImmediateReflow(element); | ||
} | ||
@@ -19,0 +14,0 @@ } |
@@ -6,3 +6,3 @@ import { px } from "@contember/utilities"; | ||
const useAutoHeightTextArea = (textAreaRef, value, minRows, maxRows) => { | ||
const measure = useCallback((ref, minRows2, maxRows2, value2) => { | ||
const measure = useCallback(async (ref, minRows2, maxRows2) => { | ||
if (ref) { | ||
@@ -18,3 +18,3 @@ const rowsAttribute = ref.rows; | ||
ref.rows = minRows2; | ||
minHeight = ref.offsetHeight; | ||
minHeight = await ref.getBoundingClientRect().height; | ||
if (maxRows2 === Infinity) { | ||
@@ -24,3 +24,3 @@ maxHeight = Infinity; | ||
ref.rows = maxRows2; | ||
maxHeight = ref.offsetHeight; | ||
maxHeight = await ref.getBoundingClientRect().height; | ||
} | ||
@@ -35,6 +35,6 @@ ref.style.height = px(height); | ||
useOnElementResize(textAreaRef, () => { | ||
measure(unwrapRefValue(textAreaRef), minRows, maxRows, value); | ||
measure(unwrapRefValue(textAreaRef), minRows, maxRows); | ||
}); | ||
useLayoutEffect(() => { | ||
measure(unwrapRefValue(textAreaRef), minRows, maxRows, value); | ||
measure(unwrapRefValue(textAreaRef), minRows, maxRows); | ||
}, [maxRows, measure, minRows, textAreaRef, value]); | ||
@@ -41,0 +41,0 @@ }; |
@@ -1,12 +0,7 @@ | ||
import { getSizeFromResizeObserverEntryFactory } from "@contember/utilities"; | ||
import { useMemo, useState, useRef, useLayoutEffect } from "react"; | ||
import { getSizeFromResizeObserverEntryFactory, getElementDimensionsCallback } from "@contember/utilities"; | ||
import { useMemo, useState, useLayoutEffect } from "react"; | ||
import { unwrapRefValue } from "./unwrapRefValue.js"; | ||
import { useOnElementResize } from "./useOnElementResize.js"; | ||
import { useScopedConsoleRef } from "../debug-context/Context.js"; | ||
function getElementWidth(element) { | ||
return element.offsetWidth; | ||
} | ||
function getElementHeight(element) { | ||
return element.offsetHeight; | ||
} | ||
import { useReferentiallyStableCallback } from "../referentiallyStable/useReferentiallyStableCallback.js"; | ||
function useElementSize(refOrElement, options = {}, timeout = 300) { | ||
@@ -16,8 +11,6 @@ const { logged } = useScopedConsoleRef("useElementSize").current; | ||
const getSizeFromResizeObserverEntry = useMemo(() => getSizeFromResizeObserverEntryFactory(box), [box]); | ||
const refValue = unwrapRefValue(refOrElement); | ||
const [width, setWidth] = useState(refValue?.offsetWidth); | ||
const [height, setHeight] = useState(refValue?.offsetHeight); | ||
const [width, setWidth] = useState(); | ||
const [height, setHeight] = useState(); | ||
logged("dimensions", { width, height }); | ||
useOnElementResize(refOrElement, (entry) => { | ||
const dimensions = logged("useOnElementResize => entry:dimensions", getSizeFromResizeObserverEntry(entry)); | ||
const maybeSetNewDimensions = useReferentiallyStableCallback((dimensions) => { | ||
if (width !== dimensions.width) { | ||
@@ -29,15 +22,12 @@ setWidth(dimensions.width); | ||
} | ||
}); | ||
useOnElementResize(refOrElement, (entry) => { | ||
const dimensions = logged("useOnElementResize => entry:dimensions", getSizeFromResizeObserverEntry(entry)); | ||
maybeSetNewDimensions(dimensions); | ||
}, { box }, timeout); | ||
const measure = useRef((element) => { | ||
logged("measure(element)", element); | ||
if (element instanceof HTMLElement) { | ||
setWidth(logged("getElementWidth(element):", getElementWidth(element))); | ||
setHeight(logged("getElementHeight(element):", getElementHeight(element))); | ||
} else if (element) { | ||
throw new Error("Exhaustive error: Expecting element to be instance of HTMLElement or Window"); | ||
} | ||
}); | ||
useLayoutEffect(() => { | ||
const element = unwrapRefValue(refOrElement); | ||
logged("useLayoutEffect => measure", measure.current(element)); | ||
if (element) { | ||
getElementDimensionsCallback(element, (dimensions) => maybeSetNewDimensions(dimensions)); | ||
} | ||
}); | ||
@@ -44,0 +34,0 @@ return { height, width }; |
@@ -12,31 +12,27 @@ import { useRef, useLayoutEffect } from "react"; | ||
const element = unwrapRefValue(refOrElement); | ||
if (element) { | ||
if (element instanceof HTMLElement) { | ||
let debouncedOnChange = function([entry]) { | ||
const timeStamp = Date.now(); | ||
const delta = timeStamp - lastTimeStamp.current; | ||
if (delta > timeout) { | ||
scopedConsoleRef.current.warned("element.resize:immediate", null); | ||
callbackRef.current(entry); | ||
lastTimeStamp.current = timeStamp; | ||
} else { | ||
clearTimeout(timeoutID); | ||
timeoutID = setTimeout(() => { | ||
scopedConsoleRef.current.warned("element.resize:debounced", null); | ||
callbackRef.current(entry); | ||
lastTimeStamp.current = timeStamp; | ||
}, timeout); | ||
} | ||
}; | ||
let timeoutID = void 0; | ||
const resizeObserver = new ResizeObserver(debouncedOnChange); | ||
resizeObserver.observe(element, { box }); | ||
return () => { | ||
clearTimeout(timeoutID); | ||
resizeObserver.unobserve(element); | ||
}; | ||
} else { | ||
throw new Error("Exhaustive error: Expecting element to be instance of HTMLElement"); | ||
} | ||
if (!element) { | ||
return; | ||
} | ||
if (!(element instanceof HTMLElement)) { | ||
throw new Error("Exhaustive error: Expecting element to be instance of HTMLElement"); | ||
} | ||
let timeoutID = void 0; | ||
function debouncedOnChange([entry]) { | ||
const timeStamp = Date.now(); | ||
const delta = timeStamp - lastTimeStamp.current; | ||
clearTimeout(timeoutID); | ||
const timeoutFinal = delta > timeout ? 0 : timeout; | ||
timeoutID = setTimeout(() => { | ||
const message = timeoutFinal > 0 ? "element.resize:debounced" : "element.resize:immediate"; | ||
scopedConsoleRef.current.warned(message, null); | ||
callbackRef.current(entry); | ||
lastTimeStamp.current = timeStamp; | ||
}, timeoutFinal); | ||
} | ||
const resizeObserver = new ResizeObserver(debouncedOnChange); | ||
resizeObserver.observe(element, { box }); | ||
return () => { | ||
clearTimeout(timeoutID); | ||
resizeObserver.unobserve(element); | ||
}; | ||
}, [box, refOrElement, scopedConsoleRef, timeout]); | ||
@@ -43,0 +39,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { assert } from "@contember/utilities"; | ||
import { getElementDimensions, assert } from "@contember/utilities"; | ||
import { useState, useLayoutEffect, useMemo } from "react"; | ||
@@ -31,5 +31,3 @@ import { unwrapRefValue } from "./unwrapRefValue.js"; | ||
if (maybeScrollContent) { | ||
updateScrollOffsetsState( | ||
getElementScrollOffsets(maybeScrollContent) | ||
); | ||
getElementScrollOffsets(maybeScrollContent).then(updateScrollOffsetsState); | ||
} | ||
@@ -54,8 +52,9 @@ }); | ||
} | ||
function getElementScrollOffsets(element) { | ||
async function getElementScrollOffsets(element) { | ||
const isIntrinsicScrolling = isIntrinsicScrollElement(element); | ||
const scrollContainer = getIntrinsicScrollContainer(element); | ||
const { scrollLeft, scrollTop, scrollHeight, scrollWidth } = scrollContainer; | ||
const height = isIntrinsicScrolling ? window.innerHeight : scrollContainer.offsetHeight; | ||
const width = isIntrinsicScrolling ? window.innerWidth : scrollContainer.offsetWidth; | ||
const { height: scrollContainerHeight, width: scrollContainerWidth } = await getElementDimensions(scrollContainer); | ||
const height = isIntrinsicScrolling ? window.innerHeight : scrollContainerHeight; | ||
const width = isIntrinsicScrolling ? window.innerWidth : scrollContainerWidth; | ||
const left = Math.round(scrollLeft); | ||
@@ -62,0 +61,0 @@ const top = Math.round(scrollTop); |
import { useRef, useLayoutEffect } from "react"; | ||
import { useOnWindowResize } from "./useOnWindowResize.js"; | ||
import { useReferentiallyStableCallback } from "../referentiallyStable/useReferentiallyStableCallback.js"; | ||
function intendedFlushOfCSSChangesToCauseImmediateReflow(element) { | ||
element.offsetHeight; | ||
} | ||
function addClassName(className, element) { | ||
if (element.classList.contains(className)) { | ||
element.classList.remove(className); | ||
intendedFlushOfCSSChangesToCauseImmediateReflow(element); | ||
} | ||
@@ -16,3 +12,2 @@ } | ||
element.classList.add(className); | ||
intendedFlushOfCSSChangesToCauseImmediateReflow(element); | ||
} | ||
@@ -19,0 +14,0 @@ } |
@@ -6,3 +6,3 @@ import { px } from "@contember/utilities"; | ||
const useAutoHeightTextArea = (textAreaRef, value, minRows, maxRows) => { | ||
const measure = useCallback((ref, minRows2, maxRows2, value2) => { | ||
const measure = useCallback(async (ref, minRows2, maxRows2) => { | ||
if (ref) { | ||
@@ -18,3 +18,3 @@ const rowsAttribute = ref.rows; | ||
ref.rows = minRows2; | ||
minHeight = ref.offsetHeight; | ||
minHeight = await ref.getBoundingClientRect().height; | ||
if (maxRows2 === Infinity) { | ||
@@ -24,3 +24,3 @@ maxHeight = Infinity; | ||
ref.rows = maxRows2; | ||
maxHeight = ref.offsetHeight; | ||
maxHeight = await ref.getBoundingClientRect().height; | ||
} | ||
@@ -35,6 +35,6 @@ ref.style.height = px(height); | ||
useOnElementResize(textAreaRef, () => { | ||
measure(unwrapRefValue(textAreaRef), minRows, maxRows, value); | ||
measure(unwrapRefValue(textAreaRef), minRows, maxRows); | ||
}); | ||
useLayoutEffect(() => { | ||
measure(unwrapRefValue(textAreaRef), minRows, maxRows, value); | ||
measure(unwrapRefValue(textAreaRef), minRows, maxRows); | ||
}, [maxRows, measure, minRows, textAreaRef, value]); | ||
@@ -41,0 +41,0 @@ }; |
@@ -1,12 +0,7 @@ | ||
import { getSizeFromResizeObserverEntryFactory } from "@contember/utilities"; | ||
import { useMemo, useState, useRef, useLayoutEffect } from "react"; | ||
import { getSizeFromResizeObserverEntryFactory, getElementDimensionsCallback } from "@contember/utilities"; | ||
import { useMemo, useState, useLayoutEffect } from "react"; | ||
import { unwrapRefValue } from "./unwrapRefValue.js"; | ||
import { useOnElementResize } from "./useOnElementResize.js"; | ||
import { useScopedConsoleRef } from "../debug-context/Context.js"; | ||
function getElementWidth(element) { | ||
return element.offsetWidth; | ||
} | ||
function getElementHeight(element) { | ||
return element.offsetHeight; | ||
} | ||
import { useReferentiallyStableCallback } from "../referentiallyStable/useReferentiallyStableCallback.js"; | ||
function useElementSize(refOrElement, options = {}, timeout = 300) { | ||
@@ -16,8 +11,6 @@ const { logged } = useScopedConsoleRef("useElementSize").current; | ||
const getSizeFromResizeObserverEntry = useMemo(() => getSizeFromResizeObserverEntryFactory(box), [box]); | ||
const refValue = unwrapRefValue(refOrElement); | ||
const [width, setWidth] = useState(refValue?.offsetWidth); | ||
const [height, setHeight] = useState(refValue?.offsetHeight); | ||
const [width, setWidth] = useState(); | ||
const [height, setHeight] = useState(); | ||
logged("dimensions", { width, height }); | ||
useOnElementResize(refOrElement, (entry) => { | ||
const dimensions = logged("useOnElementResize => entry:dimensions", getSizeFromResizeObserverEntry(entry)); | ||
const maybeSetNewDimensions = useReferentiallyStableCallback((dimensions) => { | ||
if (width !== dimensions.width) { | ||
@@ -29,15 +22,12 @@ setWidth(dimensions.width); | ||
} | ||
}); | ||
useOnElementResize(refOrElement, (entry) => { | ||
const dimensions = logged("useOnElementResize => entry:dimensions", getSizeFromResizeObserverEntry(entry)); | ||
maybeSetNewDimensions(dimensions); | ||
}, { box }, timeout); | ||
const measure = useRef((element) => { | ||
logged("measure(element)", element); | ||
if (element instanceof HTMLElement) { | ||
setWidth(logged("getElementWidth(element):", getElementWidth(element))); | ||
setHeight(logged("getElementHeight(element):", getElementHeight(element))); | ||
} else if (element) { | ||
throw new Error("Exhaustive error: Expecting element to be instance of HTMLElement or Window"); | ||
} | ||
}); | ||
useLayoutEffect(() => { | ||
const element = unwrapRefValue(refOrElement); | ||
logged("useLayoutEffect => measure", measure.current(element)); | ||
if (element) { | ||
getElementDimensionsCallback(element, (dimensions) => maybeSetNewDimensions(dimensions)); | ||
} | ||
}); | ||
@@ -44,0 +34,0 @@ return { height, width }; |
@@ -12,31 +12,27 @@ import { useRef, useLayoutEffect } from "react"; | ||
const element = unwrapRefValue(refOrElement); | ||
if (element) { | ||
if (element instanceof HTMLElement) { | ||
let debouncedOnChange = function([entry]) { | ||
const timeStamp = Date.now(); | ||
const delta = timeStamp - lastTimeStamp.current; | ||
if (delta > timeout) { | ||
scopedConsoleRef.current.warned("element.resize:immediate", null); | ||
callbackRef.current(entry); | ||
lastTimeStamp.current = timeStamp; | ||
} else { | ||
clearTimeout(timeoutID); | ||
timeoutID = setTimeout(() => { | ||
scopedConsoleRef.current.warned("element.resize:debounced", null); | ||
callbackRef.current(entry); | ||
lastTimeStamp.current = timeStamp; | ||
}, timeout); | ||
} | ||
}; | ||
let timeoutID = void 0; | ||
const resizeObserver = new ResizeObserver(debouncedOnChange); | ||
resizeObserver.observe(element, { box }); | ||
return () => { | ||
clearTimeout(timeoutID); | ||
resizeObserver.unobserve(element); | ||
}; | ||
} else { | ||
throw new Error("Exhaustive error: Expecting element to be instance of HTMLElement"); | ||
} | ||
if (!element) { | ||
return; | ||
} | ||
if (!(element instanceof HTMLElement)) { | ||
throw new Error("Exhaustive error: Expecting element to be instance of HTMLElement"); | ||
} | ||
let timeoutID = void 0; | ||
function debouncedOnChange([entry]) { | ||
const timeStamp = Date.now(); | ||
const delta = timeStamp - lastTimeStamp.current; | ||
clearTimeout(timeoutID); | ||
const timeoutFinal = delta > timeout ? 0 : timeout; | ||
timeoutID = setTimeout(() => { | ||
const message = timeoutFinal > 0 ? "element.resize:debounced" : "element.resize:immediate"; | ||
scopedConsoleRef.current.warned(message, null); | ||
callbackRef.current(entry); | ||
lastTimeStamp.current = timeStamp; | ||
}, timeoutFinal); | ||
} | ||
const resizeObserver = new ResizeObserver(debouncedOnChange); | ||
resizeObserver.observe(element, { box }); | ||
return () => { | ||
clearTimeout(timeoutID); | ||
resizeObserver.unobserve(element); | ||
}; | ||
}, [box, refOrElement, scopedConsoleRef, timeout]); | ||
@@ -43,0 +39,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { assert } from "@contember/utilities"; | ||
import { getElementDimensions, assert } from "@contember/utilities"; | ||
import { useState, useLayoutEffect, useMemo } from "react"; | ||
@@ -31,5 +31,3 @@ import { unwrapRefValue } from "./unwrapRefValue.js"; | ||
if (maybeScrollContent) { | ||
updateScrollOffsetsState( | ||
getElementScrollOffsets(maybeScrollContent) | ||
); | ||
getElementScrollOffsets(maybeScrollContent).then(updateScrollOffsetsState); | ||
} | ||
@@ -54,8 +52,9 @@ }); | ||
} | ||
function getElementScrollOffsets(element) { | ||
async function getElementScrollOffsets(element) { | ||
const isIntrinsicScrolling = isIntrinsicScrollElement(element); | ||
const scrollContainer = getIntrinsicScrollContainer(element); | ||
const { scrollLeft, scrollTop, scrollHeight, scrollWidth } = scrollContainer; | ||
const height = isIntrinsicScrolling ? window.innerHeight : scrollContainer.offsetHeight; | ||
const width = isIntrinsicScrolling ? window.innerWidth : scrollContainer.offsetWidth; | ||
const { height: scrollContainerHeight, width: scrollContainerWidth } = await getElementDimensions(scrollContainer); | ||
const height = isIntrinsicScrolling ? window.innerHeight : scrollContainerHeight; | ||
const width = isIntrinsicScrolling ? window.innerWidth : scrollContainerWidth; | ||
const left = Math.round(scrollLeft); | ||
@@ -62,0 +61,0 @@ const top = Math.round(scrollTop); |
import { RefObjectOrElement } from './unwrapRefValue'; | ||
export type ElementSize = { | ||
height: number; | ||
width: number; | ||
}; | ||
/** | ||
@@ -3,0 +7,0 @@ * Measure HTMLElement |
{ | ||
"name": "@contember/react-utils", | ||
"license": "Apache-2.0", | ||
"version": "1.2.1", | ||
"version": "1.2.2", | ||
"type": "module", | ||
@@ -35,5 +35,5 @@ "sideEffects": false, | ||
"dependencies": { | ||
"@contember/utilities": "1.2.1", | ||
"@contember/utilities": "1.2.2", | ||
"fast-deep-equal": "^3.1.3" | ||
} | ||
} |
@@ -5,6 +5,2 @@ import { useLayoutEffect, useRef } from 'react' | ||
function intendedFlushOfCSSChangesToCauseImmediateReflow(element: HTMLElement) { | ||
element.offsetHeight | ||
} | ||
function addClassName( | ||
@@ -16,3 +12,2 @@ className: string, | ||
element.classList.remove(className) | ||
intendedFlushOfCSSChangesToCauseImmediateReflow(element) | ||
} | ||
@@ -27,3 +22,2 @@ } | ||
element.classList.add(className) | ||
intendedFlushOfCSSChangesToCauseImmediateReflow(element) | ||
} | ||
@@ -30,0 +24,0 @@ } |
@@ -12,3 +12,3 @@ import { px } from '@contember/utilities' | ||
) => { | ||
const measure = useCallback((ref: HTMLTextAreaElement | null, minRows: number, maxRows: number, value: string) => { | ||
const measure = useCallback(async (ref: HTMLTextAreaElement | null, minRows: number, maxRows: number) => { | ||
if (ref) { | ||
@@ -27,3 +27,3 @@ const rowsAttribute = ref.rows | ||
ref.rows = minRows | ||
minHeight = ref.offsetHeight | ||
minHeight = await ref.getBoundingClientRect().height | ||
@@ -34,3 +34,3 @@ if (maxRows === Infinity) { | ||
ref.rows = maxRows | ||
maxHeight = ref.offsetHeight | ||
maxHeight = await ref.getBoundingClientRect().height | ||
} | ||
@@ -48,8 +48,8 @@ | ||
useOnElementResize(textAreaRef, () => { | ||
measure(unwrapRefValue(textAreaRef), minRows, maxRows, value) | ||
measure(unwrapRefValue(textAreaRef), minRows, maxRows) | ||
}) | ||
useLayoutEffect(() => { | ||
measure(unwrapRefValue(textAreaRef), minRows, maxRows, value) | ||
measure(unwrapRefValue(textAreaRef), minRows, maxRows) | ||
}, [maxRows, measure, minRows, textAreaRef, value]) | ||
} |
@@ -1,15 +0,13 @@ | ||
import { getSizeFromResizeObserverEntryFactory } from '@contember/utilities' | ||
import { useLayoutEffect, useMemo, useRef, useState } from 'react' | ||
import { getElementDimensionsCallback, getSizeFromResizeObserverEntryFactory } from '@contember/utilities' | ||
import { useLayoutEffect, useMemo, useState } from 'react' | ||
import { useScopedConsoleRef } from '../debug-context' | ||
import { useReferentiallyStableCallback } from '../referentiallyStable' | ||
import { RefObjectOrElement, unwrapRefValue } from './unwrapRefValue' | ||
import { useOnElementResize } from './useOnElementResize' | ||
function getElementWidth(element: HTMLElement) { | ||
return element.offsetWidth | ||
export type ElementSize = { | ||
height: number | ||
width: number | ||
} | ||
function getElementHeight(element: HTMLElement) { | ||
return element.offsetHeight | ||
} | ||
/** | ||
@@ -31,11 +29,8 @@ * Measure HTMLElement | ||
const refValue = unwrapRefValue(refOrElement) | ||
const [width, setWidth] = useState<number | undefined>(refValue?.offsetWidth) | ||
const [height, setHeight] = useState<number | undefined>(refValue?.offsetHeight) | ||
const [width, setWidth] = useState<number | undefined>() | ||
const [height, setHeight] = useState<number | undefined>() | ||
logged('dimensions', { width, height }) | ||
useOnElementResize(refOrElement, entry => { | ||
const dimensions = logged('useOnElementResize => entry:dimensions', getSizeFromResizeObserverEntry(entry)) | ||
const maybeSetNewDimensions = useReferentiallyStableCallback((dimensions: ElementSize) => { | ||
if (width !== dimensions.width) { | ||
@@ -47,26 +42,14 @@ setWidth(dimensions.width) | ||
} | ||
}) | ||
useOnElementResize(refOrElement, entry => { | ||
const dimensions = logged('useOnElementResize => entry:dimensions', getSizeFromResizeObserverEntry(entry)) | ||
maybeSetNewDimensions(dimensions) | ||
}, { box }, timeout) | ||
// INTENTIONAL AVOID OF ESLint ERROR: We need measure on every Layout side-effect | ||
// otherwise the browser will paint and cause layout shifts. | ||
// | ||
// React Hook useLayoutEffect contains a call to 'setWidth'. Without a list of dependencies, | ||
// this can lead to an infinite chain of updates. To fix this, pass [element] as a second argument | ||
// to the useLayoutEffect Hook. | ||
// | ||
// Seems like only pure function lets us measure before the browser has a chance to paint | ||
const measure = useRef((element: HTMLElement | null) => { | ||
logged('measure(element)', element) | ||
if (element instanceof HTMLElement) { | ||
setWidth(logged('getElementWidth(element):', getElementWidth(element))) | ||
setHeight(logged('getElementHeight(element):', getElementHeight(element))) | ||
} else if (element) { | ||
throw new Error('Exhaustive error: Expecting element to be instance of HTMLElement or Window') | ||
} | ||
}) | ||
useLayoutEffect(() => { | ||
const element = unwrapRefValue(refOrElement) | ||
logged('useLayoutEffect => measure', measure.current(element)) | ||
if (element) { | ||
getElementDimensionsCallback(element, dimensions => maybeSetNewDimensions(dimensions)) | ||
} | ||
}) | ||
@@ -73,0 +56,0 @@ |
@@ -19,38 +19,35 @@ import { useLayoutEffect, useRef } from 'react' | ||
const element = unwrapRefValue(refOrElement) | ||
if (!element) { | ||
return | ||
} | ||
if (!(element instanceof HTMLElement)) { | ||
throw new Error('Exhaustive error: Expecting element to be instance of HTMLElement') | ||
} | ||
if (element) { | ||
if (element instanceof HTMLElement) { | ||
let timeoutID: number | undefined = undefined | ||
let timeoutID: number | undefined = undefined | ||
function debouncedOnChange([entry]: ResizeObserverEntry[]) { | ||
const timeStamp = Date.now() | ||
const delta = timeStamp - lastTimeStamp.current | ||
function debouncedOnChange([entry]: ResizeObserverEntry[]) { | ||
const timeStamp = Date.now() | ||
const delta = timeStamp - lastTimeStamp.current | ||
if (delta > timeout) { | ||
scopedConsoleRef.current.warned('element.resize:immediate', null) | ||
callbackRef.current(entry) | ||
lastTimeStamp.current = timeStamp | ||
} else { | ||
clearTimeout(timeoutID) | ||
timeoutID = setTimeout(() => { | ||
scopedConsoleRef.current.warned('element.resize:debounced', null) | ||
callbackRef.current(entry) | ||
lastTimeStamp.current = timeStamp | ||
}, timeout) | ||
} | ||
} | ||
clearTimeout(timeoutID) | ||
const timeoutFinal = delta > timeout ? 0 : timeout | ||
const resizeObserver = new ResizeObserver(debouncedOnChange) | ||
timeoutID = setTimeout(() => { | ||
const message = timeoutFinal > 0 ? 'element.resize:debounced' : 'element.resize:immediate' | ||
scopedConsoleRef.current.warned(message, null) | ||
callbackRef.current(entry) | ||
lastTimeStamp.current = timeStamp | ||
}, timeoutFinal) | ||
} | ||
resizeObserver.observe(element, { box }) | ||
const resizeObserver = new ResizeObserver(debouncedOnChange) | ||
return () => { | ||
clearTimeout(timeoutID) | ||
resizeObserver.unobserve(element) | ||
} | ||
} else { | ||
throw new Error('Exhaustive error: Expecting element to be instance of HTMLElement') | ||
} | ||
resizeObserver.observe(element, { box }) | ||
return () => { | ||
clearTimeout(timeoutID) | ||
resizeObserver.unobserve(element) | ||
} | ||
}, [box, refOrElement, scopedConsoleRef, timeout]) | ||
} |
@@ -1,2 +0,2 @@ | ||
import { assert } from '@contember/utilities' | ||
import { assert, getElementDimensions } from '@contember/utilities' | ||
import { useLayoutEffect, useMemo, useState } from 'react' | ||
@@ -40,5 +40,3 @@ import { useScopedConsoleRef } from '../debug-context' | ||
if (maybeScrollContent) { | ||
updateScrollOffsetsState( | ||
getElementScrollOffsets(maybeScrollContent), | ||
) | ||
getElementScrollOffsets(maybeScrollContent).then(updateScrollOffsetsState) | ||
} | ||
@@ -73,3 +71,3 @@ }) | ||
function getElementScrollOffsets(element: HTMLElement | Document): Offsets { | ||
async function getElementScrollOffsets(element: HTMLElement | Document): Promise<Offsets> { | ||
const isIntrinsicScrolling = isIntrinsicScrollElement(element) | ||
@@ -79,5 +77,6 @@ const scrollContainer = getIntrinsicScrollContainer(element) | ||
const { scrollLeft, scrollTop, scrollHeight, scrollWidth } = scrollContainer | ||
const { height: scrollContainerHeight, width: scrollContainerWidth } = await getElementDimensions(scrollContainer) | ||
const height = isIntrinsicScrolling ? window.innerHeight : scrollContainer.offsetHeight | ||
const width = isIntrinsicScrolling ? window.innerWidth : scrollContainer.offsetWidth | ||
const height = isIntrinsicScrolling ? window.innerHeight : scrollContainerHeight | ||
const width = isIntrinsicScrolling ? window.innerWidth : scrollContainerWidth | ||
@@ -84,0 +83,0 @@ const left = Math.round(scrollLeft) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
369980
4087
+ Added@contember/utilities@1.2.2(transitive)
- Removed@contember/utilities@1.2.1(transitive)
Updated@contember/utilities@1.2.2