0.1.0
Initial release of KWave: animated, customizable layered wave hero backgrounds for Compose
Multiplatform.
Added
KWavedrop-in composable that owns its ownwithFrameNanosanimation loop. It is
lifecycle-aware (pauses belowSTARTED, resumes with no time jump), honors the system
reduce-motion setting (renders a single static frame when on), supports anisPlayingfreeze and
aspeedmultiplier, and reads a livephaseShiftevery recomposition for pager/scroll sync. It
randomizes its initial phase per instance so multiple instances do not synchronize.- Stateless
KWave(config, phase, time, modifier)composable: a deterministic function
of(phase, time)with no internal state, for screenshot tests and external
synchronization. WaveColorscolor strategy (theme-free; noMaterialTheme) built through factories:
gradient(top, bottom),palette(colors)(rainbow, depth-sampled per layer), andsolid(color).
Per-layer fills are palette-derived, never a hardcoded black.ShadowModesealed interface:Auto(default, per-layer black/white by luminance),
FromWave,None, andCustom(color, alpha). Controls both the depth shadow band and the
luminous highlight lip.WaveConfigwith a neutralDefaultpreset and agenerate(waveCount, crests, harmonic, spacing, amplitude, variation, colors, shadow, gradientEnd, seed)factory that auto-distributes
the static per-layer phase, alpha-by-depth, breathing, and per-layer tint.crestsis a relative
crest density (1= baseline) and its twinharmonicis the crest roughness (0= clean rounded
sine, higher = choppier).harmonic(crest roughness) param ongenerate(), the twin ofcrests(density):
0is a clean rounded sine, higher mixes in more second-harmonic weight for choppier, less regular
crests. Jittered per layer like the other generator inputs.WaveLayerSpecadvanced low-level layer spec with all values coerced into valid ranges at
construction, pluswithTint/withAlphaergonomic overrides.- Configurable
gradientEndvertical gradient fraction. - Per-layer
harmonicweight with0fproducing a pure sine wave. spacing,variation, andseedparameters onWaveConfig.generate.spacingcontrols
the vertical spread/overlap of the layers,variation(in[0, 1]) is the amount of per-layer
pseudo-random jitter that desyncs the layers, andseedmakes that jitter
deterministic (same seed ⇒ same layout; change it for a different one).- Renderer honors the caller's
Modifierverbatim (no forcedfillMaxSize), guards against
zero-size layouts, cachesPathobjects across frames, and keeps thedropLast(1)depth effect
safe at any layer count (includingN = 0andN = 1). - Kotlin Multiplatform targets:
androidTarget,iosArm64,iosSimulatorArm64,jvm. - Stable public API: regular
@Immutableclasses (notdata classes) andImmutableListlayers,
tracked by the binary-compatibility-validator with a committedapi/dump; Dokka API docs. - Compose Desktop sample app (
./gradlew :sample:run) doubling as a live visual test harness.
Changed
- Drop-in motion is now in-place breathing, not horizontal drift. The drop-in
KWaveholds the
ambientphaseconstant (phase = initialPhase + phaseShift); the only ambient motion is the
per-layer amplitude breathing (time = elapsed * speed), so the waves oscillate in place rather
than marching sideways.speedis now the breathing/bob tempo multiplier (not a drift speed), and
phaseShiftremains a live external signal for explicit horizontal translation (e.g. a pager
offset). solid()and same-colorgradient()now ramp the per-layer fill by depth (darker back →
lighter front) so monochrome/same-color waves stay visible over the same-color background, instead
of relying on alpha alone.palette()background calmed to a muted wash (rainbow stays on the wave fills). The background
is no longer the full saturated multi-stop palette; it is a muted two-stop gradient derived
(darkened) from the palette extremes, so the colorful waves stay the subject.generate()gainedgradientEnd;seedmoved to the end as an advanced param. Callers can
now set the background gradient end directly instead of rebuilding a secondWaveConfig;seedis
now the last argument and documented as advanced (leave at0unless you need a reproducible
re-roll or to pin a screenshot).phaseSpreadremoved fromgenerate(). Its effect was a barely-perceptible static crest
reshuffle, swamped in practice by the per-layer phase jitter, so the high-level factory no longer
exposes it. The low-levelWaveLayerSpec.phaseOffsetis unchanged and still lets power users
set a per-layer horizontal phase directly.
Fixed
ShadowMode.Custom.alphanow drives the rendered shadow band. It was previously ignored
(a no-op); the supplied alpha is now applied as the band's peak opacity.- Degenerate background gradient when
gradientEnd → 0.WaveConfig.gradientEndis now floored
at a small positive minimum (GRADIENT_END_MIN ≈ 0.04), so the backgroundverticalGradientnever
spans zero height (which painted a flat, broken color).
Full Changelog: https://github.com/Shyzkanza/KWave/commits/0.1.0