@myst-theme/site 0.1.34 → 0.1.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +9 -9
- package/src/components/DocumentOutline.tsx +28 -8
- package/src/components/FooterLinksBlock.tsx +2 -1
- package/src/components/Navigation/Navigation.tsx +4 -3
- package/src/components/Navigation/TableOfContents.tsx +30 -6
- package/src/components/Navigation/ThemeButton.tsx +3 -3
- package/src/components/Navigation/TopNav.tsx +16 -17
- package/src/components/Navigation/index.tsx +1 -1
- package/src/components/index.ts +1 -1
- package/src/index.ts +0 -1
- package/src/types.ts +4 -7
- package/src/hooks/index.ts +0 -23
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myst-theme/site",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.36",
|
|
4
4
|
"main": "./src/index.ts",
|
|
5
5
|
"types": "./src/index.ts",
|
|
6
6
|
"files": [
|
|
@@ -16,16 +16,16 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@headlessui/react": "^1.7.13",
|
|
18
18
|
"@heroicons/react": "^2.0.14",
|
|
19
|
-
"@myst-theme/diagrams": "^0.1.
|
|
20
|
-
"@myst-theme/frontmatter": "^0.1.
|
|
21
|
-
"@myst-theme/jupyter": "^0.1.
|
|
22
|
-
"@myst-theme/providers": "^0.1.
|
|
19
|
+
"@myst-theme/diagrams": "^0.1.36",
|
|
20
|
+
"@myst-theme/frontmatter": "^0.1.36",
|
|
21
|
+
"@myst-theme/jupyter": "^0.1.36",
|
|
22
|
+
"@myst-theme/providers": "^0.1.36",
|
|
23
23
|
"classnames": "^2.3.2",
|
|
24
24
|
"lodash.throttle": "^4.1.1",
|
|
25
|
-
"myst-common": "^0.0.
|
|
26
|
-
"myst-config": "^0.0.
|
|
27
|
-
"myst-demo": "^0.1.
|
|
28
|
-
"myst-to-react": "^0.1.
|
|
25
|
+
"myst-common": "^0.0.16",
|
|
26
|
+
"myst-config": "^0.0.12",
|
|
27
|
+
"myst-demo": "^0.1.36",
|
|
28
|
+
"myst-to-react": "^0.1.36",
|
|
29
29
|
"nbtx": "^0.2.3",
|
|
30
30
|
"node-cache": "^5.1.2",
|
|
31
31
|
"node-fetch": "^2.6.7",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useNavigation } from '@remix-run/react';
|
|
1
2
|
import classNames from 'classnames';
|
|
2
3
|
import throttle from 'lodash.throttle';
|
|
3
4
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
@@ -155,32 +156,51 @@ const useIntersectionObserver = (highlight: () => void, onScreen: Set<HTMLHeadin
|
|
|
155
156
|
const DOC_OUTLINE_CLASS =
|
|
156
157
|
'fixed z-10 bottom-0 right-[max(0px,calc(50%-45rem))] w-[14rem] lg:w-[18rem] py-10 px-4 lg:px-8 overflow-y-auto hidden lg:block';
|
|
157
158
|
|
|
159
|
+
export function useOutlineHeight<T extends HTMLElement = HTMLElement>() {
|
|
160
|
+
const container = useRef<T>(null);
|
|
161
|
+
const outline = useRef<T>(null);
|
|
162
|
+
const transitionState = useNavigation().state;
|
|
163
|
+
const setHeight = () => {
|
|
164
|
+
if (!container.current || !outline.current) return;
|
|
165
|
+
const height = container.current.offsetHeight - window.scrollY;
|
|
166
|
+
outline.current.style.display = height < 50 ? 'none' : '';
|
|
167
|
+
outline.current.style.height = height > window.innerHeight ? '' : `${height}px`;
|
|
168
|
+
outline.current.style.opacity = height && height > 300 ? '' : '0';
|
|
169
|
+
outline.current.style.pointerEvents = height && height > 300 ? '' : 'none';
|
|
170
|
+
};
|
|
171
|
+
useEffect(() => {
|
|
172
|
+
setHeight();
|
|
173
|
+
setTimeout(setHeight, 100); // Some lag sometimes
|
|
174
|
+
const handleScroll = () => setHeight();
|
|
175
|
+
window.addEventListener('scroll', handleScroll);
|
|
176
|
+
return () => {
|
|
177
|
+
window.removeEventListener('scroll', handleScroll);
|
|
178
|
+
};
|
|
179
|
+
}, [container, outline, transitionState]);
|
|
180
|
+
return { container, outline };
|
|
181
|
+
}
|
|
182
|
+
|
|
158
183
|
export const DocumentOutline = ({
|
|
184
|
+
outlineRef,
|
|
159
185
|
top,
|
|
160
|
-
height,
|
|
161
186
|
className = DOC_OUTLINE_CLASS,
|
|
162
187
|
}: {
|
|
188
|
+
outlineRef?: React.RefObject<HTMLElement>;
|
|
163
189
|
top?: number;
|
|
164
190
|
height?: number;
|
|
165
191
|
className?: string;
|
|
166
192
|
}) => {
|
|
167
193
|
const { activeId, headings, highlight } = useHeaders();
|
|
168
|
-
if (height && height < 50) return null;
|
|
169
194
|
if (headings.length <= 1) return <nav suppressHydrationWarning />;
|
|
170
195
|
return (
|
|
171
196
|
<nav
|
|
197
|
+
ref={outlineRef}
|
|
172
198
|
aria-label="Document Outline"
|
|
173
199
|
suppressHydrationWarning
|
|
174
200
|
className={classNames('not-prose transition-opacity overflow-y-auto', className)}
|
|
175
201
|
style={{
|
|
176
202
|
top: top ?? 0,
|
|
177
|
-
height:
|
|
178
|
-
typeof document === 'undefined' || (height && height > window.innerHeight)
|
|
179
|
-
? undefined
|
|
180
|
-
: height,
|
|
181
203
|
maxHeight: `calc(100vh - ${(top ?? 0) + 20}px)`,
|
|
182
|
-
opacity: height && height > 300 ? undefined : 0,
|
|
183
|
-
pointerEvents: height && height > 300 ? undefined : 'none',
|
|
184
204
|
}}
|
|
185
205
|
>
|
|
186
206
|
<div className="text-slate-900 mb-4 text-sm leading-6 dark:text-slate-100 uppercase">
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import classNames from 'classnames';
|
|
2
2
|
import { Link } from '@remix-run/react';
|
|
3
|
-
import
|
|
3
|
+
import ArrowLeftIcon from '@heroicons/react/24/outline/ArrowLeftIcon';
|
|
4
|
+
import ArrowRightIcon from '@heroicons/react/24/outline/ArrowRightIcon';
|
|
4
5
|
import type { FooterLinks, NavigationLink } from '../types';
|
|
5
6
|
import { useUrlbase, withUrlbase } from '@myst-theme/providers';
|
|
6
7
|
|
|
@@ -5,14 +5,14 @@ export function Navigation({
|
|
|
5
5
|
children,
|
|
6
6
|
projectSlug,
|
|
7
7
|
top,
|
|
8
|
-
|
|
8
|
+
tocRef,
|
|
9
9
|
hide_toc,
|
|
10
10
|
footer,
|
|
11
11
|
}: {
|
|
12
12
|
children?: React.ReactNode;
|
|
13
13
|
projectSlug?: string;
|
|
14
14
|
top?: number;
|
|
15
|
-
|
|
15
|
+
tocRef?: React.RefObject<HTMLDivElement>;
|
|
16
16
|
hide_toc?: boolean;
|
|
17
17
|
footer?: React.ReactNode;
|
|
18
18
|
}) {
|
|
@@ -23,11 +23,12 @@ export function Navigation({
|
|
|
23
23
|
{open && (
|
|
24
24
|
<div
|
|
25
25
|
className="fixed inset-0 bg-black opacity-50 z-30"
|
|
26
|
+
style={{ marginTop: top }}
|
|
26
27
|
onClick={() => setOpen(false)}
|
|
27
28
|
></div>
|
|
28
29
|
)}
|
|
29
30
|
{children}
|
|
30
|
-
<TableOfContents projectSlug={projectSlug} top={top}
|
|
31
|
+
<TableOfContents tocRef={tocRef} projectSlug={projectSlug} top={top} footer={footer} />
|
|
31
32
|
</>
|
|
32
33
|
);
|
|
33
34
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
|
-
import { NavLink, useParams, useLocation } from '@remix-run/react';
|
|
3
|
+
import { NavLink, useParams, useLocation, useNavigation } from '@remix-run/react';
|
|
4
4
|
import type { SiteManifest } from 'myst-config';
|
|
5
5
|
import { useNavOpen, useSiteManifest, useUrlbase, withUrlbase } from '@myst-theme/providers';
|
|
6
6
|
import { getProjectHeadings } from '../../loaders';
|
|
@@ -102,14 +102,39 @@ const Headings = ({ folder, headings, sections }: Props) => {
|
|
|
102
102
|
);
|
|
103
103
|
};
|
|
104
104
|
|
|
105
|
+
export function useTocHeight<T extends HTMLElement = HTMLElement>(top?: number) {
|
|
106
|
+
const container = useRef<T>(null);
|
|
107
|
+
const toc = useRef<HTMLDivElement>(null);
|
|
108
|
+
const transitionState = useNavigation().state;
|
|
109
|
+
const setHeight = () => {
|
|
110
|
+
if (!container.current || !toc.current) return;
|
|
111
|
+
const height = container.current.offsetHeight - window.scrollY;
|
|
112
|
+
const div = toc.current.firstChild as HTMLDivElement;
|
|
113
|
+
const MAGIC_PADDING = 16; // I dunno, just go with it ...
|
|
114
|
+
if (div) div.style.height = `min(calc(100vh - ${top ?? 0}px), ${height + MAGIC_PADDING}px)`;
|
|
115
|
+
const nav = toc.current.querySelector('nav');
|
|
116
|
+
if (nav) nav.style.opacity = height > 150 ? '1' : '0';
|
|
117
|
+
};
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
setHeight();
|
|
120
|
+
setTimeout(setHeight, 100); // Some lag sometimes
|
|
121
|
+
const handleScroll = () => setHeight();
|
|
122
|
+
window.addEventListener('scroll', handleScroll);
|
|
123
|
+
return () => {
|
|
124
|
+
window.removeEventListener('scroll', handleScroll);
|
|
125
|
+
};
|
|
126
|
+
}, [container, toc, transitionState]);
|
|
127
|
+
return { container, toc };
|
|
128
|
+
}
|
|
129
|
+
|
|
105
130
|
export const TableOfContents = ({
|
|
106
131
|
projectSlug,
|
|
107
132
|
top,
|
|
108
|
-
|
|
133
|
+
tocRef,
|
|
109
134
|
footer,
|
|
110
135
|
}: {
|
|
111
136
|
top?: number;
|
|
112
|
-
|
|
137
|
+
tocRef?: React.RefObject<HTMLDivElement>;
|
|
113
138
|
projectSlug?: string;
|
|
114
139
|
footer?: React.ReactNode;
|
|
115
140
|
}) => {
|
|
@@ -124,13 +149,13 @@ export const TableOfContents = ({
|
|
|
124
149
|
if (!headings) return null;
|
|
125
150
|
return (
|
|
126
151
|
<div
|
|
152
|
+
ref={tocRef}
|
|
127
153
|
className={classNames(
|
|
128
154
|
'fixed xl:article-grid article-grid-gap xl:w-screen z-30 xl:pointer-events-none overflow-auto max-xl:min-w-[300px]',
|
|
129
155
|
{ hidden: !open },
|
|
130
156
|
)}
|
|
131
157
|
style={{
|
|
132
158
|
top: top ?? 0,
|
|
133
|
-
height: `min(calc(100vh - ${top ?? 0}px), ${height}px)`,
|
|
134
159
|
}}
|
|
135
160
|
>
|
|
136
161
|
<div
|
|
@@ -149,7 +174,6 @@ export const TableOfContents = ({
|
|
|
149
174
|
<nav
|
|
150
175
|
aria-label="Table of Contents"
|
|
151
176
|
className="flex-grow overflow-y-auto transition-opacity mt-6 pb-3 ml-3 xl:ml-0 mr-3"
|
|
152
|
-
style={{ opacity: height && height > 150 ? undefined : 0 }}
|
|
153
177
|
>
|
|
154
178
|
<Headings folder={resolvedProjectSlug} headings={headings} sections={config?.projects} />
|
|
155
179
|
</nav>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useTheme } from '@myst-theme/providers';
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import MoonIcon from '@heroicons/react/24/solid/MoonIcon';
|
|
3
|
+
import SunIcon from '@heroicons/react/24/outline/SunIcon';
|
|
4
4
|
import classNames from 'classnames';
|
|
5
5
|
|
|
6
6
|
export function ThemeButton({ className = 'mx-3 h-8 w-8' }: { className?: string }) {
|
|
@@ -8,7 +8,7 @@ export function ThemeButton({ className = 'mx-3 h-8 w-8' }: { className?: string
|
|
|
8
8
|
return (
|
|
9
9
|
<button
|
|
10
10
|
className={classNames(
|
|
11
|
-
'theme rounded-full border border-white border-solid overflow-hidden text-white hover:text-stone-500 hover:
|
|
11
|
+
'theme rounded-full border border-stone-700 dark:border-white hover:bg-neutral-100 border-solid overflow-hidden text-stone-700 dark:text-white hover:text-stone-500 dark:hover:text-neutral-800',
|
|
12
12
|
className,
|
|
13
13
|
)}
|
|
14
14
|
title={`Change theme to ${isDark ? 'light' : 'dark'} mode.`}
|
|
@@ -2,11 +2,9 @@ import { Link, NavLink } from '@remix-run/react';
|
|
|
2
2
|
import { Fragment } from 'react';
|
|
3
3
|
import classNames from 'classnames';
|
|
4
4
|
import { Menu, Transition } from '@headlessui/react';
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
ChevronDownIcon,
|
|
9
|
-
} from '@heroicons/react/24/solid';
|
|
5
|
+
import EllipsisVerticalIcon from '@heroicons/react/24/solid/EllipsisVerticalIcon';
|
|
6
|
+
import MenuIcon from '@heroicons/react/24/solid/Bars3Icon';
|
|
7
|
+
import ChevronDownIcon from '@heroicons/react/24/solid/ChevronDownIcon';
|
|
10
8
|
import type { SiteManifest, SiteNavItem } from 'myst-config';
|
|
11
9
|
import { ThemeButton } from './ThemeButton';
|
|
12
10
|
import { useNavOpen, useSiteManifest } from '@myst-theme/providers';
|
|
@@ -58,7 +56,7 @@ function NavItem({ item }: { item: SiteNavItem }) {
|
|
|
58
56
|
to={item.url ?? ''}
|
|
59
57
|
className={({ isActive }) =>
|
|
60
58
|
classNames(
|
|
61
|
-
'inline-flex items-center justify-center w-full mx-2 py-1 text-md font-medium text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75',
|
|
59
|
+
'inline-flex items-center justify-center w-full mx-2 py-1 text-md font-medium dark:text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75',
|
|
62
60
|
{
|
|
63
61
|
'border-b border-stone-200': isActive,
|
|
64
62
|
},
|
|
@@ -73,12 +71,9 @@ function NavItem({ item }: { item: SiteNavItem }) {
|
|
|
73
71
|
return (
|
|
74
72
|
<Menu as="div" className="relative grow-0 inline-block mx-2">
|
|
75
73
|
<div className="inline-block">
|
|
76
|
-
<Menu.Button className="inline-flex items-center justify-center w-full mx-2 py-1 text-md font-medium text-white rounded-md focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75">
|
|
74
|
+
<Menu.Button className="inline-flex items-center justify-center w-full mx-2 py-1 text-md font-medium text-stone-900 dark:text-white rounded-md focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75">
|
|
77
75
|
<span>{item.title}</span>
|
|
78
|
-
<ChevronDownIcon
|
|
79
|
-
className="w-5 h-5 ml-2 -mr-1 text-violet-200 hover:text-violet-100"
|
|
80
|
-
aria-hidden="true"
|
|
81
|
-
/>
|
|
76
|
+
<ChevronDownIcon className="w-5 h-5 ml-2 -mr-1 text-violet-200 hover:text-violet-100" />
|
|
82
77
|
</Menu.Button>
|
|
83
78
|
</div>
|
|
84
79
|
<Transition
|
|
@@ -184,11 +179,15 @@ function HomeLink({ logo, logoText, name }: { logo?: string; logoText?: string;
|
|
|
184
179
|
const nothingSet = !logo && !logoText;
|
|
185
180
|
return (
|
|
186
181
|
<Link
|
|
187
|
-
className="flex items-center text-white w-fit ml-3 md:ml-5 xl:ml-7"
|
|
182
|
+
className="flex items-center dark:text-white w-fit ml-3 md:ml-5 xl:ml-7"
|
|
188
183
|
to="/"
|
|
189
184
|
prefetch="intent"
|
|
190
185
|
>
|
|
191
|
-
{logo &&
|
|
186
|
+
{logo && (
|
|
187
|
+
<div className="dark:bg-white dark:rounded p-1 mr-3">
|
|
188
|
+
<img src={logo} className="h-9" alt={logoText || name} height="2.25rem"></img>
|
|
189
|
+
</div>
|
|
190
|
+
)}
|
|
192
191
|
<span
|
|
193
192
|
className={classNames('text-md sm:text-xl tracking-tight sm:mr-5', {
|
|
194
193
|
'sr-only': !(logoText || nothingSet),
|
|
@@ -205,18 +204,18 @@ export function TopNav() {
|
|
|
205
204
|
const config = useSiteManifest();
|
|
206
205
|
const { logo, logo_text, logoText, actions, title, nav } = config ?? ({} as SiteManifest);
|
|
207
206
|
return (
|
|
208
|
-
<div className="bg-stone-700 p-3 md:px-8 fixed w-screen top-0 z-30 h-[60px]">
|
|
207
|
+
<div className="bg-white/80 backdrop-blur dark:bg-stone-900/80 shadow dark:shadow-stone-700 p-3 md:px-8 fixed w-screen top-0 z-30 h-[60px]">
|
|
209
208
|
<nav className="flex items-center justify-between flex-wrap max-w-[1440px] mx-auto">
|
|
210
209
|
<div className="flex flex-row xl:min-w-[19.5rem] mr-2 sm:mr-7 justify-start items-center">
|
|
211
210
|
<div className="block xl:hidden">
|
|
212
211
|
<button
|
|
213
|
-
className="flex items-center text-stone-
|
|
212
|
+
className="flex items-center border-stone-400 text-stone-800 hover:text-stone-900 dark:text-stone-200 hover:dark:text-stone-100"
|
|
214
213
|
onClick={() => {
|
|
215
214
|
setOpen(!open);
|
|
216
215
|
}}
|
|
217
216
|
>
|
|
217
|
+
<MenuIcon className="h-8 w-8 p-1" />
|
|
218
218
|
<span className="sr-only">Open Menu</span>
|
|
219
|
-
<MenuIcon className="fill-current h-8 w-8 p-1" />
|
|
220
219
|
</button>
|
|
221
220
|
</div>
|
|
222
221
|
<HomeLink name={title} logo={logo} logoText={logo_text || logoText} />
|
|
@@ -232,7 +231,7 @@ export function TopNav() {
|
|
|
232
231
|
{actions?.map((action, index) => (
|
|
233
232
|
<ExternalOrInternalLink
|
|
234
233
|
key={action.url || index}
|
|
235
|
-
className="inline-block text-md px-4 py-2 mx-1 leading-none border rounded
|
|
234
|
+
className="inline-block text-md px-4 py-2 mx-1 leading-none border rounded border-stone-700 dark:border-white text-stone-700 dark:text-white hover:text-stone-500 dark:hover:text-neutral-800 hover:bg-neutral-100 mt-0"
|
|
236
235
|
to={action.url}
|
|
237
236
|
>
|
|
238
237
|
{action.title}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { ThemeButton } from './ThemeButton';
|
|
2
2
|
export { TopNav, DEFAULT_NAV_HEIGHT } from './TopNav';
|
|
3
3
|
export { Navigation } from './Navigation';
|
|
4
|
-
export { TableOfContents } from './TableOfContents';
|
|
4
|
+
export { TableOfContents, useTocHeight } from './TableOfContents';
|
|
5
5
|
export { LoadingBar } from './Loading';
|
package/src/components/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { ContentBlocks } from './ContentBlocks';
|
|
2
|
-
export { DocumentOutline } from './DocumentOutline';
|
|
2
|
+
export { DocumentOutline, useOutlineHeight } from './DocumentOutline';
|
|
3
3
|
export { FooterLinksBlock } from './FooterLinksBlock';
|
|
4
4
|
export { ContentReload } from './ContentReload';
|
|
5
5
|
export { Bibliography } from './Bibliography';
|
package/src/index.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import type { Root } from 'mdast';
|
|
2
|
-
import type { References } from 'myst-common';
|
|
2
|
+
import type { References, Dependency, SourceFileKind } from 'myst-common';
|
|
3
3
|
import type { SiteManifest } from 'myst-config';
|
|
4
4
|
import type { PageFrontmatter } from 'myst-frontmatter';
|
|
5
5
|
import type { Theme } from '@myst-theme/providers';
|
|
6
6
|
|
|
7
|
-
enum KINDS {
|
|
8
|
-
Article = 'Article',
|
|
9
|
-
Notebook = 'Notebook',
|
|
10
|
-
}
|
|
11
|
-
|
|
12
7
|
export type Heading = {
|
|
13
8
|
slug?: string;
|
|
14
9
|
path?: string;
|
|
@@ -38,7 +33,7 @@ export type FooterLinks = {
|
|
|
38
33
|
};
|
|
39
34
|
|
|
40
35
|
export type PageLoader = {
|
|
41
|
-
kind:
|
|
36
|
+
kind: SourceFileKind;
|
|
42
37
|
file: string;
|
|
43
38
|
sha256: string;
|
|
44
39
|
slug: string;
|
|
@@ -47,4 +42,6 @@ export type PageLoader = {
|
|
|
47
42
|
mdast: Root;
|
|
48
43
|
references: References;
|
|
49
44
|
footer?: FooterLinks;
|
|
45
|
+
// This may not be defined
|
|
46
|
+
dependencies?: Dependency[];
|
|
50
47
|
};
|
package/src/hooks/index.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { useTransition } from '@remix-run/react';
|
|
2
|
-
import { useEffect, useRef, useState } from 'react';
|
|
3
|
-
|
|
4
|
-
export function useNavigationHeight<T extends HTMLElement = HTMLElement>() {
|
|
5
|
-
const ref = useRef<T>(null);
|
|
6
|
-
const [height, setHeightState] = useState(1000);
|
|
7
|
-
const transitionState = useTransition().state;
|
|
8
|
-
const setHeight = () => {
|
|
9
|
-
if (ref.current) {
|
|
10
|
-
setHeightState(ref.current.offsetHeight - window.scrollY);
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
useEffect(() => {
|
|
14
|
-
setHeight();
|
|
15
|
-
setTimeout(setHeight, 100); // Some lag sometimes
|
|
16
|
-
const handleScroll = () => setHeight();
|
|
17
|
-
window.addEventListener('scroll', handleScroll);
|
|
18
|
-
return () => {
|
|
19
|
-
window.removeEventListener('scroll', handleScroll);
|
|
20
|
-
};
|
|
21
|
-
}, [ref, transitionState]);
|
|
22
|
-
return { ref, height };
|
|
23
|
-
}
|