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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@manet/ui

v0.0.4

Published

Reusable UI components and utilities for MANET Agent UI.

Downloads

422

Readme

@manet/ui

Reusable UI components and utilities for MANET Agent UI.

Installation

pnpm add @manet/ui

Components

Basic Components

Dialog

Modal dialog component with backdrop and animations.

import { Dialog, DialogPanel, DialogTitle } from '@manet/ui';

<Dialog open={isOpen} onClose={() => setIsOpen(false)}>
  <DialogPanel>
    <DialogTitle>Confirm Action</DialogTitle>
    <p>Are you sure you want to proceed?</p>
  </DialogPanel>
</Dialog>;

Props:

  • open: boolean - Controls dialog visibility
  • onClose: () => void - Close callback
  • maxWidth?: string | false - Maximum width constraint
  • fullWidth?: boolean - Full width mode
  • children: React.ReactNode - Dialog content

ConfirmDialog

Pre-built confirmation dialog with action buttons.

import { ConfirmDialog } from '@manet/ui';

<ConfirmDialog
  open={showConfirm}
  title="Delete File"
  message="This action cannot be undone."
  confirmText="Delete"
  onConfirm={handleDelete}
  onCancel={() => setShowConfirm(false)}
  variant="danger"
/>;

Props:

  • open: boolean - Controls dialog visibility
  • title: string - Dialog title
  • message: string - Confirmation message
  • confirmText?: string - Confirm button text (default: 'Confirm')
  • cancelText?: string - Cancel button text (default: 'Cancel')
  • onConfirm: () => void - Confirm action callback
  • onCancel: () => void - Cancel action callback
  • variant?: 'default' | 'danger' - Visual style variant

LoadingSpinner

Animated loading spinner component.

import { LoadingSpinner } from '@manet/ui';

<LoadingSpinner size={8} className="border-blue-500 border-t-transparent" />;

Props:

  • size?: number - Spinner size (default: 8)
  • className?: string - Additional CSS classes for styling

Tooltip

Tooltip component for displaying contextual information.

import { Tooltip } from '@manet/ui';

<Tooltip content="This is a helpful tip">
  <button>Hover me</button>
</Tooltip>;

AI Components

ActionBlock

Displays AI action blocks with status indicators and animations.

import { ActionBlock } from '@manet/ui';

<ActionBlock
  title="Processing Request"
  status="running"
  description="Analyzing user input..."
/>;

BrowserShell

Browser-like interface shell for displaying web content.

import { BrowserShell } from '@manet/ui';

<BrowserShell
  url="https://example.com"
  title="Example Site"
  onNavigate={(url) => console.log('Navigate to:', url)}
/>;

ThinkingAnimation

Animated thinking indicator for AI processing states.

import { ThinkingAnimation } from '@manet/ui';

<ThinkingAnimation message="Thinking..." />;

Code Editors

MonacoCodeEditor

Full-featured code editor powered by Monaco Editor with IntelliSense and editing capabilities.

import { MonacoCodeEditor } from '@manet/ui';

<MonacoCodeEditor
  code="const x = 42;"
  fileName="script.ts"
  readOnly={false}
  onChange={(value) => console.log(value)}
/>;

Props:

  • code: string - Source code to display/edit
  • fileName?: string - File name for language detection
  • filePath?: string - Full file path for display
  • fileSize?: string - File size for display
  • readOnly?: boolean - Read-only mode (default: true)
  • showLineNumbers?: boolean - Show line numbers (default: true)
  • maxHeight?: string - Maximum height (default: 'none')
  • className?: string - Additional CSS classes
  • onCopy?: () => void - Copy button callback
  • onChange?: (value: string | undefined) => void - Content change callback

DiffViewer

Side-by-side diff viewer for comparing code changes.

import { DiffViewer } from '@manet/ui';

const diffContent = `
--- a/file.js
+++ b/file.js
@@ -1,3 +1,3 @@
-const x = 1;
+const x = 2;
`;

<DiffViewer diffContent={diffContent} fileName="file.js" maxHeight="500px" />;

Props:

  • diffContent: string - Git-style diff content
  • fileName?: string - File name for display
  • maxHeight?: string - Maximum height (default: '400px')
  • className?: string - Additional CSS classes

Utilities

File Utilities

getMonacoLanguage(extension: string): string

Maps file extensions to Monaco Editor language identifiers.

import { getMonacoLanguage } from '@manet/ui';

getMonacoLanguage('ts'); // 'typescript'
getMonacoLanguage('py'); // 'python'
getMonacoLanguage('unknown'); // 'plaintext'

getDisplayFileName(fileName?: string, filePath?: string): string

Extracts display name from file name or path.

import { getDisplayFileName } from '@manet/ui';

getDisplayFileName('script.js'); // 'script.js'
getDisplayFileName(undefined, '/path/to/file.ts'); // 'file.ts'
getDisplayFileName(); // 'Untitled'

getFileExtension(fileName?: string): string

