kitschpatrol / svelte-tweakpane-ui

A Svelte component library wrapping UI elements from Tweakpane, plus some additional functionality for convenience and flexibility.
https:///kitschpatrol.com/svelte-tweakpane-ui
MIT License
105 stars 3 forks source link

AutoObject for List or RadioButtons #3

Closed m4nh closed 5 months ago

m4nh commented 5 months ago

Thank you for your amazing work! I also tried to create a PR for this change, but I'm not able to do so easily 😈

Is it simple to implement a special key:value for AutoObject in order to automatically create a List control (aka a Select) or a RadioGroup buttons?

For example, it could be implemented with:

myKey: ['alpha', 'beta']

Or with labels:

myKey: [{alpha:'AlphaLabel', beta:'BetaLabel'}]

Given that the Array is not checked as an input type in the AutoObject if statement, I think it is feasible. Thanks!

kitschpatrol commented 5 months ago

Hi, thanks for using the library and contributing this idea for a new feature!

First I just want to make sure components like <List> and <RadioGrid> are on your radar, since they make it easy to create select and radio button controls, for example:

<script lang="ts">
    import { List, RadioGrid } from 'svelte-tweakpane-ui';
    let value: string;
</script>

<List bind:value options={{ 'Alpha Label': 'alpha', 'Beta Label': 'beta' }} />
<RadioGrid bind:value values={['alpha', 'beta']} />

The <AutoObject> (and <AutoValue>) components trade configurability for convenience, since they use the same object or value to both define the structure of the UI and react to control changes. Because of this, the tricky thing here would be how to separate defining the list options from the state value representing the active selection:

// Hypothetical, not currently implemented!
<script lang="ts">
    import { AutoObject } from 'svelte-tweakpane-ui';
    let object = {
      myKey: ['alpha', 'beta']
    };
</script>

<AutoObject bind:object >
{object.myKey} // ???

The only ways that I can think of to disambiguate state from configuration are:

A. Add a prop with additional configuration to define the list, at which point I think it makes more sense to use the more specific components like <List> that already have props for this.

B. Come up with a special object shape that puts the selected value state alongside the list definition. I guess <AutoObject> could look for a type like { [key: string]: { value: T; options: T[] }; }, so the example above would become:

// Hypothetical, not currently implemented!
<script lang="ts">
    import { AutoObject } from 'svelte-tweakpane-ui';
    let object = { 
        myKey: { value: 'alpha', options: ['alpha', 'beta'] }
    };
</script>

<AutoObject bind:object >
{object.myKey.value} // alpha

There's some precedent for this kind of magic control inference in vanilla Tweakpane, and that's mirrored in how <AutoObject> infers color and point controls based on object shape... but for lists, I think vanilla Tweakpane always separates the list options from the bound value, like in this example, so I'm not sure if a special object shape would end up creating more confusion than convenience. (Though we might have some room for magic in a component with "Auto" in its name...)

Open to your ideas — it would be great to hear a bit more info on how you envisioned binding working. I could be missing something obvious.

m4nh commented 5 months ago

Thank you very much for the response. I hadn't grasped the concept of Value Binding; indeed, it only makes sense when Value and UI Configuration coincide, so it's complex with Lists, and anyway, it would undermine the utility of AutoObject.

We will try to use the components separately for our application. However, if I come up with an elegant idea to solve the problem, I'll propose it to you :)

kitschpatrol commented 5 months ago

Sounds good, thanks for the discussion and good luck with your project.