Soundorv0.13.0

Components

The components a Soundor plugin UI is made of, from @soundor/react.

@soundor/react renders a plugin's UI with React Native's components and conventions, in every runtime: natively, where there is no DOM, and in the browser. Each page here runs its component live: edit the code, then apply.

import { Pressable, Text, View, useParameter } from '@soundor/react';
import { parameters } from 'soundor:parameters';

// A parameter's value, re-rendered whenever it changes: here, from the
// buttons; in a plugin, from host automation and presets too.
export default function Gain() {
  const gain = useParameter(parameters.gain);
  const step = (by: number) => parameters.gain.set(gain + by);

  return (
    <View style={{ alignItems: 'center', gap: 12 }}>
      <Text style={{ fontSize: 28, color: '#e6e7ea' }}>
        Gain {gain.toFixed(2)}
      </Text>
      <View style={{ flexDirection: 'row', gap: 8 }}>
        {[
          { label: '−', onPress: () => step(-0.1) },
          { label: 'Reset', onPress: () => parameters.gain.set(0.5) },
          { label: '+', onPress: () => step(0.1) },
        ].map(({ label, onPress }) => (
          <Pressable
            key={label}
            onPress={onPress}
            style={({ pressed, hovered }) => ({
              minWidth: 44,
              alignItems: 'center',
              paddingVertical: 8,
              paddingHorizontal: 14,
              borderRadius: 8,
              backgroundColor: pressed
                ? '#2a5fd0'
                : hovered
                  ? '#4f8bff'
                  : '#3a7bfd',
            })}
          >
            <Text style={{ color: 'white', fontSize: 15 }}>{label}</Text>
          </Pressable>
        ))}
      </View>
    </View>
  );
}
gain.tsxSource
ComponentWhat it is
ViewA box laid out with flexbox: the building block.
TextText. Every string goes in one.
ImageA bundled image.
PressableA view that responds to presses, with its state for styling.
TextInputA single-line text input.
ScrollViewContent that scrolls.
CanvasPixels code draws, with a 2D or WebGL 2 context.
Animated.ViewA view whose style changes animate.
PortalChildren rendered elsewhere: over everything, or into a host.
ModalA layer over the view that takes its input until it closes.
FocusScopeA boundary for keyboard focus: trap, autofocus, restore.

Every component takes:

  • style: flexbox layout, spacing, text and paint, as in React Native. StyleSheet.create() names styles with their types.
  • Event props: Web-style pointer, wheel, key and focus events that capture and bubble as in the DOM.
  • Accessibility props: what the component is to a screen reader.
  • ref: its soundor:ui node, for its layout, bounds, focus and animations (soundor:ui).

Rendering

A plugin's src/main.tsx renders its root component into the plugin view:

import { render } from '@soundor/react';

import { App } from './App';

render(<App />);
  • render(element) renders into the whole plugin view, replacing what it showed, and returns its root.
  • createRoot(node?) makes a root that renders into a soundor:ui node (by default the view's root): { render(element), unmount() }.
  • flushSync(fn) runs fn and applies the updates it schedules before returning, for code that needs the nodes to be there at once.

The hooks connect components to parameters and frames, and the React UI guide explains how the renderer works.

On this page