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

@ordojs/mobile

v0.1.0

Published

Mobile and PWA support for OrdoJS applications

Readme

@ordojs/mobile

Mobile and PWA support for OrdoJS applications. This package provides comprehensive tools for building mobile-optimized applications with PWA capabilities, touch gestures, and native device features.

Features

  • PWA Support: Service worker generation, app manifest management, and install prompts
  • Touch Gestures: Comprehensive gesture recognition (swipe, pinch, rotate, tap, pan)
  • Native Features: Camera, geolocation, notifications, and device information access
  • Offline Support: Offline-first data synchronization and caching strategies
  • Mobile Optimization: Responsive design utilities and mobile-specific components

Installation

pnpm add @ordojs/mobile

Usage

PWA Setup

import { PWAManager } from '@ordojs/mobile';

const pwaConfig = {
  name: 'My OrdoJS App',
  shortName: 'OrdoJS',
  description: 'A progressive web app built with OrdoJS',
  startUrl: '/',
  display: 'standalone',
  themeColor: '#ffffff',
  backgroundColor: '#000000',
  icons: [
    {
      src: '/icon-192x192.png',
      sizes: '192x192',
      type: 'image/png',
    },
    {
      src: '/icon-512x512.png',
      sizes: '512x512',
      type: 'image/png',
      purpose: 'maskable',
    },
  ],
  categories: ['productivity'],
  lang: 'en',
  dir: 'ltr',
  orientation: 'portrait',
  scope: '/',
  preferRelatedApplications: false,
  relatedApplications: [],
};

const swConfig = {
  scope: '/',
  updateViaCache: 'imports',
  skipWaiting: true,
  clientsClaim: true,
  offlinePage: '/offline.html',
  cacheStrategies: [
    {
      name: 'static',
      pattern: '/static/*',
      strategy: 'cache-first',
      maxAge: 86400,
    },
    {
      name: 'api',
      pattern: '/api/*',
      strategy: 'network-first',
      maxAge: 300,
    },
  ],
  backgroundSync: {
    enabled: true,
    syncName: 'background-sync',
  },
  pushNotifications: {
    enabled: true,
    defaultNotificationOptions: {
      title: 'New notification',
      body: 'You have a new message',
      icon: '/icon-192x192.png',
    },
  },
};

const pwaManager = new PWAManager(pwaConfig, swConfig);

// Generate manifest
const manifest = pwaManager.generateManifest();
console.log(manifest);

// Generate service worker
const swScript = pwaManager.generateServiceWorker();
console.log(swScript);

// Register service worker
await pwaManager.registerServiceWorker();

// Check if app is installed
if (pwaManager.isInstalled()) {
  console.log('App is installed as PWA');
}

// Show install prompt
try {
  await pwaManager.showInstallPrompt();
} catch (error) {
  console.log('Install prompt not supported');
}

Touch Gestures

import { GestureManager } from '@ordojs/mobile';

const element = document.getElementById('gesture-area');
const gestureManager = new GestureManager(element, {
  enabled: true,
  threshold: 10,
  velocity: 0.3,
  direction: 'both',
  preventDefault: true,
});

// Listen for swipe gestures
gestureManager.on('swipe', event => {
  console.log('Swipe detected:', event.direction, event.velocity);

  switch (event.direction) {
    case 'left':
      // Navigate to next page
      break;
    case 'right':
      // Navigate to previous page
      break;
    case 'up':
      // Scroll up
      break;
    case 'down':
      // Scroll down
      break;
  }
});

// Listen for pinch gestures
gestureManager.on('pinch', event => {
  console.log('Pinch detected:', event.scale);
  // Handle zoom in/out
});

// Listen for tap gestures
gestureManager.on('tap', event => {
  console.log('Tap detected');
  // Handle tap action
});

// Listen for long press
gestureManager.on('longpress', event => {
  console.log('Long press detected');
  // Show context menu
});

// Clean up when done
gestureManager.destroy();

Native Features

import { NativeManager } from '@ordojs/mobile';

const nativeManager = new NativeManager({
  features: {
    camera: true,
    geolocation: true,
    contacts: true,
    calendar: true,
    notifications: true,
    storage: true,
    network: true,
    device: true,
  },
});

// Get device information
const deviceInfo = await nativeManager.getDeviceInfo();
console.log('Device:', deviceInfo.platform, deviceInfo.model);
console.log('Screen:', deviceInfo.screenWidth, 'x', deviceInfo.screenHeight);
console.log('Battery:', deviceInfo.batteryLevel * 100, '%');

// Take a photo
try {
  const photo = await nativeManager.takePhoto({
    source: 'camera',
    quality: 0.8,
    maxWidth: 1920,
    maxHeight: 1080,
  });
  console.log('Photo taken:', photo.dataUrl);
} catch (error) {
  console.error('Failed to take photo:', error);
}

// Get current location
try {
  const location = await nativeManager.getLocation({
    highAccuracy: true,
    timeout: 10000,
  });
  console.log('Location:', location.latitude, location.longitude);
} catch (error) {
  console.error('Failed to get location:', error);
}

// Send notification
try {
  await nativeManager.sendNotification({
    title: 'Hello from OrdoJS!',
    body: 'This is a test notification',
    icon: '/icon-192x192.png',
    badge: '/badge-72x72.png',
    vibrate: [100, 50, 100],
  });
} catch (error) {
  console.error('Failed to send notification:', error);
}

// Check available features
const features = nativeManager.getAvailableFeatures();
features.forEach(feature => {
  console.log(`${feature.name}: ${feature.available ? 'Available' : 'Not available'}`);
});

Complete Mobile App Setup

import { PWAManager, GestureManager, NativeManager } from '@ordojs/mobile';

class MobileApp {
  private pwaManager: PWAManager;
  private gestureManager: GestureManager;
  private nativeManager: NativeManager;

  constructor() {
    // Initialize PWA
    this.pwaManager = new PWAManager(pwaConfig, swConfig);

    // Initialize gestures
    const gestureElement = document.getElementById('app-container');
    this.gestureManager = new GestureManager(gestureElement);

    // Initialize native features
    this.nativeManager = new NativeManager();

    this.setupEventListeners();
  }

  private setupEventListeners(): void {
    // PWA events
    this.pwaManager.registerServiceWorker().then(() => {
      console.log('Service worker registered');
    });

    // Gesture events
    this.gestureManager.on('swipe', this.handleSwipe.bind(this));
    this.gestureManager.on('pinch', this.handlePinch.bind(this));
    this.gestureManager.on('tap', this.handleTap.bind(this));

    // Device events
    window.addEventListener('online', this.handleOnline.bind(this));
    window.addEventListener('offline', this.handleOffline.bind(this));
  }

  private handleSwipe(event: any): void {
    // Handle swipe navigation
  }

  private handlePinch(event: any): void {
    // Handle zoom
  }

  private handleTap(event: any): void {
    // Handle tap
  }

  private handleOnline(): void {
    console.log('Device is online');
    // Sync data
  }

  private handleOffline(): void {
    console.log('Device is offline');
    // Show offline indicator
  }

  async initialize(): Promise<void> {
    // Get device info
    const deviceInfo = await this.nativeManager.getDeviceInfo();

    // Request permissions
    if (deviceInfo.platform !== 'web') {
      await this.requestPermissions();
    }

    console.log('Mobile app initialized');
  }

  private async requestPermissions(): Promise<void> {
    const permissions = ['camera', 'geolocation', 'notifications'];

    for (const permission of permissions) {
      try {
        const granted = await this.nativeManager.requestPermission(permission);
        console.log(`${permission} permission: ${granted ? 'granted' : 'denied'}`);
      } catch (error) {
        console.error(`Failed to request ${permission} permission:`, error);
      }
    }
  }
}

