@bbx-audio/nectarCollection of JUCE-y modules for building web-based plugin GUIs 🧃
nectar is primarily a TypeScript wrapper around the JUCE javascript code that is used for building WebView-based GUIs.
It also contains a number of other classes and utilities for things like parameter management, event handling, errors, and math.
This library is framework-agnostic, so feel free to use it in any web-based project 🍻
# NPM
npm i @bbx-audio/nectar
# Yarn
yarn add @bbx-audio/nectar
Please refer to the documentation for a comprehensive overview of this library.
The juce module contains code that needs to be
executed early in your program so that the communication with the JUCE backend is initialized properly.
This is done by simply adding an extra import statement to the top of your frontend's entrypoint file:
// In an entrypoint file e.g., main.ts or index.ts
import '@bbx-audio/nectar/init'
The error module contains the Result type, which generally helps improve error handling.
It does this by wrapping the result of a function call in a structure that either contains the result as expected or the error that occurred during the function's execution.
import { Result } from '@bbx-audio/nectar'
function divide(a: number, b: number): Result<number> {
if (b === 0) {
return [null, new Error('Unable to divide by zero')]
} else {
return [a / b, null]
}
}
const [result, error] = divide(1, 0)
if (error) {
// Handle the error
} else {
// Proceed with the result
}
The event module contains a class that allows you to register listener callbacks that are executed when global
window and DOM events are emitted. This has two main benefits:
import { GlobalEventManager } from '@bbx-audio/nectar'
const unsubscribeToClick = GlobalEventManager.subscribeToClick((event: MouseEvent) => {
// Do something when the mouse is clicked.
})
// Be sure to invoke the unsubscribe closure that we get as a result of subscribing to the event.
unsubscribeToClick()
// You can also subscribe to key-based events.
const unsubscribeToEnterKey = GlobalEventManager.subscribeToKey('Enter', (pressed: boolean, event: KeyboardEvent) => {
if (pressed) {
// Do something when the key is pressed.
} else {
// Do something when the key is not pressed (after being pressed).
}
})
// Cleanup the subscription later.
unsubscribeToEnterKey()
The parameter module contains the classes and utilities to properly setup bidirectional communication with the JUCE backend.
There are three different types of parameters:
You can subscribe to a parameter of any type to register callbacks when its internal value is updated. This is useful when making sure the UI elements are in-sync with the backend values.
React:
import { IBooleanParameter, ParameterChangeSource } from '@bbx-audio/nectar'
interface IToggleButtonProps {
parameter: IBooleanParameter
}
const ToggleButton = ({ parameter }: IToggleButtonProps) => {
const [isToggled, setIsToggled] = useState(parameter.getValue())
useEffect(() => {
const unsubscribe = parameter.subscribe((value, source) => {
if (isToggled !== value) {
setIsToggled(value)
}
})
return () => unsubscribe()
}, [])
function onClick(): void {
parameter.setValue(!isToggled, ParameterChangeSource.Frontend)
}
return (
<button onClick={onClick}>
{isToggled ? 'On' : 'Off'}
</button>
)
}
Svelte:
The ParameterManager is a global object that handles backend communication for each parameter that is registered with it.
You can register parameters individually or call a special method that loads parameter data from the backend.
:warning: Do NOT call the initializeParameters method to unless the backend has been properly setup to pass parameter
configuration information to the frontend in JSON format.
import { ParameterManager, ParameterType } from '@bbx-audio/nectar'
// Create the parameter manager
const manager = new ParameterManager()
// Register a simple boolean parameter for toggling mono on and off
const monoParameter = manager.registerParameter<ParameterType.Boolean>({
id: 'MONO',
name: 'Mono',
type: ParameterType.Boolean,
defaultValue: false,
})
// Pass your mono parameter to a component, like a toggle button
// ...
// Be sure to clean up the manager as well
manager.cleanup()
This project is open and welcoming of outside contributions! There are multiple ways you can contribute: