Fix: Vue node/widget positioning and scroll issue (#5441)

* [feat] Refactor overlay compatibility into reusable composable

- Create useTransformCompatOverlayProps composable for centralized overlay prop management
- Update Select, MultiSelect, TreeSelect, and FileUpload components to use composable
- Provides appendTo='self' for transform inheritance in CSS-transformed parents
- Enables easy future additions of other transform compatibility props
- Fix duplicate v-bind attributes by combining props into single computed object

* fix: Keep the canvas container from being scrolled by children

* types: Align the appendTo type with primevue internals

* Update test expectations [skip ci]

---------

Co-authored-by: bymyself <cbyrne@comfy.org>
Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
Alexander Brown
2025-09-08 16:05:33 -07:00
committed by GitHub
parent aa7f8912a7
commit fa9f5fbca6
181 changed files with 85 additions and 33 deletions

View File

@@ -20,6 +20,7 @@
:model-value="selectedFile?.name"
:options="[selectedFile?.name || '']"
:disabled="true"
v-bind="transformCompatProps"
class="min-w-[8em] max-w-[20em] text-xs"
size="small"
:pt="{
@@ -88,6 +89,7 @@
:model-value="selectedFile?.name"
:options="[selectedFile?.name || '']"
:disabled="true"
v-bind="transformCompatProps"
class="min-w-[8em] max-w-[20em] text-xs"
size="small"
:pt="{
@@ -182,6 +184,7 @@ import Select from 'primevue/select'
import { computed, onUnmounted, ref, watch } from 'vue'
import { useWidgetValue } from '@/composables/graph/useWidgetValue'
import { useTransformCompatOverlayProps } from '@/composables/useTransformCompatOverlayProps'
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
const props = defineProps<{
@@ -201,6 +204,9 @@ const { localValue, onChange } = useWidgetValue({
emit
})
// Transform compatibility props for overlay positioning
const transformCompatProps = useTransformCompatOverlayProps()
const fileInputRef = ref<HTMLInputElement | null>(null)
// Since we only support single file, get the first file

View File

@@ -2,9 +2,9 @@
<WidgetLayoutField :widget="widget">
<MultiSelect
v-model="localValue"
v-bind="filteredProps"
v-bind="combinedProps"
:disabled="readonly"
:class="cn(WidgetInputBaseClass, 'w-full text-xs')"
class="w-full text-xs"
size="small"
display="chip"
:pt="{
@@ -20,14 +20,13 @@ import MultiSelect from 'primevue/multiselect'
import { computed } from 'vue'
import { useWidgetValue } from '@/composables/graph/useWidgetValue'
import { useTransformCompatOverlayProps } from '@/composables/useTransformCompatOverlayProps'
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
import { cn } from '@/utils/tailwindUtil'
import {
PANEL_EXCLUDED_PROPS,
filterWidgetProps
} from '@/utils/widgetPropFilter'
import { WidgetInputBaseClass } from './layout'
import WidgetLayoutField from './layout/WidgetLayoutField.vue'
const props = defineProps<{
@@ -48,24 +47,17 @@ const { localValue, onChange } = useWidgetValue({
emit
})
// Transform compatibility props for overlay positioning
const transformCompatProps = useTransformCompatOverlayProps()
// MultiSelect specific excluded props include overlay styles
const MULTISELECT_EXCLUDED_PROPS = [
...PANEL_EXCLUDED_PROPS,
'overlayStyle'
] as const
const filteredProps = computed(() => {
const filtered = filterWidgetProps(
props.widget.options,
MULTISELECT_EXCLUDED_PROPS
)
// Ensure options array is available for MultiSelect
const values = props.widget.options?.values
if (values && Array.isArray(values)) {
filtered.options = values
}
return filtered
})
const combinedProps = computed(() => ({
...filterWidgetProps(props.widget.options, MULTISELECT_EXCLUDED_PROPS),
...transformCompatProps.value
}))
</script>

View File

@@ -3,9 +3,9 @@
<Select
v-model="localValue"
:options="selectOptions"
v-bind="filteredProps"
v-bind="combinedProps"
:disabled="readonly"
:class="cn(WidgetInputBaseClass, 'w-full text-xs')"
class="w-full text-xs bg-[#F9F8F4] dark-theme:bg-[#0E0E12] border-[#E1DED5] dark-theme:border-[#15161C] !rounded-lg"
size="small"
:pt="{
option: 'text-xs'
@@ -20,14 +20,13 @@ import Select from 'primevue/select'
import { computed } from 'vue'
import { useWidgetValue } from '@/composables/graph/useWidgetValue'
import { useTransformCompatOverlayProps } from '@/composables/useTransformCompatOverlayProps'
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
import { cn } from '@/utils/tailwindUtil'
import {
PANEL_EXCLUDED_PROPS,
filterWidgetProps
} from '@/utils/widgetPropFilter'
import { WidgetInputBaseClass } from './layout'
import WidgetLayoutField from './layout/WidgetLayoutField.vue'
const props = defineProps<{
@@ -48,9 +47,13 @@ const { localValue, onChange } = useWidgetValue({
emit
})
const filteredProps = computed(() =>
filterWidgetProps(props.widget.options, PANEL_EXCLUDED_PROPS)
)
// Transform compatibility props for overlay positioning
const transformCompatProps = useTransformCompatOverlayProps()
const combinedProps = computed(() => ({
...filterWidgetProps(props.widget.options, PANEL_EXCLUDED_PROPS),
...transformCompatProps.value
}))
// Extract select options from widget options
const selectOptions = computed(() => {

View File

@@ -2,9 +2,9 @@
<WidgetLayoutField :widget="widget">
<TreeSelect
v-model="localValue"
v-bind="filteredProps"
v-bind="combinedProps"
:disabled="readonly"
:class="cn(WidgetInputBaseClass, 'w-full text-xs')"
class="w-full text-xs"
size="small"
@update:model-value="onChange"
/>
@@ -16,14 +16,13 @@ import TreeSelect from 'primevue/treeselect'
import { computed } from 'vue'
import { useWidgetValue } from '@/composables/graph/useWidgetValue'
import { useTransformCompatOverlayProps } from '@/composables/useTransformCompatOverlayProps'
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
import { cn } from '@/utils/tailwindUtil'
import {
PANEL_EXCLUDED_PROPS,
filterWidgetProps
} from '@/utils/widgetPropFilter'
import { WidgetInputBaseClass } from './layout'
import WidgetLayoutField from './layout/WidgetLayoutField.vue'
const props = defineProps<{
@@ -44,6 +43,9 @@ const { localValue, onChange } = useWidgetValue({
emit
})
// Transform compatibility props for overlay positioning
const transformCompatProps = useTransformCompatOverlayProps()
// TreeSelect specific excluded props
const TREE_SELECT_EXCLUDED_PROPS = [
...PANEL_EXCLUDED_PROPS,
@@ -51,7 +53,8 @@ const TREE_SELECT_EXCLUDED_PROPS = [
'inputStyle'
] as const
const filteredProps = computed(() =>
filterWidgetProps(props.widget.options, TREE_SELECT_EXCLUDED_PROPS)
)
const combinedProps = computed(() => ({
...filterWidgetProps(props.widget.options, TREE_SELECT_EXCLUDED_PROPS),
...transformCompatProps.value
}))
</script>