Skip to content

Releases: Grandgular/rive

v2.0.0 — Renderer split (WebGL2 + Canvas)

26 Apr 20:08
0e62b39

Choose a tag to compare

Tag: v2.0.0
Packages: @grandgular/rive-angular-webgl2@2.0.0 · @grandgular/rive-angular-canvas@2.0.0

This release is a major product-line change: Rive for Angular is split into two renderer-specific npm packages, matching Rive’s Canvas vs WebGL2 model (similar to rive-react). The monolithic @grandgular/rive-angular meta package is no longer built from this repository — you choose one runtime at install time (@rive-app/webgl2 or @rive-app/canvas).

The Angular public API (<rive-canvas>, RiveCanvasComponent, RiveFileService, provideRiveRuntime, data binding, etc.) stays the same; what changes are package names, import paths, and peer dependencies.

What’s new

Item Role
@grandgular/rive-angular-webgl2 Recommended for most apps — Rive Renderer via peer @rive-app/webgl2
@grandgular/rive-angular-canvas Smaller Canvas2D runtime via peer @rive-app/canvas
Embedded rive-angular-core Shared code is copied into each published package; npm run sync:rive-angular-core syncs from libs/rive-angular-core
libs/rive-angular-core Internal library for shared tests/utilities (not published on its own)

Install (pick one)

WebGL2 / Rive Renderer (recommended):

npm install @grandgular/rive-angular-webgl2 @rive-app/webgl2

Canvas2D:

npm install @grandgular/rive-angular-canvas @rive-app/canvas

Code change

Replace the old import with the package you install:

// Before (meta package — no longer published from this repo)
import { RiveCanvasComponent, Fit, Alignment } from '@grandgular/rive-angular';

// After — WebGL2 (example)
import { RiveCanvasComponent, Fit, Alignment } from '@grandgular/rive-angular-webgl2';

// After — Canvas2D (example)
// import { RiveCanvasComponent, Fit, Alignment } from '@grandgular/rive-angular-canvas';

Template usage is unchanged:

<rive-canvas
  src="assets/animation.riv"
  [fit]="Fit.Contain"
  [alignment]="Alignment.Center"
/>

Optional: provideRiveRuntime (unchanged API)

import { ApplicationConfig } from '@angular/core';
import { provideRiveRuntime } from '@grandgular/rive-angular-webgl2';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRiveRuntime({
      wasmUrl: 'assets/rive/rive.wasm',
      lazy: true,
    }),
  ],
};

(Use the same import path as the package you chose — rive-angular-webgl2 or rive-angular-canvas.)

Migration from @grandgular/rive-angular

  1. Remove the old package: npm uninstall @grandgular/rive-angular
  2. Install one of the two packages and its Rive peer (@rive-app/webgl2 or @rive-app/canvas) as above
  3. Update all imports from '@grandgular/rive-angular' to the new package name
  4. If the legacy package still exists on npm for your users, mark it deprecated with a message pointing to the new package names (see repository maintainer notes)

Why 2.0.0 on new package names?

Both new packages ship as 2.0.0 to mark the next major in the Grandgular Rive Angular line: removing the single meta package and requiring new install paths and peers is a breaking change for consumers, even where the component API is unchanged. See the root README (“Why 2.0.0”).

Details

GitHub release title (copy-paste)

v2.0.0 — Renderer split (WebGL2 + Canvas)

Use this file as the release description body, or paste the sections you need into the GitHub “Release notes” field when you publish tag v2.0.0.

v1.1.0 - Configurable runtime initialization

16 Apr 09:10

Choose a tag to compare

Adds provideRiveRuntime() to control when the Rive WASM runtime initializes (eager by default, optional lazy mode). Changes are additive relative to v1.0.0 - no breaking changes.

What's new

API Role
provideRiveRuntime({ wasmUrl }) Eager runtime initialization on app startup
provideRiveRuntime({ wasmUrl, lazy: true }) Lazy runtime initialization on first real usage
RiveRuntimeConfig Public config type export for runtime setup
Internal shared runtime initializer Idempotent + deduplicated runtime readiness across component/service

