mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-09 23:20:04 +00:00
refactor: replace withDefaults with Vue 3.5 props destructuring (#9150)
## Summary - Replace all `withDefaults(defineProps<...>())` with Vue 3.5 reactive props destructuring across 14 components - Update `props.xxx` references to use destructured variables directly in script and template - Fixes #2334 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9150-refactor-replace-withDefaults-with-Vue-3-5-props-destructuring-3116d73d365081e7a721db3369600671) by [Unito](https://www.unito.io)
This commit is contained in:
committed by
GitHub
parent
be70f6c1e6
commit
724827d8cc
@@ -78,9 +78,7 @@ interface Props {
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
isActive: false
|
||||
})
|
||||
const { item, isActive = false } = defineProps<Props>()
|
||||
|
||||
const nodeDefStore = useNodeDefStore()
|
||||
const hasMissingNodes = computed(() =>
|
||||
@@ -103,7 +101,7 @@ const rename = async (
|
||||
) => {
|
||||
if (newName && newName !== initialName) {
|
||||
// Synchronize the node titles with the new name
|
||||
props.item.updateTitle?.(newName)
|
||||
item.updateTitle?.(newName)
|
||||
|
||||
if (workflowStore.activeSubgraph) {
|
||||
workflowStore.activeSubgraph.name = newName
|
||||
@@ -127,13 +125,13 @@ const rename = async (
|
||||
}
|
||||
}
|
||||
|
||||
const isRoot = props.item.key === 'root'
|
||||
const isRoot = item.key === 'root'
|
||||
|
||||
const tooltipText = computed(() => {
|
||||
if (hasMissingNodes.value && isRoot) {
|
||||
return t('breadcrumbsMenu.missingNodesWarning')
|
||||
}
|
||||
return props.item.label
|
||||
return item.label
|
||||
})
|
||||
|
||||
const startRename = async () => {
|
||||
@@ -145,7 +143,7 @@ const startRename = async () => {
|
||||
}
|
||||
|
||||
isEditing.value = true
|
||||
itemLabel.value = props.item.label as string
|
||||
itemLabel.value = item.label as string
|
||||
void nextTick(() => {
|
||||
if (itemInputRef.value?.$el) {
|
||||
itemInputRef.value.$el.focus()
|
||||
@@ -165,12 +163,12 @@ const handleClick = (event: MouseEvent) => {
|
||||
}
|
||||
|
||||
if (event.detail === 1) {
|
||||
if (props.isActive) {
|
||||
if (isActive) {
|
||||
menu.value?.toggle(event)
|
||||
} else {
|
||||
props.item.command?.({ item: props.item, originalEvent: event })
|
||||
item.command?.({ item: item, originalEvent: event })
|
||||
}
|
||||
} else if (props.isActive && event.detail === 2) {
|
||||
} else if (isActive && event.detail === 2) {
|
||||
menu.value?.hide()
|
||||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
@@ -180,7 +178,7 @@ const handleClick = (event: MouseEvent) => {
|
||||
|
||||
const inputBlur = async (doRename: boolean) => {
|
||||
if (doRename) {
|
||||
await rename(itemLabel.value, props.item.label as string)
|
||||
await rename(itemLabel.value, item.label as string)
|
||||
}
|
||||
|
||||
isEditing.value = false
|
||||
|
||||
@@ -24,9 +24,7 @@ interface Props {
|
||||
modelValue: number
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
step: 1
|
||||
})
|
||||
const { label, min, max, step = 1, modelValue } = defineProps<Props>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: number]
|
||||
|
||||
@@ -75,15 +75,10 @@ import { useSidebarTabStore } from '@/stores/workspace/sidebarTabStore'
|
||||
|
||||
type OverlayState = 'hidden' | 'active' | 'expanded'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
expanded?: boolean
|
||||
menuHovered?: boolean
|
||||
}>(),
|
||||
{
|
||||
menuHovered: false
|
||||
}
|
||||
)
|
||||
const { expanded, menuHovered = false } = defineProps<{
|
||||
expanded?: boolean
|
||||
menuHovered?: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:expanded', value: boolean): void
|
||||
@@ -106,13 +101,12 @@ const {
|
||||
currentNodeProgressStyle
|
||||
} = useQueueProgress()
|
||||
const isHovered = ref(false)
|
||||
const isOverlayHovered = computed(() => isHovered.value || props.menuHovered)
|
||||
const isOverlayHovered = computed(() => isHovered.value || menuHovered)
|
||||
const internalExpanded = ref(false)
|
||||
const isExpanded = computed({
|
||||
get: () =>
|
||||
props.expanded === undefined ? internalExpanded.value : props.expanded,
|
||||
get: () => (expanded === undefined ? internalExpanded.value : expanded),
|
||||
set: (value) => {
|
||||
if (props.expanded === undefined) {
|
||||
if (expanded === undefined) {
|
||||
internalExpanded.value = value
|
||||
}
|
||||
emit('update:expanded', value)
|
||||
|
||||
@@ -17,10 +17,7 @@
|
||||
@mouseenter="onPopoverEnter"
|
||||
@mouseleave="onPopoverLeave"
|
||||
>
|
||||
<JobDetailsPopover
|
||||
:job-id="props.jobId"
|
||||
:workflow-id="props.workflowId"
|
||||
/>
|
||||
<JobDetailsPopover :job-id="jobId" :workflow-id="workflowId" />
|
||||
</div>
|
||||
</Teleport>
|
||||
<Teleport to="body">
|
||||
@@ -36,7 +33,7 @@
|
||||
>
|
||||
<QueueAssetPreview
|
||||
:image-url="iconImageUrl!"
|
||||
:name="props.title"
|
||||
:name="title"
|
||||
:time-label="rightText || undefined"
|
||||
@image-click="emit('view')"
|
||||
/>
|
||||
@@ -49,23 +46,20 @@
|
||||
>
|
||||
<div
|
||||
v-if="
|
||||
props.state === 'running' &&
|
||||
hasAnyProgressPercent(
|
||||
props.progressTotalPercent,
|
||||
props.progressCurrentPercent
|
||||
)
|
||||
state === 'running' &&
|
||||
hasAnyProgressPercent(progressTotalPercent, progressCurrentPercent)
|
||||
"
|
||||
:class="progressBarContainerClass"
|
||||
>
|
||||
<div
|
||||
v-if="hasProgressPercent(props.progressTotalPercent)"
|
||||
v-if="hasProgressPercent(progressTotalPercent)"
|
||||
:class="progressBarPrimaryClass"
|
||||
:style="progressPercentStyle(props.progressTotalPercent)"
|
||||
:style="progressPercentStyle(progressTotalPercent)"
|
||||
/>
|
||||
<div
|
||||
v-if="hasProgressPercent(props.progressCurrentPercent)"
|
||||
v-if="hasProgressPercent(progressCurrentPercent)"
|
||||
:class="progressBarSecondaryClass"
|
||||
:style="progressPercentStyle(props.progressCurrentPercent)"
|
||||
:style="progressPercentStyle(progressCurrentPercent)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -93,8 +87,8 @@
|
||||
</div>
|
||||
|
||||
<div class="relative z-1 min-w-0 flex-1">
|
||||
<div class="truncate opacity-90" :title="props.title">
|
||||
<slot name="primary">{{ props.title }}</slot>
|
||||
<div class="truncate opacity-90" :title="title">
|
||||
<slot name="primary">{{ title }}</slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -131,7 +125,7 @@
|
||||
class="inline-flex items-center gap-2 pr-1"
|
||||
>
|
||||
<Button
|
||||
v-if="props.state === 'failed' && computedShowClear"
|
||||
v-if="state === 'failed' && computedShowClear"
|
||||
v-tooltip.top="deleteTooltipConfig"
|
||||
variant="destructive"
|
||||
size="icon"
|
||||
@@ -142,8 +136,8 @@
|
||||
</Button>
|
||||
<Button
|
||||
v-else-if="
|
||||
props.state !== 'completed' &&
|
||||
props.state !== 'running' &&
|
||||
state !== 'completed' &&
|
||||
state !== 'running' &&
|
||||
computedShowClear
|
||||
"
|
||||
v-tooltip.top="cancelTooltipConfig"
|
||||
@@ -155,14 +149,14 @@
|
||||
<i class="icon-[lucide--x] size-4" />
|
||||
</Button>
|
||||
<Button
|
||||
v-else-if="props.state === 'completed'"
|
||||
v-else-if="state === 'completed'"
|
||||
variant="textonly"
|
||||
size="sm"
|
||||
@click.stop="emit('view')"
|
||||
>{{ t('menuLabels.View') }}</Button
|
||||
>
|
||||
<Button
|
||||
v-if="props.showMenu !== undefined ? props.showMenu : true"
|
||||
v-if="showMenu !== undefined ? showMenu : true"
|
||||
v-tooltip.top="moreTooltipConfig"
|
||||
variant="textonly"
|
||||
size="icon-sm"
|
||||
@@ -172,17 +166,13 @@
|
||||
<i class="icon-[lucide--more-horizontal] size-4" />
|
||||
</Button>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="props.state !== 'running'"
|
||||
key="secondary"
|
||||
class="pr-2"
|
||||
>
|
||||
<slot name="secondary">{{ props.rightText }}</slot>
|
||||
<div v-else-if="state !== 'running'" key="secondary" class="pr-2">
|
||||
<slot name="secondary">{{ rightText }}</slot>
|
||||
</div>
|
||||
</Transition>
|
||||
<!-- Running job cancel button - always visible -->
|
||||
<Button
|
||||
v-if="props.state === 'running' && computedShowClear"
|
||||
v-if="state === 'running' && computedShowClear"
|
||||
v-tooltip.top="cancelTooltipConfig"
|
||||
variant="destructive"
|
||||
size="icon"
|
||||
@@ -209,34 +199,33 @@ import type { JobState } from '@/types/queue'
|
||||
import { iconForJobState } from '@/utils/queueDisplay'
|
||||
import { cn } from '@/utils/tailwindUtil'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
jobId: string
|
||||
workflowId?: string
|
||||
state: JobState
|
||||
title: string
|
||||
rightText?: string
|
||||
iconName?: string
|
||||
iconImageUrl?: string
|
||||
showClear?: boolean
|
||||
showMenu?: boolean
|
||||
progressTotalPercent?: number
|
||||
progressCurrentPercent?: number
|
||||
activeDetailsId?: string | null
|
||||
}>(),
|
||||
{
|
||||
workflowId: undefined,
|
||||
rightText: '',
|
||||
iconName: undefined,
|
||||
iconImageUrl: undefined,
|
||||
showClear: undefined,
|
||||
showMenu: undefined,
|
||||
progressTotalPercent: undefined,
|
||||
progressCurrentPercent: undefined,
|
||||
runningNodeName: undefined,
|
||||
activeDetailsId: null
|
||||
}
|
||||
)
|
||||
const {
|
||||
jobId,
|
||||
workflowId,
|
||||
state,
|
||||
title,
|
||||
rightText = '',
|
||||
iconName,
|
||||
iconImageUrl,
|
||||
showClear,
|
||||
showMenu,
|
||||
progressTotalPercent,
|
||||
progressCurrentPercent,
|
||||
activeDetailsId = null
|
||||
} = defineProps<{
|
||||
jobId: string
|
||||
workflowId?: string
|
||||
state: JobState
|
||||
title: string
|
||||
rightText?: string
|
||||
iconName?: string
|
||||
iconImageUrl?: string
|
||||
showClear?: boolean
|
||||
showMenu?: boolean
|
||||
progressTotalPercent?: number
|
||||
progressCurrentPercent?: number
|
||||
activeDetailsId?: string | null
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'cancel'): void
|
||||
@@ -262,14 +251,14 @@ const deleteTooltipConfig = computed(() => buildTooltipConfig(t('g.delete')))
|
||||
const moreTooltipConfig = computed(() => buildTooltipConfig(t('g.more')))
|
||||
|
||||
const rowRef = ref<HTMLDivElement | null>(null)
|
||||
const showDetails = computed(() => props.activeDetailsId === props.jobId)
|
||||
const showDetails = computed(() => activeDetailsId === jobId)
|
||||
|
||||
const onRowEnter = () => {
|
||||
if (!isPreviewVisible.value) emit('details-enter', props.jobId)
|
||||
if (!isPreviewVisible.value) emit('details-enter', jobId)
|
||||
}
|
||||
const onRowLeave = () => emit('details-leave', props.jobId)
|
||||
const onPopoverEnter = () => emit('details-enter', props.jobId)
|
||||
const onPopoverLeave = () => emit('details-leave', props.jobId)
|
||||
const onRowLeave = () => emit('details-leave', jobId)
|
||||
const onPopoverEnter = () => emit('details-enter', jobId)
|
||||
const onPopoverLeave = () => emit('details-leave', jobId)
|
||||
|
||||
const isPreviewVisible = ref(false)
|
||||
const previewHideTimer = ref<number | null>(null)
|
||||
@@ -286,9 +275,7 @@ const clearPreviewShowTimer = () => {
|
||||
previewShowTimer.value = null
|
||||
}
|
||||
}
|
||||
const canShowPreview = computed(
|
||||
() => props.state === 'completed' && !!props.iconImageUrl
|
||||
)
|
||||
const canShowPreview = computed(() => state === 'completed' && !!iconImageUrl)
|
||||
const scheduleShowPreview = () => {
|
||||
if (!canShowPreview.value) return
|
||||
clearPreviewHideTimer()
|
||||
@@ -343,23 +330,23 @@ watch(
|
||||
const isHovered = ref(false)
|
||||
|
||||
const iconClass = computed(() => {
|
||||
if (props.iconName) return props.iconName
|
||||
return iconForJobState(props.state)
|
||||
if (iconName) return iconName
|
||||
return iconForJobState(state)
|
||||
})
|
||||
|
||||
const shouldSpin = computed(
|
||||
() =>
|
||||
props.state === 'pending' &&
|
||||
state === 'pending' &&
|
||||
iconClass.value === iconForJobState('pending') &&
|
||||
!props.iconImageUrl
|
||||
!iconImageUrl
|
||||
)
|
||||
|
||||
const computedShowClear = computed(() => {
|
||||
if (props.showClear !== undefined) return props.showClear
|
||||
return props.state !== 'completed'
|
||||
if (showClear !== undefined) return showClear
|
||||
return state !== 'completed'
|
||||
})
|
||||
|
||||
const emitDetailsLeave = () => emit('details-leave', props.jobId)
|
||||
const emitDetailsLeave = () => emit('details-leave', jobId)
|
||||
|
||||
const onCancelClick = () => {
|
||||
emitDetailsLeave()
|
||||
@@ -372,7 +359,7 @@ const onDeleteClick = () => {
|
||||
}
|
||||
|
||||
const onContextMenu = (event: MouseEvent) => {
|
||||
const shouldShowMenu = props.showMenu !== undefined ? props.showMenu : true
|
||||
const shouldShowMenu = showMenu !== undefined ? showMenu : true
|
||||
if (shouldShowMenu) emit('menu', event)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -11,21 +11,22 @@ interface Props {
|
||||
disable?: boolean
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
duration: 150,
|
||||
easingEnter: 'ease-in-out',
|
||||
easingLeave: 'ease-in-out',
|
||||
opacityClosed: 0,
|
||||
opacityOpened: 1
|
||||
})
|
||||
const {
|
||||
duration = 150,
|
||||
easingEnter = 'ease-in-out',
|
||||
easingLeave = 'ease-in-out',
|
||||
opacityClosed = 0,
|
||||
opacityOpened = 1,
|
||||
disable
|
||||
} = defineProps<Props>()
|
||||
|
||||
const closed = '0px'
|
||||
|
||||
const isMounted = ref(false)
|
||||
onMounted(() => (isMounted.value = true))
|
||||
|
||||
const duration = computed(() =>
|
||||
isMounted.value && !props.disable ? props.duration : 0
|
||||
const animationDuration = computed(() =>
|
||||
isMounted.value && !disable ? duration : 0
|
||||
)
|
||||
|
||||
interface initialStyle {
|
||||
@@ -95,7 +96,7 @@ function getEnterKeyframes(height: string, initialStyle: initialStyle) {
|
||||
return [
|
||||
{
|
||||
height: closed,
|
||||
opacity: props.opacityClosed,
|
||||
opacity: opacityClosed,
|
||||
paddingTop: closed,
|
||||
paddingBottom: closed,
|
||||
borderTopWidth: closed,
|
||||
@@ -105,7 +106,7 @@ function getEnterKeyframes(height: string, initialStyle: initialStyle) {
|
||||
},
|
||||
{
|
||||
height,
|
||||
opacity: props.opacityOpened,
|
||||
opacity: opacityOpened,
|
||||
paddingTop: initialStyle.paddingTop,
|
||||
paddingBottom: initialStyle.paddingBottom,
|
||||
borderTopWidth: initialStyle.borderTopWidth,
|
||||
@@ -121,7 +122,7 @@ function enterTransition(element: Element, done: () => void) {
|
||||
const initialStyle = getElementStyle(HTMLElement)
|
||||
const height = prepareElement(HTMLElement, initialStyle)
|
||||
const keyframes = getEnterKeyframes(height, initialStyle)
|
||||
const options = { duration: duration.value, easing: props.easingEnter }
|
||||
const options = { duration: animationDuration.value, easing: easingEnter }
|
||||
animateTransition(HTMLElement, initialStyle, done, keyframes, options)
|
||||
}
|
||||
|
||||
@@ -132,7 +133,7 @@ function leaveTransition(element: Element, done: () => void) {
|
||||
HTMLElement.style.height = height
|
||||
HTMLElement.style.overflow = 'hidden'
|
||||
const keyframes = getEnterKeyframes(height, initialStyle).reverse()
|
||||
const options = { duration: duration.value, easing: props.easingLeave }
|
||||
const options = { duration: animationDuration.value, easing: easingLeave }
|
||||
animateTransition(HTMLElement, initialStyle, done, keyframes, options)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -16,20 +16,17 @@ import type { TopbarBadge as TopbarBadgeType } from '@/types/comfy'
|
||||
|
||||
import TopbarBadge from './TopbarBadge.vue'
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
displayMode?: 'full' | 'compact' | 'icon-only'
|
||||
reverseOrder?: boolean
|
||||
noPadding?: boolean
|
||||
backgroundColor?: string
|
||||
}>(),
|
||||
{
|
||||
displayMode: 'full',
|
||||
reverseOrder: false,
|
||||
noPadding: false,
|
||||
backgroundColor: 'var(--comfy-menu-bg)'
|
||||
}
|
||||
)
|
||||
const {
|
||||
displayMode = 'full',
|
||||
reverseOrder = false,
|
||||
noPadding = false,
|
||||
backgroundColor = 'var(--comfy-menu-bg)'
|
||||
} = defineProps<{
|
||||
displayMode?: 'full' | 'compact' | 'icon-only'
|
||||
reverseOrder?: boolean
|
||||
noPadding?: boolean
|
||||
backgroundColor?: string
|
||||
}>()
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
|
||||
@@ -129,21 +129,19 @@ import { computed, ref } from 'vue'
|
||||
import type { TopbarBadge } from '@/types/comfy'
|
||||
import { cn } from '@/utils/tailwindUtil'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
badge: TopbarBadge
|
||||
displayMode?: 'full' | 'compact' | 'icon-only'
|
||||
reverseOrder?: boolean
|
||||
noPadding?: boolean
|
||||
backgroundColor?: string
|
||||
}>(),
|
||||
{
|
||||
displayMode: 'full',
|
||||
reverseOrder: false,
|
||||
noPadding: false,
|
||||
backgroundColor: 'var(--comfy-menu-bg)'
|
||||
}
|
||||
)
|
||||
const {
|
||||
badge,
|
||||
displayMode = 'full',
|
||||
reverseOrder = false,
|
||||
noPadding = false,
|
||||
backgroundColor = 'var(--comfy-menu-bg)'
|
||||
} = defineProps<{
|
||||
badge: TopbarBadge
|
||||
displayMode?: 'full' | 'compact' | 'icon-only'
|
||||
reverseOrder?: boolean
|
||||
noPadding?: boolean
|
||||
backgroundColor?: string
|
||||
}>()
|
||||
|
||||
const popover = ref<InstanceType<typeof Popover>>()
|
||||
|
||||
@@ -151,10 +149,10 @@ const togglePopover = (event: Event) => {
|
||||
popover.value?.toggle(event)
|
||||
}
|
||||
|
||||
const variant = computed(() => props.badge.variant ?? 'info')
|
||||
const variant = computed(() => badge.variant ?? 'info')
|
||||
|
||||
const menuBackgroundStyle = computed(() => ({
|
||||
backgroundColor: props.backgroundColor
|
||||
backgroundColor: backgroundColor
|
||||
}))
|
||||
|
||||
const labelClasses = computed(() => {
|
||||
@@ -184,8 +182,8 @@ const textClasses = computed(() => {
|
||||
const iconColorClass = computed(() => textClasses.value)
|
||||
|
||||
const iconClass = computed(() => {
|
||||
if (props.badge.icon) {
|
||||
return props.badge.icon
|
||||
if (badge.icon) {
|
||||
return badge.icon
|
||||
}
|
||||
switch (variant.value) {
|
||||
case 'error':
|
||||
|
||||
@@ -19,16 +19,10 @@ import { useTopbarBadgeStore } from '@/stores/topbarBadgeStore'
|
||||
|
||||
import TopbarBadge from './TopbarBadge.vue'
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
reverseOrder?: boolean
|
||||
noPadding?: boolean
|
||||
}>(),
|
||||
{
|
||||
reverseOrder: false,
|
||||
noPadding: false
|
||||
}
|
||||
)
|
||||
const { reverseOrder = false, noPadding = false } = defineProps<{
|
||||
reverseOrder?: boolean
|
||||
noPadding?: boolean
|
||||
}>()
|
||||
|
||||
const breakpoints = useBreakpoints(breakpointsTailwind)
|
||||
const isXl = breakpoints.greaterOrEqual('xl')
|
||||
|
||||
Reference in New Issue
Block a user