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

@trilogy-innovations/video-applets-player

v0.0.4

Published

A React video player component that renders interactive videos from JSON schemas with timeline controls

Readme

@trilogy-innovations/video-applets-player

A powerful React video player component that renders interactive videos from JSON schemas with timeline controls, animations, and educational elements.

npm version

✨ Features

  • 🎬 Interactive Video Player - Render videos from declarative JSON schemas
  • ⏱️ Timeline Controls - Play, pause, seek, reset, fullscreen controls
  • 🎭 Rich Elements - Text, shapes, images, videos, clocks, arrows, line plots
  • 🎨 Smooth Animations - Keyframe-based interpolation with 60fps rendering
  • 📐 Flexible Layouts - Vertical, horizontal, absolute, and grid positioning
  • 🎯 Educational Focus - Purpose-built for interactive learning content
  • 📱 Responsive Design - Works across desktop, tablet, and mobile
  • ⌨️ Keyboard Support - Full keyboard navigation and shortcuts
  • 🔧 TypeScript Ready - Complete type definitions included

📦 Installation

npm install @trilogy-innovations/video-applets-player
yarn add @trilogy-innovations/video-applets-player
pnpm add @trilogy-innovations/video-applets-player

🚀 Quick Start

Basic Usage

import React from 'react';
import { VideoPlayer, CompactTimeline, useVideoPlayer } from '@trilogy-innovations/video-applets-player';
import '@trilogy-innovations/video-applets-player/dist/styles.css';

function MyVideoApp() {
  const schema = {
    meta: {
      width: 1920,
      height: 1080, 
      duration: 10,
      fps: 30
    },
    nodes: [
      {
        kind: 'container',
        id: 'root',
        layout: { type: 'vertical', splits: [1] },
        children: ['welcome-text']
      },
      {
        kind: 'element',
        id: 'welcome-text',
        type: 'text',
        text: 'Welcome to Video Applets!',
        fontSize: 48,
        fontWeight: 'bold',
        color: '#2c3e50',
        timeline: { in: 0, out: 10 },
        keyframes: [
          { time: 0, opacity: 0, scaleX: 0.5, scaleY: 0.5 },
          { time: 1, opacity: 1, scaleX: 1, scaleY: 1 },
          { time: 9, opacity: 1 },
          { time: 10, opacity: 0 }
        ],
        layoutRef: 'root'
      }
    ]
  };

  const videoPlayer = useVideoPlayer(schema);

  return (
    <div style={{ width: '100%', maxWidth: '800px', margin: '0 auto' }}>
      <VideoPlayer 
        schema={schema}
        {...videoPlayer}
        style={{ width: '100%', aspectRatio: '16/9' }}
      />
      <CompactTimeline {...videoPlayer} />
    </div>
  );
}

export default MyVideoApp;

Advanced Example with Multiple Elements

import { VideoPlayer, CompactTimeline, useVideoPlayer } from '@trilogy-innovations/video-applets-player';
import '@trilogy-innovations/video-applets-player/dist/styles.css';

function EducationalContent() {
  const mathLessonSchema = {
    meta: { width: 1920, height: 1080, duration: 15 },
    nodes: [
      // Root container with 2x2 grid
      {
        kind: 'container',
        id: 'root',
        layout: { 
          type: 'grid', 
          rows: 2, 
          cols: 2,
          gaps: { row: 20, col: 20 }
        },
        children: ['title', 'clock', 'plot', 'arrow']
      },
      
      // Animated title
      {
        kind: 'element',
        id: 'title', 
        type: 'title',
        text: 'Time and Data Visualization',
        fontSize: 36,
        timeline: { in: 0, out: 15 },
        keyframes: [
          { time: 0, y: -50, opacity: 0 },
          { time: 1, y: 0, opacity: 1 }
        ],
        layoutRef: 'root'
      },
      
      // Interactive clock
      {
        kind: 'element',
        id: 'clock',
        type: 'clock',
        clockConfig: {
          hours: 3,
          minutes: 15,
          size: 200,
          showNumbers: true,
          highlightMinuteHand: { type: 'glow', color: '#e74c3c' }
        },
        timeline: { in: 2, out: 15 },
        layoutRef: 'root'
      },
      
      // Data visualization
      {
        kind: 'element',
        id: 'plot',
        type: 'lineplot',
        linePlotConfig: {
          title: 'Student Heights',
          data: [
            { value: 48, color: '#3498db' },
            { value: 52, color: '#3498db' },
            { value: 47, color: '#3498db' },
            { value: 50, color: '#3498db' }
          ],
          plotType: 'frequency',
          pointShape: 'circle',
          pointSize: 20,
          xAxis: { title: 'Height (inches)', min: 45, max: 55 }
        },
        timeline: { in: 5, out: 15 },
        layoutRef: 'root'
      },
      
      // Pointing arrow
      {
        kind: 'element',
        id: 'arrow',
        type: 'arrow',
        arrowConfig: {
          startPoint: { x: 0.1, y: 0.1 },
          endPoint: { x: 0.9, y: 0.9 },
          strokeColor: '#f39c12',
          strokeWidth: 4,
          arrowHeadType: 'triangle'
        },
        timeline: { in: 8, out: 12 },
        keyframes: [
          { time: 8, opacity: 0 },
          { time: 9, opacity: 1 }
        ],
        layoutRef: 'root'
      }
    ]
  };

  const videoPlayer = useVideoPlayer(mathLessonSchema);

  return (
    <div className="educational-video">
      <VideoPlayer schema={mathLessonSchema} {...videoPlayer} />
      <CompactTimeline {...videoPlayer} />
    </div>
  );
}

