mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-07 22:20:03 +00:00
## Summary Enable `better-tailwindcss/enforce-consistent-class-order` lint rule and auto-fix all 1027 violations across 263 files. Stacked on #9427. ## Changes - **What**: Sort Tailwind classes into consistent order via `eslint --fix` - Enable `enforce-consistent-class-order` as `'error'` in eslint config - Purely cosmetic reordering — no behavioral or visual changes ## Review Focus Mechanical auto-fix PR — all changes are class reordering only. This is the largest diff but lowest risk since it changes no class names, only their order. **Stack:** #9417 → #9427 → **this PR** Fixes #9300 (partial — 3 of 3 rules) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9428-fix-enable-enforce-consistent-class-order-tailwind-lint-rule-31a6d73d3650811c9065f5178ba3e724) by [Unito](https://www.unito.io)
232 lines
5.9 KiB
Vue
232 lines
5.9 KiB
Vue
<template>
|
|
<div
|
|
ref="containerRef"
|
|
class="maskEditor-dialog-root flex size-full flex-col"
|
|
@contextmenu.prevent
|
|
@dragstart="handleDragStart"
|
|
@keydown.stop
|
|
>
|
|
<div
|
|
id="maskEditorCanvasContainer"
|
|
ref="canvasContainerRef"
|
|
@contextmenu.prevent
|
|
>
|
|
<canvas
|
|
ref="imgCanvasRef"
|
|
class="absolute top-0 left-0 z-0 size-full"
|
|
@contextmenu.prevent
|
|
/>
|
|
<canvas
|
|
ref="rgbCanvasRef"
|
|
class="absolute top-0 left-0 z-10 size-full"
|
|
@contextmenu.prevent
|
|
/>
|
|
<canvas
|
|
ref="maskCanvasRef"
|
|
class="absolute top-0 left-0 z-30 size-full"
|
|
@contextmenu.prevent
|
|
/>
|
|
<!-- GPU Preview Canvas -->
|
|
<canvas
|
|
ref="gpuCanvasRef"
|
|
class="pointer-events-none absolute top-0 left-0 size-full"
|
|
:class="{
|
|
'z-20': store.activeLayer === 'rgb',
|
|
'z-40': store.activeLayer === 'mask'
|
|
}"
|
|
/>
|
|
<div ref="canvasBackgroundRef" class="size-full bg-white" />
|
|
</div>
|
|
|
|
<div class="maskEditor-ui-container flex min-h-0 flex-1 flex-col">
|
|
<div class="flex min-h-0 flex-1 overflow-hidden">
|
|
<ToolPanel
|
|
v-if="initialized"
|
|
ref="toolPanelRef"
|
|
:tool-manager="toolManager!"
|
|
/>
|
|
|
|
<PointerZone
|
|
v-if="initialized"
|
|
:tool-manager="toolManager!"
|
|
:pan-zoom="panZoom!"
|
|
/>
|
|
|
|
<SidePanel
|
|
v-if="initialized"
|
|
ref="sidePanelRef"
|
|
:tool-manager="toolManager!"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<BrushCursor v-if="initialized" :container-ref="containerRef" />
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
|
|
|
import { useImageLoader } from '@/composables/maskeditor/useImageLoader'
|
|
import { useKeyboard } from '@/composables/maskeditor/useKeyboard'
|
|
import { useMaskEditorLoader } from '@/composables/maskeditor/useMaskEditorLoader'
|
|
import { usePanAndZoom } from '@/composables/maskeditor/usePanAndZoom'
|
|
import { useToolManager } from '@/composables/maskeditor/useToolManager'
|
|
import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
|
|
import { useDialogStore } from '@/stores/dialogStore'
|
|
import { useMaskEditorDataStore } from '@/stores/maskEditorDataStore'
|
|
import { useMaskEditorStore } from '@/stores/maskEditorStore'
|
|
|
|
import BrushCursor from './BrushCursor.vue'
|
|
import PointerZone from './PointerZone.vue'
|
|
import SidePanel from './SidePanel.vue'
|
|
import ToolPanel from './ToolPanel.vue'
|
|
|
|
const { node } = defineProps<{
|
|
node: LGraphNode
|
|
}>()
|
|
|
|
const store = useMaskEditorStore()
|
|
const dataStore = useMaskEditorDataStore()
|
|
const dialogStore = useDialogStore()
|
|
|
|
const loader = useMaskEditorLoader()
|
|
|
|
const containerRef = ref<HTMLElement>()
|
|
const canvasContainerRef = ref<HTMLDivElement>()
|
|
const imgCanvasRef = ref<HTMLCanvasElement>()
|
|
const maskCanvasRef = ref<HTMLCanvasElement>()
|
|
const rgbCanvasRef = ref<HTMLCanvasElement>()
|
|
const gpuCanvasRef = ref<HTMLCanvasElement>()
|
|
const canvasBackgroundRef = ref<HTMLDivElement>()
|
|
|
|
const toolPanelRef = ref<InstanceType<typeof ToolPanel>>()
|
|
const sidePanelRef = ref<InstanceType<typeof SidePanel>>()
|
|
|
|
const initialized = ref(false)
|
|
|
|
const keyboard = useKeyboard()
|
|
const panZoom = usePanAndZoom()
|
|
|
|
const toolManager = useToolManager(keyboard, panZoom)
|
|
|
|
let resizeObserver: ResizeObserver | null = null
|
|
|
|
const handleDragStart = (event: DragEvent) => {
|
|
if (event.ctrlKey) {
|
|
event.preventDefault()
|
|
}
|
|
}
|
|
|
|
const initUI = async () => {
|
|
if (!containerRef.value) {
|
|
console.error(
|
|
'[MaskEditorContent] Cannot initialize - missing required refs'
|
|
)
|
|
return
|
|
}
|
|
|
|
if (
|
|
!imgCanvasRef.value ||
|
|
!maskCanvasRef.value ||
|
|
!rgbCanvasRef.value ||
|
|
!canvasContainerRef.value ||
|
|
!canvasBackgroundRef.value
|
|
) {
|
|
console.error('[MaskEditorContent] Cannot initialize - missing canvas refs')
|
|
return
|
|
}
|
|
|
|
store.maskCanvas = maskCanvasRef.value
|
|
store.rgbCanvas = rgbCanvasRef.value
|
|
store.imgCanvas = imgCanvasRef.value
|
|
store.canvasContainer = canvasContainerRef.value
|
|
store.canvasBackground = canvasBackgroundRef.value
|
|
|
|
try {
|
|
await loader.loadFromNode(node)
|
|
|
|
const imageLoader = useImageLoader()
|
|
const image = await imageLoader.loadImages()
|
|
|
|
await panZoom.initializeCanvasPanZoom(
|
|
image,
|
|
containerRef.value,
|
|
toolPanelRef.value?.$el as HTMLElement | undefined,
|
|
sidePanelRef.value?.$el as HTMLElement | undefined
|
|
)
|
|
|
|
store.canvasHistory.saveInitialState()
|
|
|
|
// Initialize GPU resources
|
|
if (toolManager.brushDrawing) {
|
|
await toolManager.brushDrawing.initGPUResources()
|
|
if (gpuCanvasRef.value && toolManager.brushDrawing.initPreviewCanvas) {
|
|
// Match preview canvas resolution to mask canvas
|
|
gpuCanvasRef.value.width = maskCanvasRef.value.width
|
|
gpuCanvasRef.value.height = maskCanvasRef.value.height
|
|
|
|
toolManager.brushDrawing.initPreviewCanvas(gpuCanvasRef.value)
|
|
}
|
|
}
|
|
|
|
initialized.value = true
|
|
} catch (error) {
|
|
console.error('[MaskEditorContent] Initialization failed:', error)
|
|
dialogStore.closeDialog()
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
keyboard.addListeners()
|
|
|
|
if (containerRef.value) {
|
|
resizeObserver = new ResizeObserver(async () => {
|
|
if (panZoom) {
|
|
await panZoom.invalidatePanZoom()
|
|
}
|
|
})
|
|
resizeObserver.observe(containerRef.value)
|
|
}
|
|
|
|
void initUI()
|
|
})
|
|
|
|
onBeforeUnmount(() => {
|
|
toolManager.brushDrawing.saveBrushSettings()
|
|
|
|
keyboard?.removeListeners()
|
|
|
|
if (resizeObserver) {
|
|
resizeObserver.disconnect()
|
|
resizeObserver = null
|
|
}
|
|
|
|
store.canvasHistory.clearStates()
|
|
|
|
store.resetState()
|
|
dataStore.reset()
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.maskEditor-dialog-root {
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.maskEditor-ui-container {
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
:deep(#maskEditorCanvasContainer) {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
z-index: 0;
|
|
}
|
|
</style>
|