@datalayer/core
Version:
[](https://datalayer.io)
115 lines (114 loc) • 4.59 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/*
* Copyright (c) 2023-2025 Datalayer, Inc.
* Distributed under the terms of the Modified BSD License.
*/
import { createElement, useState, } from 'react';
import { Dialog } from '@jupyterlab/apputils';
import { ReactWidget } from '@jupyterlab/ui-components';
import { PromiseDelegate } from '@lumino/coreutils';
import { Widget } from '@lumino/widgets';
import { FocusKeys } from '@primer/behaviors';
import { Checkbox, FormControl, useFocusZone } from '@primer/react';
import { Dialog as PrimerDialog, } from '@primer/react/experimental';
import { JupyterReactTheme } from '@datalayer/jupyter-react';
function DialogFooter(props) {
const { checkbox, footerButtons, setChecked } = props;
const [checked, setLocalChecked] = useState();
const { containerRef: footerRef } = useFocusZone({
bindKeys: FocusKeys.ArrowHorizontal | FocusKeys.Tab,
focusInStrategy: 'closest',
});
return (_jsxs(PrimerDialog.Footer, { className: "dla-dialog-footer", ref: footerRef, children: [checkbox && (_jsxs(FormControl, { layout: "horizontal", children: [_jsx(Checkbox, { className: checkbox.className ?? '', checked: checked, defaultChecked: checkbox.checked, onChange: e => {
setLocalChecked(e.target.checked);
setChecked(e.target.checked);
}, title: checkbox.caption ?? '' }), _jsx(FormControl.Label, { children: checkbox.label ?? '' })] })), _jsx("div", { className: "dla-dialog-footer-spacer" }), footerButtons && (_jsx(PrimerDialog.Buttons, { buttons: footerButtons }))] }));
}
/**
* A primer dialog mimicking the JupyterLab dialog interface
*/
export class JupyterDialog extends ReactWidget {
body;
checkbox;
buttons;
host;
dialogTitle;
_closing = new PromiseDelegate();
_result = {
button: null,
isChecked: null,
value: null,
};
/**
* Create a dialog instance.
*/
constructor(options = {}) {
super();
this.host = options.host ?? document.body;
this.body = options.body ?? (() => null);
this.checkbox = options.checkbox ?? null;
this.buttons = options.buttons ?? [
Dialog.cancelButton(),
Dialog.okButton(),
];
this.dialogTitle = options.title;
}
_renderBody = (props) => (_jsx(PrimerDialog.Body, { children: createElement(this.body, {
...props,
setValue: this.setValue,
}) }));
_renderFooter = (props) => (_jsx(DialogFooter, { ...props, checkbox: this.checkbox, setChecked: this.setChecked }));
render() {
// TODO title color is enforced for JupyterLab.
// This may be fixed in the jupyter-react theme (Primer generates h1 for the dialog title).
return (_jsx(JupyterReactTheme, { children: _jsx(PrimerDialog, { title: _jsx("span", { style: { color: 'var(--fgColor-default)' }, children: this.dialogTitle }), onClose: this.close, renderBody: this._renderBody, renderFooter: this._renderFooter, footerButtons: this.buttons.map((but, idx) => {
const footerButton = {
buttonType: but.displayType === 'default'
? but.accept
? 'primary'
: 'default'
: 'danger',
onClick: () => {
this.handleButton(idx);
},
content: but.label,
'aria-label': but.ariaLabel,
autoFocus: but.accept,
};
return footerButton;
}) }) }));
}
/**
* Launch the dialog as a modal window.
*
* @returns a promise that resolves with the result of the dialog.
*/
async launch() {
Widget.attach(this, this.host);
await this._closing.promise;
return this._result;
}
handleButton = (idx) => {
this.setButton(this.buttons[idx]);
this.close();
};
setButton = (button) => {
this._result.button = button;
};
setChecked = (c) => {
this._result.isChecked = c;
};
setValue = (v) => {
if (v instanceof Error) {
this._closing.reject(v);
}
else {
this._result.value = v;
}
};
close = () => {
Widget.detach(this);
this._closing.resolve();
};
}
export default JupyterDialog;