Thanks to earlier help, I was able to bring my notebook into a React component.
However, the component renders at the dimensions of the viewport, plus some additional pixels, leading to vertical and horizontal scrollbars being shown that hide content. The internal dimensions are not calculated correctly, which also leads to some unwanted vertical space between the two top panels and the bottom one:
In my notebook, I have two variables mutable viewportWidth and mutable viewportHeight which rely on the value of width to set up, size and render the genomeSpace cell within the Observablehq notebook environment.
I would like to use standard React routines to resize this notebook component before it is rendered in a React application.
Custom sizing will allow me to try to integrate the notebook component with other React components and UI widgets.
I am attempting to glue the instantiation routine here to a resize event:
import React, {Component} from "react";
import {Runtime, Inspector, Library} from "@observablehq/runtime";
import notebook from "0f7b50a23d98b321";
class App extends Component {
constructor(props) {
super(props);
this.state = {
width: 0,
height: 0
};
this.genomeSpaceRef = React.createRef();
this.viewportWidth = {};
this.viewportHeight = {};
}
componentDidMount() {
const genomeSpace = this.genomeSpaceRef.current;
const library = new Library();
const runtime = new Runtime();
const main = runtime.module(notebook, name => {
if (name === "viewof genomeSpace") {
return new Inspector(genomeSpace);
}
if (name === "mutable viewportWidth") {
return {fulfilled: (value) => {
this.viewportWidth = value;
}};
}
if (name === "mutable viewportHeight") {
return {fulfilled: (value) => {
this.viewportHeight = value;
}};
}
});
main.redefine("width", library.Generators.observe(notify => {
let width = notify(genomeSpace.clientWidth);
function resized() {
let newWidth = genomeSpace.clientWidth;
if (newWidth !== width) {
notify(width = newWidth)
}
}
window.addEventListener("resize", resized);
return () => window.removeEventListener("resize", resized);
}));
window.addEventListener('resize', this.updateDimensions);
setTimeout(() => {
window.dispatchEvent(new Event('resize'));
}, 2500);
}
componentWillUnmount() {
window.removeEventListener('resize', this.updateDimensions);
}
componentDidUpdate(nextProps, nextState) {}
updateDimensions = () => {
this.setState({
width: window.innerWidth,
height: window.innerHeight
}, () => {
this.viewportWidth.value = parseInt(this.state.width);
this.viewportHeight.value = parseInt(this.state.height);
});
};
render() {
return (
<div id="parent" className="parent">
<div ref={this.genomeSpaceRef} className="genomeSpace"></div>
</div>
);
}
}
export default App;
While updateDimensions will be called as a result of dispatching a resize event via window.dispatchEvent(new Event('resize')), the problem is that the notebook does not always redraw correctly. Sometimes it works, sometimes it doesnāt.
When it does redraw correctly, there is a delay of 2.5 sec (give or take) before that redraw occurs.
What I would like to do is size the notebook viewof genomeSpace cell before it is drawn, by setting the mutable viewportWidth and mutable viewportHeight values via this.setState(...).
What is the correct and reliable way to dynamically resize a notebook component to whatever is set in application state?
