@jupyterlab/statusbar 4.0.0-alpha.19 → 4.0.0-alpha.20

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": "@jupyterlab/statusbar",
3
- "version": "4.0.0-alpha.19",
3
+ "version": "4.0.0-alpha.20",
4
4
  "description": "JupyterLab statusbar package.",
5
5
  "homepage": "https://github.com/jupyterlab/jupyterlab",
6
6
  "bugs": {
@@ -22,7 +22,8 @@
22
22
  "files": [
23
23
  "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
24
24
  "style/**/*.{css,eot,gif,html,jpg,json,png,svg,woff2,ttf}",
25
- "style/index.js"
25
+ "style/index.js",
26
+ "src/**/*.{ts,tsx}"
26
27
  ],
27
28
  "scripts": {
28
29
  "build": "tsc -b",
@@ -36,20 +37,20 @@
36
37
  "watch": "tsc -b --watch"
37
38
  },
38
39
  "dependencies": {
39
- "@jupyterlab/ui-components": "^4.0.0-alpha.34",
40
- "@lumino/algorithm": "^2.0.0-beta.0",
41
- "@lumino/coreutils": "^2.0.0-beta.0",
42
- "@lumino/disposable": "^2.0.0-beta.1",
43
- "@lumino/messaging": "^2.0.0-beta.0",
44
- "@lumino/signaling": "^2.0.0-beta.1",
45
- "@lumino/widgets": "^2.0.0-beta.1",
40
+ "@jupyterlab/ui-components": "^4.0.0-alpha.35",
41
+ "@lumino/algorithm": "^2.0.0-rc.0",
42
+ "@lumino/coreutils": "^2.0.0-rc.0",
43
+ "@lumino/disposable": "^2.0.0-rc.0",
44
+ "@lumino/messaging": "^2.0.0-rc.0",
45
+ "@lumino/signaling": "^2.0.0-rc.0",
46
+ "@lumino/widgets": "^2.0.0-rc.0",
46
47
  "react": "^18.2.0"
47
48
  },
48
49
  "devDependencies": {
49
- "@jupyterlab/testing": "^4.0.0-alpha.19",
50
+ "@jupyterlab/testing": "^4.0.0-alpha.20",
50
51
  "@types/jest": "^29.2.0",
51
52
  "rimraf": "~3.0.0",
52
- "typescript": "~4.7.3"
53
+ "typescript": "~5.0.0-beta"
53
54
  },
54
55
  "publishConfig": {
55
56
  "access": "public"
@@ -0,0 +1,48 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+
4
+ import * as React from 'react';
5
+
6
+ /**
7
+ * A tsx component for a set of items logically grouped together.
8
+ */
9
+ export function GroupItem(
10
+ props: GroupItem.IProps & React.HTMLAttributes<HTMLDivElement>
11
+ ): React.ReactElement<GroupItem.IProps> {
12
+ const { spacing, children, className, ...rest } = props;
13
+ const numChildren = React.Children.count(children);
14
+
15
+ return (
16
+ <div className={`jp-StatusBar-GroupItem ${className}`} {...rest}>
17
+ {React.Children.map(children, (child, i) => {
18
+ if (i === 0) {
19
+ return <div style={{ marginRight: `${spacing}px` }}>{child}</div>;
20
+ } else if (i === numChildren - 1) {
21
+ return <div style={{ marginLeft: `${spacing}px` }}>{child}</div>;
22
+ } else {
23
+ return <div style={{ margin: `0px ${spacing}px` }}>{child}</div>;
24
+ }
25
+ })}
26
+ </div>
27
+ );
28
+ }
29
+
30
+ /**
31
+ * A namespace for GroupItem statics.
32
+ */
33
+ export namespace GroupItem {
34
+ /**
35
+ * Props for the GroupItem.
36
+ */
37
+ export interface IProps {
38
+ /**
39
+ * The spacing, in px, between the items in the group.
40
+ */
41
+ spacing: number;
42
+
43
+ /**
44
+ * The items to arrange in a group.
45
+ */
46
+ children: JSX.Element[];
47
+ }
48
+ }
@@ -0,0 +1,214 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+
4
+ import { HoverBox } from '@jupyterlab/ui-components';
5
+ import { Message } from '@lumino/messaging';
6
+ import { PanelLayout, Widget } from '@lumino/widgets';
7
+
8
+ /**
9
+ * Create and show a popup component.
10
+ *
11
+ * @param options - options for the popup
12
+ *
13
+ * @returns the popup that was created.
14
+ */
15
+ export function showPopup(options: Popup.IOptions): Popup {
16
+ const dialog = new Popup(options);
17
+ if (!options.startHidden) {
18
+ dialog.launch();
19
+ }
20
+ return dialog;
21
+ }
22
+
23
+ /**
24
+ * A class for a Popup widget.
25
+ */
26
+ export class Popup extends Widget {
27
+ /**
28
+ * Construct a new Popup.
29
+ */
30
+ constructor(options: Omit<Popup.IOptions, 'startHidden'>) {
31
+ super();
32
+ this._body = options.body;
33
+ this._body.addClass('jp-StatusBar-HoverItem');
34
+ this._anchor = options.anchor;
35
+ this._align = options.align;
36
+ if (options.hasDynamicSize) {
37
+ this._observer = new ResizeObserver(() => {
38
+ this.update();
39
+ });
40
+ }
41
+ const layout = (this.layout = new PanelLayout());
42
+ layout.addWidget(options.body);
43
+ this._body.node.addEventListener('resize', () => {
44
+ this.update();
45
+ });
46
+ }
47
+
48
+ /**
49
+ * Attach the popup widget to the page.
50
+ */
51
+ launch(): void {
52
+ this._setGeometry();
53
+ Widget.attach(this, document.body);
54
+ this.update();
55
+ this._anchor.addClass('jp-mod-clicked');
56
+ this._anchor.removeClass('jp-mod-highlight');
57
+ }
58
+
59
+ /**
60
+ * Handle `'update'` messages for the widget.
61
+ */
62
+ protected onUpdateRequest(msg: Message): void {
63
+ this._setGeometry();
64
+ super.onUpdateRequest(msg);
65
+ }
66
+
67
+ /**
68
+ * Handle `'after-attach'` messages for the widget.
69
+ */
70
+ protected onAfterAttach(msg: Message): void {
71
+ document.addEventListener('click', this, false);
72
+ this.node.addEventListener('keydown', this, false);
73
+ window.addEventListener('resize', this, false);
74
+ this._observer?.observe(this._body.node);
75
+ }
76
+
77
+ /**
78
+ * Handle `'before-detach'` messages for the widget.
79
+ */
80
+ protected onBeforeDetach(msg: Message): void {
81
+ this._observer?.disconnect();
82
+ document.removeEventListener('click', this, false);
83
+ this.node.removeEventListener('keydown', this, false);
84
+ window.removeEventListener('resize', this, false);
85
+ }
86
+
87
+ /**
88
+ * Handle `'resize'` messages for the widget.
89
+ */
90
+ protected onResize(): void {
91
+ this.update();
92
+ }
93
+
94
+ /**
95
+ * Dispose of the widget.
96
+ */
97
+ dispose(): void {
98
+ this._observer?.disconnect();
99
+ super.dispose();
100
+ this._anchor.removeClass('jp-mod-clicked');
101
+ this._anchor.addClass('jp-mod-highlight');
102
+ }
103
+
104
+ /**
105
+ * Handle DOM events for the widget.
106
+ */
107
+ handleEvent(event: Event): void {
108
+ switch (event.type) {
109
+ case 'keydown':
110
+ this._evtKeydown(event as KeyboardEvent);
111
+ break;
112
+ case 'click':
113
+ this._evtClick(event as MouseEvent);
114
+ break;
115
+ case 'resize':
116
+ this.onResize();
117
+ break;
118
+ default:
119
+ break;
120
+ }
121
+ }
122
+
123
+ private _evtClick(event: MouseEvent): void {
124
+ if (
125
+ !!event.target &&
126
+ !(
127
+ this._body.node.contains(event.target as HTMLElement) ||
128
+ this._anchor.node.contains(event.target as HTMLElement)
129
+ )
130
+ ) {
131
+ this.dispose();
132
+ }
133
+ }
134
+
135
+ private _evtKeydown(event: KeyboardEvent): void {
136
+ // Check for escape key
137
+ switch (event.keyCode) {
138
+ case 27: // Escape.
139
+ event.stopPropagation();
140
+ event.preventDefault();
141
+ this.dispose();
142
+ break;
143
+ default:
144
+ break;
145
+ }
146
+ }
147
+
148
+ private _setGeometry(): void {
149
+ let aligned = 0;
150
+ const anchorRect = this._anchor.node.getBoundingClientRect();
151
+ const bodyRect = this._body.node.getBoundingClientRect();
152
+ if (this._align === 'right') {
153
+ aligned = -(bodyRect.width - anchorRect.width);
154
+ }
155
+ const style = window.getComputedStyle(this._body.node);
156
+ HoverBox.setGeometry({
157
+ anchor: anchorRect,
158
+ host: document.body,
159
+ maxHeight: 500,
160
+ minHeight: 20,
161
+ node: this._body.node,
162
+ offset: {
163
+ horizontal: aligned
164
+ },
165
+ privilege: 'forceAbove',
166
+ style
167
+ });
168
+ }
169
+
170
+ private _body: Widget;
171
+ private _anchor: Widget;
172
+ private _align: 'left' | 'right' | undefined;
173
+ private _observer: ResizeObserver | null;
174
+ }
175
+
176
+ /**
177
+ * A namespace for Popup statics.
178
+ */
179
+ export namespace Popup {
180
+ /**
181
+ * Options for creating a Popup widget.
182
+ */
183
+ export interface IOptions {
184
+ /**
185
+ * The content of the popup.
186
+ */
187
+ body: Widget;
188
+
189
+ /**
190
+ * The widget to which we are attaching the popup.
191
+ */
192
+ anchor: Widget;
193
+
194
+ /**
195
+ * Whether to align the popup to the left or the right of the anchor.
196
+ */
197
+ align?: 'left' | 'right';
198
+
199
+ /**
200
+ * Whether the body has dynamic size or not.
201
+ * By default, this is `false`.
202
+ */
203
+ hasDynamicSize?: boolean;
204
+
205
+ /**
206
+ * Whether to start the popup in hidden mode or not.
207
+ * By default, this is `false`.
208
+ *
209
+ * ### Note
210
+ * The popup can be displayed using `launch` method.
211
+ */
212
+ startHidden?: boolean;
213
+ }
214
+ }
@@ -0,0 +1,8 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+
4
+ export * from './group';
5
+ export * from './hover';
6
+ export * from './progressBar';
7
+ export * from './text';
8
+ export * from './progressCircle';
@@ -0,0 +1,87 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+
4
+ import * as React from 'react';
5
+
6
+ /**
7
+ * A namespace for ProgressBar statics.
8
+ */
9
+ export namespace ProgressBar {
10
+ /**
11
+ * Props for the ProgressBar.
12
+ */
13
+ export interface IProps {
14
+ /**
15
+ * The current progress percentage, from 0 to 100
16
+ */
17
+ percentage: number;
18
+
19
+ /**
20
+ * Width of progress bar in pixel.
21
+ */
22
+ width?: number;
23
+
24
+ /**
25
+ * Text to show inside progress bar.
26
+ */
27
+ content?: string;
28
+ }
29
+ }
30
+
31
+ /**
32
+ * A functional tsx component for a progress bar.
33
+ */
34
+ export function ProgressBar(props: ProgressBar.IProps): JSX.Element {
35
+ const { width, percentage, ...rest } = props;
36
+ return (
37
+ <div
38
+ className={'jp-Statusbar-ProgressBar-progress-bar'}
39
+ role="progressbar"
40
+ aria-valuemin={0}
41
+ aria-valuemax={100}
42
+ aria-valuenow={percentage}
43
+ >
44
+ <Filler {...{ percentage, ...rest }} contentWidth={width} />
45
+ </div>
46
+ );
47
+ }
48
+
49
+ /**
50
+ * A namespace for Filler statics.
51
+ */
52
+ namespace Filler {
53
+ /**
54
+ * Props for the Filler component.
55
+ */
56
+ export interface IProps {
57
+ /**
58
+ * The current percentage filled, from 0 to 100
59
+ */
60
+ percentage: number;
61
+
62
+ /**
63
+ * Width of content inside filler.
64
+ */
65
+ contentWidth?: number;
66
+
67
+ /**
68
+ * Text to show inside filler.
69
+ */
70
+ content?: string;
71
+ }
72
+ }
73
+
74
+ /**
75
+ * A functional tsx component for a partially filled div.
76
+ */
77
+ function Filler(props: Filler.IProps) {
78
+ return (
79
+ <div
80
+ style={{
81
+ width: `${props.percentage}%`
82
+ }}
83
+ >
84
+ <p>{props.content}</p>
85
+ </div>
86
+ );
87
+ }
@@ -0,0 +1,75 @@
1
+ /*
2
+ * Copyright (c) Jupyter Development Team.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+
6
+ import React from 'react';
7
+ export namespace ProgressCircle {
8
+ /**
9
+ * Props for the ProgressBar.
10
+ */
11
+ export interface IProps {
12
+ /**
13
+ * The current progress percentage, from 0 to 100
14
+ */
15
+ progress: number;
16
+ /**
17
+ * The aria-label for the widget
18
+ */
19
+ label?: string;
20
+ /**
21
+ * Element width
22
+ */
23
+ width?: number;
24
+ /**
25
+ * Element height
26
+ */
27
+ height?: number;
28
+ }
29
+ }
30
+
31
+ export function ProgressCircle(props: ProgressCircle.IProps): JSX.Element {
32
+ const radius = 104;
33
+ const d = (progress: number): string => {
34
+ const angle = Math.max(progress * 3.6, 0.1);
35
+ const rad = (angle * Math.PI) / 180,
36
+ x = Math.sin(rad) * radius,
37
+ y = Math.cos(rad) * -radius,
38
+ mid = angle < 180 ? 1 : 0,
39
+ shape =
40
+ `M 0 0 v -${radius} A ${radius} ${radius} 1 ` +
41
+ mid +
42
+ ' 0 ' +
43
+ x.toFixed(4) +
44
+ ' ' +
45
+ y.toFixed(4) +
46
+ ' z';
47
+ return shape;
48
+ };
49
+ return (
50
+ <div
51
+ className={'jp-Statusbar-ProgressCircle'}
52
+ role="progressbar"
53
+ aria-label={props.label || 'Unlabelled progress circle'}
54
+ aria-valuemin={0}
55
+ aria-valuemax={100}
56
+ aria-valuenow={props.progress}
57
+ >
58
+ <svg viewBox="0 0 250 250">
59
+ <circle
60
+ cx="125"
61
+ cy="125"
62
+ r={`${radius}`}
63
+ stroke="var(--jp-inverse-layout-color3)"
64
+ strokeWidth="20"
65
+ fill="none"
66
+ />
67
+ <path
68
+ transform="translate(125,125) scale(.9)"
69
+ d={d(props.progress)}
70
+ fill={'var(--jp-inverse-layout-color3)'}
71
+ />
72
+ </svg>
73
+ </div>
74
+ );
75
+ }
@@ -0,0 +1,42 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+
4
+ import * as React from 'react';
5
+
6
+ /**
7
+ * A namespace for TextItem statics.
8
+ */
9
+ export namespace TextItem {
10
+ /**
11
+ * Props for a TextItem.
12
+ */
13
+ export interface IProps {
14
+ /**
15
+ * The content of the text item.
16
+ */
17
+ source: string | number;
18
+
19
+ /**
20
+ * Hover text to give to the node.
21
+ */
22
+ title?: string;
23
+ }
24
+ }
25
+
26
+ /**
27
+ * A functional tsx component for a text item.
28
+ */
29
+ export function TextItem(
30
+ props: TextItem.IProps & React.HTMLAttributes<HTMLSpanElement>
31
+ ): React.ReactElement<TextItem.IProps> {
32
+ const { title, source, className, ...rest } = props;
33
+ return (
34
+ <span
35
+ className={`jp-StatusBar-TextItem ${className}`}
36
+ title={title}
37
+ {...rest}
38
+ >
39
+ {source}
40
+ </span>
41
+ );
42
+ }
package/src/index.ts ADDED
@@ -0,0 +1,12 @@
1
+ /* -----------------------------------------------------------------------------
2
+ | Copyright (c) Jupyter Development Team.
3
+ | Distributed under the terms of the Modified BSD License.
4
+ |----------------------------------------------------------------------------*/
5
+ /**
6
+ * @packageDocumentation
7
+ * @module statusbar
8
+ */
9
+
10
+ export * from './components';
11
+ export * from './statusbar';
12
+ export * from './tokens';
@@ -0,0 +1,185 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+
4
+ import { ArrayExt } from '@lumino/algorithm';
5
+ import {
6
+ DisposableDelegate,
7
+ DisposableSet,
8
+ IDisposable
9
+ } from '@lumino/disposable';
10
+ import { Message } from '@lumino/messaging';
11
+ import { Panel, PanelLayout, Widget } from '@lumino/widgets';
12
+ import { IStatusBar } from './tokens';
13
+
14
+ /**
15
+ * Main status bar object which contains all items.
16
+ */
17
+ export class StatusBar extends Widget implements IStatusBar {
18
+ constructor() {
19
+ super();
20
+ this.addClass('jp-StatusBar-Widget');
21
+
22
+ const rootLayout = (this.layout = new PanelLayout());
23
+
24
+ const leftPanel = (this._leftSide = new Panel());
25
+ const middlePanel = (this._middlePanel = new Panel());
26
+ const rightPanel = (this._rightSide = new Panel());
27
+
28
+ leftPanel.addClass('jp-StatusBar-Left');
29
+ middlePanel.addClass('jp-StatusBar-Middle');
30
+ rightPanel.addClass('jp-StatusBar-Right');
31
+
32
+ rootLayout.addWidget(leftPanel);
33
+ rootLayout.addWidget(middlePanel);
34
+ rootLayout.addWidget(rightPanel);
35
+ }
36
+
37
+ /**
38
+ * Register a new status item.
39
+ *
40
+ * @param id - a unique id for the status item.
41
+ *
42
+ * @param statusItem - The item to add to the status bar.
43
+ */
44
+ registerStatusItem(id: string, statusItem: IStatusBar.IItem): IDisposable {
45
+ if (id in this._statusItems) {
46
+ throw new Error(`Status item ${id} already registered.`);
47
+ }
48
+
49
+ // Populate defaults for the optional properties of the status item.
50
+ const fullStatusItem = {
51
+ ...Private.statusItemDefaults,
52
+ ...statusItem
53
+ } as Private.IFullItem;
54
+ const { align, item, rank } = fullStatusItem;
55
+
56
+ // Connect the activeStateChanged signal to refreshing the status item,
57
+ // if the signal was provided.
58
+ const onActiveStateChanged = () => {
59
+ this._refreshItem(id);
60
+ };
61
+ if (fullStatusItem.activeStateChanged) {
62
+ fullStatusItem.activeStateChanged.connect(onActiveStateChanged);
63
+ }
64
+
65
+ const rankItem = { id, rank };
66
+
67
+ fullStatusItem.item.addClass('jp-StatusBar-Item');
68
+ this._statusItems[id] = fullStatusItem;
69
+
70
+ if (align === 'left') {
71
+ const insertIndex = this._findInsertIndex(this._leftRankItems, rankItem);
72
+ if (insertIndex === -1) {
73
+ this._leftSide.addWidget(item);
74
+ this._leftRankItems.push(rankItem);
75
+ } else {
76
+ ArrayExt.insert(this._leftRankItems, insertIndex, rankItem);
77
+ this._leftSide.insertWidget(insertIndex, item);
78
+ }
79
+ } else if (align === 'right') {
80
+ const insertIndex = this._findInsertIndex(this._rightRankItems, rankItem);
81
+ if (insertIndex === -1) {
82
+ this._rightSide.addWidget(item);
83
+ this._rightRankItems.push(rankItem);
84
+ } else {
85
+ ArrayExt.insert(this._rightRankItems, insertIndex, rankItem);
86
+ this._rightSide.insertWidget(insertIndex, item);
87
+ }
88
+ } else {
89
+ this._middlePanel.addWidget(item);
90
+ }
91
+ this._refreshItem(id); // Initially refresh the status item.
92
+
93
+ const disposable = new DisposableDelegate(() => {
94
+ delete this._statusItems[id];
95
+ if (fullStatusItem.activeStateChanged) {
96
+ fullStatusItem.activeStateChanged.disconnect(onActiveStateChanged);
97
+ }
98
+ item.parent = null;
99
+ item.dispose();
100
+ });
101
+ this._disposables.add(disposable);
102
+ return disposable;
103
+ }
104
+
105
+ /**
106
+ * Dispose of the status bar.
107
+ */
108
+ dispose(): void {
109
+ this._leftRankItems.length = 0;
110
+ this._rightRankItems.length = 0;
111
+ this._disposables.dispose();
112
+ super.dispose();
113
+ }
114
+
115
+ /**
116
+ * Handle an 'update-request' message to the status bar.
117
+ */
118
+ protected onUpdateRequest(msg: Message): void {
119
+ this._refreshAll();
120
+ super.onUpdateRequest(msg);
121
+ }
122
+
123
+ private _findInsertIndex(
124
+ side: Private.IRankItem[],
125
+ newItem: Private.IRankItem
126
+ ): number {
127
+ return ArrayExt.findFirstIndex(side, item => item.rank > newItem.rank);
128
+ }
129
+
130
+ private _refreshItem(id: string) {
131
+ const statusItem = this._statusItems[id];
132
+ if (statusItem.isActive()) {
133
+ statusItem.item.show();
134
+ statusItem.item.update();
135
+ } else {
136
+ statusItem.item.hide();
137
+ }
138
+ }
139
+
140
+ private _refreshAll(): void {
141
+ Object.keys(this._statusItems).forEach(id => {
142
+ this._refreshItem(id);
143
+ });
144
+ }
145
+
146
+ private _leftRankItems: Private.IRankItem[] = [];
147
+ private _rightRankItems: Private.IRankItem[] = [];
148
+ private _statusItems: { [id: string]: Private.IFullItem } = {};
149
+ private _disposables = new DisposableSet();
150
+ private _leftSide: Panel;
151
+ private _middlePanel: Panel;
152
+ private _rightSide: Panel;
153
+ }
154
+
155
+ /**
156
+ * A namespace for private functionality.
157
+ */
158
+ namespace Private {
159
+ type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
160
+ /**
161
+ * Default options for a status item, less the item itself.
162
+ */
163
+ export const statusItemDefaults: Omit<IStatusBar.IItem, 'item'> = {
164
+ align: 'left',
165
+ rank: 0,
166
+ isActive: () => true,
167
+ activeStateChanged: undefined
168
+ };
169
+
170
+ /**
171
+ * An interface for storing the rank of a status item.
172
+ */
173
+ export interface IRankItem {
174
+ id: string;
175
+ rank: number;
176
+ }
177
+
178
+ export type DefaultKeys = 'align' | 'rank' | 'isActive';
179
+
180
+ /**
181
+ * Type of statusbar item with defaults filled in.
182
+ */
183
+ export type IFullItem = Required<Pick<IStatusBar.IItem, DefaultKeys>> &
184
+ Omit<IStatusBar.IItem, DefaultKeys>;
185
+ }
package/src/tokens.ts ADDED
@@ -0,0 +1,67 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+
4
+ import { Token } from '@lumino/coreutils';
5
+ import { IDisposable } from '@lumino/disposable';
6
+ import { ISignal } from '@lumino/signaling';
7
+ import { Widget } from '@lumino/widgets';
8
+
9
+ // tslint:disable-next-line:variable-name
10
+ export const IStatusBar = new Token<IStatusBar>(
11
+ '@jupyterlab/statusbar:IStatusBar'
12
+ );
13
+
14
+ /**
15
+ * Main status bar object which contains all widgets.
16
+ */
17
+ export interface IStatusBar {
18
+ /**
19
+ * Register a new status item.
20
+ *
21
+ * @param id - a unique id for the status item.
22
+ *
23
+ * @param options - The options for how to add the status item.
24
+ *
25
+ * @returns an `IDisposable` that can be disposed to remove the item.
26
+ */
27
+ registerStatusItem(id: string, statusItem: IStatusBar.IItem): IDisposable;
28
+ }
29
+
30
+ /**
31
+ * A namespace for status bar statics.
32
+ */
33
+ export namespace IStatusBar {
34
+ export type Alignment = 'right' | 'left' | 'middle';
35
+
36
+ /**
37
+ * Options for status bar items.
38
+ */
39
+ export interface IItem {
40
+ /**
41
+ * The item to add to the status bar.
42
+ */
43
+ item: Widget;
44
+
45
+ /**
46
+ * Which side to place item.
47
+ * Permanent items are intended for the right and left side,
48
+ * with more transient items in the middle.
49
+ */
50
+ align?: Alignment;
51
+
52
+ /**
53
+ * Ordering of Items -- higher rank items are closer to the middle.
54
+ */
55
+ rank?: number;
56
+
57
+ /**
58
+ * Whether the item is shown or hidden.
59
+ */
60
+ isActive?: () => boolean;
61
+
62
+ /**
63
+ * A signal that is fired when the item active state changes.
64
+ */
65
+ activeStateChanged?: ISignal<any, void>;
66
+ }
67
+ }