mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-03 12:10:11 +00:00
[TS] Fix ts-strict errors in Vue components (Part 2) (#3123)
Co-authored-by: Christian Byrne <cbyrne@comfy.org>
This commit is contained in:
@@ -35,9 +35,10 @@ const onConfirm = () => {
|
||||
useDialogStore().closeDialog()
|
||||
}
|
||||
|
||||
const inputRef = ref(null)
|
||||
const inputRef = ref<InstanceType<typeof InputText> | undefined>()
|
||||
const selectAllText = () => {
|
||||
if (!inputRef.value) return
|
||||
// @ts-expect-error - $el is an internal property of the InputText component
|
||||
const inputElement = inputRef.value.$el
|
||||
inputElement.setSelectionRange(0, inputElement.value.length)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
scrollHeight="100%"
|
||||
:optionDisabled="
|
||||
(option: SettingTreeNode) =>
|
||||
!queryIsEmpty && !searchResultsCategories.has(option.label)
|
||||
!queryIsEmpty && !searchResultsCategories.has(option.label ?? '')
|
||||
"
|
||||
class="border-none w-full"
|
||||
/>
|
||||
@@ -266,8 +266,8 @@ const handleSearch = (query: string) => {
|
||||
|
||||
const queryIsEmpty = computed(() => searchQuery.value.length === 0)
|
||||
const inSearch = computed(() => !queryIsEmpty.value && !searchInProgress.value)
|
||||
const tabValue = computed(() =>
|
||||
inSearch.value ? 'Search Results' : activeCategory.value?.label
|
||||
const tabValue = computed<string>(() =>
|
||||
inSearch.value ? 'Search Results' : activeCategory.value?.label ?? ''
|
||||
)
|
||||
// Don't allow null category to be set outside of search.
|
||||
// In search mode, the active category can be null to show all search results.
|
||||
|
||||
@@ -187,7 +187,7 @@ const createUser = (formData: IssueReportFormData): User => ({
|
||||
})
|
||||
|
||||
const createExtraData = async (formData: IssueReportFormData) => {
|
||||
const result = {}
|
||||
const result: Record<string, unknown> = {}
|
||||
const isChecked = (fieldValue: string) => formData[fieldValue]
|
||||
|
||||
await Promise.all(
|
||||
@@ -243,7 +243,7 @@ const submit = async (event: FormSubmitEvent) => {
|
||||
toast.add({
|
||||
severity: 'error',
|
||||
summary: t('g.error'),
|
||||
detail: error.message,
|
||||
detail: error instanceof Error ? error.message : String(error),
|
||||
life: 3000
|
||||
})
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
<ContentDivider orientation="vertical" :width="0.2" />
|
||||
<div class="flex-1 flex flex-col isolate">
|
||||
<InfoPanel
|
||||
v-if="!hasMultipleSelections"
|
||||
v-if="!hasMultipleSelections && selectedNodePack"
|
||||
:node-pack="selectedNodePack"
|
||||
/>
|
||||
<InfoPanelMultiItem v-else :node-packs="selectedNodePacks" />
|
||||
@@ -149,8 +149,8 @@ const isEmptySearch = computed(() => searchQuery.value === '')
|
||||
|
||||
const getInstalledSearchResults = async () => {
|
||||
if (isEmptySearch.value) return getInstalledPacks()
|
||||
return searchResults.value.filter((pack) =>
|
||||
comfyManagerStore.installedPacksIds.has(pack.name)
|
||||
return searchResults.value.filter(
|
||||
(pack) => pack.name && comfyManagerStore.installedPacksIds.has(pack.name)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -162,15 +162,16 @@ watchEffect(async () => {
|
||||
}
|
||||
})
|
||||
|
||||
const resultsWithKeys = computed(() =>
|
||||
displayPacks.value.map((item) => ({
|
||||
...item,
|
||||
key: item.id || item.name
|
||||
}))
|
||||
const resultsWithKeys = computed(
|
||||
() =>
|
||||
displayPacks.value.map((item) => ({
|
||||
...item,
|
||||
key: item.id || item.name
|
||||
})) as (components['schemas']['Node'] & { key: string })[]
|
||||
)
|
||||
|
||||
const selectedNodePacks = ref<components['schemas']['Node'][]>([])
|
||||
const selectedNodePack = computed(() =>
|
||||
const selectedNodePack = computed<components['schemas']['Node'] | null>(() =>
|
||||
selectedNodePacks.value.length === 1 ? selectedNodePacks.value[0] : null
|
||||
)
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ const getPackNodes = async (pack: components['schemas']['Node']) => {
|
||||
if (!comfyRegistryService.packNodesAvailable(pack)) return []
|
||||
return comfyRegistryService.getNodeDefs({
|
||||
packId: pack.id,
|
||||
versionId: pack.latest_version.id
|
||||
versionId: pack.latest_version?.id
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import NodePreview from '@/components/node/NodePreview.vue'
|
||||
import { ComfyNodeDef } from '@/schemas/nodeDef/nodeDefSchemaV2'
|
||||
import { components } from '@/types/comfyRegistryTypes'
|
||||
|
||||
defineProps<{
|
||||
@@ -24,7 +25,8 @@ defineProps<{
|
||||
}>()
|
||||
|
||||
// TODO: when registry returns node defs, use them here
|
||||
const placeholderNodeDef = {
|
||||
const placeholderNodeDef: ComfyNodeDef = {
|
||||
name: 'Sample Node',
|
||||
display_name: 'Sample Node',
|
||||
description: 'This is a sample node for preview purposes',
|
||||
inputs: {
|
||||
@@ -32,8 +34,11 @@ const placeholderNodeDef = {
|
||||
input2: { name: 'Input 2', type: 'CONDITIONING' }
|
||||
},
|
||||
outputs: [
|
||||
{ name: 'Output 1', type: 'IMAGE', index: 0 },
|
||||
{ name: 'Output 2', type: 'MASK', index: 1 }
|
||||
]
|
||||
{ name: 'Output 1', type: 'IMAGE', index: 0, is_list: false },
|
||||
{ name: 'Output 2', type: 'MASK', index: 1, is_list: false }
|
||||
],
|
||||
category: 'Utility',
|
||||
output_node: false,
|
||||
python_module: 'nodes'
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -128,7 +128,7 @@ const isUpdateAvailable = computed(() => {
|
||||
const latestVersion = nodePack.latest_version?.version
|
||||
if (!latestVersion) return false
|
||||
|
||||
const installedVersion = getInstalledPackVersion(nodePack.id)
|
||||
const installedVersion = getInstalledPackVersion(nodePack.id ?? '')
|
||||
|
||||
// Don't attempt to show update available for nightly GitHub packs
|
||||
if (installedVersion && !isSemVer(installedVersion)) return false
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
icon="pi pi-ellipsis-h"
|
||||
text
|
||||
severity="secondary"
|
||||
@click="menu.show($event)"
|
||||
@click="menu?.show($event)"
|
||||
/>
|
||||
<ContextMenu ref="menu" :model="contextMenuItems" />
|
||||
</template>
|
||||
|
||||
@@ -157,7 +157,10 @@ interface ICommandData {
|
||||
const commandsData = computed<ICommandData[]>(() => {
|
||||
return Object.values(commandStore.commands).map((command) => ({
|
||||
id: command.id,
|
||||
label: t(`commands.${normalizeI18nKey(command.id)}.label`, command.label),
|
||||
label: t(
|
||||
`commands.${normalizeI18nKey(command.id)}.label`,
|
||||
command.label ?? ''
|
||||
),
|
||||
keybinding: keybindingStore.getKeybindingByCommandId(command.id)
|
||||
}))
|
||||
})
|
||||
@@ -166,7 +169,7 @@ const selectedCommandData = ref<ICommandData | null>(null)
|
||||
const editDialogVisible = ref(false)
|
||||
const newBindingKeyCombo = ref<KeyComboImpl | null>(null)
|
||||
const currentEditingCommand = ref<ICommandData | null>(null)
|
||||
const keybindingInput = ref(null)
|
||||
const keybindingInput = ref<InstanceType<typeof InputText> | null>(null)
|
||||
|
||||
const existingKeybindingOnCombo = computed<KeybindingImpl | null>(() => {
|
||||
if (!currentEditingCommand.value) {
|
||||
@@ -201,6 +204,7 @@ watchEffect(() => {
|
||||
if (editDialogVisible.value) {
|
||||
// nextTick doesn't work here, so we use a timeout instead
|
||||
setTimeout(() => {
|
||||
// @ts-expect-error - $el is an internal property of the InputText component
|
||||
keybindingInput.value?.$el?.focus()
|
||||
}, 300)
|
||||
}
|
||||
|
||||
@@ -106,7 +106,9 @@ watchEffect(() => {
|
||||
|
||||
watchEffect(() => {
|
||||
const spellcheckEnabled = settingStore.get('Comfy.TextareaWidget.Spellcheck')
|
||||
const textareas = document.querySelectorAll('textarea.comfy-multiline-input')
|
||||
const textareas = document.querySelectorAll<HTMLTextAreaElement>(
|
||||
'textarea.comfy-multiline-input'
|
||||
)
|
||||
|
||||
textareas.forEach((textarea: HTMLTextAreaElement) => {
|
||||
textarea.spellcheck = spellcheckEnabled
|
||||
|
||||
@@ -28,12 +28,12 @@ import { normalizeI18nKey } from '@/utils/formatUtil'
|
||||
let idleTimeout: number
|
||||
const nodeDefStore = useNodeDefStore()
|
||||
const settingStore = useSettingStore()
|
||||
const tooltipRef = ref<HTMLDivElement>()
|
||||
const tooltipRef = ref<HTMLDivElement | undefined>()
|
||||
const tooltipText = ref('')
|
||||
const left = ref<string>()
|
||||
const top = ref<string>()
|
||||
|
||||
const hideTooltip = () => (tooltipText.value = null)
|
||||
const hideTooltip = () => (tooltipText.value = '')
|
||||
|
||||
const showTooltip = async (tooltip: string | null | undefined) => {
|
||||
if (!tooltip) return
|
||||
@@ -44,7 +44,9 @@ const showTooltip = async (tooltip: string | null | undefined) => {
|
||||
|
||||
await nextTick()
|
||||
|
||||
const rect = tooltipRef.value.getBoundingClientRect()
|
||||
const rect = tooltipRef.value?.getBoundingClientRect()
|
||||
if (!rect) return
|
||||
|
||||
if (rect.right > window.innerWidth) {
|
||||
left.value = comfyApp.canvas.mouse[0] - rect.width + 'px'
|
||||
}
|
||||
@@ -60,7 +62,7 @@ const onIdle = () => {
|
||||
if (!node) return
|
||||
|
||||
const ctor = node.constructor as { title_mode?: 0 | 1 | 2 | 3 }
|
||||
const nodeDef = nodeDefStore.nodeDefsByName[node.type]
|
||||
const nodeDef = nodeDefStore.nodeDefsByName[node.type ?? '']
|
||||
|
||||
if (
|
||||
ctor.title_mode !== LiteGraph.NO_TITLE &&
|
||||
@@ -80,8 +82,8 @@ const onIdle = () => {
|
||||
if (inputSlot !== -1) {
|
||||
const inputName = node.inputs[inputSlot].name
|
||||
const translatedTooltip = st(
|
||||
`nodeDefs.${normalizeI18nKey(node.type)}.inputs.${normalizeI18nKey(inputName)}.tooltip`,
|
||||
nodeDef.inputs[inputName]?.tooltip
|
||||
`nodeDefs.${normalizeI18nKey(node.type ?? '')}.inputs.${normalizeI18nKey(inputName)}.tooltip`,
|
||||
nodeDef.inputs[inputName]?.tooltip ?? ''
|
||||
)
|
||||
return showTooltip(translatedTooltip)
|
||||
}
|
||||
@@ -94,8 +96,8 @@ const onIdle = () => {
|
||||
)
|
||||
if (outputSlot !== -1) {
|
||||
const translatedTooltip = st(
|
||||
`nodeDefs.${normalizeI18nKey(node.type)}.outputs.${outputSlot}.tooltip`,
|
||||
nodeDef.outputs[outputSlot]?.tooltip
|
||||
`nodeDefs.${normalizeI18nKey(node.type ?? '')}.outputs.${outputSlot}.tooltip`,
|
||||
nodeDef.outputs[outputSlot]?.tooltip ?? ''
|
||||
)
|
||||
return showTooltip(translatedTooltip)
|
||||
}
|
||||
@@ -104,8 +106,8 @@ const onIdle = () => {
|
||||
// Dont show for DOM widgets, these use native browser tooltips as we dont get proper mouse events on these
|
||||
if (widget && !isDOMWidget(widget)) {
|
||||
const translatedTooltip = st(
|
||||
`nodeDefs.${normalizeI18nKey(node.type)}.inputs.${normalizeI18nKey(widget.name)}.tooltip`,
|
||||
nodeDef.inputs[widget.name]?.tooltip
|
||||
`nodeDefs.${normalizeI18nKey(node.type ?? '')}.inputs.${normalizeI18nKey(widget.name)}.tooltip`,
|
||||
nodeDef.inputs[widget.name]?.tooltip ?? ''
|
||||
)
|
||||
// Widget tooltip can be set dynamically, current translation collection does not support this.
|
||||
return showTooltip(widget.tooltip ?? translatedTooltip)
|
||||
|
||||
@@ -41,7 +41,7 @@ const emit = defineEmits<{
|
||||
(e: 'update:widgetValue', value: string | object): void
|
||||
}>()
|
||||
|
||||
const widgetElement = ref<HTMLElement>()
|
||||
const widgetElement = ref<HTMLElement | undefined>()
|
||||
|
||||
const { style: positionStyle, updatePositionWithTransform } =
|
||||
useAbsolutePosition()
|
||||
@@ -61,6 +61,8 @@ const enableDomClipping = computed(() =>
|
||||
|
||||
const updateDomClipping = () => {
|
||||
const lgCanvas = canvasStore.canvas
|
||||
if (!lgCanvas || !widgetElement.value) return
|
||||
|
||||
const selectedNode = Object.values(
|
||||
lgCanvas.selected_nodes ?? {}
|
||||
)[0] as LGraphNode
|
||||
@@ -130,7 +132,7 @@ const inputSpec = widget.node.constructor.nodeData
|
||||
const tooltip = inputSpec?.inputs?.[widget.name]?.tooltip
|
||||
|
||||
onMounted(() => {
|
||||
if (isDOMWidget(widget)) {
|
||||
if (isDOMWidget(widget) && widgetElement.value) {
|
||||
widgetElement.value.appendChild(widget.element)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -41,10 +41,11 @@ const props = defineProps<{
|
||||
node: RenderedTreeExplorerNode<ComfyModelDef>
|
||||
}>()
|
||||
|
||||
const modelDef = computed(() => props.node.data)
|
||||
// Note: The leaf node should always have a model definition on node.data.
|
||||
const modelDef = computed<ComfyModelDef>(() => props.node.data!)
|
||||
|
||||
const modelPreviewUrl = computed(() => {
|
||||
if (modelDef.value?.image) {
|
||||
if (modelDef.value.image) {
|
||||
return modelDef.value.image
|
||||
}
|
||||
const folder = modelDef.value.directory
|
||||
@@ -69,6 +70,8 @@ const sidebarLocation = computed<'left' | 'right'>(() =>
|
||||
|
||||
const handleModelHover = async () => {
|
||||
const hoverTarget = modelContentElement.value
|
||||
if (!hoverTarget) return
|
||||
|
||||
const targetRect = hoverTarget.getBoundingClientRect()
|
||||
|
||||
const previewHeight = previewRef.value?.$el.offsetHeight || 0
|
||||
@@ -87,8 +90,8 @@ const handleModelHover = async () => {
|
||||
modelDef.value.load()
|
||||
}
|
||||
|
||||
const container = ref<HTMLElement | null>(null)
|
||||
const modelContentElement = ref<HTMLElement | null>(null)
|
||||
const container = ref<HTMLElement | undefined>()
|
||||
const modelContentElement = ref<HTMLElement | undefined>()
|
||||
const isHovered = ref(false)
|
||||
|
||||
const showPreview = computed(() => {
|
||||
@@ -114,7 +117,8 @@ const handleMouseLeave = () => {
|
||||
isHovered.value = false
|
||||
}
|
||||
onMounted(() => {
|
||||
modelContentElement.value = container.value?.closest('.p-tree-node-content')
|
||||
modelContentElement.value =
|
||||
container.value?.closest('.p-tree-node-content') ?? undefined
|
||||
modelContentElement.value?.addEventListener('mouseenter', handleMouseEnter)
|
||||
modelContentElement.value?.addEventListener('mouseleave', handleMouseLeave)
|
||||
modelDef.value.load()
|
||||
|
||||
@@ -52,7 +52,7 @@ onMounted(() => {
|
||||
|
||||
const updateIconColor = () => {
|
||||
if (iconElement.value && customization.value) {
|
||||
iconElement.value.style.color = customization.value.color
|
||||
iconElement.value.style.color = customization.value.color ?? ''
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ onUnmounted(() => {
|
||||
|
||||
const expandedKeys = inject(InjectKeyExpandedKeys)
|
||||
const handleItemDrop = (node: RenderedTreeExplorerNode) => {
|
||||
if (!expandedKeys) return
|
||||
expandedKeys.value[node.key] = true
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -20,7 +20,7 @@ import BaseThumbnail from '@/components/templates/thumbnails/BaseThumbnail.vue'
|
||||
defineProps<{
|
||||
src: string
|
||||
alt: string
|
||||
hoverZoom?: number
|
||||
hoverZoom: number
|
||||
isHovered?: boolean
|
||||
}>()
|
||||
</script>
|
||||
|
||||
@@ -59,7 +59,9 @@ function updateToastPosition() {
|
||||
document.getElementById('dynamic-toast-style') || createStyleElement()
|
||||
const rect = document
|
||||
.querySelector('.graph-canvas-container')
|
||||
.getBoundingClientRect()
|
||||
?.getBoundingClientRect()
|
||||
if (!rect) return
|
||||
|
||||
styleElement.textContent = `
|
||||
.p-toast.p-component.p-toast-top-right {
|
||||
top: ${rect.top + 20}px !important;
|
||||
|
||||
@@ -89,7 +89,7 @@ eventBus.on((event: string, payload: any) => {
|
||||
onMounted(() => {
|
||||
if (isElectron()) {
|
||||
electronAPI().changeTheme({
|
||||
height: topMenuRef.value.getBoundingClientRect().height
|
||||
height: topMenuRef.value?.getBoundingClientRect().height ?? 0
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -68,7 +68,7 @@ const workspaceStore = useWorkspaceStore()
|
||||
const workflowStore = useWorkflowStore()
|
||||
const workflowService = useWorkflowService()
|
||||
const workflowBookmarkStore = useWorkflowBookmarkStore()
|
||||
const rightClickedTab = ref<WorkflowOption>(null)
|
||||
const rightClickedTab = ref<WorkflowOption | undefined>()
|
||||
const menu = ref()
|
||||
|
||||
const workflowToOption = (workflow: ComfyWorkflow): WorkflowOption => ({
|
||||
@@ -114,7 +114,7 @@ const onCloseWorkflow = (option: WorkflowOption) => {
|
||||
closeWorkflows([option])
|
||||
}
|
||||
|
||||
const showContextMenu = (event, option) => {
|
||||
const showContextMenu = (event: MouseEvent, option: WorkflowOption) => {
|
||||
rightClickedTab.value = option
|
||||
menu.value.show(event)
|
||||
}
|
||||
|
||||
@@ -396,7 +396,10 @@ const normalizeVersion = (version: string) =>
|
||||
.map(Number)
|
||||
.filter((part) => !Number.isNaN(part))
|
||||
|
||||
export function compareVersions(versionA: string, versionB: string): number {
|
||||
export function compareVersions(
|
||||
versionA: string | undefined,
|
||||
versionB: string | undefined
|
||||
): number {
|
||||
versionA ??= '0.0.0'
|
||||
versionB ??= '0.0.0'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user