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

@hamak/ui-shell

v0.5.1

Published

UI Shell Framework with theming, routing, and layout management

Readme

UI Shell

A comprehensive application shell framework providing theme management, feature flags, routing, and layout orchestration for microkernel-based applications.

Package Structure

This is a monorepo package containing four sub-packages following the API-SPI-IMPL pattern:

Features

Theme Management

  • Dynamic theme switching between light, dark, and system modes
  • LocalStorage persistence for user preferences
  • System preference detection with automatic fallback
  • Custom CSS variables support
  • Event-driven theme change notifications

Feature Configuration

  • Feature flags for enabling/disabling functionality
  • Type-safe feature access with generic types
  • Subscribe to feature changes with fine-grained listeners
  • Bulk feature updates for configuration management
  • Includes common feature definitions for quick setup

Router Integration

  • Lazy loading support for route components
  • Navigation guards for route protection
  • History and hash modes for different deployment scenarios
  • Route metadata for custom data attachment
  • Event-driven navigation updates

Layout Management

  • Slot-based layout system with priority ordering
  • Responsive breakpoints (xs, sm, md, lg, xl, 2xl)
  • Viewport utilities for responsive behavior
  • CSS Grid layouts with pre-built templates
  • Touch detection and device pixel ratio utilities

Microkernel Integration

  • Plugin module for seamless microkernel integration
  • Dependency injection tokens for all services
  • Command registration for shell operations
  • Event forwarding to microkernel hooks
  • Service providers for easy consumption

Installation

# Install the packages you need
bun add @hamak/ui-shell-api @hamak/ui-shell-impl @hamak/ui-shell-templates

Usage

Basic Shell Setup

import { createShellPlugin } from '@hamak/ui-shell-impl';

const shellPlugin = createShellPlugin({
  theme: {
    mode: 'system', // 'light' | 'dark' | 'system'
    cssVariables: {
      '--primary-color': '#007bff',
    },
  },
  features: {
    'ui.sidebar': true,
    'experimental.ssr': false,
  },
});

// Register with your microkernel
kernel.registerPlugin(shellPlugin);

Theme Management

import { SHELL_TOKEN } from '@hamak/ui-shell-api';
import type { IShell } from '@hamak/ui-shell-api';

// In your plugin or component
const shell = context.resolve<IShell>(SHELL_TOKEN);
const themeManager = shell.getThemeManager();

// Set theme
themeManager.setTheme('dark');

// Toggle theme
themeManager.toggleTheme();

// Subscribe to changes
themeManager.subscribe((theme) => {
  console.log('Theme changed to:', theme);
});

// Get resolved theme (converts 'system' to actual theme)
const resolvedTheme = themeManager.getResolvedTheme(); // 'light' | 'dark'

Feature Flags

const featureManager = shell.getFeatureManager();

// Check if enabled
if (featureManager.isEnabled('ui.sidebar')) {
  // Show sidebar
}

// Get feature value
const pollingInterval = featureManager.get('performance.polling', 5000);

// Toggle feature
featureManager.toggle('experimental.ssr');

// Subscribe to changes
featureManager.subscribe('ui.sidebar', (enabled) => {
  console.log('Sidebar:', enabled ? 'enabled' : 'disabled');
});

Router Setup

import { SHELL_TOKEN } from '@hamak/ui-shell-api';

const shell = context.resolve(SHELL_TOKEN);
const router = shell.setupRouter({
  mode: 'history',
  routes: [
    {
      path: '/',
      component: () => import('./pages/Home'),
    },
    {
      path: '/about',
      component: () => import('./pages/About'),
      meta: { title: 'About Us' },
    },
    {
      path: '/dashboard',
      component: () => import('./pages/Dashboard'),
      beforeEnter: (to, from) => {
        // Route guard logic
        return isAuthenticated();
      },
    },
  ],
});

// Navigate
await router.push('/about');

// Subscribe to route changes
router.subscribe((route) => {
  console.log('Navigated to:', route.path);
});

Layout Management

import { SHELL_TOKEN } from '@hamak/ui-shell-api';

const shell = context.resolve(SHELL_TOKEN);
const layoutManager = shell.getLayoutManager();

// Register slots
layoutManager.registerSlot({
  id: 'main-nav',
  area: 'header',
  priority: 10,
});

// Get slots for an area
const headerSlots = layoutManager.getSlots('header');

// Responsive utilities
if (ViewportUtils.isMinBreakpoint('md')) {
  // Desktop layout
} else {
  // Mobile layout
}

const currentBreakpoint = ViewportUtils.getCurrentBreakpoint();

Microkernel Plugin Integration

import { createShellPlugin } from '@hamak/ui-shell-impl';
import { CommonFeatures } from '@hamak/ui-shell-api';

export const shellPlugin = createShellPlugin({
  theme: { mode: 'system' },
  features: {
    'ui.sidebar': true,
  },
});

