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

svelte-split-flap

v1.0.7

Published

A Svelte component library for creating realistic split-flap displays with animations and sound effects

Readme

Svelte Split-Flap

A modern Svelte component library for creating realistic split-flap displays with smooth animations and sound effects. Perfect for creating retro mechanical displays with authentic flip animations.

Features

  • Smooth Animations: Realistic split-flap flip effects
  • Customizable Styling: Support for colors, fonts, and sizes
  • Sound Effects: Realistic split-flap audio with Web Audio API
  • Svelte 5 Ready: Built with modern Svelte 5 runes
  • Self-contained: No external dependencies required

Installation

npm install svelte-split-flap

Quick Start

Basic Usage

<script>
	import { SplitFlap } from 'svelte-split-flap';
	import 'svelte-split-flap/styles.css';

	let currentText = 'HELLO WORLD';
</script>

<SplitFlap text={currentText} />

Dynamic Text Updates

<script>
	import { SplitFlap } from 'svelte-split-flap';
	import 'svelte-split-flap/styles.css';

	let messages = ['TOKYO SK07', 'BERLIN 12', 'ATHENS 97'];
	let currentIndex = 0;

	function changeText() {
		currentIndex = (currentIndex + 1) % messages.length;
	}
</script>

<SplitFlap text={messages[currentIndex]} size="large" fontFamily="din" />

<button onclick={changeText}>Change Text</button>

Component API

SplitFlap Props

| Prop | Type | Default | Description | | -------------- | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ---------------------------------- | | text | string | '' | Text to display | | chars | string[] | 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 '.split('') | Available character set | | length | number \| undefined | undefined | Fixed display length with padding | | padChar | string | ' ' | Character used for padding | | padMode | 'auto' \| 'start' \| 'end' | 'auto' | Padding alignment | | timing | number | 60 | Animation timing in milliseconds | | duration | number | 300 | Flip duration in milliseconds | | easing | string | 'ease-in-out' | CSS easing function | | size | number \| string | 'medium' | Size variant or custom pixel size | | color | string | 'white' | Text color (CSS or Tailwind class) | | fontFamily | 'din' \| 'brains' \| 'mono' \| 'ibm' \| 'roboto' \| 'mont' \| 'barlow' \| 'cabin' \| 'cabinCondensed' | 'roboto' | Font family | | fontWeight | 'extralight' \| 'light' \| 'medium' \| 'semibold' \| 'bold' | 'bold' | Font weight | | soundEnabled | boolean | true | Enable sound effects | | soundUrl | string | 'default' | Custom sound file URL | | styles | StyleOverrides | {} | Custom CSS styles for components |

Size Options

  • 'xsmall' - 16px
  • 'small' - 24px
  • 'medium' - 48px (default)
  • 'large' - 72px
  • 'xlarge' - 96px
  • '2xlarge' - 120px
  • '3xlarge' - 144px
  • number - Custom pixel size (e.g., 64)

Style Overrides

The styles prop accepts an object with CSS strings for different component parts:

| Style Key | Target | Description | | ------------ | ------------------------------- | ---------------------------------------------------------------------- | | container | Main container div | Overall display container styles | | digit | Individual character containers | Digit/character container styles | | flap | Individual flap elements | Flap panel styles (background, borders, etc.) - applies to both halves | | flapTop | Top flap half only | Styles for upper flap half only | | flapBottom | Bottom flap half only | Styles for lower flap half only | | text | Text content spans | Text styling within flaps | | hinge | Hinge line between flaps | Center divider line styles |

Examples

Airport-Style Display

<SplitFlap
	text="FLIGHT AB1234"
	color="#FFD700"
	fontFamily="din"
	fontWeight="semibold"
	size="large"
	length={16}
	padMode="end"
/>

Retro Counter

<SplitFlap
	text="000042"
	color="green-400"
	fontFamily="mono"
	fontWeight="bold"
	length={6}
	padMode="start"
	padChar="0"
/>

Train Station Display

<SplitFlap
	text="PLATFORM 9¾"
	color="white"
	fontFamily="din"
	fontWeight="medium"
	timing={80}
	duration={250}
	soundEnabled={true}
/>

Sound Configuration

<!-- Default bundled sound -->
<SplitFlap text="HELLO" />

<!-- External URL - uses HTML Audio Element (CORS-friendly) -->
<SplitFlap text="HELLO" soundUrl="https://www.soundjay.com/communication/typewriter-2.wav" />

