lfocomp 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,24 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.1.1] - 2026-03-28
9
+
10
+ ### Fixed
11
+ - LFO widget param sliders overflowing their containers (`min-width: 0` on grid cells)
12
+ - LFO widgets too narrow (~213 px) on typical viewports — panel moved above main grid, each widget now ~343 px
13
+ - `destroyLFO` now removes incoming LFO-chain routes as well as outgoing ones
14
+ - `ModIndicator._reposition` crash due to undefined `badge` variable
15
+ - Arc canvas height mismatch between construction and draw path
16
+ - `pointercancel` during drag left SVG wire overlay in the DOM
17
+ - Color-cycling underflow (`LFO_COLORS[-1] === undefined`) when label provided but color omitted on first `createLFO` call
18
+ - Stale `ModIndicator` badges persisting after routes deleted externally — `_pruneDeadRoutes()` runs each tick
19
+ - Escape key in click-to-type param editor no longer commits the value
20
+
21
+ ### Added
22
+ - LFO widget params split into two visual groups: Rate/Depth (primary) and Phase/Offs./Jitter/Skew (secondary)
23
+ - 91-test suite across three files: `engine.test.js`, `widget.test.js`, `comp.test.js`
24
+ - Coverage thresholds in `vitest.config.js` (60 % lines/functions, 50 % branches)
25
+
8
26
  ## [0.1.0] - 2026-03-28
9
27
 
10
28
  ### Added
@@ -20,5 +38,6 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
20
38
  - Log-scaled rate slider (0.01 Hz – 10 Hz)
21
39
  - Zero runtime dependencies
22
40
 
