UNPKG

thebe-react

Version:

React providers and components for thebe-core

269 lines 12.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useNotebookfromSourceLegacy = exports.useNotebookFromSource = exports.useNotebook = exports.useNotebookBase = exports.findErrors = void 0; const react_1 = require("react"); const ThebeServerProvider_1 = require("../ThebeServerProvider"); const ThebeLoaderProvider_1 = require("../ThebeLoaderProvider"); const ThebeSessionProvider_1 = require("../ThebeSessionProvider"); const ThebeRenderMimeRegistryProvider_1 = require("../ThebeRenderMimeRegistryProvider"); function findErrors(execReturns) { return execReturns.reduce((acc, retval, index) => { if (retval === null || retval === void 0 ? void 0 : retval.error) { if (acc == null) return [Object.assign(Object.assign({}, retval), { index })]; else return [...acc, Object.assign(Object.assign({}, retval), { index })]; } return acc; }, null); } exports.findErrors = findErrors; function useNotebookBase() { const { session, ready: sessionReady } = (0, ThebeSessionProvider_1.useThebeSession)(); const [notebook, setNotebook] = (0, react_1.useState)(); // TODO move the refs to caller hooks as it does so little to maintain them in here. const [refs, setRefs] = (0, react_1.useState)([]); const [sessionAttached, setSessionAttached] = (0, react_1.useState)(false); const [executing, setExecuting] = (0, react_1.useState)(false); const [executed, setExecuted] = (0, react_1.useState)(false); const [errors, setErrors] = (0, react_1.useState)(null); /** * When the notebook and session is avaiable, attach to session */ (0, react_1.useEffect)(() => { if (!notebook || !session || !sessionReady) return; console.debug(`thebe-react: attaching notebook to session`, { notebook, session }); notebook.attachSession(session); setSessionAttached(true); }, [notebook, session, sessionReady]); const executeAll = (options) => { var _a, _b; if (!notebook) throw new Error('executeAll called before notebook available'); if (!session) throw new Error('executeAll called before session available'); (_a = options === null || options === void 0 ? void 0 : options.before) === null || _a === void 0 ? void 0 : _a.call(options); setExecuting(true); return notebook .executeAll((_b = options === null || options === void 0 ? void 0 : options.stopOnError) !== null && _b !== void 0 ? _b : true, options === null || options === void 0 ? void 0 : options.preprocessor) .then((execReturns) => { var _a; (_a = options === null || options === void 0 ? void 0 : options.after) === null || _a === void 0 ? void 0 : _a.call(options); const errs = findErrors(execReturns); if (errs != null) setErrors(errs); setExecuted(true); setExecuting(false); return execReturns; }); }; const executeSome = (predicate, options) => { var _a, _b; if (!notebook) throw new Error('executeSome called before notebook available'); if (!session) throw new Error('executeAll called before session available'); (_a = options === null || options === void 0 ? void 0 : options.before) === null || _a === void 0 ? void 0 : _a.call(options); setExecuting(true); const filteredCells = notebook.cells.filter(predicate).map((c) => c.id); return notebook .executeCells(filteredCells, (_b = options === null || options === void 0 ? void 0 : options.stopOnError) !== null && _b !== void 0 ? _b : true, options === null || options === void 0 ? void 0 : options.preprocessor) .then((execReturns) => { var _a; (_a = options === null || options === void 0 ? void 0 : options.after) === null || _a === void 0 ? void 0 : _a.call(options); const errs = findErrors(execReturns); if (errs != null) setErrors(errs); setExecuted(true); setExecuting(false); return execReturns; }); }; const clear = () => { if (!notebook) throw new Error('clear called before notebook available'); notebook.clear(); setExecuted(false); }; return { ready: !!notebook && sessionAttached, attached: sessionAttached, executing, executed, errors, notebook, setNotebook, refs, setRefs, executeAll, executeSome, clear, session, }; } exports.useNotebookBase = useNotebookBase; /** * @param name - provided to the fetcher function * @param fetchNotebook - an async function, that given a name, can return a JSON representation of an ipynb file (INotebookContent) * @param opts - options.refsForWidgetsOnly=false allows refs to be generated for all notebook cells, rather than onlythose with widget tags * @returns */ function useNotebook(name, fetchNotebook, opts = { refsForWidgetsOnly: true }) { var _a, _b; const { core } = (0, ThebeLoaderProvider_1.useThebeLoader)(); const { config } = (0, ThebeServerProvider_1.useThebeConfig)(); const rendermime = (0, ThebeRenderMimeRegistryProvider_1.useRenderMimeRegistry)(); const [loading, setLoading] = (0, react_1.useState)(false); if (!rendermime) throw new Error('ThebeSessionProvider requires a RenderMimeRegistryProvider'); const { ready, attached, executing, executed, errors, notebook, setNotebook, refs, setRefs, executeAll, executeSome, clear, session, } = useNotebookBase(); /** * - set loading flag * - load the notebook * - setup callback refs, to auto-attach to dom * - set notebook, which triggers * - clear loading flag */ (0, react_1.useEffect)(() => { if (!core || !config) return; setLoading(true); fetchNotebook(name) .then((ipynb) => { return core === null || core === void 0 ? void 0 : core.ThebeNotebook.fromIpynb(ipynb, config, rendermime); }) .then((nb) => { var _a, _b; const cells = (opts === null || opts === void 0 ? void 0 : opts.refsForWidgetsOnly) ? (_a = nb === null || nb === void 0 ? void 0 : nb.widgets) !== null && _a !== void 0 ? _a : [] : (_b = nb === null || nb === void 0 ? void 0 : nb.cells) !== null && _b !== void 0 ? _b : []; // set up an array of callback refs to update the DOM elements setRefs(Array(cells.length) .fill(null) .map((_, idx) => (node) => { console.debug(`new ref[${idx}] - attaching to dom...`, node); if (node != null) cells[idx].attachToDOM(node); })); setNotebook(nb); setLoading(false); }); }, [core, config]); return { ready, loading, attached, executing, executed, errors, notebook, cellRefs: refs, cellIds: (opts.refsForWidgetsOnly ? (_a = notebook === null || notebook === void 0 ? void 0 : notebook.widgets) !== null && _a !== void 0 ? _a : [] : (_b = notebook === null || notebook === void 0 ? void 0 : notebook.cells) !== null && _b !== void 0 ? _b : []).map((c) => c.id), executeAll, executeSome, clear, session, }; } exports.useNotebook = useNotebook; /** * @param sourceCode - just an array of valid code blocks as single line strings * @param opts - options.refsForWidgetsOnly=false allows refs to be generated for all notebook cells, rather than onlythose with widget tags * @returns */ function useNotebookFromSource(sourceCode, opts = { refsForWidgetsOnly: true }) { var _a, _b; const { core } = (0, ThebeLoaderProvider_1.useThebeLoader)(); const { config } = (0, ThebeServerProvider_1.useThebeConfig)(); const rendermime = (0, ThebeRenderMimeRegistryProvider_1.useRenderMimeRegistry)(); const [loading, setLoading] = (0, react_1.useState)(false); if (!rendermime) throw new Error('ThebeSessionProvider requires a RenderMimeRegistryProvider'); const { ready, attached, executing, executed, errors, notebook, setNotebook, refs, setRefs, executeAll, executeSome, clear, session, } = useNotebookBase(); (0, react_1.useEffect)(() => { var _a, _b; if (!core || !config || loading || notebook) return; setLoading(true); const nb = core.ThebeNotebook.fromCodeBlocks(sourceCode.map((source) => ({ id: core === null || core === void 0 ? void 0 : core.shortId(), source })), config, rendermime); const cells = (opts === null || opts === void 0 ? void 0 : opts.refsForWidgetsOnly) ? (_a = nb === null || nb === void 0 ? void 0 : nb.widgets) !== null && _a !== void 0 ? _a : [] : (_b = nb === null || nb === void 0 ? void 0 : nb.cells) !== null && _b !== void 0 ? _b : []; setRefs(Array(cells.length) .fill(null) .map((_, idx) => (node) => { console.debug(`new ref[${idx}] - attaching to dom...`, node); if (node != null) cells[idx].attachToDOM(node); })); setNotebook(nb); setLoading(false); }, [core, notebook, loading]); return { ready, loading, attached, executing, executed, errors, notebook, cellRefs: refs, cellIds: (opts.refsForWidgetsOnly ? (_a = notebook === null || notebook === void 0 ? void 0 : notebook.widgets) !== null && _a !== void 0 ? _a : [] : (_b = notebook === null || notebook === void 0 ? void 0 : notebook.cells) !== null && _b !== void 0 ? _b : []).map((c) => c.id), executeAll, executeSome, clear, session, }; } exports.useNotebookFromSource = useNotebookFromSource; /** * DEPRECATED - migrate to useNotebookFromSource */ function useNotebookfromSourceLegacy(sourceCode) { const { core } = (0, ThebeLoaderProvider_1.useThebeLoader)(); const { config } = (0, ThebeServerProvider_1.useThebeConfig)(); const rendermime = (0, ThebeRenderMimeRegistryProvider_1.useRenderMimeRegistry)(); if (!rendermime) throw new Error('ThebeSessionProvider requires a RenderMimeRegistryProvider'); const [busy, setBusy] = (0, react_1.useState)(false); const [notebook, setNotebook] = (0, react_1.useState)(); const [_, setReRender] = (0, react_1.useState)({}); const [cellRefs] = (0, react_1.useState)(Array(sourceCode.length) .fill(undefined) .map(() => (0, react_1.createRef)())); (0, react_1.useEffect)(() => { if (!core || !config || notebook) return; setNotebook(core.ThebeNotebook.fromCodeBlocks(sourceCode.map((source) => ({ id: core === null || core === void 0 ? void 0 : core.shortId(), source })), config, rendermime)); }, [core, notebook]); const execute = () => { if (!notebook) throw new Error('execute called before notebook available'); setBusy(true); notebook.executeAll().then(() => { setBusy(false); }); }; const attach = (session) => { if (session.kernel == null) return; if (!notebook) { console.warn('attach called before notebook available'); return; } notebook === null || notebook === void 0 ? void 0 : notebook.detachSession(); notebook === null || notebook === void 0 ? void 0 : notebook.attachSession(session); notebook === null || notebook === void 0 ? void 0 : notebook.cells.forEach((cell, idx) => { var _a; if (cellRefs[idx].current) cell.attachToDOM((_a = cellRefs[idx].current) !== null && _a !== void 0 ? _a : undefined); }); }; return { notebook, busy, execute, attach, cellRefs, rerender: () => setReRender({}), }; } exports.useNotebookfromSourceLegacy = useNotebookfromSourceLegacy; //# sourceMappingURL=notebook.js.map