npm package: @principal-ade/argdown-renderer
Description: Industry-themed Argdown renderer UI component with integrated theming
Author: Principal ADE Team
Latest version: 0.1.7

# @principal-ade/argdown-renderer

Industry-themed Argdown renderer wrapper with integrated theming support for visualizing argument maps.

## Features

- Seamless integration with `@a24z/industry-theme`
- Automatic theme synchronization with Argdown visualizations
- Built on `@argdown/core` and `@argdown/map-views`
- Support for debate-specific features (speaker filtering, time ranges)
- TypeScript support with full type definitions
- Custom CSS theming via CSS custom properties
- Interactive zoom and pan controls
- Export capabilities (SVG, PNG, PDF)
- Minimap for navigation
- Configurable layouts and views

## Installation

```bash
npm install @principal-ade/argdown-renderer @argdown/core @argdown/map-views @a24z/industry-theme
```

or with bun:

```bash
bun add @principal-ade/argdown-renderer @argdown/core @argdown/map-views @a24z/industry-theme
```

## Usage

### Basic Usage with Theme Provider

```tsx
import { ArgdownRendererWithProvider } from '@principal-ade/argdown-renderer';
import '@principal-ade/argdown-renderer/styles.css';

const argdownSource = `
# Should AI Be Regulated?

[AI should be regulated]: AI regulation is necessary. #speaker-a

  + <Existential Risk Argument>: AI poses risks to humanity. #speaker-a
    (1) AI systems could harm humans
    (2) Oversight prevents harmful decisions
    ----
    (3) Therefore, AI should be regulated

  - <Innovation Argument>: Regulation harms progress. #speaker-b
    (1) Technology develops too quickly
    (2) Regulation cannot keep pace
    ----
    (3) Therefore, AI should not be regulated
`;

function App() {
  return (
    <ArgdownRendererWithProvider
      source={argdownSource}
      config={{
        viewMode: 'map',
        showToolbar: true,
        showMinimap: true,
        interactive: true,
      }}
    />
  );
}
```

### Usage with Explicit Theme

```tsx
import { ArgdownRenderer } from '@principal-ade/argdown-renderer';
import { useTheme } from '@a24z/industry-theme';
import '@principal-ade/argdown-renderer/styles.css';

function DebateVisualization() {
  const { theme } = useTheme();

  return (
    <ArgdownRenderer
      theme={theme}
      source={argdownSource}
      config={{
        viewMode: 'map',
        zoom: {
          enabled: true,
          initialZoom: 1.0,
          minZoom: 0.1,
          maxZoom: 3.0,
        },
        layout: {
          rankDir: 'TB', // Top to bottom
          nodeSep: 50,
          rankSep: 50,
        },
      }}
      onRenderComplete={(data) => {
        console.log('Map rendered:', data);
      }}
    />
  );
}
```

### With Debate-Specific Filters

```tsx
import { ArgdownRenderer } from '@principal-ade/argdown-renderer';
import { useTheme } from '@a24z/industry-theme';

function FilteredDebateView() {
  const { theme } = useTheme();
  const [filters, setFilters] = React.useState({
    speakers: ['speaker-a'],
    argumentTypes: ['support'],
  });

  return (
    <ArgdownRenderer
      theme={theme}
      source={argdownSource}
      config={{
        filters,
        interactive: true,
      }}
    />
  );
}
```

### Using the Hook

```tsx
import { useArgdownRenderer } from '@principal-ade/argdown-renderer';
import { useTheme } from '@a24z/industry-theme';

function CustomRenderer() {
  const { theme } = useTheme();
  const { getCSSVariables, getStyles } = useArgdownRenderer(theme);

  return (
    <div style={getStyles()}>
      {/* Your custom Argdown visualization */}
    </div>
  );
}
```

### Processing Argdown Content

```tsx
import { processArgdown, validateArgdown, extractMetadata } from '@principal-ade/argdown-renderer';

// Validate Argdown syntax
const validation = await validateArgdown(argdownSource);
if (!validation.valid) {
  console.error('Errors:', validation.errors);
}

// Process Argdown to map data
const mapData = await processArgdown(argdownSource);
console.log('Processed:', mapData);

// Extract metadata
const metadata = extractMetadata(argdownSource);
console.log('Speakers:', metadata.speakers);
console.log('Tags:', metadata.tags);
console.log('Title:', metadata.title);
```

## API

### ArgdownRenderer Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `theme` | `Theme` | Required | Industry theme object |
| `source` | `string` | Required | Argdown source text |
| `config` | `RendererConfig` | `{}` | Renderer configuration |
| `loadingComponent` | `React.ReactNode` | - | Custom loading component |
| `errorComponent` | `(error: Error) => React.ReactNode` | - | Custom error component |
| `onRenderComplete` | `(data: ArgdownMapData) => void` | - | Callback when rendering completes |
| `onError` | `(error: Error) => void` | - | Callback when error occurs |
| `className` | `string` | `''` | Additional CSS classes |
| `style` | `React.CSSProperties` | `{}` | Additional inline styles |
| `debug` | `boolean` | `false` | Enable debug mode |

