-
Notifications
You must be signed in to change notification settings - Fork 842
/
Copy pathinner_text.tsx
76 lines (68 loc) · 2.13 KB
/
inner_text.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import {
FunctionComponent,
ReactElement,
useCallback,
useEffect,
useState,
} from 'react';
type RefT = HTMLElement | Element | undefined | null;
export function useInnerText(
innerTextFallback?: string
): [(node: RefT) => void, string | undefined] {
const [ref, setRef] = useState<RefT>(null);
const [innerText, setInnerText] = useState(innerTextFallback);
const updateInnerText = useCallback(
(node: RefT) => {
if (!node) return;
setInnerText(
// Check for `innerText` implementation rather than a simple OR check
// because in real cases the result of `innerText` could correctly be `null`
// while the result of `textContent` could correctly be non-`null` due to
// differing reliance on browser layout calculations.
// We prefer the result of `innerText`, if available.
'innerText' in node
? node.innerText
: node.textContent || innerTextFallback
);
},
[innerTextFallback]
);
useEffect(() => {
const observer = new MutationObserver((mutationsList) => {
if (mutationsList.length) updateInnerText(ref);
});
if (ref) {
updateInnerText(ref);
observer.observe(ref, {
characterData: true,
subtree: true,
childList: true,
});
}
return () => {
observer.disconnect();
};
}, [ref, updateInnerText]);
return [setRef, innerText];
}
export interface EuiInnerTextProps {
/**
* ReactNode to render as this component's content
*/
children: (ref?: (node: RefT) => void, innerText?: string) => ReactElement;
fallback?: string;
}
export const EuiInnerText: FunctionComponent<EuiInnerTextProps> = ({
children,
fallback,
}) => {
const [ref, innerText] = useInnerText(fallback);
return children(ref, innerText);
};