mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-05 15:40:10 +00:00
Most of the features in this pull request are completed and can be
reviewed and merged.
## TODO
- [x] no selection panel
- [x] group selected panel
- [x] tabs
- [x] favorites tab
- [x] global settings tab
- [x] nodes tab
- [x] widget actions menu
- [x] [Bug]: style bugs
- [x] button zoom to the node on canvas.
- [x] rename widgets on widget actions
- [ ] [Bug]: the canvas has not been updated after renaming.
- [x] global settings
- [ ] setting item: "show advanced parameters"
- blocked by other things. skip for now.
- [x] setting item: show toolbox on selection
- [x] setting item: nodes 2.0
- [ ] setting item: "background color"
- blocked by other things. skip for now.
- [x] setting item: grid spacing
- [x] setting item: snap nodes to grid
- [x] setting item: link shape
- [x] setting item: show connected links
- [x] form style reuses the form style of node widgets
- [x] group node cases
- [x] group node settings
- [x] show all nodes in group
- [x] show frame name on nodes when multiple selections are made
- [x] group multiple selections
- [x] [Bug]: nodes without widgets cannot display the location and their
group
- [x] [Bug]: labels layout
- [x] favorites
- [x] the indicator on widgets
- [x] favorite and unfavorite buttons on widgets
- [x] [Bug]: show node name in favorite widgets + improve labels layout
- [ ] [Bug]: After canceling the like, the like list will not be updated
immediately.
- [x] [Bug]: The favorite function does not work for the project on
Subgraph.
- [x] subgraph
- [x] add the node name from where this parameter comes from when node
is subgraph
- [x] show and hide directly on Inputs
- [x] some bugs need to be fixed.
- [x] advanced widgets
- [x] button: show advanced inputs
- Clicking button expands the "Advanced Inputs" section on the right
side panel, regardless of whether the panel is open or not
- [x] [Bug]: style bugs
- [x] advanced inputs section when node is subgraph
- [x] inputs tab rearranging
- [x] favorited inputs rearranging
- [x] subgraph inputs rearranging
- [ ] review and reconstruction to improve complexity and architecture
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7812-feat-right-side-panel-favorites-no-selection-state-and-more-2da6d73d36508134b503d676f9b3d248)
by [Unito](https://www.unito.io)
---------
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: bymyself <cbyrne@comfy.org>
145 lines
4.2 KiB
Vue
145 lines
4.2 KiB
Vue
<script setup lang="ts">
|
|
import { computed, onMounted, ref } from 'vue'
|
|
|
|
// From: https://stackoverflow.com/a/71426342/22392721
|
|
interface Props {
|
|
duration?: number
|
|
easingEnter?: string
|
|
easingLeave?: string
|
|
opacityClosed?: number
|
|
opacityOpened?: number
|
|
disable?: boolean
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
duration: 150,
|
|
easingEnter: 'ease-in-out',
|
|
easingLeave: 'ease-in-out',
|
|
opacityClosed: 0,
|
|
opacityOpened: 1
|
|
})
|
|
|
|
const closed = '0px'
|
|
|
|
const isMounted = ref(false)
|
|
onMounted(() => (isMounted.value = true))
|
|
|
|
const duration = computed(() =>
|
|
isMounted.value && !props.disable ? props.duration : 0
|
|
)
|
|
|
|
interface initialStyle {
|
|
height: string
|
|
width: string
|
|
position: string
|
|
visibility: string
|
|
overflow: string
|
|
paddingTop: string
|
|
paddingBottom: string
|
|
borderTopWidth: string
|
|
borderBottomWidth: string
|
|
marginTop: string
|
|
marginBottom: string
|
|
}
|
|
|
|
function getElementStyle(element: HTMLElement) {
|
|
return {
|
|
height: element.style.height,
|
|
width: element.style.width,
|
|
position: element.style.position,
|
|
visibility: element.style.visibility,
|
|
overflow: element.style.overflow,
|
|
paddingTop: element.style.paddingTop,
|
|
paddingBottom: element.style.paddingBottom,
|
|
borderTopWidth: element.style.borderTopWidth,
|
|
borderBottomWidth: element.style.borderBottomWidth,
|
|
marginTop: element.style.marginTop,
|
|
marginBottom: element.style.marginBottom
|
|
}
|
|
}
|
|
|
|
function prepareElement(element: HTMLElement, initialStyle: initialStyle) {
|
|
const { width } = getComputedStyle(element)
|
|
element.style.width = width
|
|
element.style.position = 'absolute'
|
|
element.style.visibility = 'hidden'
|
|
element.style.height = ''
|
|
const { height } = getComputedStyle(element)
|
|
element.style.width = initialStyle.width
|
|
element.style.position = initialStyle.position
|
|
element.style.visibility = initialStyle.visibility
|
|
element.style.height = closed
|
|
element.style.overflow = 'hidden'
|
|
return initialStyle.height && initialStyle.height !== closed
|
|
? initialStyle.height
|
|
: height
|
|
}
|
|
|
|
function animateTransition(
|
|
element: HTMLElement,
|
|
initialStyle: initialStyle,
|
|
done: () => void,
|
|
keyframes: Keyframe[] | PropertyIndexedKeyframes | null,
|
|
options?: number | KeyframeAnimationOptions
|
|
) {
|
|
const animation = element.animate(keyframes, options)
|
|
// Set height to 'auto' to restore it after animation
|
|
element.style.height = initialStyle.height
|
|
animation.onfinish = () => {
|
|
element.style.overflow = initialStyle.overflow
|
|
done()
|
|
}
|
|
}
|
|
|
|
function getEnterKeyframes(height: string, initialStyle: initialStyle) {
|
|
return [
|
|
{
|
|
height: closed,
|
|
opacity: props.opacityClosed,
|
|
paddingTop: closed,
|
|
paddingBottom: closed,
|
|
borderTopWidth: closed,
|
|
borderBottomWidth: closed,
|
|
marginTop: closed,
|
|
marginBottom: closed
|
|
},
|
|
{
|
|
height,
|
|
opacity: props.opacityOpened,
|
|
paddingTop: initialStyle.paddingTop,
|
|
paddingBottom: initialStyle.paddingBottom,
|
|
borderTopWidth: initialStyle.borderTopWidth,
|
|
borderBottomWidth: initialStyle.borderBottomWidth,
|
|
marginTop: initialStyle.marginTop,
|
|
marginBottom: initialStyle.marginBottom
|
|
}
|
|
]
|
|
}
|
|
|
|
function enterTransition(element: Element, done: () => void) {
|
|
const HTMLElement = element as HTMLElement
|
|
const initialStyle = getElementStyle(HTMLElement)
|
|
const height = prepareElement(HTMLElement, initialStyle)
|
|
const keyframes = getEnterKeyframes(height, initialStyle)
|
|
const options = { duration: duration.value, easing: props.easingEnter }
|
|
animateTransition(HTMLElement, initialStyle, done, keyframes, options)
|
|
}
|
|
|
|
function leaveTransition(element: Element, done: () => void) {
|
|
const HTMLElement = element as HTMLElement
|
|
const initialStyle = getElementStyle(HTMLElement)
|
|
const { height } = getComputedStyle(HTMLElement)
|
|
HTMLElement.style.height = height
|
|
HTMLElement.style.overflow = 'hidden'
|
|
const keyframes = getEnterKeyframes(height, initialStyle).reverse()
|
|
const options = { duration: duration.value, easing: props.easingLeave }
|
|
animateTransition(HTMLElement, initialStyle, done, keyframes, options)
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<Transition :css="false" @enter="enterTransition" @leave="leaveTransition">
|
|
<slot />
|
|
</Transition>
|
|
</template>
|