feat: add math_wave color strip source type
Lint & Test / test (push) Has been cancelled

Mathematical wave generator that produces per-LED colors from
configurable waveform layers (sine, triangle, sawtooth, square) with
superposition, mapped through a gradient palette. Supports sync clocks,
bindable speed, and up to 8 wave layers.

- Storage model with wave validation and apply_update
- Numpy-vectorized stream with gradient LUT color mapping
- API schemas (create/update/response) and route registration
- Frontend editor with dynamic wave layer rows, gradient picker,
  speed widget, and IconSelect waveform selectors
- i18n in en/ru/zh
This commit is contained in:
2026-04-05 00:41:07 +03:00
parent edc6d27e2e
commit ace24715c8
16 changed files with 977 additions and 5 deletions
+2
View File
@@ -90,6 +90,8 @@ Plain `<select>` dropdowns should be enhanced with visual selectors depending on
Both widgets hide the native `<select>` but keep it in the DOM with its value in sync. **The `<select>` and the visual widget are two separate things — changing one does NOT automatically update the other.** After programmatically changing the `<select>` value, call `.refresh()` (EntitySelect) or `.setValue(val)` (IconSelect) to update the trigger display. Call `.destroy()` when the modal closes.
**CRITICAL pitfall — `<option>` elements required:** `IconSelect` does NOT create `<option>` elements in the native `<select>` — it only builds a visual popup grid. The native `<select>` must already contain matching `<option value="...">` elements (either from the Jinja2 template or added via JS) **before** `.value` is set. Setting `.value` on a `<select>` with no matching `<option>` **silently fails** — the value stays empty, and all downstream logic (section switching, auto-naming, type setup) breaks with no error. **When adding a new type to any IconSelect-enhanced `<select>`, you MUST add the `<option>` in the HTML template too.**
**Common pitfall:** Using a preset/palette selector (e.g. gradient preset dropdown or effect type picker) that changes the underlying `<select>` value but forgets to call `.setValue()` on the IconSelect — the visual grid still shows the old selection.
**IMPORTANT:** For `IconSelect` item icons, use SVG icons from `js/core/icon-paths.ts` (via `_icon(P.iconName)`) or styled `<span>` elements (e.g., `<span style="font-weight:bold">A</span>`). **Never use emoji** — they render inconsistently across platforms and themes.