// Update the scroll position of the list view to ensure the selected item is visible.
 _updateScrollPosition(): void {
   if (!(this.refs && this.refs['selectionList'])) {
     return;
   }
   const listNode = ReactDOM.findDOMNode(this.refs['selectionList']);
   const selectedNode = listNode.getElementsByClassName('selected')[0];
   // false is passed for @centerIfNeeded parameter, which defaults to true.
   // Passing false causes the minimum necessary scroll to occur, so the selection sticks to the
   // top/bottom.
   if (selectedNode) {
     selectedNode.scrollIntoViewIfNeeded(false);
   }
 }
示例#2
0
 const dispose = () => {
   if (popupElement) {
     ReactDOM.unmountComponentAtNode(popupElement);
     invariant(popupElement.parentNode != null);
     popupElement.parentNode.removeChild(popupElement);
     popupElement = null;
   }
   if (paneItemSubscription) {
     paneItemSubscription.dispose();
     paneItemSubscription = null;
   }
   clearDisposeTimeout();
 };
示例#3
0
 it('should use the correct, unique radio group name', () => {
   const props = {optionLabels: ['foo', 'bar'], selectedIndex: 1};
   const component = renderIntoDocument(
     <NuclideRadioGroup {...props} />
   );
   const radioInputs = scryRenderedDOMComponentsWithTag(
     component,
     'input'
   );
   // Global uid is `1` as this point, since this is the second RadioGroup component to be created.
   expect(ReactDOM.findDOMNode(radioInputs[0]).getAttribute('name')).toEqual('radiogroup-1');
   expect(ReactDOM.findDOMNode(radioInputs[1]).getAttribute('name')).toEqual('radiogroup-1');
   const component2 = renderIntoDocument(
     <NuclideRadioGroup {...props} />
   );
   const radioInputs2 = scryRenderedDOMComponentsWithTag(
     component2,
     'input'
   );
   expect(ReactDOM.findDOMNode(radioInputs2[0]).getAttribute('name')).toEqual('radiogroup-2');
   expect(ReactDOM.findDOMNode(radioInputs2[1]).getAttribute('name')).toEqual('radiogroup-2');
 });
示例#4
0
文件: main.js 项目: kamyShi/nuclide
 /**
  * Update the attributes on the current element. Custom attributes won't be added by React because
  * "webview" isn't a valid custom element name (custom elements need a dash), so we set the
  * attributes ourselves. But not "className" or "style" because React has special rules for those.
  * *sigh*
  */
 updateAttributes(prevProps: Object): void {
   const element = ReactDOM.findDOMNode(this);
   const specialProps = ['className', 'style', 'onDidFinishLoad'];
   const normalProps = Object.keys(this.props).filter(prop => specialProps.indexOf(prop) === -1);
   normalProps.forEach(prop => {
     const value = this.props[prop];
     const prevValue = prevProps[prop];
     const valueChanged = value !== prevValue;
     if (valueChanged) {
       element[prop] = value;
     }
   });
 }
示例#5
0
  _renderActiveModal(): void {
    if (this.state.activeModalComponent == null) {
      return;
    }

    let panel = this._activeModalPanel;
    if (panel == null) {
      const item = document.createElement('div');
      panel = this._activeModalPanel = atom.workspace.addModalPanel({item});
    }

    ReactDOM.render(this.state.activeModalComponent, panel.getItem());
  }
示例#6
0
 renderState(state: RefactorState) {
   if (state.type === 'open') {
     if (this._panel == null) {
       const element = document.createElement('div');
       this._panel = atom.workspace.addModalPanel({item: element});
     }
     ReactDOM.render(
       <MainRefactorComponent
         appState={state}
         store={this._store}
       />,
       this._panel.getItem(),
     );
   } else {
     if (this._panel != null) {
       const panel = this._panel;
       ReactDOM.unmountComponentAtNode(panel.getItem());
       panel.destroy();
       this._panel = null;
     }
   }
 }
示例#7
0
 _render(): QuickSelectionComponent {
   const component = ReactDOM.render(
     <QuickSelectionComponent
       activeProvider={this._currentProvider}
       onProviderChange={this.handleActiveProviderChange.bind(this)}
       maxScrollableAreaHeight={this._maxScrollableAreaHeight}
       onBlur={this.closeSearchPanel.bind(this)}
     />,
     this._reactDiv
   );
   invariant(component instanceof QuickSelectionComponent);
   return component;
 }
