Skip to content

Make FlowfileEditor embeddable as a Vue component library#338

Open
Edwardvaneechoud wants to merge 7 commits intomainfrom
claude/embeddable-flowfile-wasm-qFQI1
Open

Make FlowfileEditor embeddable as a Vue component library#338
Edwardvaneechoud wants to merge 7 commits intomainfrom
claude/embeddable-flowfile-wasm-qFQI1

Conversation

@Edwardvaneechoud
Copy link
Owner

Summary

This PR transforms the FlowfileEditor from a standalone application into an embeddable Vue component library that can be integrated into other Vue 3 applications. The editor can now be published to npm and used as a reusable component with a clean public API.

Key Changes

New Public API & Component Export

  • Added FlowfileEditor.vue as the main embeddable component with comprehensive props for configuration
  • Created lib/index.ts as the library entry point exporting the component, plugin, and all public types
  • Implemented FlowfileEditorPlugin for easy registration via app.use()
  • Defined complete TypeScript interfaces for all public APIs (FlowfileEditorProps, FlowfileEditorAPI, etc.)

Library Build Configuration

  • Updated vite.config.ts to support dual build modes: app (dev/preview) and library (npm package)
  • Configured library build to output ES module format with proper entry points
  • Updated package.json with library metadata (main, module, types, exports, files)
  • Renamed package from flowfile-wasm to flowfile-editor for clarity

Styling & Theme System

  • Added comprehensive editor.css (1367 lines) with design token system aligned with flowfile_frontend
  • Implemented CSS custom properties for colors, typography, spacing, shadows, and animations
  • Added dark theme support via data-theme="dark" attribute
  • Scoped all styles under .flowfile-editor-root for isolation in embedded contexts
  • Customized AG Grid and Vue Flow component themes to match design system

Embedded Mode Features

  • Enhanced theme-store.ts with embedded flag to prevent global document theme changes
  • Added setEmbedded() method to isolate theme application to component scope only
  • Implemented input data injection via injectInputData() for programmatic data loading
  • Added output callbacks in flow-store.ts for capturing execution results
  • Exposed programmatic API via defineExpose() for template ref access

Toolbar & UI Customization

  • Made toolbar buttons conditionally visible via effectiveToolbar config
  • Replaced Material Icons with inline SVGs for better library portability
  • Updated Canvas.vue to respect toolbar configuration (showRun, showSaveLoad, showClear, showCodeGen, showDemo)
  • Updated PreviewSettings.vue and DemoButton.vue to use inline SVGs

Icon Management

  • Created utils/iconUrls.ts to explicitly import all node icons as base64 data URIs
  • Ensures icons work correctly in library builds without import.meta.url issues

Props & Configuration

  • FlowfileEditorProps supports: initialFlow, inputData, pyodide config, theme, toolbar, nodeCategories, readonly, height, width
  • PyodideConfig allows custom CDN URLs and auto-initialization control
  • ToolbarConfig provides granular control over visible toolbar buttons
  • InputDataMap enables programmatic data injection matched by node_reference

Notable Implementation Details

  • Component emits events for ready, flow-change, execution-complete, output, error, and loading-status
  • Exposed API includes: isReady, isExecuting, executeFlow, executeNode, exportFlow, importFlow, setInputData, getNodeResult, clearFlow, initializePyodide
  • Theme system respects system preference while allowing explicit override
  • Loading overlay shown during Pyodide initialization (can be disabled)
  • All styles use CSS custom properties for easy theming and dark mode support

Add library build mode so flowfile_wasm can be used as a drop-in
`<FlowfileEditor>` component in any Vue 3 app, similar to VueFlow.

New files:
- src/lib/types.ts: Public API types (props, events, exposed methods)
- src/lib/FlowfileEditor.vue: Main wrapper component with prop/event bridge
- src/lib/plugin.ts: Vue plugin installer (auto-installs Pinia if needed)
- src/lib/index.ts: Library entry point exporting component and types
- src/styles/editor.css: Scoped CSS (vars under .flowfile-editor-root)
- src/utils/iconUrls.ts: Explicit icon imports for library build