📚 API Reference

Components

VideoPlayer

Main video player component that renders the schema.

interface VideoPlayerProps {
  schema: VideoSchema;
  currentTime: number;
  style?: React.CSSProperties;
  className?: string;
}

CompactTimeline

Timeline controls component with play/pause, seek, and fullscreen.

interface TimelineControlsProps {
  currentTime: number;
  duration: number;
  isPlaying: boolean;
  onSeek: (time: number) => void;
  onTogglePlay: () => void;
  onReset?: () => void;
  onFullscreen?: () => void;
  className?: string;
}

Hooks

useVideoPlayer(schema: VideoSchema)

Main hook that manages video player state.

const videoPlayer = useVideoPlayer(schema);
// Returns: {
//   currentTime: number;
//   isPlaying: boolean;
//   duration: number;
//   onTogglePlay: () => void;
//   onSeek: (time: number) => void;
//   onReset: () => void;
//   onFullscreen: () => void;
// }

useSchema(initialSchema: VideoSchema)

Hook for schema management and validation.

const { schema, validationErrors, isValid, updateSchema } = useSchema(initialSchema);

useAnimation()

Hook for animation state management.

const { currentTime, isPlaying, play, pause, seek, reset } = useAnimation();

useFullscreen()

Hook for fullscreen functionality.

const { isFullscreen, toggleFullscreen, exitFullscreen } = useFullscreen();

Services

SchemaService

Validates and processes video schemas.

import { SchemaService } from '@trilogy-innovations/video-applets-player';

const errors = SchemaService.validateSchema(schema);
const isValid = errors.length === 0;

AssetManager

Manages loading and caching of media assets.

import { AssetManager } from '@trilogy-innovations/video-applets-player';

AssetManager.preloadAsset('image', 'https://example.com/image.jpg');

🎨 Schema Structure

Meta Configuration

interface VideoMeta {
  width: number;          // Canvas width in pixels
  height: number;         // Canvas height in pixels  
  duration: number;       // Total duration in seconds
  fps?: number;          // Frame rate (default: 30)
  backgroundColor?: string; // Background color
}

Container Nodes

interface ContainerNode {
  kind: 'container';
  id: string;
  layout: {
    type: 'vertical' | 'horizontal' | 'absolute' | 'grid';
    splits?: number[];     // For vertical/horizontal
    rows?: number;         // For grid
    cols?: number;         // For grid
    gaps?: { row: number; col: number }; // For grid
  };
  children: string[];      // Child node IDs
  style?: React.CSSProperties;
}

Element Nodes

interface ElementNode {
  kind: 'element';
  id: string;
  type: 'text' | 'shape' | 'image' | 'video' | 'html' | 'title' | 'box' | 'clock' | 'arrow' | 'lineplot';
  layoutRef: string;       // Parent container ID
  timeline: {
    in: number;           // Start time in seconds
    out: number;          // End time in seconds
  };
  keyframes?: Keyframe[];  // Animation keyframes
  stateChanges?: StateChange[]; // State change events
  // Element-specific properties...
}

Keyframes