示例#8
0
 _renderEditors(): void {
   const {filePath, oldEditorState: oldState, newEditorState: newState} = this.state;
   this._oldEditorComponent = ReactDOM.render(
       <DiffViewEditorPane
         headerTitle={oldState.revisionTitle}
         textBuffer={this._readonlyBuffer}
         filePath={filePath}
         offsets={oldState.offsets}
         highlightedLines={oldState.highlightedLines}
         savedContents={oldState.text}
         initialTextContent={oldState.text}
         inlineElements={oldState.inlineElements}
         handleNewOffsets={this._handleNewOffsets}
         readOnly={true}
         onChange={EMPTY_FUNCTION}
         onDidUpdateTextEditorElement={EMPTY_FUNCTION}
       />,
       this._getPaneElement(this._oldEditorPane),
   );
   const textBuffer = bufferForUri(filePath);
   this._newEditorComponent = ReactDOM.render(
       <DiffViewEditorPane
         headerTitle={newState.revisionTitle}
         textBuffer={textBuffer}
         filePath={filePath}
         offsets={newState.offsets}
         highlightedLines={newState.highlightedLines}
         initialTextContent={newState.text}
         savedContents={newState.savedContents}
         inlineElements={newState.inlineElements}
         handleNewOffsets={this._handleNewOffsets}
         onDidUpdateTextEditorElement={this._onDidUpdateTextEditorElement}
         readOnly={false}
         onChange={this._onChangeNewTextEditor}
       />,
       this._getPaneElement(this._newEditorPane),
   );
 }
  beforeEach(() => {
    spyOn(Date, 'now').andCallFake(() => window.now);

    componentRoot = document.createElement('div');
    document.body.appendChild(componentRoot);

    const testProvider = new TestQuickSelectionProvider({});
    component = ReactDOM.render(
      <QuickSelectionComponent
        provider={testProvider}
      />,
      componentRoot
    );
  });
示例#10
0
      .forEach(pane => {
        const items = pane.getItems();
        const activeItem = pane.getActiveItem();

        // Iterate in reverse so that we can't get tripped up by the items we're adding.
        for (let index = items.length - 1; index >= 0; index--) {
          const item = items[index];

          // If the item is a placeholder, try to replace it. If we were successful, then we know
          // the item is up-to-date, so there's no need to update it and we can move on to the
          // next item.
          if (this.replacePlaceholder(item, pane, index) != null) {
            continue;
          }

          const GadgetComponent = state.get('components').get(item);

          // If there's no component for this item, it isn't a gadget.
          if (GadgetComponent == null) {
            continue;
          }

          // Update the props for the item.
          const oldProps = state.get('props').get(item);
          const newProps = {
            ...oldProps,
            active: item === activeItem,
          };

          // Don't re-render if the props haven't changed.
          if (shallowEqual(oldProps, newProps)) {
            continue;
          }

          // Re-render the item with the new props.
          ReactDOM.render(
            <GadgetComponent {...newProps} />,
            item.element,
          );

          // $FlowIssue(t10268095)
          this._observer.onNext({
            type: ActionTypes.UPDATE_PANE_ITEM,
            payload: {
              item,
              props: newProps,
            },
          });
        }
      });
示例#11
0
  _onClick(event: SyntheticMouseEvent) {
    const deep = event.altKey;
    if (
      ReactDOM.findDOMNode(this.refs['arrowContainer']).contains(event.target)
      && event.clientX < ReactDOM.findDOMNode(
        this.refs['pathContainer']).getBoundingClientRect().left
    ) {
      this._toggleNodeExpanded(deep);
      return;
    }

    const modifySelection = event.ctrlKey || event.metaKey;
    if (modifySelection) {
      getActions().toggleSelectNode(this.props.rootKey, this.props.nodeKey);
    } else {
      if (!this.props.isSelected) {
        getActions().selectSingleNode(this.props.rootKey, this.props.nodeKey);
      }
      if (this.props.isSelected || this.props.usePreviewTabs) {
        this._toggleNodeExpanded(deep);
      }
    }
  }
示例#12
0
 dispose(): void {
   if (this._mouseUpTimeout != null) {
     clearTimeout(this._mouseUpTimeout);
   }
   if (this._marker != null) {
     this._marker.destroy();
   }
   if (this._mouseSubscription != null) {
     this._mouseSubscription.unsubscribe();
   }
   ReactDOM.unmountComponentAtNode(this._hostElement);
   this._hostElement.remove();
   this._subscriptions.dispose();
 }
