// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
import { ReactWidget } from '@jupyterlab/apputils';
import { Widget, PanelLayout } from '@phosphor/widgets';
import React, { useState, useRef, useEffect } from 'react';
import { Variables } from '../index';
export class Search extends Widget {
constructor(model: Variables.IModel) {
super();
this.addClass('jp-DebuggerVariables-search');
const layout = new PanelLayout();
this.layout = layout;
this.scope = new ScopeSearch(model);
this.search = new SearchInput(model);
layout.addWidget(this.scope);
layout.addWidget(this.search);
}
readonly scope: Widget;
readonly search: Widget;
}
const SearchComponent = ({ model }: any) => {
const [state, setState] = useState('');
model.filter = state;
return (
{
setState(e.target.value);
}}
/>
);
};
class SearchInput extends ReactWidget {
search: string;
model: Variables.IModel;
constructor(model: Variables.IModel) {
super();
this.model = model;
this.search = model.filter;
this.node.style;
this.addClass('jp-DebuggerVariables-input');
}
render() {
return ;
}
}
class ScopeSearch extends ReactWidget {
constructor(model: Variables.IModel) {
super();
this.model = model;
this.node.style.overflow = 'visible';
this.node.style.width = '85px';
this.addClass('jp-DebuggerVariables-scope');
}
model: Variables.IModel;
render() {
return ;
}
}
const useOutsideClick = (
ref: React.MutableRefObject,
callback: Function
) => {
const handleClickOutside = (e: Event) => {
if (ref.current && !ref.current.contains(e.target)) {
callback();
}
};
useEffect(() => {
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
});
};
const ScopeMenuComponent = ({ model }: { model: Variables.IModel }) => {
const [toggleState, setToggle] = useState(false);
const [scopes, setScopes] = useState(model.scopes);
const [scope, setScope] = useState(model.currentScope);
const wrapperRef = useRef(null);
useEffect(() => {
const updateScopes = (_: Variables.IModel, updates: Variables.IScope[]) => {
const scope = !!updates && updates.length > 0 ? updates[0] : null;
setScopes(updates);
setScope(scope);
};
model.scopesChanged.connect(updateScopes);
return () => {
model.scopesChanged.disconnect(updateScopes);
};
});
const onClickOutSide = () => {
setToggle(false);
};
const toggle = () => {
if (!!scopes) {
setToggle(!toggleState);
}
};
useOutsideClick(wrapperRef, onClickOutSide);
const changeScope = (newScope: Variables.IScope) => {
if (newScope === scope) {
return;
}
setScope(newScope);
model.currentScope = newScope;
setToggle(false);
};
const List = (
{!!scopes
? scopes.map(scope => (
- changeScope(scope)}>
{scope.name}
))
: null}
);
return (
toggle()} ref={wrapperRef}>
{scope ? scope.name : '-'}
{toggleState ? List : null}
);
};