npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@elearn/smile

v0.1.0

Published

Seamless Media and Interactive Learning Experience

Readme

SMILE — Seamless Media and Interactive Learning Experience

A React-based framework for creating interactive, animated educational presentations with synchronized audio, declarative scene definitions, and an extensible plugin system.

Overview

SMILE enables creators to produce rich learning experiences that combine smooth animations, interactive quizzes, and audio narration — all defined declaratively through JSON scene definitions. It supports a plugin architecture for custom shapes and animations, a tile-based responsive layout system, and LLM-friendly scene authoring.

Key Features

  • Declarative Scene Definitions — Define scenes as JSON with shapes, animations, audio, and layout
  • Plugin Architecture — Extensible shape and animation plugins with a central registry
  • Tile-Based Responsive Layout — All positions/sizes use virtual grid units that scale to any screen size
  • Audio Synchronization — Timeline animations synchronized with audio playback, with buffering handling
  • Interactive Components — Built-in quiz plugin with multi-choice cards and 3D flip animations
  • Playback Controls — Full media player controls: play/pause, seek, volume, fullscreen
  • Event System — Pub/sub event system for inter-component and plugin communication
  • LLM-Compatible — Scene definitions designed for GenAI-driven content generation

Quick Start

Installation

npm install @duongtdn/smile

Basic Usage

import React from 'react';
import { SmilePlayer, PluginRegistry, builtin } from '@duongtdn/smile';

// Register built-in plugins
PluginRegistry.registerPlugin(builtin);

const sceneDefinition = {
  id: 'my-scene',
  layout: {
    aspectRatio: '16:9',
    gridSize: [32, 18],
    backgroundColor: '#1a1a2e'
  },
  shapes: [
    {
      id: 'title',
      type: 'text',
      position: { x: 4, y: 3 },
      size: { width: 24, height: 4 },
      pluginRef: 'builtin',
      props: {
        content: 'Hello SMILE!',
        format: { fontSize: 2, color: '#ffffff', fontWeight: 'bold' }
      }
    }
  ],
  animations: [
    {
      target: 'title',
      pluginRef: 'builtin',
      animation: { type: 'typing', params: { duration: 50, staggerDelay: 80 } },
      at: 0
    }
  ],
  audio: { src: '/narration.mp3' }
};

function App() {
  return (
    <div style={{ width: 720 }}>
      <SmilePlayer scene={sceneDefinition} />
    </div>
  );
}

Architecture