<!-- Custom local file in user's public folder -->
<SplitFlap text="HELLO" soundUrl="/my-custom-sound.mp3" />

<!-- Silent mode -->
<SplitFlap text="HELLO" soundEnabled={false} />

Sound Loading Strategy:

  • Default: Uses bundled split-flap audio with full features (HTML Audio Element + Web Audio API for advanced features)
  • External URLs: Uses HTML Audio Element only (basic playback, no panning/advanced features due to CORS)
  • Fallback: Gracefully falls back to silent mode if audio fails to load

Note: External URLs have limited audio features due to browser CORS restrictions. For full feature support, use local files or the bundled sound.

Custom Styling

Two-Tone Flaps (Different Colors for Top/Bottom)

<SplitFlap
	text="DEPARTURE"
	styles={{
		flapTop:
			'background: linear-gradient(145deg, #4f46e5, #3730a3); border-bottom: 1px solid #1e1b4b;',
		flapBottom:
			'background: linear-gradient(145deg, #dc2626, #991b1b); border-top: 1px solid #7f1d1d;',
		text: 'color: white; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.5);',
		hinge: 'background: #1f2937; height: 2px; box-shadow: 0 1px 3px rgba(0,0,0,0.8);'
	}}
	fontFamily="din"
	size="large"
/>

Classic Airport Style with Split Colors

<SplitFlap
	text="FLIGHT 1234"
	styles={{
		container: 'background: #1a1a1a; padding: 20px; border-radius: 8px;',
		flapTop:
			'background: linear-gradient(145deg, #2d2d2d, #1e1e1e); border-bottom: 1px solid #000;',
		flapBottom:
			'background: linear-gradient(145deg, #404040, #2d2d2d); border-top: 1px solid #555;',
		text: 'color: #ffd700; font-weight: bold; text-shadow: 0 0 8px rgba(255,215,0,0.5);',
		hinge: 'background: linear-gradient(90deg, #666, #888, #666); height: 2px;'
	}}
	fontFamily="din"
	fontWeight="bold"
	size="large"
/>

Override component styles for complete customization:

<SplitFlap
	text="CUSTOM"
	styles={{
		container:
			'background: linear-gradient(45deg, #ff6b35, #f7931e); padding: 20px; border-radius: 12px;',
		digit: 'border: 2px solid #fff; border-radius: 8px; margin: 4px;',
		flap: 'background: linear-gradient(145deg, #2c3e50, #34495e); border: 1px solid #3498db;',
		text: 'color: #ecf0f1; text-shadow: 0 1px 2px rgba(0,0,0,0.5);',
		hinge: 'background: #e74c3c; height: 3px; box-shadow: 0 0 5px rgba(0,0,0,0.3);'
	}}
/>

Neon/Cyberpunk Style

<SplitFlap
	text="CYBER 2077"
	styles={{
		container: 'filter: drop-shadow(0 0 10px #00ff41);',
		flap: 'background: linear-gradient(145deg, #000, #111); border: 1px solid #00ff41; box-shadow: inset 0 1px 1px rgba(0,255,65,0.1);',
		text: 'color: #00ff41; text-shadow: 0 0 10px #00ff41, 0 0 20px #00ff41;',
		hinge: 'background: #00ff41; height: 2px; box-shadow: 0 0 5px #00ff41;'
	}}
	fontFamily="mono"
	size="large"
/>

Vintage/Retro Style

<SplitFlap
	text="DEPARTURE 15:42"
	styles={{
		container:
			'background: #8b4513; padding: 16px; border: 4px solid #654321; border-radius: 4px;',
		flap: 'background: linear-gradient(145deg, #f4a460, #daa520); border: 1px solid #8b4513; box-shadow: inset 0 1px 2px rgba(255,255,255,0.2);',
		text: 'color: #2f1b14; font-weight: bold; text-shadow: 0 1px 1px rgba(255,255,255,0.3);',
		hinge: 'background: #654321; height: 3px;'
	}}
	fontFamily="din"
	size="medium"
/>

Minimalist Style

<SplitFlap
	text="MINIMAL"
	styles={{
		container: 'background: #f8f9fa; padding: 12px; border-radius: 8px;',
		flap: 'background: #ffffff; border: 1px solid #e9ecef; box-shadow: 0 1px 3px rgba(0,0,0,0.1);',
		text: 'color: #212529; font-weight: 500;',
		hinge: 'background: #dee2e6; height: 1px;'
	}}
	fontFamily="ibm"
	size="medium"
