jupyter-specta 0.1.1 → 0.1.3
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/lib/app.js +1 -1
- package/lib/components/cellSkeleton.d.ts +6 -0
- package/lib/components/cellSkeleton.js +19 -0
- package/lib/components/divider.d.ts +2 -0
- package/lib/components/divider.js +4 -0
- package/lib/components/icon/gear.d.ts +2 -0
- package/lib/components/icon/gear.js +17 -0
- package/lib/components/iconButton.d.ts +8 -0
- package/lib/components/iconButton.js +4 -0
- package/lib/document/factory.d.ts +5 -1
- package/lib/document/factory.js +12 -3
- package/lib/document/plugin.js +5 -1
- package/lib/extension_plugins.js +7 -1
- package/lib/layout/article.d.ts +12 -0
- package/lib/layout/article.js +35 -0
- package/lib/layout/default.js +2 -5
- package/lib/layout/layout_registry.d.ts +1 -0
- package/lib/layout/layout_registry.js +6 -0
- package/lib/layout/plugin.js +5 -0
- package/lib/shell.js +0 -1
- package/lib/specta_cell_output.d.ts +9 -2
- package/lib/specta_cell_output.js +20 -1
- package/lib/specta_model.d.ts +1 -2
- package/lib/specta_model.js +74 -12
- package/lib/specta_widget.d.ts +5 -1
- package/lib/specta_widget.js +23 -7
- package/lib/specta_widget_factory.d.ts +2 -1
- package/lib/specta_widget_factory.js +6 -2
- package/lib/token.d.ts +13 -0
- package/lib/tool.d.ts +3 -1
- package/lib/tool.js +5 -16
- package/lib/topbar/kernelStatus.d.ts +28 -0
- package/lib/topbar/kernelStatus.js +20 -0
- package/lib/topbar/plugin.d.ts +5 -0
- package/lib/topbar/plugin.js +32 -0
- package/lib/topbar/settingDialog.d.ts +7 -0
- package/lib/topbar/settingDialog.js +73 -0
- package/lib/topbar/widget.d.ts +9 -0
- package/lib/topbar/widget.js +41 -0
- package/package.json +18 -11
- package/style/article.css +314 -0
- package/style/base.css +125 -0
- package/style/index.css +2 -0
- package/style/index.js +3 -1
- package/style/skeleton.css +87 -0
- package/style/style.css +9 -4
|
@@ -4,7 +4,7 @@ import { DocumentRegistry } from '@jupyterlab/docregistry';
|
|
|
4
4
|
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
|
|
5
5
|
import { ServiceManager } from '@jupyterlab/services';
|
|
6
6
|
import { AppWidget } from './specta_widget';
|
|
7
|
-
import { ISpectaLayoutRegistry } from './token';
|
|
7
|
+
import { ISpectaAppConfig, ISpectaLayoutRegistry } from './token';
|
|
8
8
|
export declare class SpectaWidgetFactory {
|
|
9
9
|
constructor(options: SpectaWidgetFactory.IOptions);
|
|
10
10
|
createNew(options: {
|
|
@@ -21,5 +21,6 @@ export declare namespace SpectaWidgetFactory {
|
|
|
21
21
|
mimeTypeService: IEditorMimeTypeService;
|
|
22
22
|
editorServices: IEditorServices;
|
|
23
23
|
spectaLayoutRegistry: ISpectaLayoutRegistry;
|
|
24
|
+
spectaConfig: ISpectaAppConfig;
|
|
24
25
|
}
|
|
25
26
|
}
|
|
@@ -8,10 +8,13 @@ export class SpectaWidgetFactory {
|
|
|
8
8
|
}
|
|
9
9
|
async createNew(options) {
|
|
10
10
|
const { context } = options;
|
|
11
|
+
const rendermime = this._options.rendermime.clone({
|
|
12
|
+
resolver: context.urlResolver
|
|
13
|
+
});
|
|
11
14
|
const model = new AppModel({
|
|
12
15
|
context,
|
|
13
16
|
manager: this._options.manager,
|
|
14
|
-
rendermime
|
|
17
|
+
rendermime,
|
|
15
18
|
tracker: this._options.tracker,
|
|
16
19
|
contentFactory: this._options.contentFactory,
|
|
17
20
|
mimeTypeService: this._options.mimeTypeService,
|
|
@@ -23,7 +26,8 @@ export class SpectaWidgetFactory {
|
|
|
23
26
|
id: UUID.uuid4(),
|
|
24
27
|
label: '',
|
|
25
28
|
model,
|
|
26
|
-
layoutRegistry: this._options.spectaLayoutRegistry
|
|
29
|
+
layoutRegistry: this._options.spectaLayoutRegistry,
|
|
30
|
+
spectaConfig: this._options.spectaConfig
|
|
27
31
|
});
|
|
28
32
|
return panel;
|
|
29
33
|
}
|
package/lib/token.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export interface ISpectaLayout {
|
|
|
14
14
|
}
|
|
15
15
|
export interface ISpectaLayoutRegistry {
|
|
16
16
|
get(name: string): ISpectaLayout | undefined;
|
|
17
|
+
getDefaultLayout(): ISpectaLayout;
|
|
17
18
|
register(name: string, layout: ISpectaLayout): void;
|
|
18
19
|
allLayouts(): string[];
|
|
19
20
|
layoutAdded: ISignal<ISpectaLayoutRegistry, string>;
|
|
@@ -27,5 +28,17 @@ export interface ISpectaLayoutRegistry {
|
|
|
27
28
|
layout: ISpectaLayout;
|
|
28
29
|
}>;
|
|
29
30
|
}
|
|
31
|
+
export interface ITopbarConfig {
|
|
32
|
+
background?: string;
|
|
33
|
+
textColor?: string;
|
|
34
|
+
title?: string;
|
|
35
|
+
icon?: string;
|
|
36
|
+
kernelActivity?: boolean;
|
|
37
|
+
themeToggle?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface ISpectaAppConfig {
|
|
40
|
+
topBar?: ITopbarConfig;
|
|
41
|
+
layout?: string;
|
|
42
|
+
}
|
|
30
43
|
export declare const ISpectaLayoutRegistry: Token<ISpectaLayoutRegistry>;
|
|
31
44
|
export declare const ISpectaDocTracker: Token<IWidgetTracker<Widget>>;
|
package/lib/tool.d.ts
CHANGED
|
@@ -5,7 +5,8 @@ import { INotebookTracker, NotebookPanel } from '@jupyterlab/notebook';
|
|
|
5
5
|
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
|
|
6
6
|
import { VoilaFileBrowser } from '@voila-dashboards/voila';
|
|
7
7
|
import { IDocumentManager } from '@jupyterlab/docmanager';
|
|
8
|
-
import { ISpectaLayoutRegistry } from './token';
|
|
8
|
+
import { ISpectaAppConfig, ISpectaLayoutRegistry } from './token';
|
|
9
|
+
export declare const SPECTA_CELL_VISIBLE_TAG = "specta:visible";
|
|
9
10
|
export declare function registerDocumentFactory(options: {
|
|
10
11
|
factoryName: string;
|
|
11
12
|
app: JupyterFrontEnd;
|
|
@@ -15,6 +16,7 @@ export declare function registerDocumentFactory(options: {
|
|
|
15
16
|
contentFactory: NotebookPanel.IContentFactory;
|
|
16
17
|
spectaTracker: WidgetTracker;
|
|
17
18
|
spectaLayoutRegistry: ISpectaLayoutRegistry;
|
|
19
|
+
spectaConfig: ISpectaAppConfig;
|
|
18
20
|
}): void;
|
|
19
21
|
export declare function createFileBrowser(options: {
|
|
20
22
|
docManager: IDocumentManager;
|
package/lib/tool.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { PageConfig, URLExt } from '@jupyterlab/coreutils';
|
|
2
2
|
import { FilterFileBrowserModel } from '@jupyterlab/filebrowser';
|
|
3
|
-
import { NotebookModelFactory } from '@jupyterlab/notebook';
|
|
4
3
|
import { VoilaFileBrowser } from '@voila-dashboards/voila';
|
|
5
4
|
import { NotebookGridWidgetFactory } from './document/factory';
|
|
6
5
|
import { SpectaWidgetFactory } from './specta_widget_factory';
|
|
6
|
+
export const SPECTA_CELL_VISIBLE_TAG = 'specta:visible';
|
|
7
7
|
export function registerDocumentFactory(options) {
|
|
8
|
-
const { factoryName, app, rendermime, tracker, editorServices, contentFactory, spectaTracker, spectaLayoutRegistry } = options;
|
|
8
|
+
const { factoryName, app, rendermime, tracker, editorServices, contentFactory, spectaTracker, spectaLayoutRegistry, spectaConfig } = options;
|
|
9
9
|
const spectaWidgetFactory = new SpectaWidgetFactory({
|
|
10
10
|
manager: app.serviceManager,
|
|
11
11
|
rendermime,
|
|
@@ -13,12 +13,13 @@ export function registerDocumentFactory(options) {
|
|
|
13
13
|
contentFactory,
|
|
14
14
|
mimeTypeService: editorServices.mimeTypeService,
|
|
15
15
|
editorServices,
|
|
16
|
-
spectaLayoutRegistry
|
|
16
|
+
spectaLayoutRegistry,
|
|
17
|
+
spectaConfig
|
|
17
18
|
});
|
|
18
19
|
const widgetFactory = new NotebookGridWidgetFactory({
|
|
19
20
|
name: factoryName,
|
|
20
21
|
modelName: 'notebook',
|
|
21
|
-
fileTypes: ['
|
|
22
|
+
fileTypes: ['notebook'],
|
|
22
23
|
spectaWidgetFactory,
|
|
23
24
|
preferKernel: true,
|
|
24
25
|
canStartKernel: true,
|
|
@@ -27,18 +28,6 @@ export function registerDocumentFactory(options) {
|
|
|
27
28
|
});
|
|
28
29
|
// Registering the widget factory
|
|
29
30
|
app.docRegistry.addWidgetFactory(widgetFactory);
|
|
30
|
-
// Creating and registering the model factory for our custom DocumentModel
|
|
31
|
-
const modelFactory = new NotebookModelFactory({});
|
|
32
|
-
app.docRegistry.addModelFactory(modelFactory);
|
|
33
|
-
// register the filetype
|
|
34
|
-
app.docRegistry.addFileType({
|
|
35
|
-
name: 'ipynb',
|
|
36
|
-
displayName: 'IPYNB',
|
|
37
|
-
mimeTypes: ['text/json'],
|
|
38
|
-
extensions: ['.ipynb', '.IPYNB'],
|
|
39
|
-
fileFormat: 'json',
|
|
40
|
-
contentType: 'notebook'
|
|
41
|
-
});
|
|
42
31
|
widgetFactory.widgetCreated.connect((sender, widget) => {
|
|
43
32
|
widget.context.pathChanged.connect(() => {
|
|
44
33
|
spectaTracker.save(widget);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare namespace ProgressCircle {
|
|
2
|
+
/**
|
|
3
|
+
* Props for the ProgressBar.
|
|
4
|
+
*/
|
|
5
|
+
interface IProps {
|
|
6
|
+
/**
|
|
7
|
+
* The current progress percentage, from 0 to 100
|
|
8
|
+
*/
|
|
9
|
+
progress: number;
|
|
10
|
+
/**
|
|
11
|
+
* The aria-label for the widget
|
|
12
|
+
*/
|
|
13
|
+
label?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Element width
|
|
16
|
+
*/
|
|
17
|
+
width?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Element height
|
|
20
|
+
*/
|
|
21
|
+
height?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Color ò the stroke
|
|
24
|
+
*/
|
|
25
|
+
stroke?: string;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export declare function ProgressCircle(props: ProgressCircle.IProps): JSX.Element;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export function ProgressCircle(props) {
|
|
3
|
+
var _a, _b;
|
|
4
|
+
const radius = 104;
|
|
5
|
+
const d = (progress) => {
|
|
6
|
+
const angle = Math.max(progress * 3.6, 0.1);
|
|
7
|
+
const rad = (angle * Math.PI) / 180, x = Math.sin(rad) * radius, y = Math.cos(rad) * -radius, mid = angle < 180 ? 1 : 0, shape = `M 0 0 v -${radius} A ${radius} ${radius} 1 ` +
|
|
8
|
+
mid +
|
|
9
|
+
' 0 ' +
|
|
10
|
+
x.toFixed(4) +
|
|
11
|
+
' ' +
|
|
12
|
+
y.toFixed(4) +
|
|
13
|
+
' z';
|
|
14
|
+
return shape;
|
|
15
|
+
};
|
|
16
|
+
return (React.createElement("div", { className: 'jp-Statusbar-ProgressCircle', role: "progressbar", "aria-label": props.label || 'Unlabelled progress circle', "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": props.progress, style: { margin: 'auto' } },
|
|
17
|
+
React.createElement("svg", { viewBox: "0 0 250 250" },
|
|
18
|
+
React.createElement("circle", { cx: "125", cy: "125", r: `${radius}`, strokeWidth: "20", fill: "none", stroke: (_a = props.stroke) !== null && _a !== void 0 ? _a : 'var(--jp-inverse-layout-color2)' }),
|
|
19
|
+
React.createElement("path", { transform: "translate(125,125) scale(.9)", d: d(props.progress), fill: (_b = props.stroke) !== null && _b !== void 0 ? _b : 'var(--jp-inverse-layout-color2)' }))));
|
|
20
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { IThemeManager } from '@jupyterlab/apputils';
|
|
2
|
+
import { ReactWidget } from '@jupyterlab/ui-components';
|
|
3
|
+
import { TopbarElement } from './widget';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { isSpectaApp } from '../tool';
|
|
6
|
+
import { ISpectaLayoutRegistry } from '../token';
|
|
7
|
+
import { PageConfig } from '@jupyterlab/coreutils';
|
|
8
|
+
/**
|
|
9
|
+
* Initialization data for the voila_topbar extension.
|
|
10
|
+
*/
|
|
11
|
+
export const topbarPlugin = {
|
|
12
|
+
id: 'specta:topba',
|
|
13
|
+
description: 'Specta topbar extension',
|
|
14
|
+
autoStart: true,
|
|
15
|
+
requires: [IThemeManager, ISpectaLayoutRegistry],
|
|
16
|
+
activate: (app, themeManager, layoutRegistry) => {
|
|
17
|
+
var _a;
|
|
18
|
+
const isSpecta = isSpectaApp();
|
|
19
|
+
if (!isSpecta) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const config = JSON.parse((_a = PageConfig.getOption('spectaConfig')) !== null && _a !== void 0 ? _a : '{}');
|
|
23
|
+
const widget = ReactWidget.create(React.createElement(TopbarElement, { config: config.topBar, themeManager: themeManager, layoutRegistry: layoutRegistry }));
|
|
24
|
+
widget.id = 'specta-topbar-widget';
|
|
25
|
+
widget.addClass('specta-topbar-element');
|
|
26
|
+
app.shell.add(widget, 'top');
|
|
27
|
+
if (widget.parent) {
|
|
28
|
+
widget.parent.node.style.boxShadow =
|
|
29
|
+
'rgba(0 0 0 / 20%) 0 2px 4px -1px, rgba(0 0 0 / 14%) 0 4px 5px 0, rgba(0 0 0 / 12%) 0 1px 10px 0';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { IThemeManager } from '@jupyterlab/apputils';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { ISpectaLayoutRegistry } from '../token';
|
|
4
|
+
export declare const SettingContent: (props: {
|
|
5
|
+
themeManager?: IThemeManager;
|
|
6
|
+
layoutRegistry?: ISpectaLayoutRegistry;
|
|
7
|
+
}) => React.JSX.Element;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React, { useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import { Divider } from '../components/divider';
|
|
3
|
+
export const SettingContent = (props) => {
|
|
4
|
+
var _a, _b, _c, _d, _e;
|
|
5
|
+
const { themeManager, layoutRegistry } = props;
|
|
6
|
+
const [themeOptions, setThemeOptions] = useState([
|
|
7
|
+
...((_a = themeManager === null || themeManager === void 0 ? void 0 : themeManager.themes) !== null && _a !== void 0 ? _a : [])
|
|
8
|
+
]);
|
|
9
|
+
const [selectedTheme, setSelectedTheme] = useState((_b = themeManager === null || themeManager === void 0 ? void 0 : themeManager.theme) !== null && _b !== void 0 ? _b : 'light');
|
|
10
|
+
const [layoutOptions, setLayoutOptions] = useState((_c = layoutRegistry === null || layoutRegistry === void 0 ? void 0 : layoutRegistry.allLayouts()) !== null && _c !== void 0 ? _c : []);
|
|
11
|
+
const [selectedLayout, setSelectedLayout] = useState((_e = (_d = layoutRegistry === null || layoutRegistry === void 0 ? void 0 : layoutRegistry.selectedLayout) === null || _d === void 0 ? void 0 : _d.name) !== null && _e !== void 0 ? _e : 'default');
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
let cb;
|
|
14
|
+
if (themeManager) {
|
|
15
|
+
cb = (sender, args) => {
|
|
16
|
+
if (args.newValue.length > 0) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
setThemeOptions([...themeManager.themes]);
|
|
20
|
+
if (themeManager.theme) {
|
|
21
|
+
setSelectedTheme(themeManager.theme);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
themeManager.themeChanged.connect(cb);
|
|
25
|
+
}
|
|
26
|
+
if (layoutRegistry) {
|
|
27
|
+
const layoutAddedCb = (sender, newLayout) => {
|
|
28
|
+
setLayoutOptions(layoutRegistry.allLayouts());
|
|
29
|
+
};
|
|
30
|
+
layoutRegistry.layoutAdded.connect(layoutAddedCb);
|
|
31
|
+
}
|
|
32
|
+
return () => {
|
|
33
|
+
if (themeManager && cb) {
|
|
34
|
+
themeManager.themeChanged.disconnect(cb);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}, [themeManager, layoutRegistry]);
|
|
38
|
+
const onThemeChange = useCallback((e) => {
|
|
39
|
+
var _a;
|
|
40
|
+
const theme = (_a = e.currentTarget) === null || _a === void 0 ? void 0 : _a.value;
|
|
41
|
+
if (theme) {
|
|
42
|
+
themeManager === null || themeManager === void 0 ? void 0 : themeManager.setTheme(theme);
|
|
43
|
+
setSelectedTheme(theme);
|
|
44
|
+
}
|
|
45
|
+
}, [themeManager]);
|
|
46
|
+
const onLayoutChange = useCallback((e) => {
|
|
47
|
+
var _a;
|
|
48
|
+
const layout = (_a = e.currentTarget) === null || _a === void 0 ? void 0 : _a.value;
|
|
49
|
+
if (layout && layoutRegistry) {
|
|
50
|
+
layoutRegistry.setSelectedLayout(layout);
|
|
51
|
+
setSelectedLayout(layout);
|
|
52
|
+
}
|
|
53
|
+
}, [layoutRegistry]);
|
|
54
|
+
return (React.createElement("div", { style: { padding: '0 10px' } },
|
|
55
|
+
React.createElement("p", { style: { marginTop: 0, marginBottom: '5px', fontSize: '1rem' } }, "SETTINGS"),
|
|
56
|
+
React.createElement(Divider, null),
|
|
57
|
+
layoutRegistry && (React.createElement("div", null,
|
|
58
|
+
React.createElement("label", { htmlFor: "" }, "Select layout"),
|
|
59
|
+
React.createElement("div", { className: "jp-select-wrapper" },
|
|
60
|
+
React.createElement("select", { className: " jp-mod-styled specta-topbar-theme", onChange: onLayoutChange, value: selectedLayout }, layoutOptions.map(el => {
|
|
61
|
+
return (React.createElement("option", { key: el, value: el, style: {
|
|
62
|
+
background: 'var(--jp-layout-color2)'
|
|
63
|
+
} }, el.charAt(0).toUpperCase() + el.slice(1)));
|
|
64
|
+
}))))),
|
|
65
|
+
themeManager && (React.createElement("div", null,
|
|
66
|
+
React.createElement("label", { htmlFor: "" }, "Select theme"),
|
|
67
|
+
React.createElement("div", { className: "jp-select-wrapper" },
|
|
68
|
+
React.createElement("select", { className: " jp-mod-styled specta-topbar-theme", onChange: onThemeChange, value: selectedTheme }, themeOptions.map(el => {
|
|
69
|
+
return (React.createElement("option", { key: el, value: el, style: {
|
|
70
|
+
background: 'var(--jp-layout-color2)'
|
|
71
|
+
} }, el));
|
|
72
|
+
})))))));
|
|
73
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { IThemeManager } from '@jupyterlab/apputils';
|
|
2
|
+
import { ISpectaLayoutRegistry, ITopbarConfig } from '../token';
|
|
3
|
+
interface IProps {
|
|
4
|
+
config?: ITopbarConfig;
|
|
5
|
+
themeManager?: IThemeManager;
|
|
6
|
+
layoutRegistry?: ISpectaLayoutRegistry;
|
|
7
|
+
}
|
|
8
|
+
export declare function TopbarElement(props: IProps): JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React, { useState, useRef, useEffect } from 'react';
|
|
2
|
+
import { GearIcon } from '../components/icon/gear';
|
|
3
|
+
import { IconButton } from '../components/iconButton';
|
|
4
|
+
import { SettingContent } from './settingDialog';
|
|
5
|
+
export function TopbarElement(props) {
|
|
6
|
+
var _a, _b;
|
|
7
|
+
const config = React.useMemo(() => {
|
|
8
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
9
|
+
return {
|
|
10
|
+
background: (_b = (_a = props.config) === null || _a === void 0 ? void 0 : _a.background) !== null && _b !== void 0 ? _b : 'var(--jp-layout-color2)',
|
|
11
|
+
title: (_d = (_c = props.config) === null || _c === void 0 ? void 0 : _c.title) !== null && _d !== void 0 ? _d : 'Specta',
|
|
12
|
+
themeToggle: Boolean((_e = props.config) === null || _e === void 0 ? void 0 : _e.themeToggle),
|
|
13
|
+
kernelActivity: Boolean((_f = props.config) === null || _f === void 0 ? void 0 : _f.kernelActivity),
|
|
14
|
+
textColor: (_h = (_g = props.config) === null || _g === void 0 ? void 0 : _g.textColor) !== null && _h !== void 0 ? _h : 'var(--jp-ui-font-color1)'
|
|
15
|
+
};
|
|
16
|
+
}, [props.config]);
|
|
17
|
+
const [open, setOpen] = useState(false);
|
|
18
|
+
const buttonRef = useRef(null);
|
|
19
|
+
const dialogRef = useRef(null);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
const handleClickOutside = (e) => {
|
|
22
|
+
if (dialogRef.current &&
|
|
23
|
+
!dialogRef.current.contains(e.target) &&
|
|
24
|
+
buttonRef.current &&
|
|
25
|
+
!buttonRef.current.contains(e.target)) {
|
|
26
|
+
setOpen(false);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
30
|
+
return () => document.removeEventListener('mousedown', handleClickOutside);
|
|
31
|
+
}, []);
|
|
32
|
+
return (React.createElement("div", { className: "specta-topbar", style: { background: (_a = config.background) !== null && _a !== void 0 ? _a : 'var(--jp-layout-color2)' } },
|
|
33
|
+
React.createElement("div", { className: "specta-topbar-left" },
|
|
34
|
+
React.createElement("div", null, config.icon && React.createElement("img", { style: { width: '50px' }, src: config.icon })),
|
|
35
|
+
React.createElement("div", { className: "specta-topbar-title", style: { color: (_b = config.textColor) !== null && _b !== void 0 ? _b : 'var(--jp-ui-font-color1)' } }, config.title)),
|
|
36
|
+
React.createElement("div", { className: "specta-topbar-right" },
|
|
37
|
+
React.createElement(IconButton, { ref: buttonRef, onClick: () => setOpen(!open), icon: React.createElement(GearIcon, { fill: "var(--jp-ui-font-color2)", height: 24, width: 24 }) }),
|
|
38
|
+
open && (React.createElement("div", { ref: dialogRef, className: "jp-Dialog-content specta-config-dialog" },
|
|
39
|
+
React.createElement("div", { className: "specta-config-arrow" }),
|
|
40
|
+
React.createElement(SettingContent, { themeManager: props.themeManager, layoutRegistry: props.layoutRegistry }))))));
|
|
41
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jupyter-specta",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"homepage": "https://github.com/trungleduc/specta",
|
|
@@ -74,13 +74,13 @@
|
|
|
74
74
|
"@jupyterlab/translation": "^4.4.2",
|
|
75
75
|
"@jupyterlab/translation-extension": "^4.4.2",
|
|
76
76
|
"@jupyterlab/ui-components": "^4.4.2",
|
|
77
|
-
"@jupyterlite/application": "^0.6.
|
|
78
|
-
"@jupyterlite/application-extension": "^0.6.
|
|
79
|
-
"@jupyterlite/contents": "^0.6.
|
|
80
|
-
"@jupyterlite/iframe-extension": "^0.6.
|
|
81
|
-
"@jupyterlite/kernel": "^0.6.
|
|
82
|
-
"@jupyterlite/server": "^0.6.
|
|
83
|
-
"@jupyterlite/services-extension": "^0.6.
|
|
77
|
+
"@jupyterlite/application": "^0.6.2",
|
|
78
|
+
"@jupyterlite/application-extension": "^0.6.2",
|
|
79
|
+
"@jupyterlite/contents": "^0.6.2",
|
|
80
|
+
"@jupyterlite/iframe-extension": "^0.6.2",
|
|
81
|
+
"@jupyterlite/kernel": "^0.6.2",
|
|
82
|
+
"@jupyterlite/server": "^0.6.2",
|
|
83
|
+
"@jupyterlite/services-extension": "^0.6.2",
|
|
84
84
|
"@lumino/algorithm": "^2.0.0",
|
|
85
85
|
"@lumino/application": "^2.0.0",
|
|
86
86
|
"@lumino/commands": "^2.0.0",
|
|
@@ -96,16 +96,20 @@
|
|
|
96
96
|
"@lumino/signaling": "^2.0.0",
|
|
97
97
|
"@lumino/virtualdom": "^2.0.0",
|
|
98
98
|
"@lumino/widgets": "^2.0.0",
|
|
99
|
-
"@voila-dashboards/voila": "^0.5.5"
|
|
99
|
+
"@voila-dashboards/voila": "^0.5.5",
|
|
100
|
+
"react": "^18.3.0",
|
|
101
|
+
"react-dom": "^18.3.0"
|
|
100
102
|
},
|
|
101
103
|
"devDependencies": {
|
|
102
104
|
"@jupyterlab/builder": "~4.4.2",
|
|
103
105
|
"@typescript-eslint/eslint-plugin": "^6.1.0",
|
|
104
106
|
"@typescript-eslint/parser": "^6.1.0",
|
|
107
|
+
"@types/react": "^18.0.26",
|
|
105
108
|
"css-loader": "^7.1.2",
|
|
106
109
|
"eslint": "^8.36.0",
|
|
107
110
|
"eslint-config-prettier": "^8.8.0",
|
|
108
111
|
"eslint-plugin-prettier": "^5.0.0",
|
|
112
|
+
"eslint-plugin-react-hooks": "^5.0.0",
|
|
109
113
|
"handlebars": "^4.7.8",
|
|
110
114
|
"html-webpack-plugin": "^5.5.3",
|
|
111
115
|
"ignore-loader": "^0.1.2",
|
|
@@ -140,7 +144,8 @@
|
|
|
140
144
|
"eslint:recommended",
|
|
141
145
|
"plugin:@typescript-eslint/eslint-recommended",
|
|
142
146
|
"plugin:@typescript-eslint/recommended",
|
|
143
|
-
"plugin:prettier/recommended"
|
|
147
|
+
"plugin:prettier/recommended",
|
|
148
|
+
"plugin:react-hooks/recommended"
|
|
144
149
|
],
|
|
145
150
|
"parser": "@typescript-eslint/parser",
|
|
146
151
|
"parserOptions": {
|
|
@@ -148,9 +153,11 @@
|
|
|
148
153
|
"sourceType": "module"
|
|
149
154
|
},
|
|
150
155
|
"plugins": [
|
|
151
|
-
"@typescript-eslint"
|
|
156
|
+
"@typescript-eslint",
|
|
157
|
+
"react-hooks"
|
|
152
158
|
],
|
|
153
159
|
"rules": {
|
|
160
|
+
"react-hooks/exhaustive-deps": "error",
|
|
154
161
|
"@typescript-eslint/naming-convention": [
|
|
155
162
|
"error",
|
|
156
163
|
{
|