┌─────────────────────────────────────────────────┐
│ SmilePlayer                                     │
│  ┌─────────────────────────────────────────────┐│
│  │ PlaybackEventProvider (React Context)       ││
│  │  ┌─────────────────────────────────────────┐││
│  │  │ Scene                                   │││
│  │  │  ├── Shape Rendering (via PluginRegistry│││
│  │  │  ├── Layout & Resize (ResizeObserver)   │││
│  │  │  ├── PlaybackControl                    │││
│  │  │  │    ├── useAnimationTimeline          │││
│  │  │  │    ├── useAudioPlayback              │││
│  │  │  │    ├── useSynchronizer               │││
│  │  │  │    └── useFullscreen                 │││
│  │  │  └── BufferingSpinner                   │││
│  │  └─────────────────────────────────────────┘││
│  └─────────────────────────────────────────────┘│
└─────────────────────────────────────────────────┘
         │                       │
    PluginRegistry          PlaybackEventSystem
    ├── builtin             (pub/sub events)
    │   ├── Shapes: Circle, Rectangle, Line, Text, CompositeRectangle
    │   └── Animations: draw, move, fadeIn, fadeOut
    └── quiz
        └── Shapes: MultiChoice (with enter animation)

Project Structure

packages/
├── index.ts                      # Public API exports
├── core/
│   ├── plugin-registry/          # Singleton plugin management
│   └── runtime/
│       ├── components/           # React UI (SmilePlayer, Scene, PlaybackControl)
│       ├── events/               # Playback event system (pub/sub)
│       ├── hooks/                # React hooks (timeline, audio, sync, fullscreen)
│       ├── lib/                  # TimelineAnimationFactory (anime.js integration)
│       └── types/                # TypeScript type definitions
├── plugins/
│   ├── types.ts                  # Plugin interface definitions
│   ├── builtin/                  # Built-in shapes & animations
│   └── quiz/                     # Quiz plugin (MultiChoice)
playground/                       # Development playground app
docs/                             # Documentation

Core Concepts

Scene Definition

A scene is defined as a SceneDefinition object:

interface SceneDefinition {
  id: string;
  layout: LayoutConfig;       // aspectRatio, gridSize, backgroundColor
  shapes?: Shape[];           // Visual elements
  animations?: Animation[];   // Timeline-based animations
  audio?: AudioConfig;        // Audio narration
}

Tile-Based Coordinate System

All positions and sizes use tile units rather than pixels. The grid is defined by gridSize (e.g., [32, 18]):

  • Tile width = container pixel width / grid columns
  • Tile height = container pixel height / grid rows

This makes scenes fully responsive — on resize, tile dimensions are recalculated, and all elements reposition automatically.

Plugin System

Plugins provide shapes (visual elements) and animations (transformations over time). Each plugin implements the Plugin interface:

interface Plugin {
  name: string;
  shape?: Record<string, ShapePlugin>;
  animation?: Record<string, AnimationPlugin>;
}

Plugins are registered with PluginRegistry.registerPlugin(plugin) and resolved automatically when scenes reference them.

Animation Timeline

Animations are orchestrated via anime.js timelines. Each Animation definition targets one or more shapes and specifies a type, parameters, and timeline position:

interface Animation {
  target: string | string[];         // Shape ID(s)
  pluginRef?: string;                // Which plugin provides the animation
  animation: {
    type: string;                    // e.g., 'draw', 'move', 'typing'
    params?: Record<string, any>;    // Duration, easing, direction, etc.
  };
  at?: number | string;              // Timeline position (ms or relative)
}

Built-in Shapes

| Shape | Description | Key Props | |-------|-------------|-----------| | Circle | SVG circle/ellipse | fill, lineColor, lineWidth, lineStyle | | Rectangle | SVG rectangle with optional rounded corners | fill, lineColor, lineWidth, lineStyle, rx, ry | | Line | SVG polyline with optional arrow | points, lineColor, lineWidth, lineStyle, showArrow | | Text | Rich text with per-character animation support | content, format, ranges | | CompositeRectangle | Rectangle with embedded text | All Rectangle + Text props, align, padding |

Built-in Animations

| Animation | Compatible Shapes | Description | |-----------|-------------------|-------------| | draw | Circle, Rectangle, Line, CompositeRectangle | Progressive stroke reveal | | move | All | Position change (absolute or relative +=/-=) | | fadeIn | All | Opacity 0 → 1 | | fadeOut | All | Opacity 1 → 0 | | typing | Text | Character-by-character reveal | | untyping | Text | Character-by-character hide | | floatIn | Text | Directional slide + fade in | | floatOut | Text | Directional slide + fade out | | enter | MultiChoice (quiz) | Full quiz entrance sequence |

Playback Event System

Components and plugins communicate via a pub/sub event system:

| Event | Purpose | |-------|---------| | scene-ready | Scene initialized and ready to play | | create-timeline | Request to build/rebuild animation timeline | | timeline-recreated | Timeline has been rebuilt | | halt-animation / unhalt-animation | Pause/resume during resize | | playing / paused / seeking | UI state notifications | | resume / pause | Programmatic play/pause control | | lock-hide-controls / unlock-hide-controls | Control visibility during interaction |

Development

Prerequisites

  • Node.js (v18+)
  • npm

Setup

git clone https://github.com/duongtdn/smile.git
cd smile/core
npm install

Scripts

| Command | Description | |---------|-------------| | npm start | Start playground dev server (port 3330) | | npm run build | Build the library to dist/ | | npm test | Run all tests | | npm run test:watch | Run tests in watch mode | | npm run test:components | Run component tests only (jsdom) | | npm run test:node | Run node tests only | | npm run test:coverage | Run tests with coverage report |

Tech Stack

  • React 19 — UI framework
  • TypeScript — Type-safe development
  • anime.js v4 — Animation engine
  • Jest — Testing framework
  • Testing Library — React component testing
  • Webpack — Bundling (playground dev server)

Documentation

License

UNLICENSED

Author

Duong Nguyen (duongtdn)