示例#13
0
        waitsForPromise(async () => {
          invariant(renderComponent);
          const component = renderComponent(props);
          await component.setRoots([nodes['G']]);

          expect(component.getSelectedNodes()).toEqual([]);

          const nodeComponents = getNodeComponents(component);
          TestUtils.Simulate.click(ReactDOM.findDOMNode(nodeComponents['G'].refs['arrow']));

          expect(component.getSelectedNodes()).toEqual([]);
          invariant(onConfirmSelection);
          expect(onConfirmSelection.callCount).toBe(0);
        });
示例#14
0
  _measureHeights(): void {
    const measuredComponent = this.refs['measured'];
    if (measuredComponent == null) {
      return;
    }

    this._initialHeightMeasured = true;

    const node = ReactDOM.findDOMNode(measuredComponent);
    const elementHeight = node.clientHeight;
    if (elementHeight !== this.state.elementHeight && elementHeight > 0) {
      this.setState({elementHeight});
    }
  }
示例#15
0
function updateToolbarCount(diffViewButton: HTMLElement, count: number): void {
  if (!changeCountElement) {
    changeCountElement = document.createElement('span');
    changeCountElement.className = 'diff-view-count';
    diffViewButton.appendChild(changeCountElement);
  }
  if (count > 0) {
    diffViewButton.classList.add('positive-count');
  } else {
    diffViewButton.classList.remove('positive-count');
  }
  const DiffCountComponent = require('./DiffCountComponent');
  ReactDOM.render(<DiffCountComponent count={count} />, changeCountElement);
}
示例#16
0
 it('does not expand on click when node is selected', () => {
   const nodeComponent = renderEntryComponentIntoDocument(
     FileTreeEntryComponent,
     {
       rootUri: '/a/',
       uri: '/a/b',
       isSelected: true,
       isContainer: false,
     }
   );
   const domNode = ReactDOM.findDOMNode(nodeComponent);
   TestUtils.Simulate.click(domNode);
   expect(actions.expandNode).not.toHaveBeenCalled();
 });
示例#17
0
  _renderPanel(didRender?: () => mixed) {
    // Initialize and render the contents of the panel only if the hosting container is visible by
    // the user's choice.
    if (!this._state.panelVisible) {
      return;
    }

    let root = this._root;

    if (!root) {
      root = document.createElement('div');
      this._root = root;
    }

    let progressValue;
    if  (this._testSuiteModel && this._executionState === TestRunnerPanel.ExecutionState.RUNNING) {
      progressValue = this._testSuiteModel.progressPercent();
    } else {
      // If there is no running test suite, fill the progress bar because there is no progress to
      // track.
      progressValue = 100;
    }

    this._testRunnerPanel = ReactDOM.render(
      <TestRunnerPanel
        attachDebuggerBeforeRunning={this._attachDebuggerBeforeRunning}
        buffer={this._buffer}
        executionState={this._executionState}
        onClickClear={this.clearOutput}
        onClickClose={this.hidePanel}
        onClickRun={this._handleClickRun}
        onClickStop={this.stopTests}
        onDebuggerCheckboxChanged={this._onDebuggerCheckboxChanged}
        path={this._path}
        progressValue={progressValue}
        runDuration={this._run && this._run.getDuration()}
        // `TestRunnerPanel` expects an Array so it can render the test runners in a dropdown and
        // maintain a selected index. `Set` maintains items in insertion order, so the ordering is
        // determinate on each render.
        testRunners={Array.from(this._testRunners)}
        testSuiteModel={this._testSuiteModel}
      />,
      root,
      didRender
    );

    if (!this._panel) {
      this._panel = atom.workspace.addBottomPanel({item: root, visible: this._state.panelVisible});
    }
  }
示例#18
0
  componentDidMount(): void {
    const {diffModel} = this.props;
    this._subscriptions.add(diffModel.onActiveFileUpdates(activeFileState => {
      this._updateLineDiffState(activeFileState);
      // The diff tree needs to update the active diffed file.
      // TODO(most): merge ActiveFileState into DiffModel's State.
      this._renderTree();
    }));
    this._subscriptions.add(diffModel.onDidUpdateState(this._onModelStateChange));
    this._subscriptions.add(atom.workspace.onDidChangeActivePaneItem(activeItem => {
      if (activeItem != null && (activeItem: any).tagName === 'NUCLIDE-DIFF-VIEW') {
        // Re-render on activation.
        this._updateLineDiffState(diffModel.getActiveFileState());
      }
    }));

    this._paneContainer = createPaneContainer();
    // The changed files status tree takes 1/5 of the width and lives on the right most,
    // while being vertically splt with the revision timeline stack pane.
    const topPane = this._newEditorPane = this._paneContainer.getActivePane();
    this._bottomRightPane = topPane.splitDown({
      flexScale: 0.3,
    });
    this._treePane = this._bottomRightPane.splitLeft({
      flexScale: 0.35,
    });
    this._navigationPane = topPane.splitRight({
      flexScale: 0.045,
    });
    this._oldEditorPane = topPane.splitLeft({
      flexScale: 1,
    });

    this._renderDiffView();

    this._subscriptions.add(
      this._destroyPaneDisposable(this._oldEditorPane),
      this._destroyPaneDisposable(this._newEditorPane),
      this._destroyPaneDisposable(this._navigationPane),
      this._destroyPaneDisposable(this._treePane),
      this._destroyPaneDisposable(this._bottomRightPane),
    );

    ReactDOM.findDOMNode(this.refs.paneContainer).appendChild(
      atom.views.getView(this._paneContainer),
    );

    this._updateLineDiffState(diffModel.getActiveFileState());
  }
  _renderStatusBar(connectionState: number, fileUri?: string): void {
    if (!this._statusBarDiv) {
      return;
    }

    const component = ReactDOM.render(
      <StatusBarTile
        connectionState={connectionState}
        fileUri={fileUri}
      />,
      this._statusBarDiv,
    );
    invariant(component instanceof StatusBarTile);
    this._statusBarTile = component;
  }
示例#20
0
文件: main.js 项目: demongel/nuclide
function renderPanel(renderState: State, onDidRender?: () => mixed): void {
  const activeViewInstance = getActiveViewInstance(renderState);
  panelComponent = ReactDOM.render(
    <PanelComponent
      dock="left"
      hidden={renderState.hidden}
      initialLength={renderState.initialLength}>
      {activeViewInstance == null
        ? <div />
        : React.createElement(activeViewInstance.view.getComponent())}
    </PanelComponent>,
    item,
    onDidRender
  );
}
        waitsForPromise(async () => {
          invariant(renderComponent);
          const component = renderComponent(props);
          await component.setRoots([nodes.G]);
          await component.expandNodeKey(nodes.H.getKey());

          expect(component.getSelectedNodes()).toEqual([]);

          const nodeComponents = getNodeComponents(component);
          TestUtils.Simulate.click(ReactDOM.findDOMNode(nodeComponents.J));
          expect(component.getSelectedNodes()).toEqual([nodes.J]);

          invariant(onConfirmSelection);
          expect(onConfirmSelection.callCount).toBe(1);
        });
示例#22
0
 dispose(): void {
   if (this._item) {
     ReactDOM.unmountComponentAtNode(this._item);
     this._item = null;
   }
   if (this._tile) {
     this._tile.destroy();
     this._tile = null;
   }
   if (this._tooltip) {
     this._tooltip.dispose();
     this._tooltip = null;
   }
   this._isMouseOver = false;
 }
示例#23
0
 it('opens a file if a selected node is clicked', () => {
   const nodeComponent = renderEntryComponentIntoDocument(
     FileTreeEntryComponent,
     {
       rootUri: '/a/',
       uri: '/a/b',
       isSelected: true,
       isContainer: false,
       usePreviewTabs: true,
     },
   );
   const domNode = ReactDOM.findDOMNode(nodeComponent);
   TestUtils.Simulate.click(domNode);
   expect(actions.confirmNode).toHaveBeenCalled();
 });
示例#24
0
        waitsForPromise(async () => {
          invariant(renderComponent);
          const component = renderComponent(props);
          await component.setRoots([nodes['G']]);

          expect(component.getSelectedNodes()).toEqual([]);

          const nodeComponents = getNodeComponents(component);

          TestUtils.Simulate.mouseDown(ReactDOM.findDOMNode(nodeComponents['G']), {button: 2});
          expect(component.getSelectedNodes()).toEqual([nodeComponents['G'].props.node]);

          TestUtils.Simulate.mouseDown(
            ReactDOM.findDOMNode(nodeComponents['H']),
            {button: 0, ctrlKey: true}
          );
          expect(component.getSelectedNodes()).toEqual([nodeComponents['H'].props.node]);

          TestUtils.Simulate.mouseDown(ReactDOM.findDOMNode(nodeComponents['I']), {button: 0});
          expect(component.getSelectedNodes()).toEqual([nodeComponents['H'].props.node]);

          invariant(onConfirmSelection);
          expect(onConfirmSelection.callCount).toBe(0);
        });
