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

react-native-sliding-blocks

v0.0.15

Published

React Native sliding blocks game library

Downloads

902

Readme

react-native-sliding-blocks

A React Native game library for building high-performance sliding block puzzles. Slide colored segments on a grid, fill rows to clear them, and watch blocks cascade. Built with Skia, Reanimated, and RxJS—60fps on iOS and Android.

This is a library package, not a standalone app. Install it in your React Native project and integrate the game with your own UI, assets, and logic.


Installation

npm install react-native-sliding-blocks
# or
yarn add react-native-sliding-blocks

Peer Dependencies

Install these in your app (they are peer dependencies):

| Package | Purpose | |---------|---------| | react | UI framework | | react-native | Mobile runtime | | @shopify/react-native-skia | 2D graphics & canvas | | react-native-reanimated | Animations | | react-native-gesture-handler | Touch and gestures | | react-native-worklets | UI thread worklets | | rxjs | Reactive streams |

Requirements: Node.js ≥ 22.11.0


Quick Start

import { SlidingBlocks } from 'react-native-sliding-blocks'

function GameScreen() {
  return (
    <SlidingBlocks
      config={{
        rowsCount: 10,
        columnsCount: 8,
        padding: 16,
        explosionPoolSize: 80,
        keysSize: 5
      }}
      callbacks={{
        onScoreChange: (score) => console.log('Score:', score),
        onGameOver: (score) => console.log('Game over:', score),
        onRemovingStart: () => playClearSound(),
        onFitComplete: ({ hadActualFit }) => hadActualFit && playSlideSound()
      }}
    />
  )
}

The library uses Skia-drawn blocks and a solid background by default. No assets required.


API

Declarative API — <SlidingBlocks />

All-in-one component. Pass config, callbacks, and optional assets/theme.

<SlidingBlocks
  config={SlidingBlocksConfig}
  callbacks?: SlidingBlocksCallbacks
  assets?: SlidingBlocksAssets
  theme?: Partial<SlidingBlocksTheme>
  settings?: SlidingBlocksSettingsOverrides
  engine?: IGameEngine
  initialState?: GameStateSnapshot | null
  onGameStateChange?: (state: GameStateSnapshot) => void
  blockRenderMode?: 'skia' | 'image'
  showFinishOption?: boolean
  onLoadProgress?: (progress: number) => void
  onLoadComplete?: () => void
/>

| Prop | Type | Description | |------|------|-------------| | config | SlidingBlocksConfig | Required. Grid layout: rowsCount, columnsCount, padding, explosionPoolSize, keysSize | | callbacks | SlidingBlocksCallbacks | Score, game over, pause, restart, sound hooks, etc. | | assets | SlidingBlocksAssets | Block PNGs, background image. Omit for Skia fallbacks | | theme | Partial<SlidingBlocksTheme> | Overlay, score bar, block colors | | settings | SlidingBlocksSettingsOverrides | Block, explosion, checkerboard, explosionPresets, animations (durations in ms), feedback (opacity values). Tune for performance: explosionPresets.explosionEnabled: false disables explosion; circlesOnly: true uses circles-only particles; set animations.* to 0 to disable animations. | | engine | IGameEngine | Optional pre-created engine | | initialState | GameStateSnapshot \| null | Restore from persisted state; host loads from storage to resume after app kill | | onGameStateChange | (state: GameStateSnapshot) => void | Called when state changes; host should persist (e.g. AsyncStorage). Snapshot includes gameOver flag; host typically clears when game over. | | blockRenderMode | 'skia' \| 'image' | 'skia' = draw blocks (default), 'image' = PNG assets | | showFinishOption | boolean | Show "Finish" in pause overlay; use with onFinish |

Imperative handle (ref)

const ref = useRef<SlidingBlocksHandle>(null)

<SlidingBlocks ref={ref} config={...} callbacks={...} />

// Then:
ref.current?.pause()
ref.current?.resume()
ref.current?.restart()
ref.current?.isPaused()  // boolean
ref.current?.getGameState()  // GameStateSnapshot for persistence

Composable API — useSlidingBlocks