RiveCanvasComponent and RiveFileService now coordinate runtime readiness in a single flow, including concurrent first-use scenarios.

import { ApplicationConfig } from '@angular/core';
import { provideRiveRuntime } from '@grandgular/rive-angular';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRiveRuntime({
      wasmUrl: 'assets/rive/rive.v1.wasm',
      lazy: true,
    }),
  ],
};

Migration note

If you previously used:

provideAppInitializer(() => RuntimeLoader.setWasmUrl('assets/rive/rive.v1.wasm'));

You can now use:

provideRiveRuntime({ wasmUrl: 'assets/rive/rive.v1.wasm' });

Details

See CHANGELOG.md and the library README.md.

v1.0.0 - Lifecycle outputs

07 Apr 21:17

Choose a tag to compare

@grandgular/rive-angular v1.0.0

First stable release under. Adds animation lifecycle outputs (aligned with @rive-app/canvas callbacks) and re-exports LoopType and LoopEvent. Changes are additive relative to v0.4.0 — no breaking changes.

What’s new

Output Role
animationPlay / animationPause / animationStop Play / pause / stop (RiveEvent, EventType)
animationLoop Loop iteration finished; event.data is LoopEvent
animationAdvance Per-frame advance (high frequency; emitted outside NgZone.run)

isPlaying / isPaused signals behave as before; the new outputs expose the same lifecycle as events.

<rive-canvas
  src="animation.riv"
  (animationPlay)="onPlay($event)"
  (animationLoop)="onLoop($event)"
/>

Details

See CHANGELOG.md and the library README.

v0.4.0 — Data Binding & ViewModel Support

23 Feb 13:17

Choose a tag to compare

@grandgular/rive-angular v0.4.0

Major feature release adding full Rive Data Binding and ViewModel support with declarative and imperative APIs. Brings Angular library to feature parity with React's @rive-app/react-webgl2 hooks.

🎉 What's New

Declarative Data Binding

🔗 dataBindings Input — New reactive input for template-driven ViewModel property updates. Keys present in the input are controlled — the input is the source of truth.

<rive-canvas
  src="assets/game.riv"
  [dataBindings]="{
    backgroundColor: '#FF5733',
    score: playerScore(),
    playerName: userName(),
    isActive: true
  }"
/>

ViewModel Selection

