@fy-/fws-vue 2.3.14 → 2.3.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# This file has been completely rewritten and optimized
|
|
1
2
|
<script setup lang="ts">
|
|
2
3
|
import type { Component } from 'vue'
|
|
3
4
|
import type { APIPaging } from '../../composables/rest'
|
|
@@ -59,8 +60,8 @@ const availableHeight = computed(() => {
|
|
|
59
60
|
height -= infoPanelHeight.value
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
//
|
|
63
|
-
return `${height
|
|
63
|
+
// Use direct pixel values
|
|
64
|
+
return `${height}px`
|
|
64
65
|
})
|
|
65
66
|
|
|
66
67
|
// Use VueUse's useFullscreen for better fullscreen handling
|
|
@@ -146,6 +147,14 @@ const currentImage = computed(() => {
|
|
|
146
147
|
const imageCount = computed(() => props.images.length)
|
|
147
148
|
const currentIndex = computed(() => modelValue.value + 1)
|
|
148
149
|
|
|
150
|
+
// Helper function to adjust image size based on natural dimensions
|
|
151
|
+
function adjustImageSize(img: HTMLImageElement, availableHeightPx: number) {
|
|
152
|
+
if (img.naturalHeight > 0) {
|
|
153
|
+
const maxHeight = Math.min(img.naturalHeight, availableHeightPx)
|
|
154
|
+
img.style.maxHeight = `${maxHeight}px`
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
149
158
|
// Image size and positioning
|
|
150
159
|
const calculateImageSize = useDebounceFn(() => {
|
|
151
160
|
if (!imageContainerRef.value) return
|
|
@@ -155,22 +164,57 @@ const calculateImageSize = useDebounceFn(() => {
|
|
|
155
164
|
|
|
156
165
|
if (!imageElements || imageElements.length === 0) return
|
|
157
166
|
|
|
167
|
+
// Get current panel heights for accurate calculations
|
|
168
|
+
const topControlsCurrentHeight = topControlsRef.value?.offsetHeight || 0
|
|
169
|
+
const infoPanelCurrentHeight = infoPanel.value && infoPanelRef.value ? infoPanelRef.value.offsetHeight : 0
|
|
170
|
+
|
|
171
|
+
// Prepare for image sizing calculation
|
|
172
|
+
|
|
158
173
|
imageElements.forEach((img) => {
|
|
159
174
|
// Reset to ensure proper recalculation
|
|
160
175
|
img.style.maxHeight = ''
|
|
176
|
+
img.style.maxWidth = ''
|
|
161
177
|
// Force browser to recalculate styles
|
|
162
178
|
void img.offsetHeight
|
|
163
179
|
|
|
164
|
-
//
|
|
165
|
-
|
|
166
|
-
|
|
180
|
+
// Apply exact pixel measurements based on actual UI elements
|
|
181
|
+
const topHeight = topControlsCurrentHeight || 0
|
|
182
|
+
const infoHeight = infoPanelCurrentHeight || 0
|
|
183
|
+
const availableHeightPx = windowHeight.value - topHeight - infoHeight - 32 // 32px for padding
|
|
184
|
+
|
|
185
|
+
if (windowWidth.value <= 768) {
|
|
186
|
+
// Mobile specific sizing - use pixel values directly
|
|
187
|
+
img.style.maxHeight = `${availableHeightPx}px`
|
|
188
|
+
img.style.maxWidth = '90vw'
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
// Desktop sizing - account for sidebar if present
|
|
192
|
+
const sidebarWidth = sidePanel.value ? sidePanelRef.value?.offsetWidth || 256 : 0
|
|
193
|
+
const availableWidthPx = windowWidth.value - sidebarWidth - 48 // 48px for padding
|
|
194
|
+
|
|
195
|
+
img.style.maxHeight = `${availableHeightPx}px`
|
|
196
|
+
img.style.maxWidth = `${availableWidthPx}px`
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// For images, add special handling for natural dimensions
|
|
200
|
+
if (img instanceof HTMLImageElement) {
|
|
201
|
+
if (img.complete) {
|
|
202
|
+
adjustImageSize(img, availableHeightPx)
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
img.onload = () => adjustImageSize(img, availableHeightPx)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
167
208
|
})
|
|
168
209
|
})
|
|
169
210
|
}, 50)
|
|
170
211
|
|
|
171
|
-
// Update all layout measurements
|
|
212
|
+
// Update all layout measurements when any relevant state changes
|
|
172
213
|
const updateLayout = useDebounceFn(() => {
|
|
173
|
-
|
|
214
|
+
// Recalculate image size with a small delay to ensure all DOM updates are processed
|
|
215
|
+
setTimeout(() => {
|
|
216
|
+
calculateImageSize()
|
|
217
|
+
}, 10)
|
|
174
218
|
}, 50)
|
|
175
219
|
|
|
176
220
|
// Modal controls
|
|
@@ -238,6 +282,11 @@ function goNextImage() {
|
|
|
238
282
|
modelValue.value = 0
|
|
239
283
|
}
|
|
240
284
|
resetControlsTimer()
|
|
285
|
+
|
|
286
|
+
// Force layout update when image changes
|
|
287
|
+
nextTick(() => {
|
|
288
|
+
updateLayout()
|
|
289
|
+
})
|
|
241
290
|
}
|
|
242
291
|
|
|
243
292
|
function goPrevImage() {
|
|
@@ -249,6 +298,11 @@ function goPrevImage() {
|
|
|
249
298
|
modelValue.value = props.images.length - 1 > 0 ? props.images.length - 1 : 0
|
|
250
299
|
}
|
|
251
300
|
resetControlsTimer()
|
|
301
|
+
|
|
302
|
+
// Force layout update when image changes
|
|
303
|
+
nextTick(() => {
|
|
304
|
+
updateLayout()
|
|
305
|
+
})
|
|
252
306
|
}
|
|
253
307
|
|
|
254
308
|
// UI control functions
|
|
@@ -439,6 +493,7 @@ watch(
|
|
|
439
493
|
galleryHeight,
|
|
440
494
|
topControlsHeight,
|
|
441
495
|
infoPanelHeight,
|
|
496
|
+
modelValue, // Watch for model value changes to update layout
|
|
442
497
|
],
|
|
443
498
|
() => {
|
|
444
499
|
updateLayout()
|
|
@@ -582,7 +637,8 @@ onUnmounted(() => {
|
|
|
582
637
|
<!-- Main Image Area - Fills available space -->
|
|
583
638
|
<div
|
|
584
639
|
class="relative flex-1 h-full flex items-center justify-center"
|
|
585
|
-
:class="{ 'lg:pr-64': sidePanel }"
|
|
640
|
+
:class="{ 'lg:pr-64': sidePanel, 'lg:max-w-[calc(100%-16rem)]': sidePanel }"
|
|
641
|
+
style="max-width: 100%;"
|
|
586
642
|
>
|
|
587
643
|
<!-- Image Navigation Controls - Left -->
|
|
588
644
|
<transition
|
|
@@ -641,6 +697,7 @@ onUnmounted(() => {
|
|
|
641
697
|
:style="{ maxHeight: availableHeight }"
|
|
642
698
|
:src="modelValueSrc"
|
|
643
699
|
:alt="`Gallery image ${modelValue + 1}`"
|
|
700
|
+
@load="updateLayout"
|
|
644
701
|
>
|
|
645
702
|
<component
|
|
646
703
|
:is="imageComponent"
|
|
@@ -672,6 +729,7 @@ onUnmounted(() => {
|
|
|
672
729
|
<div
|
|
673
730
|
v-if="showControls && images.length > 1"
|
|
674
731
|
class="absolute right-0 z-40 h-full flex items-center px-2 md:px-4"
|
|
732
|
+
:class="{ 'lg:mr-64': sidePanel }"
|
|
675
733
|
>
|
|
676
734
|
<button
|
|
677
735
|
class="btn bg-fv-neutral-800/70 hover:bg-fv-neutral-700/90 backdrop-blur-sm p-2 rounded-full transition-transform transform hover:scale-110"
|
|
@@ -714,7 +772,7 @@ onUnmounted(() => {
|
|
|
714
772
|
<div
|
|
715
773
|
v-if="sidePanel"
|
|
716
774
|
ref="sidePanelRef"
|
|
717
|
-
class="side-panel hidden lg:block absolute right-0 top-0 bottom-0 w-64 bg-fv-neutral-800/90 backdrop-blur-md overflow-y-auto z-40"
|
|
775
|
+
class="side-panel hidden lg:block absolute right-0 top-0 bottom-0 w-64 bg-fv-neutral-800/90 backdrop-blur-md overflow-y-auto z-40 cool-scroll"
|
|
718
776
|
:style="{ 'padding-top': `${topControlsHeight}px` }"
|
|
719
777
|
>
|
|
720
778
|
<!-- Paging Controls if needed -->
|