{"id":28624583,"url":"https://github.com/zakariaf/svg-toolbelt","last_synced_at":"2026-03-10T14:34:07.673Z","repository":{"id":296847774,"uuid":"992061914","full_name":"zakariaf/svg-toolbelt","owner":"zakariaf","description":"Professional SVG interaction toolkit with zero dependencies. Add smooth zoom, pan, touch controls, and accessibility features to any SVG","archived":false,"fork":false,"pushed_at":"2026-03-08T10:50:24.000Z","size":408,"stargazers_count":13,"open_issues_count":13,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-08T14:27:14.897Z","etag":null,"topics":["accessibility","diagrams","documentation","javascript","keyboard-navigation","library","mermaid","pan","svg","touch-gestures","typescript","vite","zero-dependencies","zoom"],"latest_commit_sha":null,"homepage":"https://zakariaf.github.io/svg-toolbelt","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zakariaf.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-28T14:59:13.000Z","updated_at":"2026-02-27T09:23:14.000Z","dependencies_parsed_at":"2025-08-14T02:19:08.354Z","dependency_job_id":"1ce91e1f-7de7-489f-9bc1-c389ea151b03","html_url":"https://github.com/zakariaf/svg-toolbelt","commit_stats":null,"previous_names":["zakariaf/svg-toolbelt"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/zakariaf/svg-toolbelt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zakariaf%2Fsvg-toolbelt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zakariaf%2Fsvg-toolbelt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zakariaf%2Fsvg-toolbelt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zakariaf%2Fsvg-toolbelt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zakariaf","download_url":"https://codeload.github.com/zakariaf/svg-toolbelt/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zakariaf%2Fsvg-toolbelt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30337297,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T12:41:07.687Z","status":"ssl_error","status_checked_at":"2026-03-10T12:41:06.728Z","response_time":106,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["accessibility","diagrams","documentation","javascript","keyboard-navigation","library","mermaid","pan","svg","touch-gestures","typescript","vite","zero-dependencies","zoom"],"created_at":"2025-06-12T07:38:09.976Z","updated_at":"2026-03-10T14:34:07.649Z","avatar_url":"https://github.com/zakariaf.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🧰 svg-toolbelt\n\n[![Build Status](https://github.com/zakariaf/svg-toolbelt/actions/workflows/main.yml/badge.svg)](https://github.com/zakariaf/svg-toolbelt/actions)\n[![Coverage Status](https://coveralls.io/repos/github/zakariaf/svg-toolbelt/badge.svg?branch=main)](https://coveralls.io/github/zakariaf/svg-toolbelt?branch=main)\n[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n**A lightweight, zero-dependency library to add smooth zoom, pan, touch, keyboard controls and fullscreen support to any SVG.**\n\nTransform any static SVG (Mermaid diagrams, D3 visualizations, technical drawings) into an interactive, zoomable, and pannable experience—fully accessible, mobile-first, and production-ready.\n\n---\n\n## 🎯 Origin Story\n\nThis library was born from a real need at **GitLab** - making large Mermaid diagrams more accessible in documentation. When complex system architecture diagrams and flowcharts became impossible to read on mobile devices or for users with visual impairments, we knew we needed a better solution.\n\n**The challenge**: Most existing solutions were either too heavy (requiring entire libraries like D3.js just for zoom/pan), too basic (missing accessibility features), or didn't work well on mobile devices.\n\n**Our solution**: A lightweight, modular, accessibility-first toolkit that works with any SVG - not just Mermaid diagrams.\n\n---\n\n## ✨ Features\n\n- 🔍 **Smooth zoom \u0026 pan**\n  - Mouse-wheel zoom with zoom-to-cursor precision\n  - Click-and-drag panning (desktop)\n  - Pinch-to-zoom \u0026 touch-drag (mobile)\n  - Keyboard shortcuts: `+`/`-` (zoom), `0` (reset), arrows (pan)\n\n- 🎛️ **Smart on-screen controls**\n  - Zoom in/out, reset, and fullscreen buttons\n  - Export functionality for saving SVG content\n  - Four positioning options: any corner of the container\n  - Fully customizable styling and behavior\n\n- 📊 **Visual feedback**\n  - Transient zoom level indicator showing current zoom percentage\n  - Appears briefly when zoom level changes (e.g., \"150%\")\n  - Accessible with screen reader support\n  - Auto-fades after 1.5 seconds\n\n- 📱 **Mobile-first design**\n  - Optimized touch interactions with proper gesture recognition\n  - Responsive UI that adapts to screen size\n  - Touch-friendly button sizes (44px minimum)\n\n- ♿ **Accessibility champion**\n  - WCAG 2.1 AA compliant with full keyboard navigation\n  - Screen reader compatible with proper ARIA labels\n  - High contrast mode and reduced motion support\n\n- 🏗️ **Modular architecture**\n  - Use only the features you need (tree-shakeable)\n  - Feature-based design: zoom, pan, touch, keyboard, controls, fullscreen\n  - Easy to extend with custom features\n\n- 🪶 **Lightweight \u0026 zero dependencies**\n  - Under 5KB minified + gzipped for both ESM and CJS builds\n  - No external libraries required\n  - Built with modern TypeScript\n\n- 🎨 **Framework agnostic**\n  - Works with React, Vue, Angular, or vanilla JavaScript\n  - Complete TypeScript definitions included\n  - Clean, predictable API\n\n---\n\n## 🚀 Quick Start\n\n### 1. Installation\n\n**Via npm/yarn/pnpm:**\n\n```bash\nnpm install svg-toolbelt\n# or\nyarn add svg-toolbelt\n# or\npnpm add svg-toolbelt\n```\n\n**Via CDN (unpkg):**\n\n```html\n\u003c!-- Include the library --\u003e\n\u003cscript src=\"https://unpkg.com/svg-toolbelt@latest/dist/svg-toolbelt.cjs.production.min.js\"\u003e\u003c/script\u003e\n\u003c!-- Include the styles --\u003e\n\u003clink rel=\"stylesheet\" href=\"https://unpkg.com/svg-toolbelt@latest/dist/svg-toolbelt.css\"\u003e\n```\n\n**For ES modules:**\n\n```html\n\u003cscript type=\"module\"\u003e\n  import { initializeSvgToolbelt } from 'https://unpkg.com/svg-toolbelt@latest/dist/svg-toolbelt.esm.js';\n  // Your code here\n\u003c/script\u003e\n```\n\n**Requirements:**\n\n- Node.js ≥18 (for development)\n- Modern browsers with ES2020+ support\n\n### 2. Try the Demo\n\n**Online demo:** [zakariaf.github.io/svg-toolbelt](https://zakariaf.github.io/svg-toolbelt)\n\n**Local development demo:** Available in the `/demo` directory with Node.js server\n\n### 3. Import Styles\n\n```typescript\n// Import the CSS in your main entry file\nimport 'svg-toolbelt/dist/svg-toolbelt.css';\n```\n\n### 4. Basic Usage\n\n#### Auto-initialize (recommended for most cases)\n\n```typescript\nimport { initializeSvgToolbelt } from 'svg-toolbelt';\n\n// Initialize all elements with the class 'zoomable'\ninitializeSvgToolbelt('.zoomable');\n```\n\n```html\n\u003c!-- Your HTML --\u003e\n\u003cdiv class=\"zoomable\"\u003e\n  \u003csvg viewBox=\"0 0 800 600\"\u003e\n    \u003c!-- Your SVG content (Mermaid, D3, hand-drawn, etc.) --\u003e\n  \u003c/svg\u003e\n\u003c/div\u003e\n```\n\n#### Manual instantiation (for more control)\n\n```typescript\nimport { SvgToolbelt } from 'svg-toolbelt';\n\nconst container = document.querySelector('#my-diagram');\nconst enhancer = new SvgToolbelt(container, {\n  minScale: 0.2,\n  maxScale: 8,\n  zoomStep: 0.15,\n  showControls: true,\n  controlsPosition: 'top-right',\n  enableTouch: true,\n  enableKeyboard: true\n});\n\nenhancer.init();\n\n// Programmatic control\nenhancer.zoomIn();\nenhancer.zoomOut();\n\n// Cleanup when done\nenhancer.destroy();\n```\n\n---\n\n## 📖 API Reference\n\n### `SvgToolbelt` Class\n\nThe main class that provides all zoom/pan functionality.\n\n```typescript\nconstructor(container: HTMLElement, config?: Partial\u003cSvgEnhancerConfig\u003e)\n```\n\n**Parameters:**\n\n- `container` - HTMLElement that contains exactly one `\u003csvg\u003e` element\n- `config` - Optional configuration overrides (see Configuration section)\n\n**Methods:**\n\n- `init()` - Initialize all features and event listeners\n- `zoomIn()` - Zoom in by one step\n- `zoomOut()` - Zoom out by one step\n- `destroy()` - Clean up all event listeners and UI elements\n\n**Events:**\n\n```typescript\nenhancer.on('zoom', ({ scale, translateX, translateY }) =\u003e {\n  console.log(`Zoomed to ${scale}x at (${translateX}, ${translateY})`);\n});\n\nenhancer.on('pan', ({ translateX, translateY }) =\u003e {\n  console.log(`Panned to (${translateX}, ${translateY})`);\n});\n```\n\n### `initializeSvgToolbelt` Function\n\nConvenience function for batch initialization.\n\n```typescript\nfunction initializeSvgToolbelt(\n  selectorOrElements: string | HTMLElement | HTMLElement[],\n  config?: Partial\u003cSvgEnhancerConfig\u003e\n): void\n```\n\n**Parameters:**\n\n- `selectorOrElements` - CSS selector string, single element, or array of elements\n- `config` - Configuration applied to all instances\n\n**Examples:**\n\n```typescript\n// CSS selector\ninitializeSvgToolbelt('.diagram');\n\n// Single element\nconst chart = document.querySelector('#chart');\ninitializeSvgToolbelt(chart);\n\n// Array of elements\nconst diagrams = document.querySelectorAll('.svg-container');\ninitializeSvgToolbelt(Array.from(diagrams));\n\n// With custom config\ninitializeSvgToolbelt('.large-diagrams', {\n  minScale: 0.1,\n  maxScale: 20,\n  controlsPosition: 'bottom-right'\n});\n```\n\n---\n\n## ⚙️ Configuration Options\n\nAll options are optional with sensible defaults:\n\n```typescript\ninterface SvgEnhancerConfig {\n  // Zoom settings\n  minScale: number;           // Default: 0.1 (10%)\n  maxScale: number;           // Default: 10 (1000%)\n  zoomStep: number;           // Default: 0.1 (10% per step)\n\n  // Animation\n  transitionDuration: number; // Default: 200 (milliseconds)\n\n  // UI Controls\n  showControls: boolean;      // Default: true\n  controlsPosition:           // Default: 'top-right'\n    | 'top-right'\n    | 'top-left'\n    | 'bottom-right'\n    | 'bottom-left';\n\n  // Feature toggles\n  enableTouch: boolean;       // Default: true\n  enableKeyboard: boolean;    // Default: true\n  showZoomLevelIndicator: boolean; // Default: true\n}\n```\n\n**Example configurations:**\n\n```typescript\n// Minimal zoom-only setup\nconst minimal = new SvgToolbelt(container, {\n  showControls: false,\n  enableKeyboard: false,\n  enableTouch: false,\n  showZoomLevelIndicator: false  // Hide zoom percentage indicator\n});\n\n// Large diagram optimized\nconst largeDiagram = new SvgToolbelt(container, {\n  minScale: 0.05,\n  maxScale: 50,\n  zoomStep: 0.2,\n  controlsPosition: 'bottom-left'\n});\n\n// Mobile-optimized\nconst mobile = new SvgToolbelt(container, {\n  zoomStep: 0.25,  // Bigger steps for touch\n  transitionDuration: 150,  // Faster animations\n  enableKeyboard: false     // Focus on touch\n});\n```\n\n---\n\n## ⌨️ Keyboard Shortcuts\n\n| Key | Action |\n|-----|--------|\n| `+` or `=` | Zoom in by one step |\n| `-` | Zoom out by one step |\n| `0` | Reset zoom and pan to defaults |\n| `↑` `↓` `←` `→` | Pan in the respective direction |\n| **Double-click** | Reset zoom and pan |\n\n**Note:** The container must have focus for keyboard shortcuts to work. Click on the diagram or tab to it.\n\n---\n\n## 👆 Touch Gestures\n\n| Gesture | Action |\n|---------|--------|\n| **Pinch** (two fingers) | Zoom in/out centered on gesture |\n| **Drag** (one finger) | Pan around the diagram |\n| **Double-tap** | Reset zoom and pan to defaults |\n\nAll touch interactions are optimized for smooth 60fps performance.\n\n---\n\n## 🎨 Styling \u0026 Customization\n\n### Default Styles\n\nThe package includes a complete CSS file:\n\n```typescript\nimport 'svg-toolbelt/dist/svg-toolbelt.css';\n```\n\n### Custom Styling\n\nOverride default styles in your CSS:\n\n```css\n/* Container styling */\n.svg-toolbelt-wrapper {\n  border: 2px solid #e2e8f0;\n  border-radius: 12px;\n  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);\n  background: #ffffff;\n}\n\n/* Controls styling */\n.svg-toolbelt-controls {\n  background: rgba(255, 255, 255, 0.98);\n  backdrop-filter: blur(8px);\n  border-radius: 8px;\n  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n}\n\n/* Button styling */\n.svg-toolbelt-controls button {\n  width: 40px;\n  height: 40px;\n  border-radius: 8px;\n  font-size: 18px;\n  transition: all 0.2s ease;\n}\n\n/* Fullscreen styles */\n:fullscreen .svg-toolbelt-wrapper {\n  background: #ffffff;\n}\n\n/* Dark theme */\n.dark .svg-toolbelt-wrapper {\n  background: #1f2937;\n  border-color: #374151;\n}\n\n.dark .svg-toolbelt-controls {\n  background: rgba(31, 41, 55, 0.95);\n  border-color: #374151;\n}\n```\n\n### Responsive Design\n\nBuilt-in responsive breakpoints:\n\n```css\n/* Mobile optimizations (automatically applied) */\n@media (max-width: 768px) {\n  .svg-toolbelt-controls button {\n    width: 44px;   /* Larger touch targets */\n    height: 44px;\n    font-size: 16px;\n  }\n}\n\n/* High contrast mode support */\n@media (prefers-contrast: high) {\n  .svg-toolbelt-controls {\n    border: 2px solid #000;\n    background: #fff;\n  }\n}\n\n/* Reduced motion support */\n@media (prefers-reduced-motion: reduce) {\n  .svg-toolbelt-wrapper * {\n    transition: none !important;\n  }\n}\n```\n\n---\n\n## 🛠️ Framework Integration\n\n### React\n\n```tsx\nimport React, { useEffect, useRef } from 'react';\nimport { SvgToolbelt, SvgEnhancerConfig } from 'svg-toolbelt';\nimport 'svg-toolbelt/dist/svg-toolbelt.css';\n\ninterface ZoomableSvgProps {\n  children: React.ReactNode;\n  config?: Partial\u003cSvgEnhancerConfig\u003e;\n  className?: string;\n}\n\nexport function ZoomableSvg({ children, config, className }: ZoomableSvgProps) {\n  const containerRef = useRef\u003cHTMLDivElement\u003e(null);\n  const enhancerRef = useRef\u003cSvgToolbelt\u003e();\n\n  useEffect(() =\u003e {\n    if (containerRef.current) {\n      enhancerRef.current = new SvgToolbelt(containerRef.current, config);\n      enhancerRef.current.init();\n    }\n\n    return () =\u003e {\n      enhancerRef.current?.destroy();\n    };\n  }, [config]);\n\n  return (\n    \u003cdiv ref={containerRef} className={className}\u003e\n      {children}\n    \u003c/div\u003e\n  );\n}\n\n// Usage\nfunction MyComponent() {\n  return (\n    \u003cZoomableSvg config={{ minScale: 0.5, maxScale: 4 }}\u003e\n      \u003csvg viewBox=\"0 0 400 300\"\u003e\n        {/* Your SVG content */}\n      \u003c/svg\u003e\n    \u003c/ZoomableSvg\u003e\n  );\n}\n```\n\n### Vue 3\n\n```vue\n\u003ctemplate\u003e\n  \u003cdiv ref=\"containerRef\" :class=\"className\"\u003e\n    \u003cslot /\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript setup lang=\"ts\"\u003e\nimport { ref, onMounted, onUnmounted } from 'vue';\nimport { SvgToolbelt, SvgEnhancerConfig } from 'svg-toolbelt';\nimport 'svg-toolbelt/dist/svg-toolbelt.css';\n\ninterface Props {\n  config?: Partial\u003cSvgEnhancerConfig\u003e;\n  className?: string;\n}\n\nconst props = defineProps\u003cProps\u003e();\nconst containerRef = ref\u003cHTMLElement\u003e();\nlet enhancer: SvgToolbelt;\n\nonMounted(() =\u003e {\n  if (containerRef.value) {\n    enhancer = new SvgToolbelt(containerRef.value, props.config);\n    enhancer.init();\n  }\n});\n\nonUnmounted(() =\u003e {\n  enhancer?.destroy();\n});\n\u003c/script\u003e\n```\n\n### Angular\n\n```typescript\nimport { Component, ElementRef, Input, OnInit, OnDestroy } from '@angular/core';\nimport { SvgToolbelt, SvgEnhancerConfig } from 'svg-toolbelt';\nimport 'svg-toolbelt/dist/svg-toolbelt.css';\n\n@Component({\n  selector: 'app-zoomable-svg',\n  template: '\u003cng-content\u003e\u003c/ng-content\u003e',\n  styleUrls: ['./zoomable-svg.component.css']\n})\nexport class ZoomableSvgComponent implements OnInit, OnDestroy {\n  @Input() config?: Partial\u003cSvgEnhancerConfig\u003e;\n\n  private enhancer?: SvgToolbelt;\n\n  constructor(private elementRef: ElementRef\u003cHTMLElement\u003e) {}\n\n  ngOnInit() {\n    this.enhancer = new SvgToolbelt(this.elementRef.nativeElement, this.config);\n    this.enhancer.init();\n  }\n\n  ngOnDestroy() {\n    this.enhancer?.destroy();\n  }\n}\n```\n\n---\n\n## 🎯 Real-World Use Cases\n\n### Mermaid Diagrams (GitLab-style)\n\n```typescript\n// Wait for Mermaid to render, then enhance\ndocument.addEventListener('DOMContentLoaded', () =\u003e {\n  // Mermaid renders asynchronously\n  setTimeout(() =\u003e {\n    initializeSvgToolbelt('.mermaid', {\n      minScale: 0.2,\n      maxScale: 6,\n      controlsPosition: 'top-right',\n      zoomStep: 0.15\n    });\n  }, 100);\n});\n```\n\n### Large System Architecture Diagrams\n\n```typescript\ninitializeSvgToolbelt('.architecture-diagram', {\n  minScale: 0.1,    // Zoom way out to see the big picture\n  maxScale: 20,     // Zoom way in to read details\n  zoomStep: 0.2,    // Bigger steps for faster navigation\n  controlsPosition: 'bottom-right'\n});\n```\n\n### Data Visualizations\n\n```typescript\n// After D3 or Chart.js renders your SVG\nconst chartContainer = d3.select('#chart').node().parentElement;\nconst enhancer = new SvgToolbelt(chartContainer, {\n  enableKeyboard: false,  // Let your chart handle keyboard events\n  showControls: false,    // Use your own UI\n  enableTouch: true       // Keep touch for mobile users\n});\nenhancer.init();\n```\n\n### Mobile Documentation\n\n```typescript\n// Mobile-optimized configuration\ninitializeSvgToolbelt('.mobile-diagram', {\n  zoomStep: 0.25,           // Larger steps for touch\n  transitionDuration: 100,  // Faster transitions\n  controlsPosition: 'bottom-right',\n  minScale: 0.3,           // Don't zoom too far out on small screens\n  maxScale: 5              // Don't need extreme zoom on mobile\n});\n```\n\n---\n\n## 🌐 Browser Support\n\n- ✅ **Chrome 60+** (including Android)\n- ✅ **Firefox 55+**\n- ✅ **Safari 12+** (including iOS)\n- ✅ **Edge 79+** (Chromium-based)\n- ✅ **Samsung Internet 8+**\n\n**Legacy Support:**\n\n- For older browsers, ensure these APIs are available (via polyfills if needed):\n  - `addEventListener`\n  - `querySelector` / `querySelectorAll`\n  - `getBoundingClientRect`\n  - `transform` CSS property\n\n---\n\n## 🛠️ Development \u0026 Testing\n\n### Project Management \u0026 Quality\n\n- **Improvement Plan**: See our [Improvement Plan](Improvement-Plan.md) for a roadmap of planned features and enhancements.\n- **Post-Code-Writing Checklist**: Refer to the [Post-Code-Writing Checklist](Post-Code-Writing-Checklist.md) to ensure code quality and consistency before committing changes.\n\n### Getting Started\n\n```bash\n# Clone and setup\ngit clone https://github.com/zakariaf/svg-toolbelt.git\ncd svg-toolbelt\nnpm install\n\n# Development\nnpm run dev        # Watch mode build (vite build --watch)\nnpm run build      # Production build\n\n# Local development demo\nnpm run demo       # Build and serve demo on http://localhost:8080 (Node.js server)\n# or\nnpm run serve      # Start server only (if already built)\n\n# Development with live reload\nnpm run dev        # Watch mode build (in one terminal)\nnpm run serve      # Start server (in another terminal)\n\n# Testing\nnpm test           # Run tests with vitest (watch mode)\nnpm test -- --run  # Run tests once (no watch mode)\nnpm test -- --coverage  # Run tests with coverage report\n\n# Quality\nnpm run lint       # ESLint check\nnpm run lint:fix   # ESLint with auto-fix\nnpm run type-check # TypeScript type checking\n\n# Bundle analysis\nnpm run size       # Check bundle size against limits (10KB)\nnpm run analyze    # Detailed bundle analysis with size-limit --why\n\n# Release (creates git tags and pushes)\nnpm run release:patch  # 0.2.0 -\u003e 0.2.1\nnpm run release:minor  # 0.2.0 -\u003e 0.3.0\nnpm run release:major  # 0.2.0 -\u003e 1.0.0\n```\n\n### Test Coverage\n\n- **Unit tests**: Individual features and core logic (\u003e98% coverage)\n- **Integration tests**: End-to-end scenarios and real DOM interactions\n- **Accessibility tests**: Keyboard navigation and screen reader compatibility\n- **Performance tests**: Memory leaks and smooth operation under load\n\n---\n\n## 📄 License\n\n**MIT License** - see [LICENSE](LICENSE) file for details.\n\n---\n\n## 🙏 Acknowledgments\n\n- **GitLab Engineering Team** - For the original requirement and use case\n- **Mermaid.js Community** - For inspiring better diagram accessibility\n- **TSDX** - For excellent TypeScript tooling\n- **Open Source Community** - For feedback, testing, and contributions\n\n---\n\n## 🤝 Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for:\n\n- 🐛 **Bug reports** and fixes\n- ✨ **Feature requests** and implementations\n- 📖 **Documentation** improvements\n- 🧪 **Test coverage** enhancements\n- 🎨 **Accessibility** improvements\n\n### Quick Start for Contributors\n\n1. Fork the repository\n2. Create a feature branch: `git checkout -b feature/amazing-feature`\n3. Make your changes with tests: `npm test`\n4. Ensure quality: `npm run lint \u0026\u0026 npm run typecheck`\n5. Submit a pull request\n\n---\n\n**Made with ❤️ for better documentation everywhere**\n\nIf svg-toolbelt helps your project, please consider starring the repository! ⭐\n\n---\n\n### 📞 Support\n\n- 📖 **Documentation**: [Complete API docs and examples](https://zakariaf.github.io/svg-toolbelt)\n- 💬 **Discussions**: [GitHub Discussions](https://github.com/zakariaf/svg-toolbelt/discussions)\n- 🐛 **Bug Reports**: [GitHub Issues](https://github.com/zakariaf/svg-toolbelt/issues)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzakariaf%2Fsvg-toolbelt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzakariaf%2Fsvg-toolbelt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzakariaf%2Fsvg-toolbelt/lists"}