feat: standalone parameters, corrected scale math, pointer events, and first tests - #11
Merged
maxwellmattryan merged 1 commit intoAug 7, 2026
Conversation
…d first tests
- Extract pure applyScale/unapplyScale into src/math/scale.ts and fix all curves:
logarithmic is now the ratio curve min*(max/min)^n (the old 10^(2n-2) ignored
min/max and was discontinuous at n=0), quadratic/cubic are real power curves
(previously silently linear), exponential is a deprecated alias of logarithmic,
and min <= 0 falls back to linear with a warning
- Export the concrete FloatParameter/BooleanParameter/ChoiceParameter classes so
standalone web apps can use parameters without a JUCE backend
- ParameterManager takes { backend: 'auto' | 'juce' | 'none' } (default 'auto',
detecting a real JUCE host), no longer clobbers defaults to zero through the
placeholder relay, and initializeParameters() fails fast without a backend
- FloatParameter: setDisplayValue now notifies listeners, honours source, and
clamps; constructor and normalizedDefaultValue clamp into [0, 1];
displayToJuceNormalized gains the missing midpoint guard
- GlobalEventManager: pointerdown replaces mousedown (subscribeToClick kept as a
deprecated alias), key subscriptions gain element scoping, a handled-protocol
(return true -> preventDefault), and opt-in auto-repeat; pressed state survives
the last unsubscribe; beginDrag() hosts one shared pointermove/up/cancel set
per gesture with central pointer capture
- First test suite in the repo (67 tests): scale round-trips and oracles, math
utils, parameter behavior regressions, event manager efficiency and lifecycle
- CI: publish-automatic now requires the Build workflow to have succeeded
- Version 0.3.0
maxwellmattryan
deleted the
feat/scale-math-standalone-params-and-events
branch
August 7, 2026 18:26
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes nectar usable by standalone web apps (no JUCE backend), fixes the scale math, extends the event manager to pointer input, and adds the repo's first test suite. Version
0.3.0.Scale math (
src/math/scale.ts, new)applyScale/unapplyScaleare now pure, exported functions with corrected curves:logarithmic10^(2n-2)— a fixed 100:1 curve that ignored min/max and was discontinuous at n=0 (a 20 Hz–20 kHz parameter jumped 20 → ~220 Hz at the bottom of travel, and read 651.8 Hz at quarter travel where a log sweep reads 112.5 Hz)min * (max/min)^n— true ratio curve; requiresmin > 0, else falls back to linear with a one-time warningquadratic/cubicn²/n³exponentialn²logarithmic(nothing anywhere setscale:, verified across every consumer repo)Parameters without JUCE
FloatParameter/BooleanParameter/ChoiceParameterare now exported — they were always backend-free; onlyParameterManagercoupled them to JUCEnew ParameterManager({ backend: 'auto' | 'juce' | 'none' }), default'auto', which detects a real JUCE host via the initialisation data platform. Without a host, the relay is skipped, so defaults are no longer clobbered to zero by the placeholder slider state, andinitializeParameters()rejects fast instead of awaiting a native call that never resolvessetDisplayValuenow clamps, notifies listeners, and honourssource(it previously did none of those, silently desyncing subscribers)normalizedDefaultValueclamp into [0, 1] (a log-scale default near min used to produce a negative normalized value)displayToJuceNormalizedgains the guard the other midpoint path already had (midpoint == min used to return 1 for every input; < min returned NaN — straight to JUCE)Event manager
pointerdownreplacesmousedowninternally (covers mouse + touch + pen);subscribeToClickremains as a deprecated alias ofsubscribeToPointerDownsubscribeToKey(key, cb, { target?, repeat? })— element scoping (one containment check per subscriber, still one document listener) and opt-in auto-repeat for held keystruemarks the event consumed and the manager callspreventDefault()— consumers no longer have to call it unconditionallybeginDrag(event, { onMove, onEnd })hosts one sharedpointermove/pointerup/pointercancelset per gesture with central pointer capture — one drag ever active, so component libraries stop attaching their own document listeners per knobTests (first in the repo — 67)
vitest run: scale round-trips across all curves plus the 20 Hz–20 kHz oracle table (20 / 112.47 / 632.46 / 20 000), math utils incl. deliberate pins ofgainToDecibels' NaN-above-unity behavior, parameter regressions (default preservation,setDisplayValuenotification, midpoint guards), and event manager lifecycle (exactly three document listeners regardless of subscription count, scoping, handled-protocol, repeat, drag listener removal on up and cancel).CI
cd.publish-automatic.ymlnow requires the triggering Build run to have succeeded — it previously fired oncompleted, so a failed build with a version bump still published to npm.Migration notes (template-plugin)
Nothing breaks at publish — template-plugin pins
0.2.0exactly. When it bumps to0.3.0:ParameterManagerbehavior is unchanged inside a real JUCE WebView ('auto'detects the host); pass{ backend: 'juce' }to force the old unconditional wiringsubscribeToClickstill works (deprecated); switch tosubscribeToPointerDownwhen convenienttrueto consume events — existing void callbacks behave as before, butpreventDefaultis no longer called unless a callback opts inTesting
yarn test— 67/67yarn build— clean;dist/index.d.tsverified to export the parameter classes, scale functions, and new event manager APInpx eslint+prettier --check— cleanFloatParameter's log scale