Build custom layouts (e.g. custom score bar, different ordering).

import { useSlidingBlocks } from 'react-native-sliding-blocks'

function CustomGameScreen() {
  const { Root, ScoreBar, GameArea, ref } = useSlidingBlocks({
    config: { rowsCount: 10, columnsCount: 8, padding: 16, explosionPoolSize: 80, keysSize: 5 },
    callbacks: { onScoreChange, onGameOver }
  })

  return (
    <Root>
      <MyCustomScoreBar />
      <GameArea blockRenderMode="skia" onLoadComplete={() => setReady(true)} />
    </Root>
  )
}

Returns:

  • Root — Wrapper; must wrap ScoreBar and GameArea
  • ScoreBar — Default score bar
  • GameArea — Game canvas (blocks, grid, overlays)
  • refSlidingBlocksHandle (pause, resume, restart, isPaused, getGameState)

For fully custom layouts, use useComposableSlidingBlocksContext() inside Root to access layout and shared values.


Low-level API

  • GameRootView — Minimal wrapper when you need full control over layout and bridge.
  • createGameEngine(config, host?, options?) — Create a React-agnostic engine for headless testing or custom integration. options can include onRowAdded, animOverrides (removeFadeMs, itemDropMs), initialState (restore from persisted state), and onGameStateChange (called when state changes for host persistence).
  • GameStateSnapshot, isSnapshotCompatible(snapshot, config), getLayoutVersion(config) — Types and helpers for game state persistence. Use isSnapshotCompatible before resuming to ensure saved state matches current layout.
  • PreloaderOverlay — Loading overlay; optional fillAnimationDurationMs prop. Use settings.animations.loadingBarFillMs for consistency.
  • scheduleIdle, cancelIdle, GESTURE_SENSITIVITY, layout constants (TOP_PAUSE, SCORE_BAR, etc.) — Exported for advanced use.

Game State Persistence

The library provides serializable game state for host-side persistence. Persistence (e.g. AsyncStorage) is the host's responsibility.

| Export | Purpose | |--------|---------| | GameStateSnapshot | Serializable type: rows, score, multiplier, layoutVersion, gameOver | | getGameState() | Engine / handle method — returns current state | | initialState prop | Pass loaded state to resume after app kill | | onGameStateChange | Callback — persist when state changes; host typically clears when gameOver: true | | isSnapshotCompatible(snapshot, config) | Validate saved state matches current layout before resume |

Example flow:

  1. On mount: load from storage → if valid and not game over → pass as initialState.
  2. On state change: onGameStateChange(state) → persist to storage.
  3. On game over: clear stored state (host decides).
  4. Use isSnapshotCompatible so layout changes (e.g. settings) don't corrupt restore.

Configuration

SlidingBlocksConfig (game layout)

type SlidingBlocksConfig = {
  rowsCount: number      // e.g. 10
  columnsCount: number   // e.g. 8
  padding: number        // screen padding (px)
  explosionPoolSize: number
  keysSize: number       // block types (colors)
}

SlidingBlocksCallbacks

| Callback | When | |----------|------| | onScoreChange | After each row clear | | onGameOver | Game ends | | onPause / onResume | User pauses/resumes | | onRestart | User restarts (from overlay) | | onFinish | User taps "Finish" in pause overlay | | onGestureStart / onGestureEnd | Pan starts/ends | | onRemovingStart / onRemovingEnd | Row clear animation starts/ends; payload { hasSuper: boolean } | | onFitStart / onFitComplete | Slide/snap animation; onFitComplete({ hadActualFit }) for slide sound (hadActualFit = true when blocks actually moved) | | onRowAdded | New row added at top |

SlidingBlocksAssets

| Asset | Description | |-------|-------------| | blockImages | Map of color hex → [1×1, 1×2, 1×3, 1×4] image sources (e.g. require(...)) | | backgroundImage | Full-screen background image source |

Omit for fallbacks: solid background, Skia-drawn blocks.

SlidingBlocksSettingsOverrides

Partial overrides merged with defaults. All optional.

