Skip to content

feat : support exporting diagrams to PNG , JPG , SVG and PDF (#97) - #106

Merged
DataDave-Dev merged 3 commits into
DataDave-Dev:mainfrom
YasserYG8:feat/diagram-export
Jun 18, 2026
Merged

feat : support exporting diagrams to PNG , JPG , SVG and PDF (#97)#106
DataDave-Dev merged 3 commits into
DataDave-Dev:mainfrom
YasserYG8:feat/diagram-export

Conversation

@YasserYG8

@YasserYG8 YasserYG8 commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Pull Request: Diagram Export to PNG, JPEG, SVG, and PDF

Description

This PR implements Issue #97 ("Export diagrams to multiple formats (PNG, JPG, PDF, SVG)").

It adds export capabilities to the React Flow interactive diagram container, allowing users to download their generated graphs in multiple formats. The export utility captures the entire graph structure (including nodes scrolled off-screen) at full 100% resolution, dynamically adjusting boundaries and respecting the active dark or light theme background.


Key Changes

1. Context Provider Setup (src/components/ui/Diagram.tsx)

  • Wrapped the interactive canvas within a <ReactFlowProvider> context.
  • Renamed the core component to DiagramFlow to utilize the useReactFlow() hook internally for node coordinates and bounding calculations, and exported a clean wrapper component Diagram as the default export.

2. Layout & Styling Calculations

  • Used getNodesBounds to find the exact rectangular area enclosing all active graph nodes.
  • Passed offset transforms to html-to-image during capture:
    transform: `translate(${-bounds.x + padding}px, ${-bounds.y + padding}px) scale(1)`
  • This captures the entire diagram at native scale without causing screen flickering, panning offsets, or layout cuts on the client's screen.

3. Theme Alignment & Format Options

  • PNG (Opaque) & JPEG: Background color automatically adjusts to match the active theme background (#0b0d12 in dark mode, #ffffff in light mode).
  • PNG (Transparent) & SVG: Exported with transparent canvases.
  • PDF Document: Dynamically loads jspdf on request, generating a document matching the aspect ratio and boundary dimensions of the diagram, embedding the opaque PNG cleanly.

4. UI Dropdown Panel

  • Added an Export selector menu (🌐 Export ▼) inside the existing diagram legend <Panel> container.
  • Includes smooth hover styles matching the dark/light glassmorphic styling system.

Verification & Testing Results

  • Unit Tests: pnpm test passed successfully (all 46/46 tests green).
  • TypeScript Compiler: pnpm typecheck completed with 0 errors.
  • Linter: pnpm lint completed with 0 formatting warnings.
  • Production Build: pnpm build completed with zero compilation or static generation issues.

Summary by CodeRabbit

  • New Features

    • Added diagram export for the currently visible viewport region as PNG (opaque/transparent), JPEG, SVG, and PDF.
    • Added an export selector/control to the diagram toolbar to choose format and trigger download.
  • Refactor / UI

    • Improved diagram rendering via an updated React Flow setup and reworked toolbar layout, including clearer separation for existing controls.
  • Chores

    • Updated project configuration, workspace build settings, and development file-ignores to support export workflows.

@ecc-tools

ecc-tools Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR.

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6433ec5e-0a5f-4250-8c1b-a9041c636d97

📥 Commits

Reviewing files that changed from the base of the PR and between 0de4071 and 9f0620e.

📒 Files selected for processing (1)
  • pnpm-workspace.yaml
💤 Files with no reviewable changes (1)
  • pnpm-workspace.yaml

📝 Walkthrough

Walkthrough

Adds multi-format diagram export (PNG, JPEG, SVG, PDF) to the Diagram component. The component is refactored to use ReactFlowProvider, delegating rendering to a new internal DiagramFlow component. An export dropdown is added to the toolbar. Dependencies html-to-image and jspdf are introduced. .gitignore swaps a stale entry for Claude-specific patterns.

Changes

Diagram Export Feature

Layer / File(s) Summary
New export dependencies and workspace config
package.json, pnpm-workspace.yaml
Adds html-to-image and jspdf to production dependencies; adds core-js entry to pnpm-workspace.yaml allowBuilds.
DiagramFlow component and ReactFlowProvider refactor
src/components/ui/Diagram.tsx
Updates React Flow imports to include ReactFlowProvider, useReactFlow, and getNodesBounds; extracts internal DiagramFlow component with exportOpen state; adjusts panel styling; exported Diagram now wraps DiagramFlow in ReactFlowProvider with export dropdown UI for PNG/JPEG/SVG/PDF.
handleExport: bounds computation and file download
src/components/ui/Diagram.tsx
Implements async handleExport that reads current nodes, computes bounds via getNodesBounds, locates the viewport DOM element, derives background color from theme, and triggers download via html-to-image or dynamically imported jspdf for PDF output.

Gitignore Cleanup

Layer / File(s) Summary
Swap stale ignore entry for Claude patterns
.gitignore
Removes proposal_issue_74.md ignore entry and adds .claude/ and CLAUDE.local.md patterns.

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant ExportDropdown
  participant handleExport
  participant ReactFlow
  participant htmlToImage
  participant jsPDF

  User->>ExportDropdown: selects format & clicks Export
  ExportDropdown->>handleExport: handleExport(format)
  handleExport->>ReactFlow: getNodes()
  ReactFlow-->>handleExport: nodes[]
  handleExport->>ReactFlow: getNodesBounds(nodes)
  ReactFlow-->>handleExport: bounds {x, y, width, height}
  handleExport->>handleExport: locate .react-flow__viewport DOM, derive bgColor
  alt format = PNG / JPEG / SVG
    handleExport->>htmlToImage: toPng/toJpeg/toSvg(viewport, options)
    htmlToImage-->>handleExport: dataUrl
    handleExport->>User: trigger anchor download
  else format = PDF
    handleExport->>htmlToImage: toPng(viewport, options)
    htmlToImage-->>handleExport: dataUrl
    handleExport->>jsPDF: new jsPDF(), addImage(dataUrl), save()
    jsPDF-->>User: PDF download
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Poem

🐇 A hop, a click, a diagram saved,
PNG or PDF — the viewport engraved!
getNodesBounds measures the scene,
html-to-image keeps the pixels clean.
The rabbit exports with a joyful leap,
Your weftmap charts are yours to keep! 🗺️

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The pull request description is comprehensive and well-structured, covering the implementation details, key changes, and verification results. However, it does not follow the repository's required template format (sections for 'Qué hace', 'Tipo', and 'Checklist'). Restructure the description to match the repository template: add 'Qué hace' section, select 'feat' type, and include the verification checklist items (pnpm lint, typecheck, test, build results).
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title clearly and concisely describes the main feature being added: export functionality for diagrams in multiple formats (PNG, JPG, SVG, PDF), directly matching the primary change in the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/components/ui/Diagram.tsx (2)

508-510: 💤 Low value

Consider providing user feedback on export failure.

Currently, export errors are only logged to console.error. Users won't know if their export failed. Consider showing a toast notification or alert.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/ui/Diagram.tsx` around lines 508 - 510, The catch block
handling export failures only logs to console without providing user feedback.
In the catch handler for the export function where "Failed to export diagram:"
is logged, add a user-facing notification mechanism such as a toast notification
or alert to inform users when the export operation fails, in addition to the
existing console error logging.

597-636: ⚖️ Poor tradeoff

Dropdown lacks keyboard navigation and focus management.

The dropdown doesn't support Escape to close or arrow key navigation between options. Focus also doesn't automatically move into the dropdown when opened. Consider adding an onKeyDown handler for Escape and managing focus for improved accessibility.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/ui/Diagram.tsx` around lines 597 - 636, The export dropdown
menu controlled by the exportOpen state lacks keyboard accessibility features.
Add an onKeyDown handler to the dropdown container div that handles the Escape
key to close the menu by calling setExportOpen(false), and implement arrow key
navigation (ArrowUp/ArrowDown) to cycle focus between the five export option
buttons (PNG Image Opaque, PNG Image Transparent, JPEG Image, SVG Vector File,
and PDF Document). Additionally, use a useRef hook to reference the dropdown
container and useEffect to automatically focus the first button when exportOpen
becomes true, ensuring proper focus management when the dropdown is opened.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pnpm-workspace.yaml`:
- Line 2: The `core-js` configuration value in pnpm-workspace.yaml is set to a
string literal instead of a boolean. Replace the string value "set this to true
or false" with an actual boolean value: use `true` if core-js build scripts are
needed for polyfill compilation, or `false` if they are not required. This will
ensure the allowBuilds directive receives the expected boolean type and allows
pnpm install to function correctly.

---

Nitpick comments:
In `@src/components/ui/Diagram.tsx`:
- Around line 508-510: The catch block handling export failures only logs to
console without providing user feedback. In the catch handler for the export
function where "Failed to export diagram:" is logged, add a user-facing
notification mechanism such as a toast notification or alert to inform users
when the export operation fails, in addition to the existing console error
logging.
- Around line 597-636: The export dropdown menu controlled by the exportOpen
state lacks keyboard accessibility features. Add an onKeyDown handler to the
dropdown container div that handles the Escape key to close the menu by calling
setExportOpen(false), and implement arrow key navigation (ArrowUp/ArrowDown) to
cycle focus between the five export option buttons (PNG Image Opaque, PNG Image
Transparent, JPEG Image, SVG Vector File, and PDF Document). Additionally, use a
useRef hook to reference the dropdown container and useEffect to automatically
focus the first button when exportOpen becomes true, ensuring proper focus
management when the dropdown is opened.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ce39d1c0-5329-45ad-93e5-2cec142505d6

📥 Commits

Reviewing files that changed from the base of the PR and between 52af067 and e4caf04.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (4)
  • .gitignore
  • package.json
  • pnpm-workspace.yaml
  • src/components/ui/Diagram.tsx
💤 Files with no reviewable changes (1)
  • .gitignore

Comment thread pnpm-workspace.yaml Outdated
The allowBuilds directive expects true or false, but the current value is a literal string "set this to true or false". This will either fail or produce undefined behavior during pnpm install.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@ecc-tools

ecc-tools Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pnpm-workspace.yaml`:
- Around line 1-7: The pnpm-workspace.yaml file contains a duplicate allowBuilds
key declaration which creates invalid YAML structure. Remove the first
allowBuilds key and all duplicate entries within the block, keeping only a
single allowBuilds declaration with one instance each of the three configuration
entries: core-js, sharp, and unrs-resolver. Ensure the final structure has
allowBuilds declared once at the top level with all three nested entries
appearing exactly once with their false values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 836a998e-8ef9-4704-a638-6898bf409e19

📥 Commits

Reviewing files that changed from the base of the PR and between e4caf04 and 0de4071.

📒 Files selected for processing (1)
  • pnpm-workspace.yaml

Comment thread pnpm-workspace.yaml Outdated
Comment on lines 1 to 7
allowBuilds:
allowBuilds:
core-js: false
sharp: false
unrs-resolver: false
sharp: false
unrs-resolver: false

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical: Duplicate allowBuilds key breaks YAML structure.

Lines 1–7 declare the allowBuilds key twice, creating an invalid YAML structure. YAML parsers will fail or behave unpredictably. The old allowBuilds block (lines 1, 6–7) must be removed entirely, leaving a single block with all three entries.

The PR objectives claim the string literal issue was fixed, and line 3 correctly shows core-js: false, but the file structure is broken.

🔧 Proposed fix: Consolidate into a single `allowBuilds` block
 allowBuilds:
-allowBuilds:
   core-js: false
   sharp: false
   unrs-resolver: false
-  sharp: false
-  unrs-resolver: false
🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 2-2: duplication of key "allowBuilds" in mapping

(key-duplicates)


[error] 6-6: duplication of key "sharp" in mapping

(key-duplicates)


[error] 7-7: duplication of key "unrs-resolver" in mapping

(key-duplicates)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pnpm-workspace.yaml` around lines 1 - 7, The pnpm-workspace.yaml file
contains a duplicate allowBuilds key declaration which creates invalid YAML
structure. Remove the first allowBuilds key and all duplicate entries within the
block, keeping only a single allowBuilds declaration with one instance each of
the three configuration entries: core-js, sharp, and unrs-resolver. Ensure the
final structure has allowBuilds declared once at the top level with all three
nested entries appearing exactly once with their false values.

@ecc-tools

ecc-tools Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR.

@DataDave-Dev
DataDave-Dev merged commit 01f6500 into DataDave-Dev:main Jun 18, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants