@myst-theme/site 0.3.3 → 0.3.4

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myst-theme/site",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "main": "./src/index.ts",
5
5
  "types": "./src/index.ts",
6
6
  "files": [
@@ -16,20 +16,20 @@
16
16
  "dependencies": {
17
17
  "@headlessui/react": "^1.7.15",
18
18
  "@heroicons/react": "^2.0.18",
19
- "@myst-theme/diagrams": "^0.3.3",
20
- "@myst-theme/frontmatter": "^0.3.3",
21
- "@myst-theme/jupyter": "^0.3.3",
22
- "@myst-theme/providers": "^0.3.3",
19
+ "@myst-theme/diagrams": "^0.3.4",
20
+ "@myst-theme/frontmatter": "^0.3.4",
21
+ "@myst-theme/jupyter": "^0.3.4",
22
+ "@myst-theme/providers": "^0.3.4",
23
23
  "classnames": "^2.3.2",
24
24
  "lodash.throttle": "^4.1.1",
25
25
  "myst-common": "^1.0.1",
26
26
  "myst-config": "^1.0.0",
27
- "myst-demo": "^0.3.3",
28
- "myst-to-react": "^0.3.3",
27
+ "myst-demo": "^0.3.4",
28
+ "myst-to-react": "^0.3.4",
29
29
  "nbtx": "^0.2.3",
30
30
  "node-cache": "^5.1.2",
31
31
  "node-fetch": "^2.6.11",
32
- "thebe-react": "^0.2.5",
32
+ "thebe-react": "^0.2.7",
33
33
  "unist-util-select": "^4.0.1"
34
34
  },
35
35
  "peerDependencies": {
@@ -3,7 +3,11 @@ import { SourceFileKind } from 'myst-common';
3
3
  import type { GenericParent } from 'myst-common';
4
4
  import { useNodeRenderers } from '@myst-theme/providers';
5
5
  import classNames from 'classnames';
6
- import { ClearCell, RunCell } from './ComputeControls';
6
+ import {
7
+ NotebookClearCell,
8
+ NotebookRunCell,
9
+ NotebookRunCellSpinnerOnly,
10
+ } from '@myst-theme/jupyter';
7
11
 
8
12
  function isACodeCell(node: GenericParent) {
9
13
  return (
@@ -18,6 +22,7 @@ function isACodeCell(node: GenericParent) {
18
22
 
19
23
  function Block({
20
24
  id,
25
+ pageKind,
21
26
  node,
22
27
  className,
23
28
  }: {
@@ -41,13 +46,22 @@ function Block({
41
46
  [subGrid]: !noSubGrid,
42
47
  })}
43
48
  >
44
- {children}
45
- {isACodeCell(node) && (
46
- <div className="hidden group-hover/block:flex md:flex-col absolute -top-[28px] md:top-0 right-0 md:-right-[28px] mt-8">
47
- <RunCell id={id} />
48
- <ClearCell id={id} />
49
- </div>
49
+ {pageKind === SourceFileKind.Notebook && isACodeCell(node) && (
50
+ <>
51
+ <div className="flex sticky top-[80px] z-10 opacity-70 group-hover/block:opacity-100 group-hover/block:hidden">
52
+ <div className="absolute top-0 -right-[28px] flex md:flex-col">
53
+ <NotebookRunCellSpinnerOnly id={id} />
54
+ </div>
55
+ </div>
56
+ <div className="hidden sticky top-[80px] z-10 opacity-70 group-hover/block:opacity-100 group-hover/block:flex">
57
+ <div className="absolute top-0 -right-[28px] flex md:flex-col">
58
+ <NotebookRunCell id={id} />
59
+ <NotebookClearCell id={id} />
60
+ </div>
61
+ </div>
62
+ </>
50
63
  )}
64
+ {children}
51
65
  </div>
52
66
  );
53
67
  }
@@ -48,7 +48,7 @@ const HeadingLink = ({
48
48
  'border-l pl-4 text-blue-500 border-current dark:text-blue-400': !isIndex && isActive,
49
49
  'font-semibold': isActive,
50
50
  'border-l pl-4 border-transparent hover:border-slate-400 dark:hover:border-slate-500 text-slate-700 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-300':
51
- !isActive,
51
+ !isIndex && !isActive,
52
52
  })
53
53
  }
54
54
  to={withBaseurl(path, baseurl)}
@@ -191,7 +191,7 @@ export const TableOfContents = ({
191
191
  </nav>
192
192
  {footer && (
193
193
  <div
194
- className="flex-none py-4 opacity-0 transition-all duration-700 translate-y-6"
194
+ className="flex-none py-4 transition-all duration-700 translate-y-6 opacity-0"
195
195
  ref={footerRef}
196
196
  >
197
197
  {footer}
@@ -1,55 +1,52 @@
1
1
  import React from 'react';
2
2
  import { ReferencesProvider } from '@myst-theme/providers';
3
- import { FrontmatterBlock } from '@myst-theme/frontmatter';
4
3
  import { Bibliography, ContentBlocks, FooterLinksBlock } from '../components';
5
4
  import { ErrorDocumentNotFound } from './ErrorDocumentNotFound';
6
5
  import { ErrorProjectNotFound } from './ErrorProjectNotFound';
7
6
  import type { PageLoader } from '../types';
8
- import { ThebeRenderMimeRegistryProvider, ThebeSessionProvider } from 'thebe-react';
9
7
  import type { GenericParent } from 'myst-common';
10
8
  import { SourceFileKind } from 'myst-common';
11
- import { EnableCompute } from '../components/EnableCompute';
12
- import { NotebookRunAll } from '../components/ComputeControls';
13
9
  import {
14
- NotebookProvider,
15
- BinderBadge,
16
10
  useComputeOptions,
11
+ ExecuteScopeProvider,
12
+ BusyScopeProvider,
13
+ NotebookToolbar,
17
14
  ConnectionStatusTray,
15
+ BinderBadge,
18
16
  } from '@myst-theme/jupyter';
17
+ import { FrontmatterBlock } from '@myst-theme/frontmatter';
19
18
 
20
19
  export const ArticlePage = React.memo(function ({ article }: { article: PageLoader }) {
21
20
  const computeOptions = useComputeOptions();
22
21
  const canCompute = computeOptions.canCompute && (article.frontmatter as any)?.thebe !== false;
23
- const { hide_title_block, hide_footer_links, binder } =
24
- (article.frontmatter as any)?.design ?? {};
25
- const isJupyter = article?.kind && article.kind === SourceFileKind.Notebook;
22
+ const { hide_title_block, hide_footer_links } = (article.frontmatter as any)?.design ?? {};
23
+
24
+ // take binder url from article frontmatter or fallback to project
25
+ const binderUrl = article.frontmatter.binder ?? computeOptions.binderBadgeUrl;
26
+
26
27
  return (
27
28
  <ReferencesProvider
28
29
  references={{ ...article.references, article: article.mdast }}
29
30
  frontmatter={article.frontmatter}
30
31
  >
31
- <ThebeRenderMimeRegistryProvider>
32
- <ThebeSessionProvider start={false} name={article.slug}>
32
+ <BusyScopeProvider>
33
+ <ExecuteScopeProvider contents={article}>
33
34
  {!hide_title_block && (
34
35
  <FrontmatterBlock kind={article.kind} frontmatter={article.frontmatter} />
35
36
  )}
36
- <NotebookProvider siteConfig={false} page={article}>
37
- <div className="flex items-center">
38
- <div className="flex-grow"></div>
39
- {binder && <BinderBadge binder={binder} />}
40
- {canCompute && isJupyter && (
41
- <EnableCompute canCompute={true} key={article.slug}>
42
- <NotebookRunAll />
43
- </EnableCompute>
44
- )}
37
+ {binderUrl && !canCompute && (
38
+ <div className="flex justify-end">
39
+ <BinderBadge binder={binderUrl} />
45
40
  </div>
46
- <ContentBlocks pageKind={article.kind} mdast={article.mdast as GenericParent} />
47
- <ConnectionStatusTray />
48
- <Bibliography />
49
- {!hide_footer_links && <FooterLinksBlock links={article.footer} />}
50
- </NotebookProvider>
51
- </ThebeSessionProvider>
52
- </ThebeRenderMimeRegistryProvider>
41
+ )}
42
+ {canCompute && article.kind === SourceFileKind.Notebook && <NotebookToolbar showLaunch />}
43
+ {canCompute && article.kind === SourceFileKind.Article && <NotebookToolbar />}
44
+ <ContentBlocks pageKind={article.kind} mdast={article.mdast as GenericParent} />
45
+ <Bibliography />
46
+ <ConnectionStatusTray />
47
+ {!hide_footer_links && <FooterLinksBlock links={article.footer} />}
48
+ </ExecuteScopeProvider>
49
+ </BusyScopeProvider>
53
50
  </ReferencesProvider>
54
51
  );
55
52
  });
@@ -1,131 +0,0 @@
1
- import { Spinner } from './Spinner';
2
- import PlayCircleIcon from '@heroicons/react/24/outline/PlayCircleIcon';
3
- import ArrowPathIcon from '@heroicons/react/24/outline/ArrowPathIcon';
4
- import MinusCircleIcon from '@heroicons/react/24/outline/MinusCircleIcon';
5
- import ArrowTopRightOnSquareIcon from '@heroicons/react/24/outline/ArrowTopRightOnSquareIcon';
6
- import classNames from 'classnames';
7
- import type { NotebookExecuteOptions } from 'thebe-react';
8
- import { useThebeServer } from 'thebe-react';
9
- import type { IThebeCellExecuteReturn } from 'thebe-core';
10
- import { useMDASTNotebook, useNotebookCellExecution } from '@myst-theme/jupyter';
11
-
12
- export function Run({
13
- ready,
14
- executing,
15
- disabled,
16
- execute,
17
- }: {
18
- ready: boolean;
19
- executing: boolean;
20
- disabled?: boolean;
21
- execute: (
22
- options?: NotebookExecuteOptions | undefined,
23
- ) => Promise<(IThebeCellExecuteReturn | null)[]>;
24
- }) {
25
- return (
26
- <div className="relative flex text-sm">
27
- <button
28
- className={classNames(
29
- 'cursor-pointer text-gray-700 active:text-green-700 hover:opacity-100',
30
- {
31
- 'opacity-10 hover:opacity-10': executing,
32
- 'opacity-60': !executing,
33
- },
34
- )}
35
- disabled={disabled || !ready || executing}
36
- onClick={() => execute()}
37
- >
38
- <PlayCircleIcon className="inline-block w-6 h-6 align-top" title="run all cells" />
39
- </button>
40
- {executing && (
41
- <span className="absolute top-0 left-0 z-10 w-[22px] h-[22px] opacity-100">
42
- <Spinner size={24} />
43
- </span>
44
- )}
45
- </div>
46
- );
47
- }
48
-
49
- export function Clear({
50
- ready,
51
- executing,
52
- disabled,
53
- clear,
54
- }: {
55
- ready: boolean;
56
- executing: boolean;
57
- disabled?: boolean;
58
- clear: () => void;
59
- }) {
60
- return (
61
- <button
62
- className="flex text-gray-700 cursor-pointer active:text-green-700 opacity-60 hover:opacity-100"
63
- disabled={disabled || !ready || executing}
64
- onClick={() => clear()}
65
- >
66
- <MinusCircleIcon className="inline-block w-6 h-6 align-top" title="clear all outputs" />
67
- </button>
68
- );
69
- }
70
-
71
- export function RunCell({ id }: { id: string }) {
72
- const exec = useNotebookCellExecution(id);
73
- if (!exec?.ready) return null;
74
- const { ready, executing, notebookIsExecuting, execute } = exec;
75
- return (
76
- <Run ready={ready} executing={executing} disabled={notebookIsExecuting} execute={execute} />
77
- );
78
- }
79
-
80
- export function ClearCell({ id }: { id: string }) {
81
- const exec = useNotebookCellExecution(id);
82
- if (!exec?.ready) return null;
83
- const { ready, executing, notebookIsExecuting, clear } = exec;
84
- return <Clear ready={ready} executing={executing} disabled={notebookIsExecuting} clear={clear} />;
85
- }
86
-
87
- export function NotebookRunAll() {
88
- const { ready: serverReady, server } = useThebeServer();
89
- const exec = useMDASTNotebook();
90
-
91
- if (!exec?.ready) return null;
92
- const { ready, executing, executeAll, restart, clear } = exec;
93
-
94
- const clickLaunchInJupyter = () => {
95
- if (!serverReady || !server?.settings) return;
96
- window.open(server.settings.baseUrl, '_blank');
97
- };
98
-
99
- return (
100
- <div className="flex">
101
- <div className="relative flex group space-x-1">
102
- <Run
103
- ready={ready}
104
- executing={executing}
105
- execute={(options) => {
106
- clear();
107
- return executeAll(options);
108
- }}
109
- />
110
- <button
111
- className="flex items-center text-gray-700 cursor-pointer active:text-green-700 opacity-60 hover:opacity-100"
112
- disabled={!ready || executing}
113
- onClick={() => restart()}
114
- >
115
- <ArrowPathIcon className="w-6 h-6" title="restart kernel" />
116
- </button>
117
- <Clear ready={ready} executing={executing} clear={clear} />
118
- <button
119
- className="flex items-center text-gray-700 cursor-pointer active:text-green-700 opacity-60 hover:opacity-100"
120
- disabled={!ready}
121
- onClick={clickLaunchInJupyter}
122
- >
123
- <ArrowTopRightOnSquareIcon
124
- className="inline-block w-6 h-6 align-top"
125
- title="launch in juptyer"
126
- />
127
- </button>
128
- </div>
129
- </div>
130
- );
131
- }
@@ -1,72 +0,0 @@
1
- import { useThebeLoader, useThebeServer, useThebeSession } from 'thebe-react';
2
- import PowerIcon from '@heroicons/react/24/outline/PowerIcon';
3
- import { useHasNotebookProvider } from '@myst-theme/jupyter';
4
- import { useNavigation } from '@remix-run/react';
5
- import { useEffect, useState } from 'react';
6
- import { Spinner } from './Spinner';
7
- import classNames from 'classnames';
8
-
9
- export function EnableCompute({
10
- canCompute,
11
- children,
12
- }: React.PropsWithChildren<{ canCompute: boolean }>) {
13
- const { load, loading, core } = useThebeLoader();
14
- const { connect, connecting, ready: serverReady, error: serverError } = useThebeServer();
15
- const { start, starting, shutdown, ready: sessionReady, error: sessionError } = useThebeSession();
16
- const hasNotebookProvider = useHasNotebookProvider();
17
- const navigation = useNavigation();
18
- const [enabling, setEnabling] = useState(false);
19
- const [enabled, setEnabled] = useState(false);
20
- const busy = enabling || loading || connecting || starting;
21
-
22
- useEffect(() => {
23
- if (!enabling) return;
24
- if (!core) return load();
25
- if (!serverReady) return connect();
26
- if (!sessionReady) start();
27
- if (sessionReady) {
28
- setEnabled(true);
29
- setEnabling(false);
30
- }
31
- }, [enabling, core, serverReady, sessionReady]);
32
-
33
- if (!canCompute || !hasNotebookProvider) return null;
34
- let title = 'Connect to a compute server';
35
- const error = !!sessionError || !!serverError;
36
- if (error) {
37
- title = 'Error connecting to compute server';
38
- }
39
- if (busy) {
40
- title = 'Connecting...';
41
- }
42
-
43
- useEffect(() => {
44
- if (navigation.state === 'loading') {
45
- shutdown();
46
- }
47
- }, [shutdown, navigation]);
48
-
49
- return (
50
- <div className="relative flex items-center mx-1 mb-2">
51
- {!enabled && (
52
- <button
53
- className={classNames(
54
- 'flex text-center mr-1 cursor-pointer rounded-full disabled:opacity-10 text-gray-700',
55
- { 'text-red-600 opacity-100': error },
56
- )}
57
- onClick={() => setEnabling(true)}
58
- disabled={connecting || starting}
59
- title={title}
60
- >
61
- <PowerIcon className="inline-block w-6 h-6 mx-1 align-top" />
62
- </button>
63
- )}
64
- {(connecting || starting) && !error && (
65
- <span className="absolute top-0 left-1 z-10 w-[22px] h-[22px] opacity-100" title={title}>
66
- <Spinner size={24} />
67
- </span>
68
- )}
69
- {enabled && <>{children}</>}
70
- </div>
71
- );
72
- }