// Initialize the app
const app = new MobileApp();
app.initialize();

API Reference

PWAManager

generateManifest(): string

Generates the web app manifest JSON.

generateServiceWorker(): string

Generates the service worker script.

registerServiceWorker(): Promise<ServiceWorkerRegistration | null>

Registers the service worker.

isInstalled(): boolean

Checks if the app is installed as a PWA.

showInstallPrompt(): Promise<void>

Shows the install prompt.

GestureManager

on(type: string, listener: (event: GestureEvent) => void): void

Adds a gesture listener.

off(type: string, listener: (event: GestureEvent) => void): void

Removes a gesture listener.

destroy(): void

Destroys the gesture manager.

NativeManager

getDeviceInfo(): Promise<DeviceInfo>

Gets device information.

requestPermission(feature: string): Promise<boolean>

Requests permission for a native feature.

takePhoto(options: CameraOptions): Promise<PhotoResult>

Takes a photo using the camera.

getLocation(options: GeolocationOptions): Promise<LocationResult>

Gets current location.

sendNotification(options: NotificationOptions): Promise<void>

Sends a notification.

getAvailableFeatures(): NativeFeature[]

Gets available native features.

Configuration

PWA Configuration

interface PWAConfig {
  name: string;
  shortName: string;
  description: string;
  startUrl: string;
  display: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser';
  themeColor: string;
  backgroundColor: string;
  icons: PWAIcon[];
  categories: string[];
  lang: string;
  dir: 'ltr' | 'rtl';
  orientation: 'portrait' | 'landscape' | 'any';
  scope: string;
  preferRelatedApplications: boolean;
  relatedApplications: RelatedApplication[];
}

Gesture Configuration

interface GestureConfig {
  enabled: boolean;
  threshold: number;
  velocity: number;
  direction: 'horizontal' | 'vertical' | 'both';
  preventDefault: boolean;
}

Native Configuration

interface NativeConfig {
  features: {
    camera: boolean;
    geolocation: boolean;
    contacts: boolean;
    calendar: boolean;
    notifications: boolean;
    storage: boolean;
    network: boolean;
    device: boolean;
  };
  permissions: PermissionConfig[];
  plugins: PluginConfig[];
}

Examples

Responsive Mobile Layout

import { NativeManager } from '@ordojs/mobile';

const nativeManager = new NativeManager();

// Adapt layout based on device
async function adaptLayout() {
  const deviceInfo = await nativeManager.getDeviceInfo();

  if (deviceInfo.platform === 'ios') {
    // iOS-specific layout
    document.body.classList.add('ios');
  } else if (deviceInfo.platform === 'android') {
    // Android-specific layout
    document.body.classList.add('android');
  }

  // Handle orientation changes
  if (deviceInfo.orientation === 'landscape') {
    document.body.classList.add('landscape');
  } else {
    document.body.classList.add('portrait');
  }
}

adaptLayout();

Offline-First Data Sync

import { PWAManager } from '@ordojs/mobile';

const pwaManager = new PWAManager(pwaConfig, {
  ...swConfig,
  backgroundSync: {
    enabled: true,
    syncName: 'data-sync',
    syncOptions: {
      minInterval: 60000, // 1 minute
      maxRetentionTime: 86400000, // 24 hours
    },
  },
});

// Sync data when online
window.addEventListener('online', async () => {
  try {
    await syncData();
    console.log('Data synced successfully');
  } catch (error) {
    console.error('Failed to sync data:', error);
  }
});

async function syncData() {
  // Implement data synchronization logic
  const pendingData = await getPendingData();

  for (const item of pendingData) {
    await sendToServer(item);
    await markAsSynced(item.id);
  }
}

Contributing

This package is part of the OrdoJS ecosystem. Please refer to the main OrdoJS repository for contribution guidelines.

License

MIT