UNPKG

@datalayer/core

Version:

[![Datalayer](https://assets.datalayer.tech/datalayer-25.svg)](https://datalayer.io)

115 lines (114 loc) 4.59 kB
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;