23
- [Unreleased]: https://github.com/KUSH42/lfocomp/compare/v0.1.0...HEAD
41
+ [Unreleased]: https://github.com/KUSH42/lfocomp/compare/v0.1.1...HEAD
42
+ [0.1.1]: https://github.com/KUSH42/lfocomp/compare/v0.1.0...v0.1.1
24
43
  [0.1.0]: https://github.com/KUSH42/lfocomp/releases/tag/v0.1.0
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
8
8
  [![zero dependencies](https://img.shields.io/badge/dependencies-0-brightgreen.svg)]()
9
9
  [![ES modules](https://img.shields.io/badge/module-ESM-f7df1e.svg)]()
10
- [![npm](https://img.shields.io/badge/npm-not%20yet%20published-lightgrey.svg)]()
10
+ [![npm](https://img.shields.io/npm/v/lfocomp.svg)](https://www.npmjs.com/package/lfocomp)
11
11
 
12
12
  **[Live demo](https://kush42.github.io/lfo.html)**
13
13
 
@@ -35,7 +35,7 @@ lfocomp is one import, three files, and you're live.
35
35
 
36
36
  ## Install
37
37
 
38
- ### npm *(coming soon)*
38
+ ### npm
39
39
  ```bash
40
40
  npm install lfocomp
41
41
  ```
package/lfo-ui.js CHANGED
@@ -149,10 +149,17 @@ const CSS = `
149
149
  gap: 5px;
150
150
  }
151
151
 
152
+ .lfo-params-secondary {
153
+ border-top: 1px solid #2a2a3e;
154
+ padding-top: 5px;
155
+ margin-top: 4px;
156
+ }
157
+
152
158
  .lfo-param-group {
153
159
  display: flex;
154
160
  flex-direction: column;
155
161
  gap: 3px;
162
+ min-width: 0;
156
163
  }
157
164
 
158
165
  .lfo-param-group label {
@@ -770,18 +777,21 @@ export class LFOWidget {
770
777
  canvasRow.appendChild(shapesEl);
771
778
  root.appendChild(canvasRow);
772
779
 
773
- // Param sliders — 3-row × 2-col grid (rate, depth, phase, offset, jitter, skew)
774
- const params = document.createElement('div');
775
- params.className = 'lfo-params';
776
-
777
- this._rateInput = this._addParam(params, 'Rate', 0.01, 10, 1, 0.01, 'baseRate', v => `${v.toFixed(2)}Hz`, 'log');
778
- this._depthInput = this._addParam(params, 'Depth', 0, 1, 1, 0.01, 'baseDepth', v => `${Math.round(v * 100)}%`);
779
- this._phaseInput = this._addParam(params, 'Phase', 0, 1, 0, 0.01, 'phase', v => `${Math.round(v * 360)}°`);
780
- this._offsetInput = this._addParam(params, 'Offs.', -1, 1, 0, 0.01, 'offset', v => v.toFixed(2));
781
- this._jitterInput = this._addParam(params, 'Jitter', 0, 1, 0, 0.01, 'jitter', v => `${Math.round(v * 100)}%`);
782
- this._skewInput = this._addParam(params, 'Skew', 0, 1, 0.5, 0.01, 'skew', v => `${Math.round((v - 0.5) * 200)}%`);
783
-
784
- root.appendChild(params);
780
+ // Param sliders — two groups: primary (rate, depth) and secondary (phase, offset, jitter, skew)
781
+ const params1 = document.createElement('div');
782
+ params1.className = 'lfo-params';
783
+ this._rateInput = this._addParam(params1, 'Rate', 0.01, 10, 1, 0.01, 'baseRate', v => `${v.toFixed(2)}Hz`, 'log');
784
+ this._depthInput = this._addParam(params1, 'Depth', 0, 1, 1, 0.01, 'baseDepth', v => `${Math.round(v * 100)}%`);
785
+
786
+ const params2 = document.createElement('div');
787
+ params2.className = 'lfo-params lfo-params-secondary';
788
+ this._phaseInput = this._addParam(params2, 'Phase', 0, 1, 0, 0.01, 'phase', v => `${Math.round(v * 360)}°`);
789
+ this._offsetInput = this._addParam(params2, 'Offs.', -1, 1, 0, 0.01, 'offset', v => v.toFixed(2));
790
+ this._jitterInput = this._addParam(params2, 'Jitter', 0, 1, 0, 0.01, 'jitter', v => `${Math.round(v * 100)}%`);
791
+ this._skewInput = this._addParam(params2, 'Skew', 0, 1, 0.5, 0.01, 'skew', v => `${Math.round((v - 0.5) * 200)}%`);
792
+
793
+ root.appendChild(params1);
794
+ root.appendChild(params2);
785
795
 
786
796
  // Connect handle
787
797
  const handle = this._handle = document.createElement('div');
package/lfo.js CHANGED
@@ -617,10 +617,17 @@ const CSS = `
617
617
  gap: 5px;
618
618
  }
619
619
 
620
+ .lfo-params-secondary {
621
+ border-top: 1px solid #2a2a3e;
622
+ padding-top: 5px;
623
+ margin-top: 4px;
624
+ }
625
+
620
626
  .lfo-param-group {
621
627
  display: flex;
622
628
  flex-direction: column;
623
629
  gap: 3px;
630
+ min-width: 0;
624
631
  }
625
632
 
626
633
  .lfo-param-group label {
@@ -1238,18 +1245,21 @@ class LFOWidget {
1238
1245
  canvasRow.appendChild(shapesEl);
1239
1246
  root.appendChild(canvasRow);
1240
1247
 
1241
- // Param sliders — 3-row × 2-col grid (rate, depth, phase, offset, jitter, skew)
1242
- const params = document.createElement('div');
1243
- params.className = 'lfo-params';
1244
-
1245
- this._rateInput = this._addParam(params, 'Rate', 0.01, 10, 1, 0.01, 'baseRate', v => `${v.toFixed(2)}Hz`, 'log');
1246
- this._depthInput = this._addParam(params, 'Depth', 0, 1, 1, 0.01, 'baseDepth', v => `${Math.round(v * 100)}%`);
1247
- this._phaseInput = this._addParam(params, 'Phase', 0, 1, 0, 0.01, 'phase', v => `${Math.round(v * 360)}°`);
1248
- this._offsetInput = this._addParam(params, 'Offs.', -1, 1, 0, 0.01, 'offset', v => v.toFixed(2));
1249
- this._jitterInput = this._addParam(params, 'Jitter', 0, 1, 0, 0.01, 'jitter', v => `${Math.round(v * 100)}%`);
1250
- this._skewInput = this._addParam(params, 'Skew', 0, 1, 0.5, 0.01, 'skew', v => `${Math.round((v - 0.5) * 200)}%`);
1251
-
1252
- root.appendChild(params);
1248
+ // Param sliders — two groups: primary (rate, depth) and secondary (phase, offset, jitter, skew)
1249
+ const params1 = document.createElement('div');
1250
+ params1.className = 'lfo-params';
1251
+ this._rateInput = this._addParam(params1, 'Rate', 0.01, 10, 1, 0.01, 'baseRate', v => `${v.toFixed(2)}Hz`, 'log');
1252
+ this._depthInput = this._addParam(params1, 'Depth', 0, 1, 1, 0.01, 'baseDepth', v => `${Math.round(v * 100)}%`);
1253
+
1254
+ const params2 = document.createElement('div');
1255
+ params2.className = 'lfo-params lfo-params-secondary';
1256
+ this._phaseInput = this._addParam(params2, 'Phase', 0, 1, 0, 0.01, 'phase', v => `${Math.round(v * 360)}°`);
1257
+ this._offsetInput = this._addParam(params2, 'Offs.', -1, 1, 0, 0.01, 'offset', v => v.toFixed(2));
1258
+ this._jitterInput = this._addParam(params2, 'Jitter', 0, 1, 0, 0.01, 'jitter', v => `${Math.round(v * 100)}%`);
1259
+ this._skewInput = this._addParam(params2, 'Skew', 0, 1, 0.5, 0.01, 'skew', v => `${Math.round((v - 0.5) * 200)}%`);
1260
+
1261
+ root.appendChild(params1);
1262
+ root.appendChild(params2);
1253
1263
 
1254
1264
  // Connect handle
1255
1265
  const handle = this._handle = document.createElement('div');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lfocomp",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Ableton-style LFO modulation component — wire LFOs to any HTML input by drag-and-drop",
5
5
  "type": "module",
6
6
  "main": "./lfo-comp.js",