// 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}
); };