Modified files:
- Canvas.vue: Accept toolbar/node config props, emit execution events,
  replace Material Icons with inline SVGs, use iconUrls utility
- DemoButton.vue, PreviewSettings.vue: Replace Material Icons with SVGs
- flow-store.ts: Add output callback mechanism for embeddable mode
- theme-store.ts: Support scoped theming (embedded mode skips global DOM)
- vite.config.ts: Dual build (app + library via BUILD_MODE=lib env var)
- package.json: Add exports, peerDependencies, build:lib script

All 192 existing tests pass. Both app and library builds succeed.

https://claude.ai/code/session_01SztvepLRjChvuh634qxFnu
@netlify
Copy link

netlify bot commented Feb 13, 2026

Deploy Preview for flowfile-wasm ready!

Name Link
🔨 Latest commit 21d75ff
🔍 Latest deploy log https://app.netlify.com/projects/flowfile-wasm/deploys/698f3d3457492d0008561215
😎 Deploy Preview https://deploy-preview-338--flowfile-wasm.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Instead of requiring indirect node_reference matching, this adds a proper
"External Data" node type that users drag onto the canvas and select a
dataset from a dropdown. The host application provides datasets via the
inputData prop, and they appear as selectable options in the node settings.

On export, only the dataset name and schema snapshot are saved (not the
actual data), so flows remain lightweight and the host re-provides data
on re-import.

https://claude.ai/code/session_01SztvepLRjChvuh634qxFnu
The right-click context menu was teleported to <body>, which placed it
outside the .flowfile-editor-root container. In embedded mode, CSS
variables are scoped to .flowfile-editor-root (not :root), so the
teleported menu lost access to --bg-secondary and --border-color,
rendering it transparent. Removing the Teleport keeps the menu in the
DOM tree where CSS variables are inherited. The position:fixed style
still positions it relative to the viewport.

Also added external_data icon mapping to FlowNode's iconMap.

https://claude.ai/code/session_01SztvepLRjChvuh634qxFnu
VueFlow renders nodes inside a transformed container, which breaks
position:fixed — making the context menu appear at the wrong coordinates.
Instead of teleporting to <body> (loses CSS vars) or rendering inline
(breaks positioning), teleport to a dedicated container div inside
Canvas.vue. This sits inside the CSS variable scope but outside VueFlow's
transform layer, fixing both the styling and positioning.

https://claude.ai/code/session_01SztvepLRjChvuh634qxFnu
- external_data code gen: generates pl.scan_csv("dataset.csv") placeholder
  with a comment telling the user to replace the path
- external_output node: full stack implementation (types, settings UI,
  execute handler, code gen). On execution, collects the input DataFrame
  and sends it to the host via output callbacks. Code gen produces
  df.collect() to materialize the result.
- New SVG icons for both external_data (blue database + inbound arrow)
  and external_output (green document + outbound arrow), replacing the
  old external_source.png

https://claude.ai/code/session_01SztvepLRjChvuh634qxFnu
Interactive example page at /embed-example that shows:
- Two editable input datasets (orders + customers) as CSV text areas
- Dataset names are editable and map to External Data node dropdown
- An "Add Dataset" button for adding more inputs on the fly
- Output results panel that shows data from External Output nodes
- The full FlowfileEditor embedded in the right panel

This serves as both a test page and reference implementation for
consumers building their own integration.

https://claude.ai/code/session_01SztvepLRjChvuh634qxFnu
DraggablePanel used position: fixed, so panels were positioned relative
to the viewport. When the editor is embedded in part of a page, panels
would overflow into the host page's other areas.

Changed to position: absolute so panels are positioned relative to
.canvas-container (which has position: relative + overflow: hidden).
All window.innerWidth/Height references now use getContainerRect()
to measure the actual container. Added ResizeObserver to track
container size changes in addition to window resize events.

Panel dragging is also now clamped to container boundaries.

https://claude.ai/code/session_01SztvepLRjChvuh634qxFnu
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