import React from "react"; import { connect } from "react-redux"; import { ImmutableCell } from "@nteract/commutable/src"; import { AppState, selectors } from "@nteract/core"; interface ComponentProps { id: string; contentRef: string; children: React.ReactNode; } interface StateProps { cell?: ImmutableCell; selected: boolean; } type Props = ComponentProps & StateProps; export class Cell extends React.Component { shouldComponentUpdate(nextProps: Props): boolean { // Update cell directly after converting between markdown and code if (this.props.cell?.cell_type !== nextProps.cell?.cell_type) { return true; } // Update cell when selecting or de-selecting it if (nextProps?.selected !== this.props?.selected) { return true } return false } render(): JSX.Element | null { // We must pick only one child to render let chosenOne: React.ReactNode | null = null; if (!this.props.cell) { return null; } const cell_type = this.props.cell.get("cell_type", "code"); // Find the first child element that matches something in this.props.data React.Children.forEach(this.props.children, child => { if (!child) { return; } if ( typeof child === "string" || typeof child === "number" || typeof child === "boolean" ) { return; } if (chosenOne) { // Already have a selection return; } if (typeof child !== "object" || !("props" in child)) { return; } if (child.props && child.props.cell_type) { const child_cell_type = child.props.cell_type; chosenOne = child_cell_type === cell_type ? child : null; return; } }); // If we didn't find a match, render nothing if (chosenOne === null) { return null; } // Render the output component that handles this output type return (
{React.cloneElement(chosenOne, { cell: this.props.cell, id: this.props.id, contentRef: this.props.contentRef })}
); } } export const makeMapStateToProps = ( initialState: AppState, ownProps: ComponentProps ): ((state: AppState) => StateProps) => { const mapStateToProps = (state: AppState): StateProps => { const { id, contentRef } = ownProps; const model = selectors.model(state, { contentRef }); let cell; let selected = false; if (model && model.type === "notebook") { cell = selectors.notebook.cellById(model, { id }); selected = selectors.notebook.cellFocused(model) === id; } return { cell, selected }; }; return mapStateToProps; }; export default connect( makeMapStateToProps )(Cell);