@fy-/fws-vue 2.0.87 → 2.0.89

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,14 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { Dialog, DialogPanel, TransitionRoot } from "@headlessui/vue";
3
- import {
4
- ref,
5
- onMounted,
6
- reactive,
7
- onUnmounted,
8
- h,
9
- computed,
10
- defineComponent,
11
- } from "vue";
3
+ import { ref, onMounted, reactive, onUnmounted, h, computed } from "vue";
12
4
  import type { APIPaging } from "../../composables/rest";
13
5
  import { useEventBus } from "../../composables/event-bus";
14
6
  import {
@@ -20,10 +12,11 @@ import {
20
12
  } from "@heroicons/vue/24/solid";
21
13
  import DefaultPaging from "./DefaultPaging.vue";
22
14
  import type { Component } from "vue";
15
+ import CollapseTransition from "./transitions/CollapseTransition.vue";
16
+
23
17
  const isGalleryOpen = ref<boolean>(false);
24
18
  const eventBus = useEventBus();
25
19
  const sidePanel = ref<boolean>(true);
26
- const direction = ref("next"); // Possible values: 'next' or 'prev'
27
20
 
28
21
  const props = withDefaults(
29
22
  defineProps<{
@@ -63,6 +56,7 @@ const props = withDefaults(
63
56
  ranking: false,
64
57
  },
65
58
  );
59
+
66
60
  const emit = defineEmits(["update:modelValue"]);
67
61
  const modelValue = computed({
68
62
  get: () => props.modelValue,
@@ -70,6 +64,9 @@ const modelValue = computed({
70
64
  emit("update:modelValue", i);
71
65
  },
72
66
  });
67
+
68
+ const direction = ref<"left" | "right">("right");
69
+
73
70
  const setModal = (value: boolean) => {
74
71
  if (value === true) {
75
72
  if (props.onOpen) props.onOpen();
@@ -78,17 +75,17 @@ const setModal = (value: boolean) => {
78
75
  }
79
76
  isGalleryOpen.value = value;
80
77
  };
78
+
81
79
  const openGalleryImage = (index: number | undefined) => {
82
- if (index === undefined) {
83
- modelValue.value = 0;
84
- } else {
85
- direction.value = index > modelValue.value ? "next" : "prev";
80
+ if (index === undefined) modelValue.value = 0;
81
+ else {
86
82
  modelValue.value = parseInt(index.toString());
87
83
  }
88
84
  setModal(true);
89
85
  };
86
+
90
87
  const goNextImage = () => {
91
- direction.value = "next";
88
+ direction.value = "right";
92
89
  if (modelValue.value < props.images.length - 1) {
93
90
  modelValue.value++;
94
91
  } else {
@@ -97,7 +94,7 @@ const goNextImage = () => {
97
94
  };
98
95
 
99
96
  const goPrevImage = () => {
100
- direction.value = "prev";
97
+ direction.value = "left";
101
98
  if (modelValue.value > 0) {
102
99
  modelValue.value--;
103
100
  } else {
@@ -111,6 +108,7 @@ const modelValueSrc = computed(() => {
111
108
  if (props.images[modelValue.value] == undefined) return false;
112
109
  return props.getImageUrl(props.images[modelValue.value]);
113
110
  });
111
+
114
112
  const start = reactive({ x: 0, y: 0 });
115
113
 
116
114
  const touchStart = (event: TouchEvent) => {
@@ -130,10 +128,10 @@ const touchEnd = (event: TouchEvent) => {
130
128
  // Add a threshold to prevent accidental swipes
131
129
  if (Math.abs(diffX) > Math.abs(diffY) && Math.abs(diffX) > 50) {
132
130
  if (diffX > 0) {
133
- direction.value = "next";
131
+ direction.value = "right";
134
132
  goNextImage();
135
133
  } else {
136
- direction.value = "prev";
134
+ direction.value = "left";
137
135
  goPrevImage();
138
136
  }
139
137
  }
@@ -145,18 +143,20 @@ const getBorderColor = (i: any) => {
145
143
  }
146
144
  return "";
147
145
  };
146
+
148
147
  const isKeyPressed = ref<boolean>(false);
148
+
149
149
  const handleKeyboardInput = (event: KeyboardEvent) => {
150
150
  if (isKeyPressed.value) return;
151
151
  switch (event.key) {
152
152
  case "ArrowRight":
153
153
  isKeyPressed.value = true;
154
- direction.value = "next";
154
+ direction.value = "right";
155
155
  goNextImage();
156
156
  break;
157
157
  case "ArrowLeft":
158
158
  isKeyPressed.value = true;
159
- direction.value = "prev";
159
+ direction.value = "left";
160
160
  goPrevImage();
161
161
  break;
162
162
  default:
@@ -169,9 +169,11 @@ const handleKeyboardRelease = (event: KeyboardEvent) => {
169
169
  isKeyPressed.value = false;
170
170
  }
171
171
  };
172
+
172
173
  const closeGallery = () => {
173
174
  setModal(false);
174
175
  };
176
+
175
177
  onMounted(() => {
176
178
  eventBus.on(`${props.id}GalleryImage`, openGalleryImage);
177
179
  eventBus.on(`${props.id}Gallery`, openGalleryImage);
@@ -181,6 +183,7 @@ onMounted(() => {
181
183
  window.addEventListener("keyup", handleKeyboardRelease);
182
184
  }
183
185
  });
186
+
184
187
  onUnmounted(() => {
185
188
  eventBus.off(`${props.id}Gallery`, openGalleryImage);
186
189
  eventBus.off(`${props.id}GalleryImage`, openGalleryImage);
@@ -190,52 +193,8 @@ onUnmounted(() => {
190
193
  window.removeEventListener("keyup", handleKeyboardRelease);
191
194
  }
192
195
  });
193
- const transitionName = computed(() => {
194
- return direction.value === "next" ? "slide-next" : "slide-prev";
195
- });
196
-
197
- const ImageComponent = defineComponent({
198
- props: ["src", "imageComponent", "modelValueSrc"],
199
- template: `
200
- <div v-if="src" class="media-wrapper">
201
- <img
202
- class="shadow max-w-full h-auto object-contain max-h-[85vh]"
203
- :src="modelValueSrc"
204
- v-if="modelValueSrc && imageComponent == 'img'"
205
- />
206
- <component
207
- v-else-if="modelValueSrc && imageComponent"
208
- :is="imageComponent"
209
- :image="modelValueSrc.image"
210
- :variant="modelValueSrc.variant"
211
- :alt="modelValueSrc.alt"
212
- class="shadow max-w-full h-auto object-contain max-h-[85vh]"
213
- />
214
- </div>
215
- `,
216
- });
217
- const VideoComponentWrapper = defineComponent({
218
- props: ["src", "videoComponent"],
219
- template: `
220
- <div v-if="src" class="media-wrapper">
221
- <ClientOnly>
222
- <component
223
- :is="videoComponent"
224
- :src="isVideo(images[modelValue])"
225
- class="shadow max-w-full h-auto object-contain max-h-[85vh]"
226
- />
227
- </ClientOnly>
228
- </div>
229
- `,
230
- });
231
- const currentMediaComponent = computed(() => {
232
- if (props.videoComponent && props.isVideo(props.images[modelValue.value])) {
233
- return VideoComponentWrapper;
234
- } else {
235
- return ImageComponent;
236
- }
237
- });
238
196
  </script>
197
+
239
198
  <template>
240
199
  <div>
241
200
  <TransitionRoot
@@ -283,26 +242,53 @@ const currentMediaComponent = computed(() => {
283
242
  </button>
284
243
  </div>
285
244
  <div
286
- class="flex-1 flex flex-col items-center justify-center max-w-full lg:max-w-[calc(100vw - 256px)]"
245
+ class="flex-1 flex flex-col items-center justify-center max-w-full lg:max-w-[calc(100vw - 256px)] overflow-hidden"
287
246
  @touchstart="touchStart"
288
247
  @touchend="touchEnd"
289
248
  >
290
- <transition :name="transitionName" mode="out-in">
291
- <component
292
- :is="currentMediaComponent"
293
- :key="modelValue"
294
- :src="modelValueSrc"
295
- :imageComponent="imageComponent"
296
- :videoComponent="videoComponent"
297
- class="flex-1 w-full max-w-full flex items-center justify-center"
298
- />
249
+ <transition :name="`slide-${direction}`">
250
+ <div
251
+ v-if="true"
252
+ :key="`image-display-${modelValue}`"
253
+ class="flex-1 w-full max-w-full flex flex-col items-center justify-center"
254
+ >
255
+ <div
256
+ class="flex-1 w-full max-w-full flex items-center justify-center"
257
+ >
258
+ <template
259
+ v-if="videoComponent && isVideo(images[modelValue])"
260
+ >
261
+ <ClientOnly>
262
+ <component
263
+ :is="videoComponent"
264
+ :src="isVideo(images[modelValue])"
265
+ class="shadow max-w-full h-auto object-contain max-h-[85vh]"
266
+ />
267
+ </ClientOnly>
268
+ </template>
269
+ <template v-else>
270
+ <img
271
+ class="shadow max-w-full h-auto object-contain max-h-[85vh]"
272
+ :src="modelValueSrc"
273
+ v-if="modelValueSrc && imageComponent == 'img'"
274
+ />
275
+ <component
276
+ v-else-if="modelValueSrc && imageComponent"
277
+ :is="imageComponent"
278
+ :image="modelValueSrc.image"
279
+ :variant="modelValueSrc.variant"
280
+ :alt="modelValueSrc.alt"
281
+ class="shadow max-w-full h-auto object-contain max-h-[85vh]"
282
+ />
283
+ </template>
284
+ </div>
285
+ <div
286
+ class="flex-0 py-2 flex items-center justify-center max-w-full w-full"
287
+ >
288
+ <slot :value="images[modelValue]"></slot>
289
+ </div>
290
+ </div>
299
291
  </transition>
300
-
301
- <div
302
- class="flex-0 py-2 flex items-center justify-center max-w-full w-full"
303
- >
304
- <slot :value="images[modelValue]"></slot>
305
- </div>
306
292
  </div>
307
293
  <div
308
294
  class="hidden lg:flex w-10 flex-shrink-0 items-center justify-center"
@@ -341,6 +327,7 @@ const currentMediaComponent = computed(() => {
341
327
  leave-to="translate-x-full"
342
328
  class="hidden lg:block flex-shrink-0 w-64 bg-fv-neutral-800 h-[100vh] max-h-[100vh] overflow-y-auto"
343
329
  >
330
+ <!-- Side panel content -->
344
331
  <div v-if="paging" class="flex items-center justify-center">
345
332
  <DefaultPaging :items="paging" :id="id" />
346
333
  </div>
@@ -349,11 +336,10 @@ const currentMediaComponent = computed(() => {
349
336
  v-for="i in images.length"
350
337
  :key="`bg_${id}_${i}`"
351
338
  class="hover:!brightness-100"
352
- :style="`${
353
- i - 1 == modelValue
354
- ? 'filter: brightness(1)'
355
- : 'filter: brightness(0.5)'
356
- }`"
339
+ :style="{
340
+ filter:
341
+ i - 1 == modelValue ? 'brightness(1)' : 'brightness(0.5)',
342
+ }"
357
343
  >
358
344
  <img
359
345
  @click="$eventBus.emit(`${id}GalleryImage`, i - 1)"
@@ -520,3 +506,30 @@ const currentMediaComponent = computed(() => {
520
506
  transform: translateX(100%);
521
507
  }
522
508
  </style>
509
+ <style scoped>
510
+ .slide-left-enter-active,
511
+ .slide-left-leave-active {
512
+ transition: transform 0.3s ease;
513
+ }
514
+ .slide-left-enter-from,
515
+ .slide-left-leave-to {
516
+ transform: translateX(100%);
517
+ }
518
+ .slide-left-enter-to,
519
+ .slide-left-leave-from {
520
+ transform: translateX(0);
521
+ }
522
+
523
+ .slide-right-enter-active,
524
+ .slide-right-leave-active {
525
+ transition: transform 0.3s ease;
526
+ }
527
+ .slide-right-enter-from,
528
+ .slide-right-leave-to {
529
+ transform: translateX(-100%);
530
+ }
531
+ .slide-right-enter-to,
532
+ .slide-right-leave-from {
533
+ transform: translateX(0);
534
+ }
535
+ </style>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fy-/fws-vue",
3
- "version": "2.0.87",
3
+ "version": "2.0.89",
4
4
  "author": "Florian 'Fy' Gasquez <m@fy.to>",
5
5
  "license": "MIT",
6
6
  "repository": {