forked from stack-auth/stack-auth
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhide-if-empty.tsx
More file actions
84 lines (74 loc) · 2.09 KB
/
hide-if-empty.tsx
File metadata and controls
84 lines (74 loc) · 2.09 KB
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
77
78
79
80
81
82
83
84
'use client';
import { Slot } from '@radix-ui/react-slot';
import { useEffect, useId, useRef, useState } from 'react';
function isEmpty(node: HTMLElement) {
for (let i = 0; i < node.childNodes.length; i++) {
const child = node.childNodes.item(i);
if (child.nodeType === Node.TEXT_NODE) {
return false;
} else if (
child.nodeType === Node.ELEMENT_NODE &&
window.getComputedStyle(child as HTMLElement).display !== 'none'
) {
return false;
}
}
return true;
}
/**
* The built-in CSS `:empty` selector cannot detect if the children is hidden, classes such as `md:hidden` causes it to fail.
* This component is an enhancement to `empty:hidden` to fix the issue described above.
*
* This can be expensive, please avoid this whenever possible.
*/
export function HideIfEmpty({ children }: { children: React.ReactNode }) {
const id = useId();
const ref = useRef<HTMLDivElement>(null);
const [empty, setEmpty] = useState<boolean | undefined>();
useEffect(() => {
const element = ref.current;
if (!element) return;
const onUpdate = () => {
setEmpty(isEmpty(element));
};
const observer = new ResizeObserver(onUpdate);
observer.observe(element);
onUpdate();
return () => {
observer.disconnect();
};
}, []);
const inject = `
function isEmpty(node) {
for (let i = 0; i < node.childNodes.length; i++) {
const child = node.childNodes.item(i);
if (child.nodeType === Node.TEXT_NODE) {
return false
} else if (
child.nodeType === Node.ELEMENT_NODE &&
window.getComputedStyle(child).display !== 'none'
) {
return false
}
}
return true;
}
const element = document.querySelector('[data-fdid="${id}"]')
if (element) {
element.setAttribute('data-empty', String(isEmpty(element)))
}`;
return (
<>
<Slot
ref={ref}
data-fdid={id}
data-empty={empty}
className="data-[empty=true]:hidden"
suppressHydrationWarning
>
{children}
</Slot>
{empty === undefined && <script>{`{ ${inject} }`}</script>}
</>
);
}