mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-30 03:01:54 +00:00
fix: enhance CardContainer and MultiSelect components with improved props handling and filtering logic
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :class="containerClasses">
|
<div :class="containerClasses" :style="containerStyle">
|
||||||
<slot name="top"></slot>
|
<slot name="top"></slot>
|
||||||
<slot name="bottom"></slot>
|
<slot name="bottom"></slot>
|
||||||
</div>
|
</div>
|
||||||
@@ -8,8 +8,14 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const { ratio = 'square' } = defineProps<{
|
const {
|
||||||
ratio?: 'square' | 'portrait' | 'tallPortrait'
|
ratio = 'square',
|
||||||
|
maxWidth,
|
||||||
|
minWidth
|
||||||
|
} = defineProps<{
|
||||||
|
maxWidth?: number
|
||||||
|
minWidth?: number
|
||||||
|
ratio?: 'square' | 'portrait' | 'tallPortrait' | 'none'
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const containerClasses = computed(() => {
|
const containerClasses = computed(() => {
|
||||||
@@ -25,4 +31,13 @@ const containerClasses = computed(() => {
|
|||||||
|
|
||||||
return `${baseClasses} ${ratioClasses[ratio]}`
|
return `${baseClasses} ${ratioClasses[ratio]}`
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const containerStyle = computed(() =>
|
||||||
|
maxWidth || minWidth
|
||||||
|
? {
|
||||||
|
maxWidth: `${maxWidth}px`,
|
||||||
|
minWidth: `${minWidth}px`
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -141,7 +141,7 @@
|
|||||||
v-for="template in displayTemplates"
|
v-for="template in displayTemplates"
|
||||||
:key="template.name"
|
:key="template.name"
|
||||||
ref="cardRefs"
|
ref="cardRefs"
|
||||||
:ratio="undefined"
|
ratio="none"
|
||||||
:max-width="300"
|
:max-width="300"
|
||||||
:min-width="200"
|
:min-width="200"
|
||||||
class="cursor-pointer transition-all duration-300 hover:scale-[1.02]"
|
class="cursor-pointer transition-all duration-300 hover:scale-[1.02]"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
-->
|
-->
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
v-model="selectedItems"
|
v-model="selectedItems"
|
||||||
v-bind="$attrs"
|
v-bind="{ ...$attrs, options: filteredOptions }"
|
||||||
option-label="name"
|
option-label="name"
|
||||||
unstyled
|
unstyled
|
||||||
:max-selected-labels="0"
|
:max-selected-labels="0"
|
||||||
@@ -100,11 +100,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import Fuse from 'fuse.js'
|
||||||
import Button from 'primevue/button'
|
import Button from 'primevue/button'
|
||||||
import MultiSelect, {
|
import MultiSelect, {
|
||||||
MultiSelectPassThroughMethodOptions
|
MultiSelectPassThroughMethodOptions
|
||||||
} from 'primevue/multiselect'
|
} from 'primevue/multiselect'
|
||||||
import { computed } from 'vue'
|
import { computed, useAttrs } from 'vue'
|
||||||
|
|
||||||
import SearchBox from '@/components/input/SearchBox.vue'
|
import SearchBox from '@/components/input/SearchBox.vue'
|
||||||
import { usePopoverSizing } from '@/composables/usePopoverSizing'
|
import { usePopoverSizing } from '@/composables/usePopoverSizing'
|
||||||
@@ -152,13 +153,41 @@ const {
|
|||||||
const selectedItems = defineModel<Option[]>({
|
const selectedItems = defineModel<Option[]>({
|
||||||
required: true
|
required: true
|
||||||
})
|
})
|
||||||
const searchQuery = defineModel<string>('searchQuery')
|
const searchQuery = defineModel<string>('searchQuery', { default: '' })
|
||||||
const selectedCount = computed(() => selectedItems.value.length)
|
const selectedCount = computed(() => selectedItems.value.length)
|
||||||
|
|
||||||
const popoverStyle = usePopoverSizing({
|
const popoverStyle = usePopoverSizing({
|
||||||
minWidth: popoverMinWidth,
|
minWidth: popoverMinWidth,
|
||||||
maxWidth: popoverMaxWidth
|
maxWidth: popoverMaxWidth
|
||||||
})
|
})
|
||||||
|
const attrs = useAttrs()
|
||||||
|
const originalOptions = computed(() => (attrs.options as Option[]) || [])
|
||||||
|
|
||||||
|
const fuse = computed(
|
||||||
|
() =>
|
||||||
|
new Fuse(originalOptions.value, {
|
||||||
|
keys: ['name', 'value'],
|
||||||
|
threshold: 0.3,
|
||||||
|
includeScore: false
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
// Filter options based on search, but always include selected items
|
||||||
|
const filteredOptions = computed(() => {
|
||||||
|
if (!searchQuery.value || searchQuery.value.trim() === '') {
|
||||||
|
return originalOptions.value
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchResults = fuse.value
|
||||||
|
.search(searchQuery.value)
|
||||||
|
.map((result) => result.item)
|
||||||
|
|
||||||
|
const selectedButNotInResults = selectedItems.value.filter(
|
||||||
|
(item) => !searchResults.some((result) => result.value === item.value)
|
||||||
|
)
|
||||||
|
|
||||||
|
return [...selectedButNotInResults, ...searchResults]
|
||||||
|
})
|
||||||
|
|
||||||
const pt = computed(() => ({
|
const pt = computed(() => ({
|
||||||
root: ({ props }: MultiSelectPassThroughMethodOptions) => ({
|
root: ({ props }: MultiSelectPassThroughMethodOptions) => ({
|
||||||
|
|||||||
Reference in New Issue
Block a user