| Category | Fields | Description | |----------|--------|-------------| | block | radius, borderWidth, borderColor, frostHighlightColor, frostHighlightHeightRatio, superGradientColors, superGradientSteps | Block appearance | | explosion | radius, baseParticleSize, riseHeight, fallDistance, pictureSize | Explosion particles | | checkerboard | defaultBaseColor, defaultDarkOpacity, defaultLightOpacity | Grid styling | | explosionPresets | particleCount, trajectoryPresetCount, shapePresetCount, circlesOnly, explosionEnabled | Explosion variety. Set explosionEnabled: false to disable. circlesOnly: true for faster rendering. | | animations | completeSnapMs, itemDropMs, willRemovePulseMs, removeFadeMs, removeExplosionMs, gameOverInMs, gameOverOutMs, pauseOverlayMs, loadingBarFillMs | Animation durations (ms). removeFadeMs = block opacity fade; removeExplosionMs = explosion particles. | | feedback | blockIdle, willRemovePulseMin, ghostActive, indicatorActive | Opacity values (0–1) for blocks, ghost, indicator |

Performance presets are host-defined. Create presets as SlidingBlocksSettingsOverrides (e.g. blockRenderMode, explosionPresets, animations) and apply via your settings store. The example app defines four presets—extra-low, low, fine, good—in example/src/settings/performancePresets.ts and exposes them as one-tap buttons with a "Custom settings" section for manual overrides.


Game Mechanics

  • Grid — Configurable columns × rows (e.g. 8×10)
  • Blocks — Colored segments (1–4 cells). Drag left/right to reposition.
  • Clearing — Fill a row completely to clear it; blocks above drop.
  • Super segments — Rare black segments; when cleared, also wipe overlapping blocks in adjacent rows for combos.
  • Score & multiplier — Animated display.

Architecture

The package uses MVVM with RxJS and Reanimated. The engine is React-agnostic; a bridge wires RxJS streams to SharedValues. No React commits during gameplay—all rendering is driven by SharedValues and Skia.

For a deep dive, see src/CONCEPTS.md.

| Layer | Path | Responsibility | |-------|------|----------------| | Engine | engine/ | Pure game logic, RxJS, no React | | Bridge | bridge/ | RxJS → SharedValues binding | | UI | ui/ | React components, Skia, SharedValues |


Project Structure

react-native-sliding-blocks/
├── src/                # Library source
│   ├── bridge/         # RxJS → SharedValues (useEngineBridge, GestureCompletionOrchestrator)
│   ├── engine/         # Game logic, RxJS, no React
│   ├── ui/             # React components, Skia, contexts
│   ├── constants/      # Layout constants, game config
│   ├── types/          # Settings, layout types
│   ├── config.ts
│   ├── CONCEPTS.md     # Architecture guide
│   └── index.ts
├── example/            # Example React Native app
└── package.json

Example App

An example app lives in example/—it demonstrates:

  • Declarative and composable APIs
  • Settings screen with performance presets (extra-low, low, fine, good) and a collapsible "Custom settings" section for manual overrides
  • Game state persistence (AsyncStorage) with a Resume button when stored state exists
  • Sounds, themes, block images
# From repo root
yarn install
yarn example              # Install example deps
yarn example:start        # Start Metro
yarn example:ios          # Run iOS (in another terminal)
yarn example:android      # Run Android (in another terminal)

Developing the library? The example uses Metro's custom resolver so changes in src/ trigger hot reload. See DEVELOPMENT.md.

Requires React Native environment setup.


Scripts

| Command | Description | |---------|-------------| | yarn lint | Lint library source | | yarn example | Install example dependencies | | yarn example:start | Start Metro | | yarn example:start:dev | Start Metro with --reset-cache (use if changes don't appear) | | yarn example:ios | Run on iOS | | yarn example:android | Run on Android |


Tech Stack

| Layer | Technology | |-------|------------| | Framework | React Native | | Graphics | Skia (@shopify/react-native-skia) | | Animations | React Native Reanimated | | Gestures | React Native Gesture Handler | | State / Streams | RxJS |


License

MIT