Extracts file extension from file name.

import { getFileExtension } from '@manet/ui';

getFileExtension('script.js'); // 'js'
getFileExtension('README.md'); // 'md'
getFileExtension('noext'); // ''

Path Utilities

normalizeFilePath(absolutePath: string): string

Normalizes file paths by replacing user directories with ~ for privacy.

import { normalizeFilePath } from '@manet/ui';

// macOS/Linux
normalizeFilePath('/Users/john/project/file.js'); // '~/project/file.js'
normalizeFilePath('/home/jane/code/app.py'); // '~/code/app.py'

// Windows
normalizeFilePath('C:\\Users\\john\\project\\file.js'); // '~\\project\\file.js'

normalizeFilePathsBatch(paths: string[]): string[]

Batch normalize multiple file paths for better performance.

isAbsolutePath(path: string): boolean

Checks if a path is absolute (starts with / on Unix or drive letter on Windows).

Cache Management

  • clearPathNormalizationCache(): void - Clear normalization cache
  • getPathNormalizationCacheSize(): number - Get cache size

Markdown Renderer

MarkdownRenderer

Full-featured markdown renderer with syntax highlighting, math support, and interactive elements.

import { MarkdownRenderer } from '@manet/ui';

const markdownContent = `
# Hello World

This is **bold** text with \`code\` and [links](https://example.com).

\`\`\`javascript
console.log('Hello!');
\`\`\`
`;

<MarkdownRenderer
  content={markdownContent}
  className="prose"
  forceDarkTheme={false}
/>;

Props:

  • content: string - Markdown content to render
  • publishDate?: string - Publication date for display
  • author?: string - Author information
  • className?: string - Additional CSS classes
  • forceDarkTheme?: boolean - Force dark theme (default: false)
  • codeBlockStyle?: React.CSSProperties - Custom code block styles

Features:

  • GitHub Flavored Markdown (GFM) support
  • Syntax highlighting for code blocks
  • Math equations with KaTeX
  • GitHub-style alerts and blockquotes
  • Interactive images with modal preview
  • Smart link handling (internal/external/hash links)
  • Responsive tables
  • Dark/light theme support

Data Viewers

JSONViewer

Interactive JSON tree viewer with expand/collapse, copy functionality, and syntax highlighting.

import { JSONViewer, JSONViewerRef } from '@manet/ui';

const data = {
  name: 'John Doe',
  age: 30,
  skills: ['JavaScript', 'React', 'Node.js'],
  address: {
    city: 'New York',
    country: 'USA',
  },
};

const viewerRef = useRef<JSONViewerRef>(null);

<JSONViewer
  data={data}
  emptyMessage="No data available"
  className="max-h-96 overflow-auto"
  ref={viewerRef}
/>;

// Copy all data as JSON
const copyAll = () => {
  const jsonString = viewerRef.current?.copyAll();
  if (jsonString) {
    navigator.clipboard.writeText(jsonString);
  }
};

Props:

  • data: any - JSON data to display
  • className?: string - Additional CSS classes
  • emptyMessage?: string - Message for empty data (default: 'No data available')
  • ref?: JSONViewerRef - Reference for programmatic access

Features:

  • Hierarchical tree structure with expand/collapse
  • Type-aware syntax highlighting (strings, numbers, booleans, null)
  • Copy individual values or entire JSON
  • Long string truncation with expand option
  • Smooth animations and hover effects
  • Dark/light theme support
  • Empty state handling

Hooks

useDarkMode

Hook for detecting and managing dark mode state.

import { useDarkMode } from '@manet/ui';

function MyComponent() {
  const isDarkMode = useDarkMode();

  return (
    <div className={isDarkMode ? 'dark-theme' : 'light-theme'}>
      Current theme: {isDarkMode ? 'Dark' : 'Light'}
    </div>
  );
}

useCopyToClipboard

Hook for copying text to clipboard with feedback state.

import { useCopyToClipboard } from '@manet/ui';

function CopyButton({ text }: { text: string }) {
  const { copied, copyToClipboard } = useCopyToClipboard();

  return (
    <button onClick={() => copyToClipboard(text)}>
      {copied ? 'Copied!' : 'Copy'}
    </button>
  );
}

Utilities

Duration Utilities

formatDuration(ms: number): string

Formats milliseconds into human-readable duration.

import { formatDuration } from '@manet/ui';

formatDuration(1500); // '1.5s'
formatDuration(65000); // '1m 5s'
formatDuration(3661000); // '1h 1m 1s'

MUI Theme

createMuiTheme(isDarkMode: boolean): Theme

Creates Material-UI theme based on dark mode preference.

import { createMuiTheme } from '@manet/ui';
import { ThemeProvider } from '@mui/material/styles';

function App() {
  const isDarkMode = useDarkMode();
  const theme = createMuiTheme(isDarkMode);

  return <ThemeProvider theme={theme}>{/* Your app content */}</ThemeProvider>;
}