### RendererConfig

```typescript
interface RendererConfig {
  viewMode?: 'map' | 'source' | 'split';
  zoom?: ZoomConfig;
  layout?: LayoutConfig;
  filters?: FilterOptions;
  interactive?: boolean;
  showMinimap?: boolean;
  showToolbar?: boolean;
}
```

### ZoomConfig

```typescript
interface ZoomConfig {
  enabled?: boolean;
  initialZoom?: number;
  minZoom?: number;
  maxZoom?: number;
  enablePan?: boolean;
}
```

### LayoutConfig

```typescript
interface LayoutConfig {
  rankDir?: 'TB' | 'BT' | 'LR' | 'RL'; // Top-Bottom, Bottom-Top, Left-Right, Right-Left
  nodeSep?: number;  // Node separation
  edgeSep?: number;  // Edge separation
  rankSep?: number;  // Rank separation
}
```

### FilterOptions

```typescript
interface FilterOptions {
  speakers?: string[];              // Filter by speaker IDs
  argumentTypes?: ('support' | 'attack')[]; // Filter by argument type
  tags?: string[];                  // Filter by tags
  timeRange?: {                     // Filter by time range
    start?: Date;
    end?: Date;
  };
}
```

### ArgdownRendererWithProvider Props

Same as `ArgdownRenderer` but without the `theme` prop (uses theme from context).

Additional props:
- `themeName?: string` - Optional theme name to override current theme

### useArgdownRenderer Hook

```typescript
function useArgdownRenderer(theme: Theme): {
  theme: Theme;
  getCSSVariables: () => Record<string, string>;
  getStyles: () => React.CSSProperties;
}
```

## CSS Custom Properties

The package uses CSS custom properties for theming:

### Base Colors
- `--argdown-bg` - Background color
- `--argdown-fg` - Foreground (text) color
- `--argdown-border` - Border color
- `--argdown-toolbar-bg` - Toolbar background

### Typography
- `--argdown-font-family` - Font family
- `--argdown-font-size` - Font size

### Node Colors
- `--argdown-node-bg` - Node background
- `--argdown-node-border` - Node border
- `--argdown-node-text` - Node text color

### Argument Colors
- `--argdown-support-bg` - Support argument background
- `--argdown-support-border` - Support argument border
- `--argdown-attack-bg` - Attack argument background
- `--argdown-attack-border` - Attack argument border

### Edge Colors
- `--argdown-edge-support` - Support edge color
- `--argdown-edge-attack` - Attack edge color
- `--argdown-edge-neutral` - Neutral edge color

### Interactive States
- `--argdown-hover-bg` - Hover background
- `--argdown-selected-border` - Selected border
- `--argdown-focus-outline` - Focus outline

## Integration with Pixel Project

This package is designed to integrate with the Pixel debate visualization system:

### Phase 2: Graph-to-Argdown Visualization

```typescript
// After converting Graphiti knowledge graph to Argdown format
import { ArgdownRenderer } from '@principal-ade/argdown-renderer';

function DebateViewer({ argdownContent }: { argdownContent: string }) {
  const { theme } = useTheme();

  return (
    <ArgdownRenderer
      theme={theme}
      source={argdownContent}
      config={{
        viewMode: 'map',
        interactive: true,
        showToolbar: true,
        filters: {
          // Enable speaker filtering for debate analysis
          speakers: ['speaker-a', 'speaker-b'],
        },
      }}
    />
  );
}
```

## Development

```bash
# Install dependencies
bun install

# Build package
bun run build

# Run in development mode
bun run dev

# Type checking
bun run typecheck

# Linting
bun run lint
bun run lint:fix

# Formatting
bun run format
bun run format:check
```

## Roadmap

- [ ] Implement D3-based map rendering using `@argdown/map-views`
- [ ] Add zoom and pan functionality with D3
- [ ] Implement export functionality (SVG, PNG, PDF)
- [ ] Add speaker filtering UI
- [ ] Add timeline visualization for temporal debates
- [ ] Implement minimap navigation
- [ ] Add interactive node selection and highlighting
- [ ] Support for custom node shapes and styles
- [ ] Add animation for argument flow visualization

## License

MIT © Principal ADE Team

## Related Packages

- [@principal-ade/industry-themed-mdx-editor](../industry-themed-mdx-editor) - MDX editor with industry theming
- [@a24z/industry-theme](https://github.com/a24z/industry-theme) - Industry theme system
- [@argdown/core](https://argdown.org) - Argdown core library
- [@argdown/map-views](https://argdown.org) - Argdown map visualization library