🎯 viewModelName Input — Select which ViewModel to use (defaults to artboard's default ViewModel). Changing this input after load automatically reinitializes the ViewModel.

<rive-canvas
  src="assets/multi-vm.riv"
  viewModelName="GameViewModel"
/>

Two-Way Reactivity

↔️ dataBindingChange Output — React to property changes from within the animation, including trigger events.

onDataChange(event: DataBindingChangeEvent) {
  console.log(`${event.path} changed to ${event.value}`);
  // event.propertyType: 'color' | 'number' | 'string' | 'boolean' | 'enum' | 'trigger'
}
<rive-canvas
  src="assets/interactive.riv"
  (dataBindingChange)="onDataChange($event)"
/>

Universal Data Binding Methods

🔧 Auto-Detecting API — Set and get any ViewModel property with automatic type detection.

riveRef = viewChild.required(RiveCanvasComponent);

// Auto-detects property types
this.riveRef().setDataBinding('score', 100);        // number
this.riveRef().setDataBinding('playerName', 'Bob'); // string
this.riveRef().setDataBinding('isActive', true);    // boolean

const score = this.riveRef().getDataBinding('score'); // returns number

// Fire triggers
this.riveRef().fireViewModelTrigger('onComplete');

Color Manipulation (Resolves ng-rive #56)

🎨 Rich Color API — Set and manipulate colors using multiple formats: hex strings, ARGB integers, or RiveColor objects.

// Multiple color formats supported
this.riveRef().setColor('backgroundColor', '#FF5733');           // hex string
this.riveRef().setColor('backgroundColor', 0xFFFF5733);          // ARGB integer
this.riveRef().setColor('backgroundColor', { r: 255, g: 87, b: 51, a: 255 });

// RGBA components
this.riveRef().setColorRgba('backgroundColor', 255, 87, 51, 255);

// Opacity manipulation (preserves RGB)
this.riveRef().setColorOpacity('backgroundColor', 0.5); // 0.0-1.0

// Get color
const color = this.riveRef().getColor('backgroundColor');
// Returns: { r: 255, g: 87, b: 51, a: 255 }

Color Utilities (Exported)

🛠️ Standalone Color Tools — Utility functions exported for consumer use.

import { parseRiveColor, riveColorToArgb, riveColorToHex } from '@grandgular/rive-angular';

// Parse any color format
const color = parseRiveColor('#FF5733');
// Returns: { r: 255, g: 87, b: 51, a: 255 }

// Convert to formats
const argb = riveColorToArgb(color);  // 0xFFFF5733
const hex = riveColorToHex(color);    // '#FF5733FF'

Controlled vs Uncontrolled Semantics

⚖️ React-inspired pattern — Keys in dataBindings input are controlled (input wins on every update). Keys outside are uncontrolled (managed imperatively). Calling setDataBinding() on a controlled key logs a warning in debug mode.

Advanced ViewModel Access

🔬 viewModelInstance Signal — Direct access to the ViewModel instance for advanced scenarios.

const vm = this.riveRef().viewModelInstance();
if (vm) {
  console.log('ViewModel properties:', vm.properties);
}

Error Handling

🏷️ New RIVE_4xx Error Codes — Data Binding validation errors emitted through loadError output:

Code Name Description
RIVE_401 ViewModelNotFound Specified ViewModel not found in file
RIVE_402 DataBindingPropertyNotFound Property path not found in ViewModel
RIVE_403 DataBindingTypeMismatch Value type mismatch, invalid color format, or opacity out of range

📐 API Reference

New Component Inputs

Input Type Description
dataBindings Record<string, DataBindingValue> Declarative ViewModel property bindings (controlled keys)
viewModelName string | undefined ViewModel name to use (defaults to artboard's default)

New Component Outputs

Output Type Description
dataBindingChange EventEmitter<DataBindingChangeEvent> Emits when ViewModel properties change from animation

New Component Signals

Signal Type Description
viewModelInstance Signal<ViewModel | null> Direct access to current ViewModel instance

New Component Methods

Method Signature Description
setDataBinding (path: string, value: DataBindingValue): void Set any ViewModel property (auto-detects type)
getDataBinding (path: string): DataBindingValue | undefined Get any ViewModel property (auto-detects type)
fireViewModelTrigger (path: string): void Fire a trigger property
setColor (path: string, color: string | number | RiveColor): void Set color (hex, ARGB, or object)
getColor (path: string): RiveColor | undefined Get color as RiveColor object
setColorRgba (path: string, r: number, g: number, b: number, a?: number): void Set color using RGBA components
setColorOpacity (path: string, opacity: number): void Set opacity (0.0-1.0)

New Exported Types

interface RiveColor {
  r: number;  // 0-255
  g: number;  // 0-255
  b: number;  // 0-255
  a: number;  // 0-255
}

type DataBindingValue = number | string | boolean | RiveColor;

type DataBindingPropertyType = 
  | 'number' 
  | 'string' 
  | 'boolean' 
  | 'color' 
  | 'enum' 
  | 'trigger';

interface DataBindingChangeEvent {
  path: string;
  value: DataBindingValue;
  propertyType: DataBindingPropertyType;
}

New Exported Utilities

// Color parsing and conversion
function parseRiveColor(input: string | number | RiveColor): RiveColor;
function riveColorToArgb(color: RiveColor): number;
function riveColorToHex(color: RiveColor): string;

🔄 Architecture

Data Binding uses Rive's official ViewModel system (introduced in @rive-app/canvas ^2.35.0) instead of direct shape manipulation. ViewModels are created in the Rive editor and provide:

  • Type-safe property bindings
  • Designer-friendly workflow
  • Two-way reactivity
  • Automatic UI updates

✅ No Breaking Changes

  • All new features are optional and additive
  • dataBindings input is optional — existing templates unaffected
  • All new methods are purely additive
  • No existing API signatures changed
  • Files without ViewModels work exactly as before

📚 Documentation

  • Updated README with Data Binding examples (declarative, imperative, color manipulation)
  • Updated error codes table with RIVE_401, RIVE_402, RIVE_403
  • Updated API reference with 8 new methods and 3 new inputs/outputs
  • Added Color Utilities section
  • See CHANGELOG.md for complete details

🎯 Issue Resolution

This release resolves ng-rive issue #56 — "How to set solid color dynamically?" by providing a comprehensive color manipulation API through the ViewModel system.

🙏 Thanks

All 112 tests passing (53 new tests for Data Binding and color scenarios). Production-ready and feature-complete for dynamic data-driven animations.

v0.3.0 — Text Run Support

17 Feb 16:33

Choose a tag to compare

@grandgular/rive-angular v0.3.0

Feature release adding full Rive Text Run support with declarative and imperative APIs, matching the official @rive-app/canvas SDK.

🎉 What's New

Declarative Text Runs

📝 textRuns Input — New reactive input for template-driven text updates. Keys present in the input are controlled — the input is the source of truth.

<rive-canvas
  src="assets/hello.riv"
  [textRuns]="{ greeting: userName(), subtitle: 'Welcome' }"
/>

Imperative Text Runs

🔧 getTextRunValue() / setTextRunValue() — Read and write text run values programmatically for keys not managed by the textRuns input (uncontrolled keys).

riveRef = viewChild.required(RiveCanvasComponent);

const value = this.riveRef().getTextRunValue('greeting');
this.riveRef().setTextRunValue('dynamicText', 'New value');

Nested Artboard Text Runs

🪆 getTextRunValueAtPath() / setTextRunValueAtPath() — Access text runs inside nested artboards and components.

this.riveRef().setTextRunValueAtPath('button_text', 'Click Me', 'NestedArtboard/Button');

Controlled vs Uncontrolled Semantics

⚖️ React-inspired pattern — Keys in textRuns input are controlled (input wins on every update). Keys outside are uncontrolled (managed imperatively). Calling setTextRunValue() on a controlled key logs a warning in debug mode.

Error Handling

🏷️ RIVE_205 Error Code — New TextRunNotFound validation error emitted through loadError output when a text run name doesn't exist in the animation file.

📐 API Compatibility

All four text run methods are a 1:1 match with the official @rive-app/canvas ^2.35.0 SDK:

Method Signature
getTextRunValue (textRunName: string): string | undefined
setTextRunValue (textRunName: string, textRunValue: string): void
getTextRunValueAtPath (textRunName: string, path: string): string | undefined
setTextRunValueAtPath (textRunName: string, textRunValue: string, path: string): void

✅ No Breaking Changes

  • textRuns input is optional — existing templates are unaffected.
  • All new methods are purely additive.
  • No existing API signatures changed.

📚 Documentation

  • Updated README with declarative, imperative, and nested text run examples.
  • Updated error codes table with RIVE_205.
  • Updated API reference table with all four new methods.
  • See CHANGELOG.md for complete details.

🙏 Thanks

All 59 tests passing (13 new tests for text run scenarios). Production-ready.

v0.2.0 — Enhanced DX, Validation & Critical Fixes

16 Feb 21:29

Choose a tag to compare

@grandgular/rive-angular v0.2.0

Major feature release with enhanced developer experience, comprehensive validation system, and critical stability improvements.

🎉 What's New

Debug Mode & Validation

  • 🛠️ Debug Mode — New debugMode input and provideRiveDebug() for configurable logging ('none' | 'error' | 'warn' | 'info' | 'debug')
  • ✅ Automatic Validation — Validates artboard, animation, state machine, and input names against loaded files with helpful suggestions
  • 🏷️ Error Codes — Structured error codes (RIVE_1xx, RIVE_2xx, RIVE_3xx) for programmatic error handling

Reactive Configuration

  • ⚡ Reactive Inputs — All component inputs (fit, alignment, artboard, animations, stateMachines) now trigger appropriate updates
  • 🎨 Layout Optimization — Changes to fit/alignment update layout without full reload

Architecture Improvements

  • 🔒 Readonly Signals — Public signals properly encapsulated to prevent external mutation
  • 🏗️ DI IntegrationElementObserver converted to Angular service for better testability
  • 📦 Type Safety — Eliminated unsafe type assertions in configuration

🐛 Critical Fixes

  • 📱 Multi-Monitor Support — Device pixel ratio now read dynamically, supporting monitor changes and zoom
  • ⏱️ Proper TimingriveReady output now emits after animation fully loads (not just instance creation)
  • 🔄 Race Conditions — Fixed race conditions in RiveFileService and cache management
  • 🧹 Memory Leaks — Fixed clearCache() to properly handle pending loads
  • 🔐 No Mutations — Service no longer mutates ArrayBuffer objects (uses WeakMap)

⚠️ Breaking Changes

1. Readonly Signals

Public signals (isPlaying, isPaused, isLoaded, riveInstance) are now readonly.

Before:

component.isPlaying.set(true); // ❌ No longer works

After:

component.playAnimation(); // ✅ Use component methods

2. riveReady Timing

riveReady output now emits after animation is fully loaded.

Before:

// Emitted immediately, instance might not be ready
(riveReady)="onReady($event)"

After:

// Emits after load, instance is guaranteed ready
(riveReady)="onReady($event)" // artboardNames available
// Or use (loaded) if you don't need the instance

📚 Documentation

See CHANGELOG.md for complete details and migration guide.

🙏 Thanks

All 45 tests passing. Production-ready with comprehensive audit completed.

v0.1.2 — Safari ResizeObserver fix

13 Feb 14:29

Choose a tag to compare

@grandgular/rive-angular v0.1.2

Patch release with a Safari browser compatibility fix.

What's Changed

🐛 ResizeObserver loop fix — Resolved ResizeObserver loop completed with undelivered notifications error that occurred in Safari browsers during canvas resize operations

Technical Details

  • Added error boundary handling for ResizeObserver callback
  • Prevents console errors without affecting animation rendering functionality

v0.1.1 — Repository links update

13 Feb 07:21

Choose a tag to compare

@grandgular/rive-angular v0.1.1

Patch release with updated package metadata.

What's Changed

🔗 Repository links — Updated GitHub repository URLs from personal account to organization account (Grandgular/rive)

Package Metadata Updates

v0.1.0 — Angular wrapper for Rive animations

12 Feb 21:48

Choose a tag to compare

@grandgular/rive-angular v0.1.0

Initial release of a modern Angular wrapper for Rive animations with reactive state management.

Highlights

  • 🚀 Modern Angular — Built with Angular 18+ signals, standalone components, and zoneless architecture
  • Performance-first — Runs outside Angular zone, OnPush change detection, IntersectionObserver for off-screen optimization
  • 🔄 Reactive API — Signal-based state management (isPlaying, isPaused, isLoaded, riveInstance)
  • 📦 File cachingRiveFileService for preloading and caching .riv files
  • 🌐 SSR-ready — Full server-side rendering support
  • 🎯 Type-safe — Full TypeScript support

What's included

  • RiveCanvasComponent — Standalone component with support for animations, state machines, triggers, and inputs
  • RiveFileService — Preload and cache .riv files with reference counting
  • Public methodsplayAnimation, pauseAnimation, stopAnimation, reset, setInput, fireTrigger
  • Event outputsloaded, loadError, stateChange, riveEvent, riveReady

Requirements

  • Angular 18.0.0 or higher
  • @rive-app/canvas 2.35.0 or higher

Install

```bash
npm install @grandgular/rive-angular @rive-app/canvas
```

Documentation

See README for full API reference and usage examples.