Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
if: matrix.node-version == '20.x'
uses: codecov/codecov-action@v4
with:
files: ./coverage/libs/rive-angular/lcov.info
files: ./coverage/libs/rive-angular-canvas/lcov.info,./coverage/libs/rive-angular-webgl2/lcov.info,./coverage/libs/rive-angular-core/lcov.info
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
Expand All @@ -69,5 +69,5 @@ jobs:
- name: Build library
run: npm run build:lib

- name: Pack library (dry-run)
- name: Pack libraries (dry-run)
run: npm run pack:lib
20 changes: 20 additions & 0 deletions libs/rive-angular/CHANGELOG.md → CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,26 @@

All notable changes to this project will be documented in this file.

## [2.0.0] - 2026-04-26

### Added

- **`@grandgular/rive-angular-canvas`**: Canvas2D runtime (peer: [`@rive-app/canvas`](https://www.npmjs.com/package/@rive-app/canvas)).
- **`@grandgular/rive-angular-webgl2`**: WebGL2 / Rive Renderer runtime (peer: [`@rive-app/webgl2`](https://www.npmjs.com/package/@rive-app/webgl2)).
- **Embedded shared sources** at `src/rive-angular-core` in each published package; `npm run sync:rive-angular-core` updates them from `libs/rive-angular-core` (and aligns shared renderer code between the two packages).
- **Tests** for shared error utilities in `libs/rive-angular-core`.

### Removed

- **`@grandgular/rive-angular`** (meta package) — removed from the monorepo. Published packages are only **`@grandgular/rive-angular-canvas`** and **`@grandgular/rive-angular-webgl2`**.

### Migration

- Uninstall the old meta package: `npm uninstall @grandgular/rive-angular` (and `@grandgular/rive-angular-canvas` if you only had it as a peer).
- Install one renderer:
`npm install @grandgular/rive-angular-webgl2 @rive-app/webgl2` **or** `npm install @grandgular/rive-angular-canvas @rive-app/canvas`.
- Change imports from `'@grandgular/rive-angular'` to `'@grandgular/rive-angular-webgl2'` or `'@grandgular/rive-angular-canvas'` (API is the same; pick runtime by Rive [Canvas vs WebGL2](https://rive.app/docs/runtimes/web/canvas-vs-webgl)).

## [1.1.0] - 2026-04-16

### Added
Expand Down
76 changes: 46 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,40 @@
<!-- Synced with libs/rive-angular/README.md — update both when changing the public README. -->
# Rive for Angular (Grandgular)

# @grandgular/rive-angular
Primary npm packages: [`@grandgular/rive-angular-webgl2`](https://www.npmjs.com/package/@grandgular/rive-angular-webgl2) (recommended) and [`@grandgular/rive-angular-canvas`](https://www.npmjs.com/package/@grandgular/rive-angular-canvas). The legacy package `@grandgular/rive-angular` is **not** maintained in this repo; migrate to one of the two packages (see [CHANGELOG](CHANGELOG.md)).

[![npm version](https://img.shields.io/npm/v/@grandgular/rive-angular.svg)](https://www.npmjs.com/package/@grandgular/rive-angular)
[![npm downloads](https://img.shields.io/npm/dm/@grandgular/rive-angular.svg)](https://www.npmjs.com/package/@grandgular/rive-angular)
[![Bundle Size](https://img.shields.io/bundlephobia/minzip/@grandgular/rive-angular)](https://bundlephobia.com/package/@grandgular/rive-angular)

[![npm webgl2](https://img.shields.io/npm/v/@grandgular/rive-angular-webgl2.svg?label=webgl2)](https://www.npmjs.com/package/@grandgular/rive-angular-webgl2)
[![npm canvas](https://img.shields.io/npm/v/@grandgular/rive-angular-canvas.svg?label=canvas)](https://www.npmjs.com/package/@grandgular/rive-angular-canvas)
[![Angular](https://img.shields.io/badge/Angular-18%2B-red)](https://angular.dev)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

![Rive Angular showcase preview](https://raw.githubusercontent.com/Grandgular/rive/main/libs/rive-angular/docs/showcase-afi.gif)

Modern Angular wrapper for [Rive](https://rive.app) animations with reactive state management, built with Angular signals and zoneless architecture.

**1.x** is the stable major line: the public API follows [Semantic Versioning](https://semver.org/).
The public API follows [Semantic Versioning](https://semver.org/).

**Why `2.0.0` for new package names?**
`@grandgular/rive-angular-webgl2` and `@grandgular/rive-angular-canvas` are **separate** npm packages (each has its own version line in the registry), but we ship them as **2.0.0** to mark one **product-level major**: the old single package **`@grandgular/rive-angular` is no longer built here**, you must **pick a renderer package** and **change import paths and peer dependencies** — that is a breaking change for consumers, even where the Angular component API stays the same. Details: [CHANGELOG](CHANGELOG.md) (section **2.0.0**) and [Migration from `@grandgular/rive-angular`](#migration-from-grandgularrive-angular) below.

## Packages (WebGL2 vs Canvas)

Rive’s web runtimes are separate npm packages; this workspace mirrors the official [Canvas vs WebGL2](https://rive.app/docs/runtimes/web/canvas-vs-webgl) and [React](https://rive.app/docs/runtimes/react/react) model with **renderer-specific** Angular packages:

| npm package | Rive runtime (peer) | Use case |
|-------------|---------------------|----------|
| `@grandgular/rive-angular-webgl2` | `@rive-app/webgl2` | **Recommended** — Rive Renderer, best quality/performance |
| `@grandgular/rive-angular-canvas` | `@rive-app/canvas` | Smaller bundle, simpler vector/raster work |

Internal shared code is maintained in `libs/rive-angular-core` and **embedded** in each published package. Renderer implementation files are kept aligned between canvas and webgl2, with only the runtime adapter differing. After changing shared code or shared renderer logic, run: `npm run sync:rive-angular-core`

### Migration from `@grandgular/rive-angular`

The npm package `@grandgular/rive-angular` is **not** built from this repository anymore. Move to either **`@grandgular/rive-angular-webgl2`** (with `@rive-app/webgl2`) or **`@grandgular/rive-angular-canvas`** (with `@rive-app/canvas`) and change your import path; the public API (components, `RiveFileService`, `provideRiveRuntime`, etc.) is unchanged. See [CHANGELOG](CHANGELOG.md) (v2.0.0).

## What is Rive?

[Rive](https://rive.app) is a real-time interactive design and animation tool. It allows designers and developers to create animations that respond to different states and user inputs. Rive animations are lightweight, interactive, and can be used in apps, games, and websites.

## Why @grandgular/rive-angular?
## Why use these packages?

This library provides a **modern, Angular-native** way to integrate Rive animations into your Angular applications:

Expand All @@ -37,7 +53,7 @@ This library provides a **modern, Angular-native** way to integrate Rive animati

[ng-rive](https://www.npmjs.com/package/ng-rive) was the previous Angular wrapper for Rive, but it has been **unmaintained since 2021** and is incompatible with modern Angular versions:

| Feature | ng-rive | @grandgular/rive-angular |
| Feature | ng-rive | @grandgular/rive-angular-webgl2 |
|---------|---------|--------------------------|
| Angular version | 9-12 (legacy) | 18+ (modern) |
| Architecture | Modules, Zone.js | Signals, standalone |
Expand All @@ -52,7 +68,7 @@ This library provides a **modern, Angular-native** way to integrate Rive animati

This library follows the design principles of the official [rive-react](https://github.com/rive-app/rive-react) library but adapts them to Angular's reactive paradigm:

| Aspect | rive-react | @grandgular/rive-angular |
| Aspect | rive-react | @grandgular/rive-angular-webgl2 |
|--------|------------|--------------------------|
| Component API | `<Rive>` component | `<rive-canvas>` |
| Reactivity | Hooks (useState, useEffect) | Signals |
Expand All @@ -70,14 +86,14 @@ Both libraries provide similar features and follow the same philosophy of provid

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

### 2. Update imports

| ng-rive | @grandgular/rive-angular |
| ng-rive | @grandgular/rive-angular-webgl2 |
|---------|--------------------------|
| `import { RiveModule } from 'ng-rive'` | `import { RiveCanvasComponent } from '@grandgular/rive-angular'` |
| `import { RiveModule } from 'ng-rive'` | `import { RiveCanvasComponent } from '@grandgular/rive-angular-webgl2'` |
| Add `RiveModule` to `NgModule.imports` | Add `RiveCanvasComponent` to `imports` of standalone component |

### 3. Update templates
Expand All @@ -91,7 +107,7 @@ npm install @grandgular/rive-angular @rive-app/canvas
</canvas>
```

**@grandgular/rive-angular:**
**@grandgular/rive-angular-webgl2:**

```html
<!-- Standalone, signals, zoneless -->
Expand All @@ -114,7 +130,7 @@ npm install @grandgular/rive-angular @rive-app/canvas
</canvas>
```

**@grandgular/rive-angular:**
**@grandgular/rive-angular-webgl2:**

```html
<rive-canvas
Expand All @@ -133,13 +149,13 @@ onLoaded() {
## Installation

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

Or with yarn:

```bash
yarn add @grandgular/rive-angular @rive-app/canvas
yarn add @grandgular/rive-angular-webgl2 @rive-app/webgl2
```

## Quick Start
Expand All @@ -148,7 +164,7 @@ yarn add @grandgular/rive-angular @rive-app/canvas

```typescript
import { Component } from '@angular/core';
import { RiveCanvasComponent, Fit, Alignment } from '@grandgular/rive-angular';
import { RiveCanvasComponent, Fit, Alignment } from '@grandgular/rive-angular-webgl2';

@Component({
selector: 'app-root',
Expand Down Expand Up @@ -189,7 +205,7 @@ export class AppComponent {

```typescript
import { Component, viewChild } from '@angular/core';
import { RiveCanvasComponent } from '@grandgular/rive-angular';
import { RiveCanvasComponent } from '@grandgular/rive-angular-webgl2';

@Component({
selector: 'app-interactive',
Expand Down Expand Up @@ -291,7 +307,7 @@ Use the `dataBindings` input for reactive, template-driven data binding:

```typescript
import { Component, signal } from '@angular/core';
import { RiveCanvasComponent } from '@grandgular/rive-angular';
import { RiveCanvasComponent } from '@grandgular/rive-angular-webgl2';

@Component({
selector: 'app-data-binding',
Expand Down Expand Up @@ -349,7 +365,7 @@ Use methods for direct, programmatic control:

```typescript
import { Component, viewChild } from '@angular/core';
import { RiveCanvasComponent } from '@grandgular/rive-angular';
import { RiveCanvasComponent } from '@grandgular/rive-angular-webgl2';

@Component({
selector: 'app-imperative',
Expand Down Expand Up @@ -405,7 +421,7 @@ export class ImperativeComponent {
The library exports color conversion utilities for advanced use cases:

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

// Parse various color formats
const color1 = parseRiveColor('#FF5733'); // { r: 255, g: 87, b: 51, a: 255 }
Expand Down Expand Up @@ -489,7 +505,7 @@ For better performance, you can preload and cache .riv files:

```typescript
import { Component, inject, DestroyRef } from '@angular/core';
import { RiveCanvasComponent, RiveFileService } from '@grandgular/rive-angular';
import { RiveCanvasComponent, RiveFileService } from '@grandgular/rive-angular-webgl2';

@Component({
selector: 'app-preload',
Expand Down Expand Up @@ -537,7 +553,7 @@ The library provides a built-in debug mode to help you troubleshoot animations.
Enable debug mode globally in your `app.config.ts`:

```typescript
import { provideRiveDebug } from '@grandgular/rive-angular';
import { provideRiveDebug } from '@grandgular/rive-angular-webgl2';

export const appConfig: ApplicationConfig = {
providers: [
Expand Down Expand Up @@ -574,7 +590,7 @@ Initializes runtime on app startup:

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

export const appConfig: ApplicationConfig = {
providers: [
Expand All @@ -589,7 +605,7 @@ Initializes runtime only when first needed (first `rive-canvas` init or `RiveFil

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

export const appConfig: ApplicationConfig = {
providers: [
Expand Down Expand Up @@ -718,7 +734,7 @@ import {
EventType,
LoopType,
type LoopEvent,
} from '@grandgular/rive-angular';
} from '@grandgular/rive-angular-webgl2';

@Component({
imports: [RiveCanvasComponent],
Expand Down Expand Up @@ -755,7 +771,7 @@ export class LifecycleDemoComponent {
}
```

`LoopType` and `LoopEvent` are re-exported from `@grandgular/rive-angular` for convenience.
`LoopType` and `LoopEvent` are re-exported from the package you install (`@grandgular/rive-angular-webgl2` or `@grandgular/rive-angular-canvas`) for convenience.

#### Public Signals (Readonly)

Expand Down Expand Up @@ -845,7 +861,7 @@ The library is fully compatible with Angular Universal and server-side rendering
- 📝 **Better error codes** for programmatic error handling
- 🧪 **Improved testability** with DI-based services

See [CHANGELOG.md](libs/rive-angular/CHANGELOG.md) for complete details, migration guide, and all improvements.
See [CHANGELOG.md](CHANGELOG.md) for complete details, migration guide, and all improvements.

## Requirements

Expand Down
14 changes: 6 additions & 8 deletions apps/showcase/src/app/app.spec.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import { TestBed } from '@angular/core/testing';
import { provideRouter } from '@angular/router';
import { App } from './app';
import { NxWelcome } from './nx-welcome';

describe('App', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [App, NxWelcome],
imports: [App],
providers: [provideRouter([])],
}).compileComponents();
});

it('should render title', async () => {
it('should create', () => {
const fixture = TestBed.createComponent(App);
await fixture.whenStable();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain(
'Welcome showcase',
);
fixture.detectChanges();
expect(fixture.componentInstance).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { Component, signal, ChangeDetectionStrategy } from '@angular/core';
import { RiveCanvasComponent, RiveEvent } from '@grandgular/rive-angular';
import {
RiveCanvasComponent,
RiveEvent,
} from '@grandgular/rive-angular-webgl2';

@Component({
selector: 'app-feedback-stars',
Expand Down
11 changes: 10 additions & 1 deletion apps/showcase/tsconfig.app.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"baseUrl": "../..",
"outDir": "../../dist/out-tsc",
"types": [],
"paths": {
"@grandgular/rive-angular": ["dist/libs/rive-angular"]
"@grandgular/rive-angular-canvas": [
"libs/rive-angular-canvas/src/index.ts"
],
"@grandgular/rive-angular-core": [
"libs/rive-angular-core/src/index.ts"
],
"@grandgular/rive-angular-webgl2": [
"libs/rive-angular-webgl2/src/index.ts"
]
}
},
"include": ["src/**/*.ts"],
Expand Down
65 changes: 65 additions & 0 deletions libs/rive-angular-canvas/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# @grandgular/rive-angular-canvas

**Rive for Angular (Canvas2D)** — a modern [Angular](https://angular.dev) (18+) library for [Rive](https://rive.app) `.riv` animations: standalone [`RiveCanvasComponent`](https://github.com/Grandgular/rive#readme), [`RiveFileService`](https://github.com/Grandgular/rive#readme) for loading and caching, optional [`provideRiveRuntime()`](https://github.com/Grandgular/rive#readme) for WASM, **ViewModel / data binding**, state machines, and signal-based, zoneless-friendly updates.

This package targets the **smaller** official runtime [`@rive-app/canvas`](https://www.npmjs.com/package/@rive-app/canvas) (HTML5 Canvas 2D). For **Rive Renderer** (WebGL2) and the default recommendation for most apps, use [`@grandgular/rive-angular-webgl2`](https://www.npmjs.com/package/@grandgular/rive-angular-webgl2) — see Rive’s [Canvas vs WebGL2](https://rive.app/docs/runtimes/web/canvas-vs-webgl) overview.

![Rive for Angular – interactive showcase (GIF)](./docs/rive-showcase.gif)

## Install

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

`@rive-app/canvas` is a **peer dependency** (install it alongside this package).

## Quick start

**1. Import the component** (standalone):

```typescript
import { RiveCanvasComponent, Fit, Alignment } from '@grandgular/rive-angular-canvas';
```

**2. Register the component** in the standalone `imports` array of your feature component (or your route `loadComponent` setup).

**3. Use the template** (shared selector and public API with the WebGL2 package):

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

**4. (Optional) Configure the Rive WASM runtime** in `app.config.ts` — see the full [README](https://github.com/Grandgular/rive#readme) and [CHANGELOG](https://github.com/Grandgular/rive/blob/main/CHANGELOG.md) for `provideRiveRuntime({ wasmUrl, lazy: true })` and `provideRiveDebug()`.

## What you get (API overview)

- **`<rive-canvas>`** — load `.riv` from `src` or `buffer`, layout, playback, state machines, ViewModel + **data binding**, lifecycle and error outputs (same component API as `@grandgular/rive-angular-webgl2`).
- **`RiveFileService`** — preload, dedupe, and cache `RiveFile` instances.
- **Types re-exported** from the Canvas peer where useful: e.g. `Rive`, `RiveFile`, `Layout`, `Fit`, `Alignment`, `LoopType`, and related types.
- **Shared helpers** (colors, errors, debug) are embedded in this package; long-form docs and migration notes: monorepo [README](https://github.com/Grandgular/rive#readme).

## When to pick Canvas2D vs WebGL2

- **This package** — smaller download, simpler 2D-style pipelines; good when you accept Canvas2D trade-offs.
- **`@grandgular/rive-angular-webgl2`** — Rive’s usual recommendation for **quality and performance** and Renderer-only features — see the official [comparison](https://rive.app/docs/runtimes/web/canvas-vs-webgl).

## Versioning and migration

Published as **2.0.0** as a **product-line major** (split into renderer packages; legacy meta package no longer built here). See [“Why 2.0.0”](https://github.com/Grandgular/rive#readme) and the **Migration** section in the root README if you used `@grandgular/rive-angular` before.

## More documentation

- **Full guide, comparisons, and advanced topics:** [GitHub `README.md`](https://github.com/Grandgular/rive#readme)
- **Changelog:** [`CHANGELOG.md`](https://github.com/Grandgular/rive/blob/main/CHANGELOG.md)
- **WebGL2 / Rive Renderer package:** [`@grandgular/rive-angular-webgl2`](https://www.npmjs.com/package/@grandgular/rive-angular-webgl2)
- **Rive runtimes (official):** [Web](https://rive.app/docs/runtimes/web/web)

## License

[MIT](https://github.com/Grandgular/rive/blob/main/LICENSE) (see repository).
Loading
Loading