/>

Font Configuration

Using Built-in Web Fonts (Default)

The library uses web fonts by default for maximum compatibility:

<SplitFlap text="HELLO" fontFamily="brains" />
<!-- JetBrains Mono -->
<SplitFlap text="HELLO" fontFamily="ibm" />
<!-- IBM Plex Mono -->
<SplitFlap text="HELLO" fontFamily="roboto" />
<!-- Roboto Mono -->
<SplitFlap text="HELLO" fontFamily="mont" />
<!-- Montserrat -->
<SplitFlap text="HELLO" fontFamily="barlow" />
<!-- Barlow Condensed -->
<SplitFlap text="HELLO" fontFamily="cabin" />
<!-- Cabin -->
<SplitFlap text="HELLO" fontFamily="cabinCondensed" /><!-- Cabin Condensed -->

Font Family Options

| Font Family | Description | Best For | | ---------------- | -------------------------------------------------- | ----------------------------------- | | brains | JetBrains Mono - Clean monospace with coding focus | Technical displays, code-like text | | ibm | IBM Plex Mono - Professional IBM typeface | Corporate, professional displays | | roboto | Roboto Mono - Google's versatile monospace | Modern, clean displays | | mont | Montserrat - Geometric sans-serif | Headlines, modern look | | barlow | Barlow Condensed - Tall, condensed sans-serif | Space-efficient displays, headlines | | cabin | Cabin - Humanist sans-serif with warmth | Friendly, approachable displays | | cabinCondensed | Cabin Condensed - Space-saving version | Compact displays, multiple lines | | din | DIN 1451 - German industrial standard | Authentic European transport look | | mono | System monospace fallback | Universal compatibility |

Font Showcase Examples

Modern Corporate Style (Barlow Condensed)

<SplitFlap
	text="QUARTERLY RESULTS"
	fontFamily="barlow"
	fontWeight="semibold"
	size="large"
	color="#0066cc"
	styles={{
		container:
			'background: linear-gradient(135deg, #f8f9fa, #e9ecef); padding: 20px; border-radius: 8px;',
		flap: 'background: linear-gradient(145deg, #ffffff, #f8f9fa); border: 1px solid #dee2e6;',
		text: 'color: #0066cc; font-weight: 600;'
	}}
/>

Friendly Information Display (Cabin)

<SplitFlap
	text="WELCOME GUESTS"
	fontFamily="cabin"
	fontWeight="medium"
	size="large"
	styles={{
		container: 'background: #2c3e50; padding: 18px; border-radius: 12px;',
		flap: 'background: linear-gradient(145deg, #ecf0f1, #bdc3c7); border: 1px solid #95a5a6;',
		text: 'color: #2c3e50; font-weight: 500;'
	}}
/>

Compact Multi-line Display (Cabin Condensed)

<SplitFlap
	text="GATE 12A BOARDING"
	fontFamily="cabinCondensed"
	fontWeight="bold"
	size="medium"
	styles={{
		container: 'background: #1a1a1a; padding: 16px;',
		flap: 'background: linear-gradient(145deg, #333, #222); border: 1px solid #444;',
		text: 'color: #ffd700; font-weight: bold; text-shadow: 0 0 8px rgba(255,215,0,0.5);'
	}}
/>

Old School Style with White Text (using new fonts)

<SplitFlap
	text="PLATFORM 9"
	fontFamily="barlow"
	fontWeight="medium"
	timing={80}
	duration={350}
	easing="ease-in-out"
	size={64}
	styles={{
		container:
			'background: #2c1810; padding: 24px; border: 4px solid #8b4513; border-radius: 8px; box-shadow: inset 0 0 20px rgba(0,0,0,0.3), 0 8px 32px rgba(0,0,0,0.4);',
		flap: 'background: linear-gradient(145deg, #f5f5dc, #e6e6fa); border: 2px solid #8b7355; box-shadow: inset 0 2px 4px rgba(0,0,0,0.1), 0 2px 6px rgba(0,0,0,0.2); border-radius: 2px;',
		text: 'color: #2f2f2f; font-weight: 600; text-shadow: 0 1px 2px rgba(255,255,255,0.8);',
		hinge: 'background: linear-gradient(90deg, #654321, #8b4513, #654321); height: 3px; box-shadow: 0 2px 4px rgba(0,0,0,0.5);'
	}}
