-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat/thebe v2 - interactive figures in articles #136
Changes from all commits
ca326e2
64b6a32
00a9460
b5c57eb
f52df10
74f22e5
a5efd80
2e32add
5741d21
09e4e11
efde2c1
9ae03d8
b67ac7d
0dad078
bf3fa3e
c6cd741
0ba558b
f341a1d
8b1e7f3
cbd6654
7f9a39a
376b86d
52d6e16
dbbde15
0a6eb0e
1052db1
428731d
f255251
db667a3
deec502
ae21e3c
0d187dd
7ce280c
b4e5b05
455ec5e
fcee577
afd973d
45b3778
94a0ba7
66c2bbe
2607ff7
60df62b
c526827
0ec804c
8d5be08
d835a1e
2e5a7b5
59cfc66
c20e74d
3eeb188
2fcb4b8
705088a
2e9e504
6292f0a
9067da0
d44ea52
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
--- | ||
'myst-to-react': patch | ||
'@myst-theme/jupyter': patch | ||
'@myst-theme/article': patch | ||
'@myst-theme/site': patch | ||
--- | ||
|
||
Updates for Jupyter |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@myst-theme/site': patch | ||
--- | ||
|
||
Fix the table of contents indentation |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,20 @@ | ||
import { useEffect, useState } from 'react'; | ||
import { useThebeServer, useThebeSession } from 'thebe-react'; | ||
import { useThebeServer } from 'thebe-react'; | ||
import { useComputeOptions } from './providers'; | ||
import type { ThebeEventData, ThebeEventType } from 'thebe-core'; | ||
import { selectAreExecutionScopesBuilding, useExecutionScope } from './execute'; | ||
|
||
export function ConnectionStatusTray() { | ||
const { thebe } = useComputeOptions(); | ||
const { connecting, ready: serverReady, error: serverError, events } = useThebeServer(); | ||
const { starting, ready: sessionReady, error: sessionError } = useThebeSession(); | ||
const { slug, ready: scopeReady, state } = useExecutionScope(); | ||
const [show, setShow] = useState(false); | ||
const [unsub, setUnsub] = useState<() => void | undefined>(); | ||
const [status, setStatus] = useState<string>('[client] Connecting...'); | ||
|
||
const error = serverError || sessionError; | ||
const ready = serverReady && sessionReady; | ||
const busy = connecting || starting; | ||
const error = serverError; // TODO scope bulding error handling || sessionError; | ||
const ready = serverReady && scopeReady; | ||
const busy = connecting || selectAreExecutionScopesBuilding(state, slug); | ||
|
||
const handleStatus = (event: any, data: ThebeEventData) => { | ||
setStatus(`[${data.subject}]: ${data.message}`); | ||
|
@@ -44,6 +45,7 @@ export function ConnectionStatusTray() { | |
|
||
const host = thebe?.useBinder ? 'Binder' : thebe?.useJupyterLite ? 'JupyterLite' : 'Local Server'; | ||
|
||
// TODO radix ui toast! | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking forward to this. :) |
||
if (show && error) { | ||
return ( | ||
<div className="fixed p-3 text-sm text-gray-700 bg-white border rounded shadow-lg bottom-2 sm:right-2 max-w-[90%] md:max-w-[300px] min-w-0"> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { useEffect, useState } from 'react'; | ||
import type { PassiveCellRenderer } from 'thebe-core'; | ||
import type { IThebeNotebookError } from 'thebe-react'; | ||
import { useThebeLoader } from 'thebe-react'; | ||
|
||
function ErrorDecoration({ children, idx }: React.PropsWithChildren<{ idx?: number }>) { | ||
return ( | ||
<div className="relative py-3 mx-2 my-8 border rounded"> | ||
<div className="absolute z-10 flex items-center bg-white -top-3 -left-2"> | ||
{idx && <div className="ml-1 text-sm text-gray-500">cell #: {idx}</div>} | ||
</div> | ||
<div className="mx-3">{children}</div> | ||
</div> | ||
); | ||
} | ||
|
||
function ErrorTrayMessage({ errors }: { errors: IThebeNotebookError[] }) { | ||
const { core } = useThebeLoader(); | ||
|
||
const [cells, setCells] = useState<PassiveCellRenderer[]>([]); | ||
const [refs, setRefs] = useState<((node: HTMLDivElement) => void)[]>([]); | ||
|
||
useEffect(() => { | ||
if (!core) return; | ||
const cs = errors.map(() => new core.PassiveCellRenderer('any')); | ||
setRefs( | ||
errors.map((_, idx) => (node: any) => { | ||
if (node) { | ||
cs[idx].attachToDOM(node); | ||
cs[idx].render(errors[idx].error ?? []); | ||
} | ||
}), | ||
); | ||
setCells(cells); | ||
}, [core, errors]); | ||
|
||
if (!core) return null; | ||
return ( | ||
<div> | ||
{errors.map((error, idx) => ( | ||
<div className="min-w-[400px]"> | ||
<ErrorDecoration idx={error.index}> | ||
<div className="z-100" key={error.id} ref={refs[idx]}></div> | ||
</ErrorDecoration> | ||
</div> | ||
))} | ||
</div> | ||
); | ||
} | ||
|
||
export function ErrorTray({ errors }: { errors: IThebeNotebookError[] }) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should also be radix in the future. |
||
return ( | ||
<div className="relative px-4 pt-3 mt-8 text-sm text-red-600 border border-red-400 rounded border-1"> | ||
<div> | ||
<span className="font-bold">Error</span> - a page refresh may resolve this. | ||
</div> | ||
<ErrorTrayMessage errors={errors} /> | ||
</div> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { useThebeServer } from 'thebe-react'; | ||
import { useNotebookExecution } from '../execute/hooks'; | ||
import { Reset, Run, SpinnerStatusButton } from './Buttons'; | ||
|
||
import { selectAreExecutionScopesBuilding } from '../execute'; | ||
|
||
export function ArticleStatusBadge({ id }: { id: string }) { | ||
const { connect, connecting } = useThebeServer(); | ||
const { slug, state, start, ready, executionCount } = useNotebookExecution(id); | ||
|
||
const building = selectAreExecutionScopesBuilding(state, slug); | ||
|
||
const handleStart = () => { | ||
connect(); | ||
start(); | ||
}; | ||
|
||
return ( | ||
<SpinnerStatusButton | ||
ready={ready} | ||
busy={building || connecting} | ||
modified={executionCount != null} | ||
onClick={handleStart} | ||
/> | ||
); | ||
} | ||
|
||
export function ArticleRunNotebook({ id }: { id: string }) { | ||
const { ready, cellIsExecuting, notebookIsBusy, execute } = useNotebookExecution(id); | ||
if (!ready) return null; | ||
return ( | ||
<Run | ||
ready={ready} | ||
executing={cellIsExecuting} | ||
disabled={notebookIsBusy} | ||
onClick={execute} | ||
title="Run the notebook that creates this figure" | ||
/> | ||
); | ||
} | ||
|
||
export function ArticleResetNotebook({ id }: { id: string }) { | ||
const { ready, notebookIsResetting, notebookIsBusy, reset } = useNotebookExecution(id); | ||
if (!ready) return null; | ||
return ( | ||
<Reset | ||
ready={ready} | ||
resetting={notebookIsResetting} | ||
disabled={notebookIsBusy} | ||
onClick={reset} | ||
title="Reset the figure to its original state and restart the kernel" | ||
/> | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stevejpurves this is more consistent with mystmd.