clarkmcc / ngraph

A blender-style node editor for React, built on xyflow
https://ngraph.clarkmccauley.com
MIT License
40 stars 2 forks source link

Use case for nodeKind #41

Open sroussey opened 7 months ago

sroussey commented 7 months ago

I am working on a set of input components with aria support styled by tailwindcss. While doing that, they have a different style from the built-in ones. Taking this and slots, I can create a "fat" style where everything is the same, but the colors are different and the inputs have more padding and animated color transitions, etc.

It would be great if a nodeKind could overload things for those with that kind but not sure how to do it without making the nodeKind non-jsonifable.

Anyhow, if that were ok, this is an idea:

const config = {
  nodeKind: {
    name:'fat',
    color: 'red',
    slots: {
       bodyTop: () => <div style={{padding-top: 20px}}></div>
       bodyBottom: () => <div style={{padding-top: 20px}}></div>
    },
    inputComponents: {
      text: MyFatTextInput,
      number: MyFatNumberInput,
    },
    ...

This make the registration of components inline with the config though, rather than separate. It does mean that they are not global though, and only will be used by that kind.

sroussey commented 7 months ago

Another way is that input components (and the main node component) could be registered as usual, but with more identifiable names, and then mapped. For example, I could register 'aria-text' as an input and then do something like this:

const config = {
  nodeKind: {
    name:'fat',
    color: 'red',
    inputOverrides: {
      text: 'aria-text',
      number: 'aria-number',
    },
    ...
clarkmcc commented 7 months ago

but not sure how to do it without making the nodeKind non-jsonifable.

So the main use-case for jsonifiable in my mind is providing the config from some external source, for example if the server were to expose a config to the frontend. I have a use-case that I'm conceptualizing with tens of thousands of node types, but loading that as a single config would be impossible --it's just too large to perform well--, so I've been trying to think of a config interface that could be lazy loaded.

The reason I share this unrelated idea is: I wonder if the use-case for jsonifiable overlaps with other use-cases like mine where the config file won't work to begin with, therefore, I'm wondering if making the config non-jsonifiable is fine, and down the road introducing a more abstract config interface that could support lazy loading the config from a serializable source like JSON, or the server, etc...

clarkmcc commented 7 months ago

On the flip side, I can see this approach getting used and abused such that it's impossible to tell what components are coming from where. You might have slots defined on the graph editor component, but then there are slots defined in the config, I assume that the config slots take precedence, but you know, it could be a confusing relationship between the different slot providers.

To make sure I understand: is the idea here is to avoid a custom component wrapper for each of your nodes, allowing them to still be automatically generated, rather than having to implement a custom component for each node with your wrapper around it?

sroussey commented 7 months ago

I want to be able to change to full rendering by changing the node kind. Sorta like a theme.

And I wouldn’t mind doing it at runtime as well. 🤪

sroussey commented 7 months ago

I do like the config being json. In fact, I would not mind other stuff being in the config, like layout engine, and slots. It’s an extra step, but done for custom nodes etc.

clarkmcc commented 7 months ago

So I'm not opposed to something like this but am still concerned about this issue

I can see this approach getting used and abused such that it's impossible to tell what components are coming from where.

I'd probably go the custom node route if it were me personally. But I'm also happy to keep thinking through it. Are there any other approaches you've considered that would meet your needs?