# @knotx/plugins-minimap

Minimap plugin that provides canvas navigation functionality for KnotX.

## Installation

```bash
npm install @knotx/plugins-minimap
```

## Overview

The Minimap plugin provides minimap functionality for KnotX, allowing users to quickly navigate in large canvases. This plugin is built on the `interactjs` library and provides zoom, pan, viewport control, and other features.

## Implementation Principle

The core implementation principles of the Minimap plugin:

1. **Node Mapping**: Maps nodes on the canvas to the minimap scale
2. **Viewport Synchronization**: Real-time synchronization of viewport state between main canvas and minimap
3. **Interaction Control**: Supports dragging and clicking on the minimap for navigation
4. **Zoom Control**: Provides zoom buttons and reset functionality

## Dependencies

### Core Dependencies
- `@knotx/core`: Provides base plugin architecture
- `@knotx/decorators`: Provides decorator support
- `interactjs`: Provides interaction functionality
- `rxjs`: Provides reactive programming support

### Plugin Dependencies
- `@knotx/plugins-canvas`: Retrieves canvas transform state and container information

## API Documentation

### Main Classes

#### Minimap

The main class of the Minimap plugin, extending `BasePlugin`.

```typescript
export class Minimap extends BasePlugin<'minimap', MinimapConfig> {
  name = 'minimap' as const
}
```

### Configuration Options

#### MinimapConfig

```typescript
export interface MinimapConfig {
  /** Minimap width */
  width?: number
  /** Minimap height */
  height?: number
  /** Node color */
  nodeColor?: string | ((node: Node) => string)
  /** Viewport area background color */
  maskColor?: string
  /** Viewport area border color */
  viewBoxColor?: string
  /** Show minimap control buttons */
  showControls?: boolean
  /** Whether zoomable */
  zoomable?: boolean
  /** Whether pannable */
  pannable?: boolean
  /** Padding from container */
  padding?: number
  /** Node border radius */
  nodeBorderRadius?: number
  /** Node stroke width */
  nodeStrokeWidth?: number
  /** Node stroke color */
  nodeStrokeColor?: string | ((node: Node) => string)
  /** Zoom step */
  zoomStep?: number
}
```

### Default Configuration

```typescript
const defaultProps: Required<Omit<MinimapConfig, 'nodeColor' | 'nodeStrokeColor'>> = {
  width: 200,
  height: 150,
  maskColor: 'rgba(240, 240, 240, 0.6)',
  viewBoxColor: '#4752E6',
  showControls: true,
  zoomable: true,
  pannable: true,
  padding: 12,
  nodeBorderRadius: 2,
  nodeStrokeWidth: 1,
  zoomStep: 0.2,
}
```

## Usage Examples

### Basic Usage

```typescript
import { Minimap } from '@knotx/plugins-minimap'

const engine = new Engine({
  plugins: [Minimap],
  pluginConfig: {
    minimap: {
      width: 200,
      height: 150,
    },
  },
})
```

### Custom Styling

```typescript
const engine = new Engine({
  plugins: [Minimap],
  pluginConfig: {
    minimap: {
      width: 250,
      height: 180,
      nodeColor: '#4A90E2',
      maskColor: 'rgba(255, 255, 255, 0.8)',
      viewBoxColor: '#FF6B6B',
      nodeBorderRadius: 4,
      nodeStrokeWidth: 2,
      nodeStrokeColor: '#333',
    },
  },
})
```

### Dynamic Node Colors

```typescript
const engine = new Engine({
  plugins: [Minimap],
  pluginConfig: {
    minimap: {
      nodeColor: (node) => {
        // Return different colors based on node type
        switch (node.type) {
          case 'start':
            return '#4CAF50'
          case 'end':
            return '#F44336'
          case 'process':
            return '#2196F3'
          default:
            return '#9E9E9E'
        }
      },
      nodeStrokeColor: (node) => {
        return node.selected ? '#FF9800' : 'transparent'
      },
    },
  },
})
```

### Disable Control Buttons

```typescript
const engine = new Engine({
  plugins: [Minimap],
  pluginConfig: {
    minimap: {
      showControls: false,
      zoomable: false,
      pannable: true,
    },
  },
})
```

### Custom Size and Position

```typescript
const engine = new Engine({
  plugins: [Minimap],
  pluginConfig: {
    minimap: {
      width: 300,
      height: 200,
      padding: 20,
      zoomStep: 0.3,
    },
  },
})
```

## Advanced Features

### Integration with Canvas Plugin

```typescript
import { Canvas } from '@knotx/plugins-canvas'
import { Minimap } from '@knotx/plugins-minimap'

const engine = new Engine({
  plugins: [Canvas, Minimap],
  pluginConfig: {
    canvas: {
      minScale: 0.1,
      maxScale: 3,
    },
    minimap: {
      width: 200,
      height: 150,
    },
  },
})
```

### Listening to Minimap Interactions

```typescript
class MinimapInteractionPlugin extends BasePlugin {
  @inject.canvas.transform()
  transform!: CanvasTransformState

  @subscribe.canvas.transform()
  onTransformChange(transform: CanvasTransformState) {
    console.log('Canvas transform changed:', transform)
    // Minimap will automatically sync transform state
  }
}
```

### Custom Minimap Behavior

```typescript
class CustomMinimapPlugin extends BasePlugin {
  @inject.minimap.config()
  minimapConfig!: MinimapConfig

  @OnInit
  init() {
    // Dynamically adjust minimap configuration
    this.minimapConfig.nodeColor = (node) => {
      const isImportant = node.data?.important
      return isImportant ? '#FF5722' : '#607D8B'
    }
  }
}
```

## Style Customization

### CSS Class Names

The minimap provides the following CSS class names for style customization:

```css
.knotx-minimap {
  /* Minimap container */
  border: 1px solid #ddd;
  border-radius: 4px;
  background: #fff;
}

.knotx-minimap__svg {
  /* SVG container */
  cursor: crosshair;
}

.knotx-minimap__controls {
  /* Control buttons container */
  display: flex;
  gap: 4px;
  margin-top: 8px;
}

.knotx-minimap__button {
  /* Control buttons */
  padding: 4px 8px;
  border: 1px solid #ccc;
  background: #f5f5f5;
  cursor: pointer;
}

.knotx-minimap__button:hover {
  background: #e0e0e0;
}

.knotx-minimap__button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
```

### Custom Style Example

```typescript
const engine = new Engine({
  plugins: [Minimap],
  pluginConfig: {
    minimap: {
      width: 200,
      height: 150,
      // Custom viewport color
      viewBoxColor: '#FF6B6B',
      // Custom mask color
      maskColor: 'rgba(255, 107, 107, 0.1)',
    },
  },
})
```

## Performance Optimization

### Node Rendering Optimization

```typescript
const engine = new Engine({
  plugins: [Minimap],
  pluginConfig: {
    minimap: {
      // Use fixed color to avoid function call overhead
      nodeColor: '#4A90E2',
      nodeStrokeColor: 'transparent',
      // Reduce border radius for better rendering performance
      nodeBorderRadius: 0,
    },
  },
})
```

### Interaction Optimization

```typescript
const engine = new Engine({
  plugins: [Minimap],
  pluginConfig: {
    minimap: {
      // Smaller zoom step for smoother experience
      zoomStep: 0.1,
      // Appropriate size balancing performance and usability
      width: 180,
      height: 120,
    },
  },
})
```

## File Directory Structure

```
packages/plugins-minimap/
├── src/
│   ├── minimap.tsx             # Main implementation file
│   └── index.ts               # Export file
├── dist/                      # Build output directory
├── package.json              # Package configuration
├── build.config.ts           # Build configuration
├── tsconfig.json             # TypeScript configuration
├── eslint.config.mjs         # ESLint configuration
└── CHANGELOG.md              # Changelog
```

### Core Files Description

- **minimap.tsx**: Contains the main implementation of the Minimap plugin, including node mapping, viewport synchronization, and interaction control
- **index.ts**: Exports the Minimap class and related type definitions

## Best Practices

### User Experience

1. **Appropriate Size**: Choose suitable minimap size based on application layout
2. **Clear Visual Feedback**: Use high-contrast colors to distinguish different elements
3. **Smooth Interactions**: Configure zoom steps and animation effects appropriately

### Performance Optimization

1. **Fixed Colors**: Use fixed colors instead of dynamic functions for large numbers of nodes
2. **Simplified Styles**: Reduce unnecessary visual effects to improve rendering performance
3. **Reasonable Size**: Adjust minimap size based on node count

### Development and Debugging

1. **Monitor State Changes**: Listen to transform state changes during development
2. **Test Interactions**: Ensure proper synchronization between minimap and main canvas
3. **Verify Boundaries**: Test extreme zoom and pan scenarios

## Notes

1. **Dependencies**: Ensure Canvas plugin is loaded before Minimap plugin
2. **Performance Considerations**: With many nodes, minimap rendering may impact performance
3. **Responsive Design**: Consider minimap display on different screen sizes
4. **Browser Compatibility**: Depends on SVG and modern JavaScript features

## License

MIT
