feat: image variants per image

This commit is contained in:
fsylvain committed 2026-10-08 19:57:51 +02:00
1 parent f567866161
commit 951fef18ba
92 files changed
+8695 -413

No files matched your search

+25 -2
View File
@@ -8,6 +8,8 @@ import { ApiError, useApi } from '@/composables/useApi'
import { useLibraryList } from '@/composables/useLibraryList'
import { classifyMediaError, type MediaItem } from '@/composables/useMedia'
import { oldestOf } from '@/composables/useMediaUpload'
import { useCanManageVariants } from '@/composables/useCanManageVariants'
import { useVariantCatalogStore } from '@/stores/variantCatalog'
import { hashFile } from '@/lib/fileHash'
import {
IMAGE_TYPE_REJECTION_TEXT,
@@ -17,6 +19,7 @@ import {
validateImageFile,
} from '@/lib/imageUpload'
import { libraryMatchText } from '@/lib/mediaFormat'
import { insertedUrl } from '@/lib/variants/variantOptions'
import { UNDERLINE_TAB_TRIGGER } from '@/lib/tabStyles'
import {
ASPECT_RATIOS,
@@ -55,7 +58,7 @@ const props = withDefaults(
const emit = defineEmits<{
uploaded: [item: MediaItem]
inserted: [item: MediaItem, alt: string]
inserted: [item: MediaItem, alt: string, src: string]
close: []
}>()
@@ -102,7 +105,9 @@ const tab = ref<Tab>('library')
const existing = ref<MediaItem | null>(null)
const selected = ref<MediaItem | null>(null)
const alt = ref('')
const variant = ref('')
let tabTouched = false
let variantsRequested = false
const naturalWidth = ref(0)
const naturalHeight = ref(0)
@@ -117,6 +122,8 @@ const sourceBitmap = ref<ImageBitmap | null>(null)
const { progress, start, abort } = useImageUpload()
const { request } = useApi()
const library = useLibraryList()
const canManageVariants = useCanManageVariants()
const catalog = useVariantCatalogStore()
let closeTimer: ReturnType<typeof setTimeout> | null = null
const uploadPercent = computed(() => {
@@ -418,11 +425,22 @@ function selectItem(item: MediaItem) {
}
selected.value = item
alt.value = ''
variant.value = ''
requestVariants()
}
function requestVariants() {
if (variantsRequested || !canManageVariants.value) {
return
}
variantsRequested = true
catalog.load()
}
async function searchLibrary(query: string) {
selected.value = null
alt.value = ''
variant.value = ''
await library.search(query)
}
@@ -430,7 +448,7 @@ function insertSelected() {
if (!selected.value) {
return
}
emit('inserted', selected.value, alt.value)
emit('inserted', selected.value, alt.value, insertedUrl(selected.value, variant.value))
open.value = false
}
@@ -710,6 +728,8 @@ watch(open, (isOpen) => {
existing.value = null
selected.value = null
alt.value = ''
variant.value = ''
variantsRequested = false
tabTouched = false
library.reset()
if (props.initialFile) {
@@ -768,6 +788,9 @@ onUnmounted(() => {
<MediaPicker
v-if="onLibraryTab"
v-model:alt="alt"
v-model:variant="variant"
:variants="catalog.status === 'ready' ? catalog.enabled : []"
:variants-ready="catalog.status === 'ready'"
:items="library.items.value"
:status="library.status.value"
:show-skeleton="library.showSkeleton.value"