// In your plugin
export function initialize(ctx) {
  // Access shell services
  const shell = ctx.resolve(SHELL_TOKEN);

  // Subscribe to theme changes
  shell.getThemeManager().subscribe((theme) => {
    console.log('Theme changed:', theme);
  });
}

export function activate(ctx) {
  // Access shell services
  const shell = ctx.resolve(SHELL_TOKEN);
  shell.getThemeManager().setTheme('dark');
}

Using React Templates

import { ShellProvider, DashboardLayout } from '@hamak/ui-shell-templates';
import { useTheme, useFeatures } from '@hamak/ui-shell-templates/hooks';

// Wrap your app with ShellProvider
function App() {
  return (
    <ShellProvider>
      <DashboardLayout />
    </ShellProvider>
  );
}

// Use hooks in your components
function MyComponent() {
  const { theme, setTheme } = useTheme();
  const { isEnabled } = useFeatures();

  return (
    <div>
      <button onClick={() => setTheme('dark')}>Dark Mode</button>
      {isEnabled('ui.sidebar') && <Sidebar />}
    </div>
  );
}

Shell Context

import { SHELL_TOKEN } from '@hamak/ui-shell-api';

const shell = context.resolve(SHELL_TOKEN);
const shellContext = shell.getContext();

// Access current theme
console.log('Current theme:', shellContext.theme);

// Set theme
shellContext.setTheme('dark');

// Check features
if (shellContext.isFeatureEnabled('ui.sidebar')) {
  // ...
}

// Responsive info
if (shellContext.viewport.isMobile) {
  // Mobile UI
} else if (shellContext.viewport.isDesktop) {
  // Desktop UI
}

Shell Events

// Subscribe to events
shell.on('theme:changed', (event) => {
  console.log('Theme changed:', event.payload);
});

shell.on('viewport:resized', (event) => {
  console.log('Viewport:', event.payload.width, 'x', event.payload.height);
});

shell.on('route:changed', (event) => {
  console.log('Navigated to:', event.payload.route.path);
});

// Listen to all events
shell.on('*', (event) => {
  console.log('Event:', event.type, event.payload);
});

API Reference

Shell

Main orchestrator for the UI shell.

Methods:

  • initialize() - Initialize the shell
  • setupRouter(options) - Setup router with routes
  • getRouter() - Get router instance
  • getThemeManager() - Get theme manager
  • getFeatureManager() - Get feature manager
  • getContext() - Get shell context for consumers
  • on(type, listener) - Subscribe to events
  • emit(type, payload) - Emit events
  • destroy() - Clean up resources

ThemeManager

Handles theme switching and persistence.

Methods:

  • getTheme() - Get current theme mode
  • getResolvedTheme() - Get resolved theme (light/dark)
  • setTheme(mode) - Set theme mode
  • toggleTheme() - Toggle between light and dark
  • subscribe(listener) - Subscribe to changes
  • setCSSVariables(vars) - Set custom CSS variables

FeatureManager

Manages feature flags and configurations.

Methods:

  • isEnabled(key) - Check if feature is enabled
  • get(key, defaultValue) - Get feature value
  • set(key, value) - Set feature value
  • enable(key) - Enable feature
  • disable(key) - Disable feature
  • toggle(key) - Toggle feature
  • subscribe(key, listener) - Subscribe to feature changes

Router

Handles client-side routing with lazy loading.

Methods:

  • push(path) - Navigate to path
  • replace(path) - Replace current route
  • back() - Go back
  • forward() - Go forward
  • getCurrentRoute() - Get current route
  • subscribe(listener) - Subscribe to route changes
  • addGuard(guard) - Add navigation guard

LayoutManager

Manages layout slots and areas.

Methods:

  • registerSlot(slot) - Register a layout slot
  • unregisterSlot(slot) - Unregister a slot
  • getSlots(area) - Get slots for area
  • getAreas() - Get all registered areas
  • hasSlots(area) - Check if area has slots

Architecture

The UI Shell is designed to integrate seamlessly with the microkernel architecture:

  1. Core Services: Theme, Features, Router, Layout
  2. Plugin Integration: Provides services via DI tokens
  3. Event System: Forwards events to microkernel hooks
  4. Commands: Registers shell commands for cross-plugin use
  5. Context API: Provides reactive access to shell state

Common Patterns

Responsive Layouts

import { useViewport } from '@hamak/ui-shell-templates/hooks';

// In React components
function MyComponent() {
  const { isMobile, isDesktop, breakpoint } = useViewport();

  return isMobile ? <MobileLayout /> : <DesktopLayout />;
}

Feature Gating

import { CommonFeatures } from '@hamak/ui-shell-api';
import { useFeatures } from '@hamak/ui-shell-templates/hooks';

function MyComponent() {
  const { isEnabled } = useFeatures();

  return (
    <div>
      {isEnabled(CommonFeatures.VOICE_MODE) && <VoiceInput />}
    </div>
  );
}

License

MIT