mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-07 14:34:41 +00:00
Compare commits
1 Commits
update-ing
...
cloud/1.44
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ab9752af8 |
@@ -40,7 +40,10 @@
|
||||
|
||||
<template #contentFilter>
|
||||
<div class="relative flex flex-wrap justify-between gap-2 px-6 pb-4">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<div
|
||||
:ref="primeVueOverlay.overlayScopeRef"
|
||||
class="flex flex-wrap gap-2"
|
||||
>
|
||||
<!-- Model Filter -->
|
||||
<MultiSelect
|
||||
v-model="selectedModelObjects"
|
||||
@@ -48,6 +51,7 @@
|
||||
class="w-[250px]"
|
||||
:label="modelFilterLabel"
|
||||
:options="modelOptions"
|
||||
:content-style="selectContentStyle"
|
||||
:show-search-box="true"
|
||||
:show-selected-count="true"
|
||||
:show-clear-button="true"
|
||||
@@ -62,6 +66,7 @@
|
||||
v-model="selectedUseCaseObjects"
|
||||
:label="useCaseFilterLabel"
|
||||
:options="useCaseOptions"
|
||||
:content-style="selectContentStyle"
|
||||
:show-search-box="true"
|
||||
:show-selected-count="true"
|
||||
:show-clear-button="true"
|
||||
@@ -76,6 +81,7 @@
|
||||
v-model="selectedRunsOnObjects"
|
||||
:label="runsOnFilterLabel"
|
||||
:options="runsOnOptions"
|
||||
:content-style="selectContentStyle"
|
||||
:show-search-box="true"
|
||||
:show-selected-count="true"
|
||||
:show-clear-button="true"
|
||||
@@ -92,6 +98,7 @@
|
||||
v-model="sortBy"
|
||||
:label="$t('templateWorkflows.sorting', 'Sort by')"
|
||||
:options="sortOptions"
|
||||
:content-style="selectContentStyle"
|
||||
class="w-62.5"
|
||||
>
|
||||
<template #icon>
|
||||
@@ -416,6 +423,7 @@ import BaseModalLayout from '@/components/widget/layout/BaseModalLayout.vue'
|
||||
import LeftSidePanel from '@/components/widget/panel/LeftSidePanel.vue'
|
||||
import { useIntersectionObserver } from '@/composables/useIntersectionObserver'
|
||||
import { useLazyPagination } from '@/composables/useLazyPagination'
|
||||
import { usePrimeVueOverlayChildStyle } from '@/composables/usePopoverSizing'
|
||||
import { useTemplateFiltering } from '@/composables/useTemplateFiltering'
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import { useTelemetry } from '@/platform/telemetry'
|
||||
@@ -632,6 +640,8 @@ const selectedRunsOnObjects = computed({
|
||||
const loadingTemplate = ref<string | null>(null)
|
||||
const hoveredTemplate = ref<string | null>(null)
|
||||
const cardRefs = ref<HTMLElement[]>([])
|
||||
const primeVueOverlay = usePrimeVueOverlayChildStyle()
|
||||
const selectContentStyle = primeVueOverlay.contentStyle
|
||||
|
||||
// Force re-render key for templates when sorting changes
|
||||
const templateListKey = ref(0)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<template>
|
||||
<div class="keybinding-panel flex flex-col gap-2">
|
||||
<div
|
||||
:ref="primeVueOverlay.overlayScopeRef"
|
||||
class="keybinding-panel flex flex-col gap-2"
|
||||
>
|
||||
<Teleport defer to="#keybinding-panel-header">
|
||||
<SearchInput
|
||||
v-model="filters['global'].value"
|
||||
@@ -15,10 +18,12 @@
|
||||
<div class="flex items-center gap-2">
|
||||
<KeybindingPresetToolbar
|
||||
:preset-names="presetNames"
|
||||
:content-style="keybindingOverlayContentStyle"
|
||||
@presets-changed="refreshPresetList"
|
||||
/>
|
||||
<DropdownMenu
|
||||
:entries="menuEntries"
|
||||
:style="keybindingOverlayContentStyle"
|
||||
icon="icon-[lucide--ellipsis]"
|
||||
item-class="text-sm gap-2"
|
||||
button-size="unset"
|
||||
@@ -238,6 +243,7 @@
|
||||
</ContextMenuTrigger>
|
||||
<ContextMenuPortal>
|
||||
<ContextMenuContent
|
||||
:style="keybindingOverlayContentStyle"
|
||||
class="z-1200 min-w-56 rounded-lg border border-border-subtle bg-base-background px-2 py-3 shadow-interface"
|
||||
>
|
||||
<ContextMenuItem
|
||||
@@ -314,6 +320,7 @@ import { showConfirmDialog } from '@/components/dialog/confirm/confirmDialog'
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import SearchInput from '@/components/ui/search-input/SearchInput.vue'
|
||||
import { useEditKeybindingDialog } from '@/composables/useEditKeybindingDialog'
|
||||
import { usePrimeVueOverlayChildStyle } from '@/composables/usePopoverSizing'
|
||||
import type { KeybindingImpl } from '@/platform/keybindings/keybinding'
|
||||
import { useKeybindingService } from '@/platform/keybindings/keybindingService'
|
||||
import { useKeybindingStore } from '@/platform/keybindings/keybindingStore'
|
||||
@@ -337,6 +344,8 @@ const settingStore = useSettingStore()
|
||||
const commandStore = useCommandStore()
|
||||
const dialogStore = useDialogStore()
|
||||
const { t } = useI18n()
|
||||
const primeVueOverlay = usePrimeVueOverlayChildStyle()
|
||||
const keybindingOverlayContentStyle = primeVueOverlay.contentStyle
|
||||
|
||||
const presetNames = ref<string[]>([])
|
||||
|
||||
|
||||
@@ -9,7 +9,10 @@
|
||||
{{ displayLabel }}
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent class="max-w-64 min-w-0 **:[[role=listbox]]:gap-1">
|
||||
<SelectContent
|
||||
:style="contentStyle"
|
||||
class="max-w-64 min-w-0 **:[[role=listbox]]:gap-1"
|
||||
>
|
||||
<div class="max-w-60">
|
||||
<SelectItem
|
||||
value="default"
|
||||
@@ -46,6 +49,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import type { StyleValue } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
@@ -57,8 +61,9 @@ import SelectValue from '@/components/ui/select/SelectValue.vue'
|
||||
import { useKeybindingPresetService } from '@/platform/keybindings/presetService'
|
||||
import { useKeybindingStore } from '@/platform/keybindings/keybindingStore'
|
||||
|
||||
const { presetNames } = defineProps<{
|
||||
const { presetNames, contentStyle } = defineProps<{
|
||||
presetNames: string[]
|
||||
contentStyle?: StyleValue
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
position="popper"
|
||||
:side-offset="8"
|
||||
align="start"
|
||||
:style="popoverStyle"
|
||||
:style="[popoverStyle, contentStyle]"
|
||||
:class="selectContentClass"
|
||||
@keydown="onContentKeydown"
|
||||
@focus-outside="preventFocusDismiss"
|
||||
@@ -152,6 +152,7 @@ import {
|
||||
ComboboxViewport
|
||||
} from 'reka-ui'
|
||||
import { computed, ref } from 'vue'
|
||||
import type { StyleValue } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
@@ -183,7 +184,8 @@ const {
|
||||
searchPlaceholder,
|
||||
listMaxHeight = '28rem',
|
||||
popoverMinWidth,
|
||||
popoverMaxWidth
|
||||
popoverMaxWidth,
|
||||
contentStyle
|
||||
} = defineProps<{
|
||||
/** Input label shown on the trigger button */
|
||||
label?: string
|
||||
@@ -207,6 +209,7 @@ const {
|
||||
popoverMinWidth?: string
|
||||
/** Maximum width of the popover (default: auto) */
|
||||
popoverMaxWidth?: string
|
||||
contentStyle?: StyleValue
|
||||
}>()
|
||||
|
||||
const selectedItems = defineModel<SelectOption[]>({
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
v-if="suggestions.length > 0"
|
||||
position="popper"
|
||||
:side-offset="4"
|
||||
:style="contentStyle"
|
||||
:class="
|
||||
cn(
|
||||
'z-3000 max-h-60 w-(--reka-combobox-trigger-width) overflow-y-auto',
|
||||
@@ -99,7 +100,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" generic="T">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import type { HTMLAttributes, StyleValue } from 'vue'
|
||||
|
||||
import { cn } from '@comfyorg/tailwind-utils'
|
||||
import {
|
||||
@@ -132,7 +133,8 @@ const {
|
||||
suggestions = [],
|
||||
optionLabel,
|
||||
optionKey,
|
||||
class: className
|
||||
class: className,
|
||||
contentStyle
|
||||
} = defineProps<{
|
||||
placeholder?: string
|
||||
icon?: string
|
||||
@@ -144,6 +146,7 @@ const {
|
||||
optionLabel?: keyof T & string
|
||||
optionKey?: keyof T & string
|
||||
class?: HTMLAttributes['class']
|
||||
contentStyle?: StyleValue
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
position="popper"
|
||||
:side-offset="8"
|
||||
align="start"
|
||||
:style="optionStyle"
|
||||
:style="[optionStyle, contentStyle]"
|
||||
:class="cn(selectContentClass, 'min-w-(--reka-select-trigger-width)')"
|
||||
@keydown="onContentKeydown"
|
||||
>
|
||||
@@ -82,6 +82,7 @@ import {
|
||||
SelectViewport
|
||||
} from 'reka-ui'
|
||||
import { ref } from 'vue'
|
||||
import type { StyleValue } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import {
|
||||
@@ -108,7 +109,8 @@ const {
|
||||
disabled = false,
|
||||
listMaxHeight = '28rem',
|
||||
popoverMinWidth,
|
||||
popoverMaxWidth
|
||||
popoverMaxWidth,
|
||||
contentStyle
|
||||
} = defineProps<{
|
||||
label?: string
|
||||
options?: SelectOption[]
|
||||
@@ -126,6 +128,7 @@ const {
|
||||
popoverMinWidth?: string
|
||||
/** Maximum width of the popover (default: auto) */
|
||||
popoverMaxWidth?: string
|
||||
contentStyle?: StyleValue
|
||||
}>()
|
||||
|
||||
const selectedItem = defineModel<string | undefined>({ required: true })
|
||||
|
||||
91
src/composables/usePopoverSizing.test.ts
Normal file
91
src/composables/usePopoverSizing.test.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
||||
import { effectScope } from 'vue'
|
||||
import type { EffectScope } from 'vue'
|
||||
|
||||
import { usePrimeVueOverlayChildStyle } from '@/composables/usePopoverSizing'
|
||||
|
||||
describe('usePrimeVueOverlayChildStyle', () => {
|
||||
let scope: EffectScope | undefined
|
||||
|
||||
function mountComposable() {
|
||||
scope = effectScope()
|
||||
let composable: ReturnType<typeof usePrimeVueOverlayChildStyle> | undefined
|
||||
|
||||
scope.run(() => {
|
||||
composable = usePrimeVueOverlayChildStyle()
|
||||
})
|
||||
|
||||
if (!composable) {
|
||||
throw new Error('Failed to mount composable')
|
||||
}
|
||||
|
||||
return composable
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
document.body.innerHTML = ''
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
scope?.stop()
|
||||
scope = undefined
|
||||
document.body.innerHTML = ''
|
||||
})
|
||||
|
||||
it('preserves existing stacking when there is no PrimeVue parent overlay', () => {
|
||||
const { overlayScopeRef, contentStyle } = mountComposable()
|
||||
|
||||
overlayScopeRef.value = document.createElement('div')
|
||||
|
||||
expect(contentStyle.value).toEqual({})
|
||||
})
|
||||
|
||||
it('renders above the closest PrimeVue dialog mask', () => {
|
||||
const { overlayScopeRef, contentStyle } = mountComposable()
|
||||
|
||||
overlayScopeRef.value = appendPrimeVueOverlay('p-dialog-mask', 5000)
|
||||
|
||||
expect(contentStyle.value).toEqual({ zIndex: 5001 })
|
||||
})
|
||||
|
||||
it('renders above the closest PrimeVue overlay mask', () => {
|
||||
const { overlayScopeRef, contentStyle } = mountComposable()
|
||||
|
||||
overlayScopeRef.value = appendPrimeVueOverlay('p-overlay-mask', 4200)
|
||||
|
||||
expect(contentStyle.value).toEqual({ zIndex: 4201 })
|
||||
})
|
||||
|
||||
it('does not drop below the Reka select overlay z-index floor', () => {
|
||||
const { overlayScopeRef, contentStyle } = mountComposable()
|
||||
|
||||
overlayScopeRef.value = appendPrimeVueOverlay('p-dialog-mask', 1200)
|
||||
|
||||
expect(contentStyle.value).toEqual({ zIndex: 3000 })
|
||||
})
|
||||
|
||||
it('preserves existing stacking when the PrimeVue overlay z-index is not numeric', () => {
|
||||
const { overlayScopeRef, contentStyle } = mountComposable()
|
||||
|
||||
overlayScopeRef.value = appendPrimeVueOverlay('p-dialog-mask')
|
||||
|
||||
expect(contentStyle.value).toEqual({})
|
||||
})
|
||||
})
|
||||
|
||||
function appendPrimeVueOverlay(
|
||||
className: string,
|
||||
zIndex?: number
|
||||
): HTMLElement {
|
||||
const overlay = document.createElement('div')
|
||||
overlay.className = className
|
||||
if (zIndex !== undefined) {
|
||||
overlay.style.zIndex = String(zIndex)
|
||||
}
|
||||
|
||||
const anchor = document.createElement('div')
|
||||
overlay.append(anchor)
|
||||
document.body.append(overlay)
|
||||
|
||||
return anchor
|
||||
}
|
||||
@@ -1,11 +1,14 @@
|
||||
import { computed } from 'vue'
|
||||
import type { CSSProperties, ComputedRef } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import type { CSSProperties, ComputedRef, Ref } from 'vue'
|
||||
|
||||
interface PopoverSizeOptions {
|
||||
minWidth?: string
|
||||
maxWidth?: string
|
||||
}
|
||||
|
||||
// Matches the highest existing Reka popover z-index (e.g. z-3000 on SearchAutocomplete).
|
||||
const PRIMEVUE_DIALOG_CHILD_Z_INDEX_FLOOR = 3000
|
||||
|
||||
/**
|
||||
* Composable for managing popover sizing styles
|
||||
* @param options Popover size configuration
|
||||
@@ -29,3 +32,30 @@ export function usePopoverSizing(
|
||||
return style
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps portaled Reka popovers above their containing PrimeVue dialog.
|
||||
*
|
||||
* This is a temporary bridge while PrimeVue dialogs and controls are
|
||||
* incrementally migrated to Reka UI. Once the affected PrimeVue parents are
|
||||
* migrated, this helper should be removed with the compatibility patch.
|
||||
*/
|
||||
export function usePrimeVueOverlayChildStyle(): {
|
||||
overlayScopeRef: Ref<HTMLElement | null>
|
||||
contentStyle: ComputedRef<CSSProperties>
|
||||
} {
|
||||
const overlayScopeRef = ref<HTMLElement | null>(null)
|
||||
const contentStyle = computed<CSSProperties>(() => {
|
||||
const overlay = overlayScopeRef.value?.closest(
|
||||
'.p-dialog-mask, .p-overlay-mask'
|
||||
)
|
||||
if (!overlay) return {}
|
||||
|
||||
const zIndex = Number.parseInt(getComputedStyle(overlay).zIndex, 10)
|
||||
if (!Number.isFinite(zIndex)) return {}
|
||||
|
||||
return { zIndex: Math.max(PRIMEVUE_DIALOG_CHILD_Z_INDEX_FLOOR, zIndex + 1) }
|
||||
})
|
||||
|
||||
return { overlayScopeRef, contentStyle }
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
<template #header>
|
||||
<div
|
||||
:ref="primeVueOverlay.overlayScopeRef"
|
||||
class="flex w-full items-center justify-between gap-2"
|
||||
@click.self="focusedAsset = null"
|
||||
>
|
||||
@@ -52,6 +53,7 @@
|
||||
<AssetFilterBar
|
||||
:assets="categoryFilteredAssets"
|
||||
:show-ownership-filter
|
||||
:content-style="selectContentStyle"
|
||||
@filter-change="updateFilters"
|
||||
@click.self="focusedAsset = null"
|
||||
/>
|
||||
@@ -72,7 +74,12 @@
|
||||
</template>
|
||||
|
||||
<template #rightPanel>
|
||||
<ModelInfoPanel v-if="focusedAsset" :asset="focusedAsset" :cache-key />
|
||||
<ModelInfoPanel
|
||||
v-if="focusedAsset"
|
||||
:asset="focusedAsset"
|
||||
:cache-key
|
||||
:select-content-style="selectContentStyle"
|
||||
/>
|
||||
<div
|
||||
v-else
|
||||
class="flex h-full items-center justify-center p-6 text-center wrap-break-word text-muted"
|
||||
@@ -92,6 +99,7 @@ import SearchInput from '@/components/ui/search-input/SearchInput.vue'
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import BaseModalLayout from '@/components/widget/layout/BaseModalLayout.vue'
|
||||
import LeftSidePanel from '@/components/widget/panel/LeftSidePanel.vue'
|
||||
import { usePrimeVueOverlayChildStyle } from '@/composables/usePopoverSizing'
|
||||
import AssetFilterBar from '@/platform/assets/components/AssetFilterBar.vue'
|
||||
import AssetGrid from '@/platform/assets/components/AssetGrid.vue'
|
||||
import ModelInfoPanel from '@/platform/assets/components/modelInfo/ModelInfoPanel.vue'
|
||||
@@ -109,6 +117,8 @@ const { t } = useI18n()
|
||||
const assetStore = useAssetsStore()
|
||||
const modelToNodeStore = useModelToNodeStore()
|
||||
const breakpoints = useBreakpoints(breakpointsTailwind)
|
||||
const primeVueOverlay = usePrimeVueOverlayChildStyle()
|
||||
const selectContentStyle = primeVueOverlay.contentStyle
|
||||
|
||||
const props = defineProps<{
|
||||
nodeType?: string
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
v-model="activeFileFormatObjects"
|
||||
:label="$t('assetBrowser.fileFormats')"
|
||||
:options="availableFileFormats"
|
||||
:content-style="contentStyle"
|
||||
class="min-w-32"
|
||||
data-component-id="asset-filter-file-formats"
|
||||
@update:model-value="handleFilterChange"
|
||||
@@ -22,6 +23,7 @@
|
||||
v-model="activeBaseModelObjects"
|
||||
:label="$t('assetBrowser.baseModels')"
|
||||
:options="availableBaseModels"
|
||||
:content-style="contentStyle"
|
||||
class="min-w-32"
|
||||
data-component-id="asset-filter-base-models"
|
||||
@update:model-value="handleFilterChange"
|
||||
@@ -32,6 +34,7 @@
|
||||
v-model="ownership"
|
||||
:label="$t('assetBrowser.ownership')"
|
||||
:options="ownershipOptions"
|
||||
:content-style="contentStyle"
|
||||
class="min-w-32"
|
||||
data-component-id="asset-filter-ownership"
|
||||
@update:model-value="handleFilterChange"
|
||||
@@ -43,6 +46,7 @@
|
||||
v-model="sortBy"
|
||||
:label="$t('assetBrowser.sortBy')"
|
||||
:options="sortOptions"
|
||||
:content-style="contentStyle"
|
||||
class="min-w-32"
|
||||
data-component-id="asset-filter-sort"
|
||||
@update:model-value="handleFilterChange"
|
||||
@@ -57,6 +61,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import type { StyleValue } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import MultiSelect from '@/components/ui/multi-select/MultiSelect.vue'
|
||||
@@ -78,9 +83,14 @@ const sortOptions = computed(() => [
|
||||
{ name: t('assetBrowser.sortZA'), value: 'name-desc' as const }
|
||||
])
|
||||
|
||||
const { assets = [], showOwnershipFilter = false } = defineProps<{
|
||||
const {
|
||||
assets = [],
|
||||
showOwnershipFilter = false,
|
||||
contentStyle
|
||||
} = defineProps<{
|
||||
assets?: AssetItem[]
|
||||
showOwnershipFilter?: boolean
|
||||
contentStyle?: StyleValue
|
||||
}>()
|
||||
|
||||
const selectedFileFormats = ref<SelectOption[]>([])
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<template>
|
||||
<div class="flex flex-col gap-4 text-sm text-muted-foreground">
|
||||
<div
|
||||
:ref="primeVueOverlay.overlayScopeRef"
|
||||
class="flex flex-col gap-4 text-sm text-muted-foreground"
|
||||
>
|
||||
<div class="flex flex-col gap-2">
|
||||
<p class="m-0">
|
||||
{{ $t('assetBrowser.modelAssociatedWithLink') }}
|
||||
@@ -39,6 +42,7 @@
|
||||
"
|
||||
:options="modelTypes"
|
||||
:disabled="isLoading"
|
||||
:content-style="selectContentStyle"
|
||||
data-attr="upload-model-step2-type-selector"
|
||||
/>
|
||||
</div>
|
||||
@@ -47,6 +51,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import SingleSelect from '@/components/ui/single-select/SingleSelect.vue'
|
||||
import { usePrimeVueOverlayChildStyle } from '@/composables/usePopoverSizing'
|
||||
import { useModelTypes } from '@/platform/assets/composables/useModelTypes'
|
||||
import type { AssetMetadata } from '@/platform/assets/schemas/assetSchema'
|
||||
|
||||
@@ -58,4 +63,6 @@ defineProps<{
|
||||
const modelValue = defineModel<string | undefined>()
|
||||
|
||||
const { modelTypes, isLoading } = useModelTypes()
|
||||
const primeVueOverlay = usePrimeVueOverlayChildStyle()
|
||||
const selectContentStyle = primeVueOverlay.contentStyle
|
||||
</script>
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
:placeholder="t('assetBrowser.modelInfo.selectModelType')"
|
||||
/>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectContent :style="selectContentStyle">
|
||||
<SelectItem
|
||||
v-for="option in modelTypes"
|
||||
:key="option.value"
|
||||
@@ -210,6 +210,7 @@
|
||||
<script setup lang="ts">
|
||||
import { useDebounceFn } from '@vueuse/core'
|
||||
import { computed, ref, useTemplateRef, watch } from 'vue'
|
||||
import type { StyleValue } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import EditableText from '@/components/common/EditableText.vue'
|
||||
@@ -257,9 +258,10 @@ const accordionClass = cn(
|
||||
'border-t border-border-default bg-modal-panel-background'
|
||||
)
|
||||
|
||||
const { asset, cacheKey } = defineProps<{
|
||||
const { asset, cacheKey, selectContentStyle } = defineProps<{
|
||||
asset: AssetDisplayItem
|
||||
cacheKey?: string
|
||||
selectContentStyle?: StyleValue
|
||||
}>()
|
||||
|
||||
const assetsStore = useAssetsStore()
|
||||
|
||||
@@ -14,16 +14,21 @@
|
||||
</template>
|
||||
|
||||
<template #header>
|
||||
<div class="flex w-full items-center justify-between gap-2">
|
||||
<div
|
||||
:ref="primeVueOverlay.overlayScopeRef"
|
||||
class="flex w-full items-center justify-between gap-2"
|
||||
>
|
||||
<div class="flex w-full items-center gap-2">
|
||||
<SingleSelect
|
||||
v-model="searchMode"
|
||||
class="min-w-34"
|
||||
:options="filterOptions"
|
||||
:content-style="selectContentStyle"
|
||||
/>
|
||||
<SearchAutocomplete
|
||||
v-model="searchQuery"
|
||||
:suggestions="suggestions"
|
||||
:content-style="selectContentStyle"
|
||||
:placeholder="$t('manager.searchPlaceholder')"
|
||||
option-label="query"
|
||||
autofocus
|
||||
@@ -87,6 +92,7 @@
|
||||
v-model="sortField"
|
||||
:label="$t('g.sort')"
|
||||
:options="availableSortOptions"
|
||||
:content-style="selectContentStyle"
|
||||
class="w-48"
|
||||
>
|
||||
<template #icon>
|
||||
@@ -163,6 +169,7 @@ import Button from '@/components/ui/button/Button.vue'
|
||||
import BaseModalLayout from '@/components/widget/layout/BaseModalLayout.vue'
|
||||
import LeftSidePanel from '@/components/widget/panel/LeftSidePanel.vue'
|
||||
import { useExternalLink } from '@/composables/useExternalLink'
|
||||
import { usePrimeVueOverlayChildStyle } from '@/composables/usePopoverSizing'
|
||||
import { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore'
|
||||
import { useComfyRegistryStore } from '@/stores/comfyRegistryStore'
|
||||
import type { components } from '@/types/comfyRegistryTypes'
|
||||
@@ -197,6 +204,8 @@ const { initialTab, initialPackId, onClose } = defineProps<{
|
||||
provide(OnCloseKey, onClose)
|
||||
|
||||
const { t } = useI18n()
|
||||
const primeVueOverlay = usePrimeVueOverlayChildStyle()
|
||||
const selectContentStyle = primeVueOverlay.contentStyle
|
||||
const { buildDocsUrl } = useExternalLink()
|
||||
const comfyManagerStore = useComfyManagerStore()
|
||||
const { getPackById } = useComfyRegistryStore()
|
||||
|
||||
Reference in New Issue
Block a user