/>

Development

Prerequisites

  • Node.js 20+
  • npm or pnpm

Setup

# Clone the repository
git clone https://github.com/socketopp/svelte-split-flap.git
cd svelte-split-flap

# Install dependencies
npm install

# Start development server
npm run dev

Building the Library

# Build CSS and package the library
npm run build

# This runs:
# 1. npm run build:css - Generates Tailwind CSS from components
# 2. npm run prepack - Runs svelte-package and publint

Testing Changes

The project includes a test environment to verify library functionality:

Method 1: Automated Testing (Recommended)

# Build library, pack it, and install in test project
npm run test-local

# This will:
# 1. Build the library (CSS + packaging)
# 2. Create svelte-split-flap-1.0.5.tgz
# 3. Install it in test-library/
# 4. Update dependencies

# Run the test project
cd test-library
npm run dev

Method 2: Manual Testing

# Build and pack the library
npm run build
npm pack

# Navigate to test project
cd test-library

# Remove old version and install new tarball
npm uninstall svelte-split-flap
npm install ../svelte-split-flap-[X.Y.Z].tgz

# Start test server
npm run dev

Test Project Structure

The test-library/ folder contains a minimal Svelte 5 application for testing:

test-library/
├── package.json          # Svelte 5 + Vite setup
├── vite.config.js        # Vite configuration
├── index.html            # Entry HTML
└── src/
    ├── main.js           # Svelte 5 mount syntax
    └── App.svelte        # Test component usage

Testing Different Scenarios

Modify test-library/src/App.svelte to test various configurations:

<script>
	import { SplitFlap } from 'svelte-split-flap';
	import 'svelte-split-flap/styles.css';

	// Test different scenarios
	let scenarios = [
		{ text: 'HELLO WORLD', size: 'medium' },
		{ text: 'FLIGHT AB1234', size: 'large', fontFamily: 'din' },
		{ text: '000042', size: 64, fontFamily: 'mono', padMode: 'start' },
		{ text: 'CUSTOM SOUND', soundUrl: 'https://www.soundjay.com/misc/beep-07a.wav' }
	];

	let currentScenario = $state(0);
</script>

{#each scenarios as scenario, i}
	<div class="mb-4">
		<h3>Scenario {i + 1}</h3>
		<SplitFlap {...scenario} />
	</div>
{/each}

Verifying the Build

After building, check that these files exist:

  • dist/styles.css - Generated Tailwind CSS
  • dist/components/ - Compiled Svelte components
  • dist/sounds/ - Audio files
  • svelte-split-flap-1.0.X.tgz - Packaged library

Publishing

# Ensure everything builds correctly
npm run build

# Publish to npm (requires npm login)
npm publish

Troubleshooting

Common Issues

CSS not loading: Make sure to import the CSS file:

import 'svelte-split-flap/styles.css';

Component not rendering: Ensure you're using Svelte 5 syntax:

import { mount } from 'svelte';
import App from './App.svelte';

mount(App, { target: document.getElementById('app') });

Audio not playing: Check browser console for audio loading errors. The component will fallback gracefully if audio files are unavailable.

Build errors: Ensure Node.js 20+ and compatible npm version.

Custom sounds not working:

  • External URLs: Should work with any publicly accessible audio file. The library uses HTML Audio Element which doesn't have CORS restrictions.
  • Local Files: Place audio files in your public folder (e.g., /my-sound.mp3)
  • File Formats: Ensure the audio format is supported by browsers (MP3, WAV, OGG recommended)
  • HTTPS: Some browsers require HTTPS for audio playback in production

Browser Support

  • Chrome 60+
  • Firefox 55+
  • Safari 11+
  • Edge 79+

License

MIT

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Test using the test-library project
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

Development Workflow

  1. Make changes to components in src/lib/
  2. Test changes: npm run test-local
  3. Verify in browser at http://localhost:5173
  4. Update documentation if needed
  5. Submit PR with clear description of changes

Credits

Credits to original creators

Roadmap

  • ✅ Custom styles parameter for all components
  • [ ] Grid/multi-line displays
    • [ ] Animation patterns
  • [ ] More font options
  • [ ] Custom sound effects
  • [ ] Accessibility improvements
  • [ ] Implement LongFlap
  • [ ] Implement Emojis/Numbers
  • [ ] Improve fonts, add capability for using fonts from fontsource
  • [ ] Setup UI testing