@myst-theme/site 0.1.37 → 0.1.38
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 +7 -7
- package/src/components/ContentBlocks.tsx +8 -6
- package/src/components/ContentReload.tsx +6 -9
- package/src/components/DocumentOutline.tsx +11 -6
- package/src/components/ExternalOrInternalLink.tsx +2 -1
- package/src/components/FooterLinksBlock.tsx +2 -3
- package/src/components/Navigation/Loading.tsx +2 -2
- package/src/components/Navigation/TableOfContents.tsx +16 -1
- package/src/components/Navigation/TopNav.tsx +4 -2
- package/src/pages/Article.tsx +1 -5
- package/src/pages/Root.tsx +13 -4
- package/src/pages/index.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myst-theme/site",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.38",
|
|
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.38",
|
|
20
|
+
"@myst-theme/frontmatter": "^0.1.38",
|
|
21
|
+
"@myst-theme/jupyter": "^0.1.38",
|
|
22
|
+
"@myst-theme/providers": "^0.1.38",
|
|
23
23
|
"classnames": "^2.3.2",
|
|
24
24
|
"lodash.throttle": "^4.1.1",
|
|
25
25
|
"myst-common": "^0.0.16",
|
|
26
26
|
"myst-config": "^0.0.14",
|
|
27
|
-
"myst-demo": "^0.1.
|
|
28
|
-
"myst-to-react": "^0.1.
|
|
27
|
+
"myst-demo": "^0.1.38",
|
|
28
|
+
"myst-to-react": "^0.1.38",
|
|
29
29
|
"nbtx": "^0.2.3",
|
|
30
30
|
"node-cache": "^5.1.2",
|
|
31
31
|
"node-fetch": "^2.6.7",
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { useParse, DEFAULT_RENDERERS } from 'myst-to-react';
|
|
2
|
-
import
|
|
2
|
+
import { SourceFileKind } from 'myst-common';
|
|
3
|
+
import type { GenericParent } from 'myst-common';
|
|
3
4
|
import { useNodeRenderers } from '@myst-theme/providers';
|
|
4
5
|
import classNames from 'classnames';
|
|
5
6
|
import { ClearCell, RunCell } from './ComputeControls';
|
|
6
7
|
|
|
7
8
|
function isACodeCell(node: GenericParent) {
|
|
8
9
|
return (
|
|
10
|
+
node &&
|
|
9
11
|
node.type === 'block' &&
|
|
10
|
-
node.children
|
|
12
|
+
node.children &&
|
|
13
|
+
node.children?.length === 2 &&
|
|
11
14
|
node.children[0].type === 'code' &&
|
|
12
15
|
node.children[1].type === 'output'
|
|
13
16
|
);
|
|
@@ -50,16 +53,15 @@ function Block({
|
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
export function ContentBlocks({
|
|
53
|
-
name,
|
|
54
|
-
pageKind,
|
|
55
56
|
mdast,
|
|
57
|
+
pageKind = SourceFileKind.Article,
|
|
56
58
|
className,
|
|
57
59
|
}: {
|
|
58
|
-
name: string;
|
|
59
|
-
pageKind: SourceFileKind;
|
|
60
60
|
mdast: GenericParent;
|
|
61
|
+
pageKind?: SourceFileKind;
|
|
61
62
|
className?: string;
|
|
62
63
|
}) {
|
|
64
|
+
if (!mdast) return null;
|
|
63
65
|
const blocks = mdast.children as GenericParent[];
|
|
64
66
|
return (
|
|
65
67
|
<>
|
|
@@ -55,12 +55,9 @@ async function mystLiveReloadConnect(config: { onOpen?: () => void; port?: strin
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
// Inspired by the LiveReload component in Remix
|
|
58
|
-
export
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}, []);
|
|
65
|
-
return null;
|
|
66
|
-
};
|
|
58
|
+
export function ContentReload({ port }: { port?: string | number }) {
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
mystLiveReloadConnect({ port });
|
|
61
|
+
}, []);
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useNavigation } from '@remix-run/react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import throttle from 'lodash.throttle';
|
|
4
|
-
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
5
5
|
|
|
6
6
|
const SELECTOR = [1, 2, 3, 4, 5, 6].map((n) => `main h${n}`).join(', ');
|
|
7
7
|
const HIGHLIGHT_CLASS = 'highlight';
|
|
@@ -176,7 +176,7 @@ export function useOutlineHeight<T extends HTMLElement = HTMLElement>() {
|
|
|
176
176
|
return () => {
|
|
177
177
|
window.removeEventListener('scroll', handleScroll);
|
|
178
178
|
};
|
|
179
|
-
}, [container, outline, transitionState]);
|
|
179
|
+
}, [container.current, outline.current, transitionState]);
|
|
180
180
|
return { container, outline };
|
|
181
181
|
}
|
|
182
182
|
|
|
@@ -191,13 +191,18 @@ export const DocumentOutline = ({
|
|
|
191
191
|
className?: string;
|
|
192
192
|
}) => {
|
|
193
193
|
const { activeId, headings, highlight } = useHeaders();
|
|
194
|
-
if (headings.length <= 1
|
|
194
|
+
if (headings.length <= 1 || !onClient) {
|
|
195
|
+
return <nav suppressHydrationWarning />;
|
|
196
|
+
}
|
|
195
197
|
return (
|
|
196
198
|
<nav
|
|
197
199
|
ref={outlineRef}
|
|
198
200
|
aria-label="Document Outline"
|
|
199
|
-
|
|
200
|
-
|
|
201
|
+
className={classNames(
|
|
202
|
+
'not-prose overflow-y-auto hidden',
|
|
203
|
+
'transition-opacity duration-700', // Animation on load
|
|
204
|
+
className,
|
|
205
|
+
)}
|
|
201
206
|
style={{
|
|
202
207
|
top: top ?? 0,
|
|
203
208
|
maxHeight: `calc(100vh - ${(top ?? 0) + 20}px)`,
|
|
@@ -206,7 +211,7 @@ export const DocumentOutline = ({
|
|
|
206
211
|
<div className="text-slate-900 mb-4 text-sm leading-6 dark:text-slate-100 uppercase">
|
|
207
212
|
In this article
|
|
208
213
|
</div>
|
|
209
|
-
|
|
214
|
+
<Headings headings={headings} activeId={activeId} highlight={highlight} />
|
|
210
215
|
</nav>
|
|
211
216
|
);
|
|
212
217
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useLinkProvider } from '@myst-theme/providers';
|
|
2
2
|
|
|
3
3
|
export function ExternalOrInternalLink({
|
|
4
4
|
to,
|
|
@@ -15,6 +15,7 @@ export function ExternalOrInternalLink({
|
|
|
15
15
|
title?: string;
|
|
16
16
|
children: React.ReactNode;
|
|
17
17
|
}) {
|
|
18
|
+
const Link = useLinkProvider();
|
|
18
19
|
if (to.startsWith('http') || isStatic) {
|
|
19
20
|
return (
|
|
20
21
|
<a href={to} className={className} target="_blank" rel="noopener noreferrer" title={title}>
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import classNames from 'classnames';
|
|
2
|
-
import { Link } from '@remix-run/react';
|
|
3
2
|
import ArrowLeftIcon from '@heroicons/react/24/outline/ArrowLeftIcon';
|
|
4
3
|
import ArrowRightIcon from '@heroicons/react/24/outline/ArrowRightIcon';
|
|
5
4
|
import type { FooterLinks, NavigationLink } from '../types';
|
|
6
|
-
import { useUrlbase, withUrlbase } from '@myst-theme/providers';
|
|
7
|
-
import { useEffect, useState } from 'react';
|
|
5
|
+
import { useLinkProvider, useUrlbase, withUrlbase } from '@myst-theme/providers';
|
|
8
6
|
|
|
9
7
|
const FooterLink = ({ title, url, group, right }: NavigationLink & { right?: boolean }) => {
|
|
10
8
|
const urlbase = useUrlbase();
|
|
9
|
+
const Link = useLinkProvider();
|
|
11
10
|
return (
|
|
12
11
|
<Link
|
|
13
12
|
prefetch="intent"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useNavigation } from '@remix-run/react';
|
|
2
2
|
import { useEffect, useMemo, useState } from 'react';
|
|
3
3
|
import classNames from 'classnames';
|
|
4
4
|
|
|
@@ -6,7 +6,7 @@ import classNames from 'classnames';
|
|
|
6
6
|
* Show a loading progess bad if the load takes more than 150ms
|
|
7
7
|
*/
|
|
8
8
|
function useLoading() {
|
|
9
|
-
const transitionState =
|
|
9
|
+
const transitionState = useNavigation().state;
|
|
10
10
|
const ref = useMemo<{ start?: NodeJS.Timeout; finish?: NodeJS.Timeout }>(() => ({}), []);
|
|
11
11
|
const [showLoading, setShowLoading] = useState(false);
|
|
12
12
|
|
|
@@ -138,6 +138,7 @@ export const TableOfContents = ({
|
|
|
138
138
|
projectSlug?: string;
|
|
139
139
|
footer?: React.ReactNode;
|
|
140
140
|
}) => {
|
|
141
|
+
const footerRef = useRef<HTMLDivElement>(null);
|
|
141
142
|
const [open] = useNavOpen();
|
|
142
143
|
const config = useSiteManifest();
|
|
143
144
|
const { folder, project } = useParams();
|
|
@@ -146,6 +147,13 @@ export const TableOfContents = ({
|
|
|
146
147
|
const headings = getProjectHeadings(config, resolvedProjectSlug, {
|
|
147
148
|
addGroups: false,
|
|
148
149
|
});
|
|
150
|
+
useEffect(() => {
|
|
151
|
+
setTimeout(() => {
|
|
152
|
+
if (!footerRef.current) return;
|
|
153
|
+
footerRef.current.style.opacity = '1';
|
|
154
|
+
footerRef.current.style.transform = 'none';
|
|
155
|
+
}, 500);
|
|
156
|
+
}, [footerRef]);
|
|
149
157
|
if (!headings) return null;
|
|
150
158
|
return (
|
|
151
159
|
<div
|
|
@@ -177,7 +185,14 @@ export const TableOfContents = ({
|
|
|
177
185
|
>
|
|
178
186
|
<Headings folder={resolvedProjectSlug} headings={headings} sections={config?.projects} />
|
|
179
187
|
</nav>
|
|
180
|
-
{footer &&
|
|
188
|
+
{footer && (
|
|
189
|
+
<div
|
|
190
|
+
className="flex-none py-4 opacity-0 transition-all duration-700 translate-y-6"
|
|
191
|
+
ref={footerRef}
|
|
192
|
+
>
|
|
193
|
+
{footer}
|
|
194
|
+
</div>
|
|
195
|
+
)}
|
|
181
196
|
</div>
|
|
182
197
|
</div>
|
|
183
198
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { 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';
|
|
@@ -7,7 +7,7 @@ import MenuIcon from '@heroicons/react/24/solid/Bars3Icon';
|
|
|
7
7
|
import ChevronDownIcon from '@heroicons/react/24/solid/ChevronDownIcon';
|
|
8
8
|
import type { SiteManifest, SiteNavItem } from 'myst-config';
|
|
9
9
|
import { ThemeButton } from './ThemeButton';
|
|
10
|
-
import { useNavOpen, useSiteManifest } from '@myst-theme/providers';
|
|
10
|
+
import { useLinkProvider, useNavOpen, useSiteManifest } from '@myst-theme/providers';
|
|
11
11
|
import { LoadingBar } from './Loading';
|
|
12
12
|
|
|
13
13
|
export const DEFAULT_NAV_HEIGHT = 60;
|
|
@@ -25,6 +25,7 @@ function ExternalOrInternalLink({
|
|
|
25
25
|
nav?: boolean;
|
|
26
26
|
prefetch?: 'intent' | 'render' | 'none';
|
|
27
27
|
}) {
|
|
28
|
+
const Link = useLinkProvider();
|
|
28
29
|
const staticClass = typeof className === 'function' ? className({ isActive: false }) : className;
|
|
29
30
|
if (to.startsWith('http') || to.startsWith('mailto:')) {
|
|
30
31
|
return (
|
|
@@ -176,6 +177,7 @@ function ActionMenu({ actions }: { actions?: SiteManifest['actions'] }) {
|
|
|
176
177
|
}
|
|
177
178
|
|
|
178
179
|
function HomeLink({ logo, logoText, name }: { logo?: string; logoText?: string; name?: string }) {
|
|
180
|
+
const Link = useLinkProvider();
|
|
179
181
|
const nothingSet = !logo && !logoText;
|
|
180
182
|
return (
|
|
181
183
|
<Link
|
package/src/pages/Article.tsx
CHANGED
|
@@ -37,11 +37,7 @@ export const ArticlePage = React.memo(function ({ article }: { article: PageLoad
|
|
|
37
37
|
</EnableCompute>
|
|
38
38
|
)}
|
|
39
39
|
</div>
|
|
40
|
-
<ContentBlocks
|
|
41
|
-
name={article.slug}
|
|
42
|
-
pageKind={article.kind}
|
|
43
|
-
mdast={article.mdast as GenericParent}
|
|
44
|
-
/>
|
|
40
|
+
<ContentBlocks pageKind={article.kind} mdast={article.mdast as GenericParent} />
|
|
45
41
|
<Bibliography />
|
|
46
42
|
{!hide_footer_links && <FooterLinksBlock links={article.footer} />}
|
|
47
43
|
</NotebookProvider>
|
package/src/pages/Root.tsx
CHANGED
|
@@ -21,17 +21,17 @@ import { ConfiguredThebeServerProvider } from '@myst-theme/jupyter';
|
|
|
21
21
|
|
|
22
22
|
export function Document({
|
|
23
23
|
children,
|
|
24
|
+
scripts,
|
|
24
25
|
theme,
|
|
25
26
|
config,
|
|
26
27
|
title,
|
|
27
|
-
CONTENT_CDN_PORT,
|
|
28
28
|
scrollTopClass = 'scroll-p-20',
|
|
29
29
|
}: {
|
|
30
30
|
children: React.ReactNode;
|
|
31
|
+
scripts?: React.ReactNode;
|
|
31
32
|
theme: Theme;
|
|
32
33
|
config?: SiteManifest;
|
|
33
34
|
title?: string;
|
|
34
|
-
CONTENT_CDN_PORT?: number | string;
|
|
35
35
|
scrollTopClass?: string;
|
|
36
36
|
}) {
|
|
37
37
|
return (
|
|
@@ -58,16 +58,25 @@ export function Document({
|
|
|
58
58
|
<ScrollRestoration />
|
|
59
59
|
<Scripts />
|
|
60
60
|
<LiveReload />
|
|
61
|
-
|
|
61
|
+
{scripts}
|
|
62
62
|
</body>
|
|
63
63
|
</html>
|
|
64
64
|
);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
export function App() {
|
|
68
|
+
const { theme, config } = useLoaderData<SiteLoader>();
|
|
69
|
+
return (
|
|
70
|
+
<Document theme={theme} config={config}>
|
|
71
|
+
<Outlet />
|
|
72
|
+
</Document>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function AppWithReload() {
|
|
68
77
|
const { theme, config, CONTENT_CDN_PORT } = useLoaderData<SiteLoader>();
|
|
69
78
|
return (
|
|
70
|
-
<Document theme={theme} config={config}
|
|
79
|
+
<Document theme={theme} config={config} scripts={<ContentReload port={CONTENT_CDN_PORT} />}>
|
|
71
80
|
<Outlet />
|
|
72
81
|
</Document>
|
|
73
82
|
);
|
package/src/pages/index.ts
CHANGED
|
@@ -2,4 +2,4 @@ export { ErrorProjectNotFound } from './ErrorProjectNotFound';
|
|
|
2
2
|
export { ErrorDocumentNotFound } from './ErrorDocumentNotFound';
|
|
3
3
|
export { ErrorSiteNotFound } from './ErrorSiteNotFound';
|
|
4
4
|
export { ArticlePage, ArticlePageCatchBoundary, ProjectPageCatchBoundary } from './Article';
|
|
5
|
-
export { App, Document, AppCatchBoundary, AppDebugErrorBoundary } from './Root';
|
|
5
|
+
export { App, AppWithReload, Document, AppCatchBoundary, AppDebugErrorBoundary } from './Root';
|