mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
Add data-capture-wheel attribute to SingleSlider and DualRangeSlider components to prevent wheel events from being intercepted by the canvas in ComfyUI's new Vue DOM render mode. This allows mouse wheel to work for adjusting slider values while still enabling workflow zoom on non-interactive widget areas. Also update event handling to use pointer events with proper stop propagation and pointer capture for reliable drag operations in both rendering modes. Update development guide with Section 8 documenting Vue DOM render mode event handling patterns and best practices.
Vue Widgets for ComfyUI LoRA Manager
This directory contains the source code for Vue 3 + PrimeVue custom widgets for ComfyUI LoRA Manager.
Structure
vue-widgets/
├── src/ # TypeScript/Vue source code
│ ├── main.ts # Main entry point that registers extensions
│ └── components/ # Vue components
│ └── DemoWidget.vue # Example demo widget
├── package.json # Dependencies and build scripts
├── vite.config.mts # Vite build configuration
├── tsconfig.json # TypeScript configuration
└── README.md # This file
Development
Install Dependencies
cd vue-widgets
npm install
Build for Production
npm run build
This compiles the TypeScript/Vue code and outputs to ../web/comfyui/vue-widgets/.
Development Mode (Watch)
npm run dev
This builds the widgets in watch mode, automatically rebuilding when files change.
Type Checking
npm run typecheck
Creating a New Widget
1. Create the Python Node
Create a new node file in /py/nodes/your_node.py:
class YourCustomNode:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"your_widget_name": ("YOUR_WIDGET_TYPE", {}),
}
}
RETURN_TYPES = ("STRING",)
FUNCTION = "process"
CATEGORY = "loramanager"
def process(self, your_widget_name):
# Process widget data
return (str(your_widget_name),)
NODE_CLASS_MAPPINGS = {
"YourCustomNode": YourCustomNode
}
2. Create the Vue Component
Create a new component in src/components/YourWidget.vue:
<template>
<div class="your-widget-container">
<!-- Your UI here using PrimeVue components -->
<Button label="Click me" @click="handleClick" />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import Button from 'primevue/button'
const props = defineProps<{
widget: { serializeValue?: (node: unknown, index: number) => Promise<unknown> }
node: { id: number }
}>()
onMounted(() => {
// Serialize widget data when workflow is saved
props.widget.serializeValue = async () => {
return { /* your data */ }
}
})
</script>
<style scoped>
/* Your styles */
</style>
3. Register the Widget
In src/main.ts, add your widget registration:
import YourWidget from '@/components/YourWidget.vue'
// In getCustomWidgets()
YOUR_WIDGET_TYPE(node) {
return createVueWidget(node, YourWidget, 'your-widget-name')
}
// In nodeCreated()
if (node.constructor?.comfyClass !== 'YourCustomNode') return
4. Register the Node
Add your node to __init__.py:
from .py.nodes.your_node import YourCustomNode
NODE_CLASS_MAPPINGS = {
# ...
"YourCustomNode": YourCustomNode
}
5. Build and Test
npm run build
Then restart ComfyUI and test your new widget!
Available PrimeVue Components
This project uses PrimeVue 4.x. Popular components include:
Button- Buttons with icons and variantsInputText- Text input fieldsInputNumber- Number input with increment/decrementDropdown- Select dropdownsCard- Card containersDataTable- Data tables with sorting/filteringDialog- Modal dialogsTree- Tree view components- And many more! See PrimeVue Docs
Notes
- Build output goes to
../web/comfyui/vue-widgets/(gitignored) - The widget type name in Python (e.g., "YOUR_WIDGET_TYPE") must match the key in
getCustomWidgets() - Widget data is serialized when the workflow is saved/executed via
serializeValue() - ComfyUI's app.js is marked as external and not bundled