Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/extensions/core/widgetInputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ export class PrimitiveNode extends LGraphNode {
undefined,
inputData
)
if (this.widgets?.[1]) widget.linkedWidgets = [this.widgets[1]]

let filter = this.widgets_values?.[2]
if (filter && this.widgets && this.widgets.length === 3) {
this.widgets[2].value = filter
Expand Down
6 changes: 3 additions & 3 deletions src/locales/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -2057,7 +2057,7 @@
"placeholderModel": "Select model...",
"placeholderUnknown": "Select media..."
},
"numberControl": {
"valueControl": {
"header": {
"prefix": "Automatically update the value",
"after": "AFTER",
Expand All @@ -2070,9 +2070,9 @@
"randomize": "Randomize Value",
"randomizeDesc": "Shuffles the value randomly after each generation",
"increment": "Increment Value",
"incrementDesc": "Adds 1 to the value number",
"incrementDesc": "Adds 1 to value or selects the next option",
"decrement": "Decrement Value",
"decrementDesc": "Subtracts 1 from the value number",
"decrementDesc": "Subtracts 1 from value or selects the previous option",
"fixed": "Fixed Value",
"fixedDesc": "Leaves value unchanged",
"editSettings": "Edit control settings"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ import RadioButton from 'primevue/radiobutton'
import { computed, ref } from 'vue'

import { useSettingStore } from '@/platform/settings/settingStore'

import { NumberControlMode } from '../composables/useStepperControl'
import type { ControlOptions } from '@/types/simplifiedWidget'

type ControlOption = {
description: string
mode: NumberControlMode
mode: ControlOptions
icon?: string
text?: string
title: string
Expand All @@ -23,39 +22,27 @@ const toggle = (event: Event) => {
}
defineExpose({ toggle })

const ENABLE_LINK_TO_GLOBAL = false

const controlOptions: ControlOption[] = [
...(ENABLE_LINK_TO_GLOBAL
? ([
{
mode: NumberControlMode.LINK_TO_GLOBAL,
icon: 'pi pi-link',
title: 'linkToGlobal',
description: 'linkToGlobalDesc'
} satisfies ControlOption
] as ControlOption[])
: []),
{
mode: NumberControlMode.FIXED,
mode: 'fixed',
icon: 'icon-[lucide--pencil-off]',
title: 'fixed',
description: 'fixedDesc'
},
{
mode: NumberControlMode.INCREMENT,
mode: 'increment',
text: '+1',
title: 'increment',
description: 'incrementDesc'
},
{
mode: NumberControlMode.DECREMENT,
mode: 'decrement',
text: '-1',
title: 'decrement',
description: 'decrementDesc'
},
{
mode: NumberControlMode.RANDOMIZE,
mode: 'randomize',
icon: 'icon-[lucide--shuffle]',
title: 'randomize',
description: 'randomizeDesc'
Expand All @@ -66,7 +53,7 @@ const widgetControlMode = computed(() =>
settingStore.get('Comfy.WidgetControlMode')
)

const controlMode = defineModel<NumberControlMode>()
const controlMode = defineModel<ControlOptions>()
</script>

<template>
Expand All @@ -76,15 +63,15 @@ const controlMode = defineModel<NumberControlMode>()
>
<div class="w-113 max-w-md p-4 space-y-4">
<div class="text-sm text-muted-foreground leading-tight">
{{ $t('widgets.numberControl.header.prefix') }}
{{ $t('widgets.valueControl.header.prefix') }}
<span class="text-base-foreground font-medium">
{{
widgetControlMode === 'before'
? $t('widgets.numberControl.header.before')
: $t('widgets.numberControl.header.after')
? $t('widgets.valueControl.header.before')
: $t('widgets.valueControl.header.after')
}}
</span>
{{ $t('widgets.numberControl.header.postfix') }}
{{ $t('widgets.valueControl.header.postfix') }}
</div>

<div class="space-y-2">
Expand Down Expand Up @@ -114,18 +101,14 @@ const controlMode = defineModel<NumberControlMode>()
<div
class="text-sm font-normal text-base-foreground leading-tight"
>
<span v-if="option.mode === NumberControlMode.LINK_TO_GLOBAL">
{{ $t('widgets.numberControl.linkToGlobal') }}
<em>{{ $t('widgets.numberControl.linkToGlobalSeed') }}</em>
</span>
<span v-else>
{{ $t(`widgets.numberControl.${option.title}`) }}
<span>
{{ $t(`widgets.valueControl.${option.title}`) }}
</span>
</div>
<div
class="text-sm font-normal text-muted-foreground leading-tight"
>
{{ $t(`widgets.numberControl.${option.description}`) }}
{{ $t(`widgets.valueControl.${option.description}`) }}
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
<script setup lang="ts">
import { computed } from 'vue'

import type { SimplifiedWidget } from '@/types/simplifiedWidget'
import type {
SimplifiedControlWidget,
SimplifiedWidget
} from '@/types/simplifiedWidget'

import WidgetInputNumberInput from './WidgetInputNumberInput.vue'
import WidgetInputNumberSlider from './WidgetInputNumberSlider.vue'
import WidgetInputNumberWithControl from './WidgetInputNumberWithControl.vue'
import WidgetWithControl from './WidgetWithControl.vue'

const props = defineProps<{
widget: SimplifiedWidget<number>
Expand All @@ -19,14 +22,23 @@ const hasControlAfterGenerate = computed(() => {
</script>

<template>
<WidgetWithControl
v-if="hasControlAfterGenerate"
v-model="modelValue"
:widget="widget as SimplifiedControlWidget<number>"
:component="
widget.type === 'slider'
? WidgetInputNumberSlider
: WidgetInputNumberInput
"
/>
<component
:is="
hasControlAfterGenerate
? WidgetInputNumberWithControl
: widget.type === 'slider'
? WidgetInputNumberSlider
: WidgetInputNumberInput
widget.type === 'slider'
? WidgetInputNumberSlider
: WidgetInputNumberInput
"
v-else
v-model="modelValue"
:widget="widget"
v-bind="$attrs"
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
:is-asset-mode="isAssetMode"
:default-layout-mode="defaultLayoutMode"
/>
<WidgetWithControl
v-else-if="widget.controlWidget"
:component="WidgetSelectDefault"
:widget="widget as StringControlWidget"
/>
<WidgetSelectDefault v-else v-model="modelValue" :widget />
</template>

Expand All @@ -20,13 +25,19 @@ import { isCloud } from '@/platform/distribution/types'
import { useSettingStore } from '@/platform/settings/settingStore'
import WidgetSelectDefault from '@/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue'
import WidgetSelectDropdown from '@/renderer/extensions/vueNodes/widgets/components/WidgetSelectDropdown.vue'
import WidgetWithControl from '@/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue'
import type { LayoutMode } from '@/renderer/extensions/vueNodes/widgets/components/form/dropdown/types'
import type { ResultItemType } from '@/schemas/apiSchema'
import { isComboInputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2'
import type { ComboInputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2'
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
import type {
SimplifiedControlWidget,
SimplifiedWidget
} from '@/types/simplifiedWidget'
import type { AssetKind } from '@/types/widgetTypes'

type StringControlWidget = SimplifiedControlWidget<string | undefined>

const props = defineProps<{
widget: SimplifiedWidget<string | undefined>
nodeType?: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@
:pt="{
option: 'text-xs',
dropdown: 'w-8',
label: 'truncate min-w-[4ch]',
label: cn('truncate min-w-[4ch]', $slots.default && 'mr-5'),
overlay: 'w-fit min-w-full'
}"
data-capture-wheel="true"
/>
<div class="absolute top-5 right-8 h-4 w-7 -translate-y-4/5 flex">
<slot />
</div>
Comment on lines +21 to +23
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find src -name "WidgetSelectDefault.vue" -type f

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 145


🏁 Script executed:

cat src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 2192


🏁 Script executed:

find src -name "WidgetLayoutField.vue" -type f

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 150


🏁 Script executed:

cat src/renderer/extensions/vueNodes/widgets/components/layout/WidgetLayoutField.vue

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 1189


🏁 Script executed:

grep -r "WidgetSelectDefault" src --include="*.vue" --include="*.ts" -l | head -10

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 138


🏁 Script executed:

rg "overflow-hidden" src/renderer/extensions/vueNodes/widgets --type vue -A 2 -B 2

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 97


🏁 Script executed:

rg "overflow-hidden" src/renderer/extensions/vueNodes/widgets -A 2 -B 2

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 2363


🏁 Script executed:

find src/renderer/extensions/vueNodes/widgets -type f -name "*.vue" | xargs grep -l "overflow"

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 537


🏁 Script executed:

find src -name "*.vue" -path "*vueNodes*" | xargs grep -l "WidgetLayoutField" | head -5

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 449


🏁 Script executed:

cat src/renderer/extensions/vueNodes/widgets/components/WidgetSelect.vue

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 3699


🏁 Script executed:

cat src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 1612


🏁 Script executed:

rg "class.*relative" src/renderer/extensions/vueNodes/widgets/components/layout -A 3

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 477


🏁 Script executed:

rg "overflow-hidden" src/renderer/extensions/vueNodes --type vue | grep -E "(WidgetLayout|Select)" | head -10

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 97


🏁 Script executed:

cat src/renderer/extensions/vueNodes/widgets/components/ValueControlPopover.vue

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 3471


🏁 Script executed:

rg "Teleport" src/renderer/extensions/vueNodes/widgets --include="*.vue" | head -5

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 511


🏁 Script executed:

rg "WidgetSelectDefault\|absolute.*top-5.*right-8" src --include="*.vue" -A 3 -B 3

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 511


🏁 Script executed:

rg "Teleport" src/renderer/extensions/vueNodes/widgets -t vue

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 97


🏁 Script executed:

rg "absolute.*top-5.*right-8" src -t vue -A 3 -B 3

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 97


🏁 Script executed:

find src/renderer/extensions/vueNodes/widgets -name "*.vue" | xargs grep -l "Teleport"

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 54


🏁 Script executed:

find src -name "*.vue" | xargs grep "absolute.*top-5.*right-8" -B 3 -A 3

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 1527


🏁 Script executed:

find src/renderer/extensions/vueNodes -name "*.vue" | xargs grep -l "WidgetInputNumberInput\|WidgetSelectDefault" | head -5

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 212


🏁 Script executed:

find src/renderer -path "*vueNodes*" -name "*.vue" | xargs grep "overflow-hidden" -l

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 476


🏁 Script executed:

find src -name "NodeComponentPanelWidget.vue" -o -name "NodeComponentPanel.vue" -o -name "*Node*.vue" | grep -E "vueNodes.*components" | head -10

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 489


🏁 Script executed:

find src/renderer/extensions/vueNodes -maxdepth 2 -name "*.vue" | xargs grep -l "WidgetSelectDefault\|WidgetInputNumberInput"

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 54


🏁 Script executed:

cat src/renderer/extensions/vueNodes/components/NodeWidgets.vue

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 6524


🏁 Script executed:

cat src/renderer/extensions/vueNodes/components/NodeContent.vue

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 1617


🏁 Script executed:

find src -name "*.vue" | xargs grep -l "grid-cols-subgrid" | head -5

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 344


🏁 Script executed:

grep -r "position.*context\|Teleport" src/renderer/extensions/vueNodes --include="*.ts" --include="*.vue" | head -10

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 52


🏁 Script executed:

rg "z-\[" src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 52


🏁 Script executed:

cat src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumber.vue | head -50

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 1133


The absolute positioning with relative parent context is correctly implemented and consistent across similar widget components. Parent containers don't use overflow: hidden, so clipping isn't a concern. However, verify that the control button's z-index doesn't conflict with the Select dropdown overlay when opened, and test dropdown interactions in constrained viewport scenarios to ensure the button remains accessible.

🤖 Prompt for AI Agents
In src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue
around lines 21 to 23, the absolute-positioned control button may conflict with
the Select dropdown overlay; ensure the button's stacking context doesn't cover
or get covered by the dropdown by adding an explicit z-index (or adjusting the
dropdown's z-index) on the button container, and if necessary create a new
stacking context (e.g., by adding a positioned ancestor or isolation) so the
dropdown overlay sits above the button; after the change, test dropdown
interactions in constrained viewports and when the dropdown is open to confirm
the button remains accessible and not clipped or blocking clicks.

</WidgetLayoutField>
</template>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<script setup lang="ts" generic="T extends WidgetValue">
import Button from 'primevue/button'
import { computed, defineAsyncComponent, ref, watch } from 'vue'
import type { Component } from 'vue'

import type {
SimplifiedControlWidget,
WidgetValue
} from '@/types/simplifiedWidget'

const ValueControlPopover = defineAsyncComponent(
() => import('./ValueControlPopover.vue')
)

const props = defineProps<{
widget: SimplifiedControlWidget<T>
component: Component
}>()

const modelValue = defineModel<T>()

const popover = ref()

const controlModel = ref(props.widget.controlWidget.value)

const controlButtonIcon = computed(() => {
switch (controlModel.value) {
case 'increment':
return 'pi pi-plus'
case 'decrement':
return 'pi pi-minus'
case 'fixed':
return 'icon-[lucide--pencil-off]'
default:
return 'icon-[lucide--shuffle]'
}
})

watch(controlModel, props.widget.controlWidget.update)

const togglePopover = (event: Event) => {
popover.value.toggle(event)
}
</script>

<template>
<div class="relative grid grid-cols-subgrid">
<component :is="component" v-bind="$attrs" v-model="modelValue" :widget>
<Button
variant="link"
size="small"
class="h-4 w-7 self-center rounded-xl bg-blue-100/30 p-0"
@pointerdown.stop.prevent="togglePopover"
>
<i :class="`${controlButtonIcon} text-blue-100 text-xs size-3.5`" />
</Button>
</component>
<ValueControlPopover ref="popover" v-model="controlModel" />
</div>
</template>
Loading