joshpoll / bluefish Goto Github PK
View Code? Open in Web Editor NEWCreate beautiful, customizable visualizations in React.
Home Page: http://bluefishjs.org
License: MIT License
Create beautiful, customizable visualizations in React.
Home Page: http://bluefishjs.org
License: MIT License
Nested coordinate systems will help bring us closer to GoG.
Conceptually cleans up facets to have nested coordinate systems.
Nested faceting can only be done in ggplot with extensions: https://teunbrand.github.io/ggh4x/articles/Facets.html#nested_facets.
Sidenote: it's a very interesting package!!
Wrap https://github.com/reymond-group/smilesDrawer so we can make molecules!
Currently context and fragment node handling isn't very smart. Many points assume there is only a single child. e.g. you have to add a top-level Group component beneath an SVG for context to work. And if you have multiple child fragments then measurement only runs for the first child.
We need to generalize this logic. The crux of the difficulty is that Context and Fragment nodes can appear arbitrarily deep in the tree.
To let other people use Bluefish, we need to separate the test React app from the package stuff. We did this with the previous Bluefish version so it shouldn't be too bad.
Once we do this, though, major modifications will require bumping the version number of republishing.
The benefit is that other people (e.g. Geoffrey) can use it in their own projects.
Why?
Jotai is a popular library for state management. Parts of Jotai explore complex state objects:
Currently the underlying dom reference is opaque to consumers of a component. This is a problem, because a consumer may want to e.g. rasterize that component for further processing.
We can expose the dom ref by extending the Measurable
type and wrapping basic components in forwardRef
then forwarding that ref to the dom.
Implement Vega Label as a reusable Bluefish component: https://github.com/vega/vega-label
This will require developing a rasterization interface. This might be a bit tricky since currently we only pass around bbox information, which is resolved at measurement time.
Rasterization is performed at render time. Moreover, rasterization in Vega Label is performed using canvas, but we're currently using SVG.
Pure layout components have a natural default rendering behavior.
Marks don't have to worry about children.
But components that both perform measurements using child components and do rendering (like lines) need access to their children at render time b/c right now we just always inject component children as SVG children. This doesn't work b/c giving a line children doesn't make any sense, and more importantly doesn't render.
Implementation effort: There is a base level of effort for threading custom interface extensions through all the existing code & deciding what the API would look like.
e.g. boundary Bézier curves. Useful for…
Euclidean geometry (requires e.g. identifying intersections between two components)
Calculus (requires e.g. computing tangents)
Boundary/line labels (requires intelligent placement along curves)
Arrows & other connectors
Incidentally would fix the line problem we have with the tree examples in a less hacky way (i.e. avoids negative widths and heights)
Implementation effort: Fortunately there are some pretty good existing Bézier curve JS libraries that we could use (e.g. paperjs). so the main hurdle is in exposing the actual interface
e.g. rasterization. Useful for…
Vega point labels
Precise placement algorithms e.g. positioning things in an organic blobby shape
Implementation effort: This could be a bit tricky since we need we are currently use SVG to render, but would need to render to canvas for rasterization (e.g. using canvg). We could also switch completely to canvas rendering, but that’s a bigger lift.
e.g. polygon approximation. Useful for…
Vega area labels
Optimizations for rasterization algorithms
Implementation effort: Again things like paperjs have nice interfaces for this stuff
There's some tearing right now, which you can see in the markops lagging behind the character list.
I'm not sure why this happens. It might have something to do with concurrent renders. See e.g. reactwg/react-18#69. It might have to do with useContext
being updated in a way I don't expect.
With more complex Bluefish structures, specifying references will get trickier. Right now we use a global context for the entire diagram, but this is not very good for composability b/c of name conflicts
We might need a more complex query/selection API for e.g. grabbing the second element of a list of items
There’s not an immediate need in any of our examples (or near term examples) to implement this, though…
Components like text need additional guidelines like baseline
to be used effectively. TeX equation layout also requires guidelines. Custom images, too, often have natural guidelines that need to be used sometimes.
This is a pretty standard part of declarative UI frameworks, and we could probably just copy their approach.
On the other hand, alignment guides could just be seen as another custom interface (see above)
This enables higher-fidelity, more real examples like nice-looking trees, annotated mathematics, etc.
There is some interesting reuse/modularity possible with these algorithms that is hard to access today. All the layout techniques I mentioned use things like bounding boxes and alignment+spacing to specify their outputs. These boxes could then be annotated/etc. using Bluefish abstractions. Some of the boxes could be replaced by arbitrary figures e.g. have a LaTeX fraction with diagrams on top and bottom instead of math expressions (cf. Andrew Head’s math augmentations paper)
This is more-or-less “just” ripping out existing algorithms and fitting them into the Bluefish ecosystem. But those scare quotes are hiding a significant amount of effort. I already have certain versions of this for tidy tree and graphviz for the older version of Bluefish, though.
We want to perform path interpolation before scaling by default, since interpolation typically happens in data space, not screen space. The problem is that D3's built-in interpolations produce path data, not new values. We can instead use https://github.com/jamesleesaunders/d3-interpolate-curve for this.
Wrap https://www.mathjax.org/ so we can add equations easily!
View/component modifiers are another common piece of UI frameworks. Instead of wrapping a component in e.g. a padding component and a background component and a translation component and a…, you pass these in as modifiers to a component
These sort of act like special syntax for single-child components, but at least in Jetpack Compose they have a slightly different semantics (though I’m not sure what it is…)
Consider adding to the type system a way to track which values are undefined and which one aren't.
This is useful for defining interfaces to a component e.g. if you want a component to have a known size or if it cannot determine its own size and must be set later by another component.
I'd suggest adding the arxiv-link to the readme
Expected behavior: passing new prop values to a diagram component should update the diagram
Observed behavior: some prop updates work, but not others. Example where it doesn't work:
Code for this:
function App() {
test_blob();
const [startOpId, setStartOpId] = React.useState('5@B');
return (
<div className="App">
<select value={startOpId} onChange={(e) => setStartOpId(e.target.value)}>
{['5@B', '6@B', '7@A'].map((opId) => (
<option value={opId}>{opId}</option>
))}
</select>
"OP ID": {startOpId}
{
<Peritext
chars={[
{ value: 'T', opId: '1@A', deleted: false, marks: ['italic'] },
{ value: 'h', opId: '2@A', deleted: true, marks: ['italic'] },
{ value: 'e', opId: '5@B', deleted: false, marks: ['bold', 'italic'] },
{ value: ' ', opId: '6@B', deleted: false, marks: ['bold', 'italic'] },
{ value: 'f', opId: '7@A', deleted: false, marks: ['bold'] },
{ value: 'o', opId: '8@A', deleted: true, marks: [] },
{ value: 'x', opId: '9@A', deleted: false, marks: [] },
]}
markOps={[
{
action: 'addMark',
opId: '18@A',
start: { opId: startOpId },
end: { opId: '7@A' },
markType: 'bold',
backgroundColor: '#F9EEEE',
borderColor: '#E57E97',
},
{
action: 'addMark',
opId: '10@B',
start: { opId: '1@A' },
end: { opId: '6@B' },
markType: 'italic',
backgroundColor: '#E3F2F7',
borderColor: '#00C2FF',
},
]}
/>
}
</div>
);
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.