# Editable props (fframes Studio)

> fframes Studio can change a component's props without code edits.

Page: https://fframes-kit.pages.dev/docs/advanced/editable-props-fframes-studio/

fframes Studio can change a component's props without code edits. In the Props panel, select
the component on the canvas, change a value, and the preview updates. The values are saved in
the project's `props.json`.

Gallery scene: `Editable`. Without a props source, it shows the component's original values.

Gallery clip of `Editable`: https://fframes-kit.pages.dev/media/scenes/Editable-32d05407.mp4

A component is editable when it has a key:
- in the struct form, `ui.show(LowerThird { .. }.editable("speaker"))`;
- in a tag, `<LowerThird editable="speaker" .. />`.

Keys must be unique within a scene.
- Without the kit feature `studio`, `editable` renders the component unchanged. Code that marks
  components therefore builds the same everywhere.
- With `studio`, every kit component implements `Props`. Its editable fields are numbers,
  `bool`, text, `Color`, `Option<Color>` (`null` is none) and a fixed `Anim<f32>`.
  - Children, slices, keyframes and styles stay in code.
  - Your own components get it with `#[derive(Props)]`. Use `#[props(skip)]` to keep a field
    out, and `#[props(min = 0.0, max = 100.0, step = 1.0, unit = "px")]` to bound a number.
  - Enums whose variants have no fields get it with `#[derive(PropChoice)]`.

The `Ui` takes its values from a `PropsSource`, set with `Ui::with_props`:

```rust
use fframes_kit::prelude::*;

fn title<'a>(frame: Frame, ctx: &FFramesContext<'a, '_>, theme: &'a Theme) -> Svgr<'a> {
    let mut ui = Ui::new(frame, ctx, theme);
    ui.show(
        LowerThird {
            name: "Ada".into(),
            ..ui.defaults()
        }
        .editable("speaker"),
    )
}

fn with_source<'a>(
    frame: Frame,
    ctx: &FFramesContext<'a, '_>,
    theme: &'a Theme,
    source: impl PropsSource + 'a,
) -> Svgr<'a> {
    let mut ui = Ui::new(frame, ctx, theme).with_props(source);
    ui!(<LowerThird editable="speaker" name="Ada" />)
}
```

When the component renders with a source:
- the source's values for it replace the code's values (`PropsSource::values`);
- it is drawn inside a `<g>` with the id the source gives (`PropsSource::element_id`);
- while the source listens, it hears the schema, the code's values and the drawn values
  (`PropsSource::rendered`);
- a value that does not fit its field is skipped with a warning in `inspect`.

The source is made per `Ui`, so it can hold one snapshot of the values; the `Ui`s of
containers share it.

### With fframes Studio

The kit does not depend on Studio. Studio's source is the `PropsStore` of the
`fframes-studio-kit` crate in the fframes Studio repository. It holds the project's
`props.json`, names each object with Studio's editor identity (the scene's
`editor_instance_key`, else its name; `video` outside scenes; the type name; the key;
`main`), and answers the props panel:

```rust title="Not compiled"
use fframes_studio_kit::PropsStore;

// render_frame of a video, and of a scene
let mut ui = Ui::new(frame, ctx, &self.theme).with_props(self.props.view());
let mut ui = Ui::for_scene(frame, ctx, theme, self).with_props(props.scene_view(self));

// the project's Studio worker
let props = Arc::new(PropsStore::load("props.json")?); // exports read the same document
props.listen(); // record each editable object's schema and values for the panel
let config = config.with_props_args(&args).with_props(props.hooks());
// export: run_export_with_props(&video, &options, &args, &props.hooks())
// export capabilities: print_export_capabilities_with_props::<MyVideo>()
```

## API

### Editable

A component with an editor key, see the module docs.

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `key` | `Cow<str>` | — | The key the editor stores this component's values under. |
| `component` | `C` | — | The component whose props the key makes editable. |

It has no theme defaults: build it with `Editable::new(..)`.

Methods:

- `fn new(key: impl Into<Cow<str>>, component: C) -> Self`

[Source](https://github.com/khanhthanhdev/fframes-kit/blob/main/fframes-kit/src/props.rs#L44)