interface Keyframe {
  time: number;           // Time in seconds
  x?: number;            // X position offset
  y?: number;            // Y position offset
  scaleX?: number;       // X scale factor
  scaleY?: number;       // Y scale factor
  rotate?: number;       // Rotation in degrees
  opacity?: number;      // Opacity (0-1)
  // Custom properties for specific elements
}

🎭 Element Types

Text Element

{
  type: 'text',
  text: 'Hello World',
  fontSize: 24,
  fontFamily: 'Arial',
  fontWeight: 'bold',
  color: '#333',
  textAlign: 'center'
}

Image Element

{
  type: 'image',
  src: 'https://example.com/image.jpg',
  alt: 'Description',
  objectFit: 'cover'
}

Video Element

{
  type: 'video',
  src: 'https://example.com/video.mp4',
  autoplay: true,
  muted: true,
  loop: false
}

Clock Element

{
  type: 'clock',
  clockConfig: {
    hours: 3,
    minutes: 15,
    seconds: 30,
    size: 200,
    showNumbers: true,
    showSecondHand: true,
    highlightHourHand: { type: 'glow', color: '#e74c3c' },
    highlightMinuteHand: { type: 'pulse', color: '#3498db' }
  }
}

Line Plot Element

{
  type: 'lineplot',
  linePlotConfig: {
    title: 'Data Visualization',
    data: [
      { value: 10, color: '#3498db', label: 'Point 1' },
      { value: 15, color: '#e74c3c', label: 'Point 2' }
    ],
    plotType: 'frequency' | 'scatter' | 'line',
    pointShape: 'circle' | 'square' | 'triangle' | 'x' | 'diamond',
    pointSize: 20,
    showFrequencyLabels: true,
    xAxis: {
      title: 'X Axis',
      min: 0,
      max: 20,
      step: 5
    },
    yAxis: {
      title: 'Y Axis', 
      min: 0,
      max: 10
    }
  }
}

Arrow Element

{
  type: 'arrow',
  arrowConfig: {
    startPoint: { x: 0.2, y: 0.3 },  // Relative coordinates (0-1)
    endPoint: { x: 0.8, y: 0.7 },
    strokeColor: '#2c3e50',
    strokeWidth: 3,
    arrowHeadType: 'triangle' | 'circle' | 'square'
  }
}

🎨 Advanced Features

State Changes and Highlighting

Add dynamic highlighting and state changes during playback:

{
  kind: 'element',
  id: 'highlighted-text',
  type: 'text',
  text: 'This text will glow!',
  stateChanges: [
    {
      timestamp: 3,
      state: 'highlighted',
      highlightConfig: {
        type: 'glow',
        color: '#f39c12',
        intensity: 0.8
      }
    },
    {
      timestamp: 6,
      state: 'normal'
    }
  ]
}

Complex Animations

Chain multiple keyframes for complex animations:

{
  keyframes: [
    { time: 0, x: -100, opacity: 0, scaleX: 0.5 },
    { time: 1, x: 0, opacity: 1, scaleX: 1 },
    { time: 3, rotate: 180 },
    { time: 5, x: 100, rotate: 360 },
    { time: 6, opacity: 0 }
  ]
}

Custom Layouts

Create complex layouts with nested containers:

{
  kind: 'container',
  id: 'main',
  layout: { type: 'vertical', splits: [0.3, 0.7] },
  children: ['header', 'content'],
  style: { padding: '20px', backgroundColor: '#f8f9fa' }
}

Educational Interactions

Perfect for educational content with step-by-step reveals:

// Show mathematical concepts progressively
{
  type: 'lineplot',
  linePlotConfig: {
    data: [
      { value: 2, color: '#3498db' },
      { value: 4, color: '#e74c3c' },
      { value: 3, color: '#2ecc71' }
    ],
    revealAnimation: {
      type: 'sequential',
      delay: 1,      // 1 second between each point
      startTime: 2   // Start revealing at 2 seconds
    }
  }
}

⌨️ Keyboard Shortcuts

  • Space - Play/Pause
  • Left Arrow - Seek backward 5 seconds
  • Right Arrow - Seek forward 5 seconds
  • Home - Reset to beginning
  • F - Toggle fullscreen
  • Escape - Exit fullscreen

🔧 TypeScript Support

Full TypeScript support with comprehensive type definitions:

import type { 
  VideoSchema, 
  VideoPlayerProps, 
  ElementNode,
  ContainerNode,
  ValidationError 
} from '@trilogy-innovations/video-applets-player';

const schema: VideoSchema = {
  meta: { width: 1920, height: 1080, duration: 10 },
  nodes: [/* ... */]
};