示例#25
0
  constructor(rawState: ?Object) {
    rawState = rawState || {};
    this._disposables = new CompositeDisposable(
      atom.commands.add(
        'body',
        'nuclide-buck-toolbar:toggle',
        () => { this._actions.togglePanelVisibility(); },
      ),
    );

    const initialState = {
      buildTarget: rawState.buildTarget || null,
      isPanelVisible: rawState.isPanelVisible || false,
      isReactNativeServerMode: rawState.isReactNativeServerMode || false,
    };

    const dispatcher = new Dispatcher();
    this._store = new BuckToolbarStore(dispatcher, initialState);
    this._disposables.add(this._store);
    this._actions = new BuckToolbarActions(dispatcher);

    const container = document.createElement('div');
    ReactDOM.render(
      <BuckToolbar store={this._store} actions={this._actions} />,
      container,
    );
    const panel = atom.workspace.addTopPanel({
      item: container,
      // Increase priority (default is 100) to ensure this toolbar comes after the 'tool-bar'
      // package's toolbar. Hierarchically the controlling toolbar should be above, and practically
      // this ensures the popover in this build toolbar stacks on top of other UI.
      priority: 200,
    });
    this._disposables.add(
      new Disposable(() => {
        ReactDOM.unmountComponentAtNode(container);
        panel.destroy();
      }),
    );

    const target = 'atom-workspace';
    this._disposables.add(
      atom.commands.add(target, 'nuclide-buck-toolbar:build', () => this._actions.build()),
      atom.commands.add(target, 'nuclide-buck-toolbar:debug', () => this._actions.debug()),
      atom.commands.add(target, 'nuclide-buck-toolbar:run', () => this._actions.run()),
      atom.commands.add(target, 'nuclide-buck-toolbar:test', () => this._actions.test()),
    );
  }
    waitsForPromise(() => new Promise((resolve: (component: any) => any, reject) => {

      component.onItemsChanged(newItems => {
        resolve(component);
      });
      component = ReactDOM.render(
        <QuickSelectionComponent
          provider={new TestQuickSelectionProvider(items)}
        />,
        componentRoot
      );
      window.advanceClock(250);

      component.clear();

    }).then(callback));
 componentDidMount(): void {
   const node = ReactDOM.findDOMNode(this);
   node.focus();
   this._disposables.add(atom.commands.add(
     node,
     {
       'core:move-up': () => this._moveSelectionIndex(-1),
       'core:move-down': () => this._moveSelectionIndex(1),
       'core:confirm': () => {
         const def = this.state.applicableDefinitions[this.state.selectionIndex];
         this._toggleWorkingSet(def.name, def.active);
       },
       'core:cancel': this.props.onClose,
     }
   ));
 }
 componentDidMount(): void {
   const node = ReactDOM.findDOMNode(this);
   node.focus();
   this._disposables.add(atom.commands.add(
     node,
     {
       'file-tree:workset-select-up': () => this._moveSelectionIndex(-1),
       'file-tree:workset-select-down': () => this._moveSelectionIndex(1),
       'file-tree:workset-select-toggle': () => {
         const def = this.state.definitions[this.state.selectionIndex];
         this._toggleWorkingSet(def.name, def.active);
       },
       'file-tree:workset-select-close': this.props.onClose,
     }
   ));
 }
示例#29
0
    it('expands on click when node is selected', () => {
      const nodeComponent = renderEntryComponentIntoDocument(
        FileTreeEntryComponent,
        {
          rootUri: '/a/',
          uri: '/a/b/',
          isSelected: true,
          isContainer: true,
        }
      );

      // The onClick is listened not by the <li> element, but by its first child.
      const domNode = ReactDOM.findDOMNode(nodeComponent).children[0];
      TestUtils.Simulate.click(domNode);
      expect(actions.expandNode).toHaveBeenCalled();
    });
示例#30
0
  componentDidMount() {
    const element = ReactDOM.findDOMNode(this);

    // Add event listeners. This has the drawbacks of 1) adding an event listener even when we don't
    // have a callback for it and 2) needing to add explicit support for each event type we want to
    // support. However, those costs aren't great enough to justify a new abstraction for managing
    // it at this time.
    element.addEventListener('did-finish-load', this._handleDidFinishLoad);
    this._disposables.add(
      new Disposable(
        () => element.removeEventListener('did-finish-load', this._handleDidFinishLoad),
      ),
    );

    this.updateAttributes({});
  }