🎨 Styling and Customization

CSS Custom Properties

Override default styles using CSS custom properties:

.video-player {
  --primary-color: #3498db;
  --secondary-color: #2c3e50;
  --background-color: #ecf0f1;
  --text-color: #2c3e50;
  --border-radius: 8px;
}

Custom CSS Classes

<VideoPlayer 
  schema={schema}
  className="my-custom-player"
  style={{ borderRadius: '12px', overflow: 'hidden' }}
/>

Timeline Customization

.compact-timeline {
  background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
  border-radius: 12px;
  padding: 16px;
}

.timeline-progress {
  background: #fff;
  border-radius: 6px;
}

🔧 Performance Tips

Schema Optimization

  • Keep keyframe arrays reasonably sized (< 100 keyframes per element)
  • Use relative positioning when possible
  • Optimize image and video assets
  • Consider using React.memo() for wrapper components

Asset Loading

import { AssetManager } from '@trilogy-innovations/video-applets-player';

// Preload assets for better performance
useEffect(() => {
  AssetManager.preloadAsset('image', '/path/to/image.jpg');
  AssetManager.preloadAsset('video', '/path/to/video.mp4');
}, []);

Memory Management

// Clean up when component unmounts
useEffect(() => {
  return () => {
    AssetManager.clearCache();
  };
}, []);

📱 Responsive Design

Make your video player responsive:

function ResponsiveVideoPlayer({ schema }) {
  return (
    <div style={{ 
      width: '100%', 
      maxWidth: '1200px',
      aspectRatio: `${schema.meta.width}/${schema.meta.height}`,
      margin: '0 auto'
    }}>
      <VideoPlayer 
        schema={schema}
        style={{ 
          width: '100%', 
          height: '100%' 
        }}
      />
    </div>
  );
}

🐛 Troubleshooting

Common Issues

Schema Validation Errors

import { SchemaService } from '@trilogy-innovations/video-applets-player';

const errors = SchemaService.validateSchema(schema);
console.log('Validation errors:', errors);

Asset Loading Issues

// Check asset loading status
AssetManager.getLoadingStatus('my-image').then(status => {
  console.log('Asset status:', status);
});

Performance Issues

  • Reduce keyframe density
  • Optimize media assets
  • Use React.memo() for parent components
  • Enable hardware acceleration in CSS

Debug Mode

Enable debug information:

<VideoPlayer 
  schema={schema}
  debug={true}  // Shows performance metrics
/>

🔗 Examples and Demos

Educational Math Lesson

const mathLesson = {
  meta: { width: 1920, height: 1080, duration: 30 },
  nodes: [
    // Problem statement
    {
      kind: 'element',
      id: 'problem',
      type: 'text',
      text: 'What is 5 + 3?',
      fontSize: 48,
      timeline: { in: 0, out: 10 }
    },
    
    // Visual representation
    {
      kind: 'element', 
      id: 'visual',
      type: 'image',
      src: '/counting-blocks.png',
      timeline: { in: 3, out: 20 }
    },
    
    // Answer reveal
    {
      kind: 'element',
      id: 'answer',
      type: 'text', 
      text: '8',
      fontSize: 72,
      color: '#27ae60',
      timeline: { in: 15, out: 30 },
      keyframes: [
        { time: 15, opacity: 0, scaleX: 2, scaleY: 2 },
        { time: 16, opacity: 1, scaleX: 1, scaleY: 1 }
      ]
    }
  ]
};

Data Visualization Story

const dataStory = {
  meta: { width: 1920, height: 1080, duration: 25 },
  nodes: [
    {
      kind: 'element',
      id: 'chart',
      type: 'lineplot',
      linePlotConfig: {
        title: 'Sales Growth Over Time',
        data: [
          { value: 100, color: '#3498db', label: 'Q1' },
          { value: 150, color: '#e74c3c', label: 'Q2' },
          { value: 200, color: '#2ecc71', label: 'Q3' },
          { value: 180, color: '#f39c12', label: 'Q4' }
        ],
        plotType: 'line',
        pointShape: 'circle',
        revealAnimation: { type: 'sequential', delay: 2 }
      },
      timeline: { in: 0, out: 25 }
    }
  ]
};

🤝 Contributing

We welcome contributions! See our Contributing Guide for details.

📞 Support


Made with ❤️ by Trilogy Innovations

Perfect for educational content, data visualization, interactive presentations, and engaging user experiences.