pukaad-ui-lib 1.211.0 → 1.212.1

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.
Files changed (53) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/card/card-place-detail.d.vue.ts +22 -3
  3. package/dist/runtime/components/card/card-place-detail.vue +52 -83
  4. package/dist/runtime/components/card/card-place-detail.vue.d.ts +22 -3
  5. package/dist/runtime/components/card/card-reaction.vue +3 -3
  6. package/dist/runtime/components/card/card-review.d.vue.ts +4 -0
  7. package/dist/runtime/components/card/card-review.vue +21 -34
  8. package/dist/runtime/components/card/card-review.vue.d.ts +4 -0
  9. package/dist/runtime/components/carousel.d.vue.ts +2 -19
  10. package/dist/runtime/components/carousel.vue +42 -52
  11. package/dist/runtime/components/carousel.vue.d.ts +2 -19
  12. package/dist/runtime/components/display/display-image-place.d.vue.ts +12 -1
  13. package/dist/runtime/components/display/display-image-place.vue +102 -4
  14. package/dist/runtime/components/display/display-image-place.vue.d.ts +12 -1
  15. package/dist/runtime/components/display/display-image-review.vue +8 -12
  16. package/dist/runtime/components/display/display-rating-summary.d.vue.ts +17 -0
  17. package/dist/runtime/components/display/display-rating-summary.vue +55 -0
  18. package/dist/runtime/components/display/display-rating-summary.vue.d.ts +17 -0
  19. package/dist/runtime/components/image/image-cropper.d.vue.ts +1 -1
  20. package/dist/runtime/components/image/image-cropper.vue.d.ts +1 -1
  21. package/dist/runtime/components/input/input-file.d.vue.ts +1 -1
  22. package/dist/runtime/components/input/input-file.vue.d.ts +1 -1
  23. package/dist/runtime/components/input/input-password.d.vue.ts +1 -1
  24. package/dist/runtime/components/input/input-password.vue.d.ts +1 -1
  25. package/dist/runtime/components/input/input-radio.d.vue.ts +1 -1
  26. package/dist/runtime/components/input/input-radio.vue.d.ts +1 -1
  27. package/dist/runtime/components/input/input-slider.d.vue.ts +1 -1
  28. package/dist/runtime/components/input/input-slider.vue.d.ts +1 -1
  29. package/dist/runtime/components/modal/modal-media-view.d.vue.ts +21 -0
  30. package/dist/runtime/components/modal/modal-media-view.vue +23 -0
  31. package/dist/runtime/components/modal/modal-media-view.vue.d.ts +21 -0
  32. package/dist/runtime/components/modal/modal-password-confirmed.d.vue.ts +1 -1
  33. package/dist/runtime/components/modal/modal-password-confirmed.vue.d.ts +1 -1
  34. package/dist/runtime/components/modal/modal-password-verify.d.vue.ts +1 -1
  35. package/dist/runtime/components/modal/modal-password-verify.vue.d.ts +1 -1
  36. package/dist/runtime/components/modal/modal.d.vue.ts +2 -0
  37. package/dist/runtime/components/modal/modal.vue +6 -4
  38. package/dist/runtime/components/modal/modal.vue.d.ts +2 -0
  39. package/dist/runtime/components/ui/carousel/CarouselContent.vue +1 -1
  40. package/dist/runtime/components/ui/carousel/CarouselNext.vue +3 -3
  41. package/dist/runtime/components/ui/carousel/CarouselPrevious.vue +3 -3
  42. package/dist/runtime/components/ui/dialog/DialogContent.d.vue.ts +2 -0
  43. package/dist/runtime/components/ui/dialog/DialogContent.vue +9 -3
  44. package/dist/runtime/components/ui/dialog/DialogContent.vue.d.ts +2 -0
  45. package/dist/runtime/components/ui/native-select/NativeSelectOptGroup.d.vue.ts +50 -50
  46. package/dist/runtime/components/ui/native-select/NativeSelectOptGroup.vue.d.ts +50 -50
  47. package/dist/runtime/components/ui/native-select/NativeSelectOption.d.vue.ts +52 -52
  48. package/dist/runtime/components/ui/native-select/NativeSelectOption.vue.d.ts +52 -52
  49. package/package.json +1 -1
  50. /package/dist/runtime/assets/svg/socials/{TikTok.svg → Tiktok.svg} +0 -0
  51. /package/dist/runtime/assets/svg/socials/{YouTube.svg → Youtube.svg} +0 -0
  52. /package/dist/runtime/assets/svg/socials/{Facebook.svg → facebook.svg} +0 -0
  53. /package/dist/runtime/assets/svg/socials/{Instagram.svg → instagram.svg} +0 -0
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pukaad-ui-lib",
3
3
  "configKey": "pukaadUI",
4
- "version": "1.211.0",
4
+ "version": "1.212.1",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
@@ -1,9 +1,28 @@
1
- import type { Place } from "@/types/components/card/card-place-detail";
1
+ interface BusinessHour {
2
+ day: string;
3
+ time_range: string;
4
+ }
5
+ interface OpeningHours {
6
+ Business_hour: BusinessHour[];
7
+ Special_hour?: BusinessHour[];
8
+ }
9
+ interface SocialLink {
10
+ name: string;
11
+ link: string;
12
+ }
13
+ interface PlaceDetail {
14
+ description?: string;
15
+ category?: string;
16
+ open_status?: string;
17
+ opening_hour: OpeningHours;
18
+ phone?: string;
19
+ links?: SocialLink[];
20
+ }
2
21
  type __VLS_Props = {
3
- item?: Place;
22
+ item?: PlaceDetail;
4
23
  };
5
24
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
6
- item: Place;
25
+ item: PlaceDetail;
7
26
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
8
27
  declare const _default: typeof __VLS_export;
9
28
  export default _default;
@@ -1,94 +1,63 @@
1
1
  <template>
2
- <div class="w-full">
3
- <Card full-width>
4
- <div class="flex flex-col gap-[8px] font-body-large">
5
- <div class="flex gap-[8px]">
6
- <div class="pt-[3px]">
7
- <Icon name="lucide:circle-alert" size="20" class="text-primary" />
8
- </div>
9
- <div>
10
- {{ props.item.description }}
11
- </div>
12
- </div>
13
- <div class="flex gap-[8px]">
14
- <div class="pt-[3px]">
15
- <Icon name="lucide:tag" size="20" class="text-primary" />
16
- </div>
17
- <div>{{ props.item.category }}</div>
18
- </div>
19
- <div class="flex gap-[8px]">
20
- <div class="pt-[3px]">
21
- <Icon name="lucide:clock" size="20" class="text-primary" />
22
- </div>
23
- <div class="w-full flex flex-col gap-[8px]">
24
- <div class="text-success font-body-large-prominent">เปิดอยู่</div>
25
- <div class="flex flex-col gap-[4px]">
26
- <div
27
- v-for="(time, index) in props.item.opening_hour.Business_hour"
28
- :key="index"
29
- class="flex items-center justify-between w-full"
30
- >
31
- <div>{{ time.day }}</div>
32
- <div>{{ time.time_range }}</div>
33
- </div>
34
- </div>
2
+ <Card variant="outline">
3
+ <div class="flex flex-col gap-[16px]">
4
+ <div class="flex gap-[12px]">
5
+ <Icon name="lucide:circle-alert" :size="20" class="text-primary shrink-0 mt-[2px]" />
6
+ <div v-if="props.item.description">{{ props.item.description }}</div>
7
+ <div v-else class="text-cloud">ไม่มีข้อมูลคำอธิบาย</div>
8
+ </div>
35
9
 
36
- <div class="text-warning font-body-large-prominent">วันทำการพิเศษ</div>
10
+ <div class="flex gap-[12px]">
11
+ <Icon name="lucide:tag" :size="20" class="text-primary shrink-0 mt-[2px]" />
12
+ <div v-if="props.item.category">{{ props.item.category }}</div>
13
+ <div v-else class="text-cloud">ไม่มีข้อมูลประเภท</div>
14
+ </div>
37
15
 
38
- <div class="flex flex-col gap-[4px]">
39
- <div
40
- v-for="(time, i) in props.item.opening_hour.Special_hour"
41
- :key="i"
42
- class="flex items-center justify-between w-full text-warning"
43
- >
44
- <div>{{ time.day }}</div>
45
- <div>{{ time.time_range }}</div>
46
- </div>
47
- </div>
48
- </div>
49
- </div>
50
- <div class="flex gap-[8px]">
51
- <div class="pt-[3px]">
52
- <Icon name="lucide:phone" size="20" class="text-primary" />
53
- </div>
54
- <div>{{ props.item.phone }}</div>
55
- </div>
16
+ <div class="flex gap-[12px]">
17
+ <Icon name="lucide:clock" :size="20" class="text-primary shrink-0 mt-[2px]" />
18
+ <div v-if="props.item.opening_hour?.Business_hour?.length" class="flex flex-col gap-[4px] flex-1">
19
+ <div class="font-body-large-prominent text-success">{{ props.item.open_status ?? "\u0E40\u0E1B\u0E34\u0E14\u0E2D\u0E22\u0E39\u0E48" }}</div>
56
20
 
57
- <div class="flex gap-[8px]">
58
- <div class="pt-[3px]">
59
- <Icon name="lucide:square-pen" size="20" class="text-primary" />
21
+ <div v-for="(time, index) in props.item.opening_hour?.Business_hour" :key="`bh-${index}`"
22
+ class="flex items-center justify-between">
23
+ <span>{{ time.day }}</span>
24
+ <span>{{ time.time_range }}</span>
60
25
  </div>
61
- <div>{{ props.item.suggested_corrections }}</div>
62
- </div>
63
- <Divider />
64
26
 
65
- <div
66
- v-if="props.item.links && props.item.links.length > 0"
67
- class="flex flex-col gap-[8px]"
68
- >
69
- <div
70
- v-for="(linkItem, index) in props.item.links"
71
- :key="index"
72
- class="flex gap-[8px]"
73
- >
74
- <div class="pt-[3px]">
75
- <Icon
76
- :name="`pukaad-social:${linkItem.name}`"
77
- :size="20"
78
- class="text-primary"
79
- />
80
- </div>
81
- <div
82
- class="cursor-pointer hover:underline"
83
- @click="onClickLink(linkItem.link)"
84
- >
85
- {{ linkItem.link }}
27
+ <template v-if="props.item.opening_hour?.Special_hour?.length">
28
+ <div class="font-body-large-prominent text-warning mt-[8px]">วันทำการพิเศษ</div>
29
+ <div v-for="(time, i) in props.item.opening_hour.Special_hour" :key="`sh-${i}`"
30
+ class="flex items-center justify-between text-warning">
31
+ <span>{{ time.day }}</span>
32
+ <span>{{ time.time_range }}</span>
86
33
  </div>
87
- </div>
34
+ </template>
35
+ </div>
36
+ <div v-else class="text-cloud">ไม่มีข้อมูลเวลาทำการ</div>
37
+ </div>
38
+
39
+ <div class="flex gap-[12px]">
40
+ <Icon name="lucide:phone" :size="20" class="text-primary shrink-0 mt-[2px]" />
41
+ <div v-if="props.item.phone">{{ props.item.phone }}</div>
42
+ <div v-else class="text-cloud">ไม่มีข้อมูลเบอร์โทรศัพท์</div>
43
+ </div>
44
+
45
+ <Divider />
46
+
47
+ <div v-if="props.item.links?.length" class="flex flex-col gap-[8px]">
48
+ <div v-for="(linkItem, index) in props.item.links" :key="index"
49
+ class="flex gap-[12px] items-center cursor-pointer hover:underline" @click="onClickLink(linkItem.link)">
50
+ <Icon :name="`pukaad-social:${linkItem.name}`" :size="20" class="shrink-0" />
51
+ <span>{{ linkItem.link }}</span>
88
52
  </div>
89
53
  </div>
90
- </Card>
91
- </div>
54
+
55
+ <div v-else class="flex gap-[12px] items-center">
56
+ <Icon name="lucide:link" :size="20" class="text-primary shrink-0" />
57
+ <span class="text-cloud">ไม่มีข้อมูลช่องทางติดต่อ</span>
58
+ </div>
59
+ </div>
60
+ </Card>
92
61
  </template>
93
62
 
94
63
  <script setup>
@@ -96,9 +65,9 @@ const props = defineProps({
96
65
  item: { type: Object, required: false, default: () => ({
97
66
  description: "",
98
67
  category: "",
68
+ open_status: "",
99
69
  opening_hour: { Business_hour: [], Special_hour: [] },
100
70
  phone: "",
101
- suggested_corrections: "",
102
71
  links: []
103
72
  }) }
104
73
  });
@@ -1,9 +1,28 @@
1
- import type { Place } from "@/types/components/card/card-place-detail";
1
+ interface BusinessHour {
2
+ day: string;
3
+ time_range: string;
4
+ }
5
+ interface OpeningHours {
6
+ Business_hour: BusinessHour[];
7
+ Special_hour?: BusinessHour[];
8
+ }
9
+ interface SocialLink {
10
+ name: string;
11
+ link: string;
12
+ }
13
+ interface PlaceDetail {
14
+ description?: string;
15
+ category?: string;
16
+ open_status?: string;
17
+ opening_hour: OpeningHours;
18
+ phone?: string;
19
+ links?: SocialLink[];
20
+ }
2
21
  type __VLS_Props = {
3
- item?: Place;
22
+ item?: PlaceDetail;
4
23
  };
5
24
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
6
- item: Place;
25
+ item: PlaceDetail;
7
26
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
8
27
  declare const _default: typeof __VLS_export;
9
28
  export default _default;
@@ -89,14 +89,14 @@ const listReaction = computed(() => {
89
89
  const reactions = [
90
90
  {
91
91
  name: "liked",
92
- icon: "pukaad:thumbs-up-regular",
93
- iconReacted: "pukaad:thumbs-up-solid",
92
+ icon: "fa6-regular:thumbs-up",
93
+ iconReacted: "fa6-solid:thumbs-up",
94
94
  action: toggleLike
95
95
  },
96
96
  {
97
97
  name: "bookmarked",
98
98
  icon: "lucide:bookmark",
99
- iconReacted: "pukaad:bookmark-solid",
99
+ iconReacted: "fa6-solid:bookmark",
100
100
  action: toggleBookmark
101
101
  },
102
102
  {
@@ -2,6 +2,8 @@ import type { CardReviewProps } from "@/types/components/card/card-review";
2
2
  type __VLS_Props = {
3
3
  item: CardReviewProps;
4
4
  isProfile: boolean;
5
+ disabledLike?: boolean;
6
+ disabledMenu?: boolean;
5
7
  };
6
8
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
7
9
  "toggle-like": (item: CardReviewProps, liked: boolean) => any;
@@ -12,6 +14,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
12
14
  }>, {
13
15
  item: CardReviewProps;
14
16
  isProfile: boolean;
17
+ disabledLike: boolean;
18
+ disabledMenu: boolean;
15
19
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
20
  declare const _default: typeof __VLS_export;
17
21
  export default _default;
@@ -1,51 +1,33 @@
1
1
  <template>
2
2
  <div class="py-[16px] border-b-[1px] border-mercury flex gap-[16px] w-full">
3
3
  <div v-if="props.item.user.avatar">
4
- <!-- <Avatar :src="props.item.user.avatar" alt="profile_myProfile" size="30" class="cursor-pointer"
5
- @click="NavigateToProfile(props.item.user.path_name)" /> -->
4
+ <Avatar :src="props.item.user.avatar" alt="profile_myProfile" :size="30" class="cursor-pointer"
5
+ @click="NavigateToProfile(props.item.user.path_name)" />
6
6
  </div>
7
7
  <div class="flex flex-col gap-[24px] w-full">
8
8
  <div class="flex flex-col gap-[8px]">
9
9
  <div class="flex flex-col gap-[6px]">
10
10
  <div class="flex flex-col gap-[4px]">
11
11
  <div class="flex justify-between items-center">
12
- <div
13
- @click="NavigateToProfile(props.item.user.path_name)"
14
- class="font-body-large cursor-pointer"
15
- >
12
+ <div @click="NavigateToProfile(props.item.user.path_name)" class="font-body-large cursor-pointer">
16
13
  {{ props.item.user?.name }}
17
14
  </div>
18
15
  <div class="flex gap-[8px] items-center">
19
- <Button
20
- type="text"
21
- :variant="liked ? 'primary' : 'black'"
22
- :icon-size="20"
23
- size="tiny"
24
- :prepend-icon="
25
- liked ? 'pukaad:thumbs-up-solid' : 'pukaad:thumbs-up-regular'
26
- "
27
- :aria-pressed="liked"
28
- @click="toggleLike"
29
- disabled-padding
30
- >
31
- <div>
32
- {{ likeCount }}
33
- </div>
16
+ <Button variant="text" :color="liked ? 'primary' : 'default'" :disabled="props.disabledLike"
17
+ :aria-pressed="liked" @click="toggleLike">
18
+ <Icon :name="liked ? 'fa6-solid:thumbs-up' : 'fa6-regular:thumbs-up'" :size="20" />
19
+ {{ convertNumber(likeCount) }}
34
20
  </Button>
35
- <PickerOptionMenuUser :state="menuType" disabled-padding />
21
+ <PickerOptionMenuUser v-if="!props.disabledMenu" :state="menuType" disabled-padding />
36
22
  </div>
37
23
  </div>
38
24
  <div class="text-gray font-body-small">
39
- {{ props.item.user?.review_count }} รีวิว •
40
- {{ props.item.user?.like_count }} ชื่นชอบรีวิว
25
+ {{ convertNumber(props.item.user?.review_count ?? 0) }} รีวิว •
26
+ {{ convertNumber(props.item.user?.like_count ?? 0) }} ชื่นชอบรีวิว
41
27
  </div>
42
28
  </div>
43
29
  <div class="flex gap-[8px] items-center">
44
- <InputRating
45
- :size="16"
46
- readonly
47
- :model-value="props.item.review?.rating"
48
- />
30
+ <InputRating :size="16" readonly :model-value="props.item.review?.rating" />
49
31
  <div class="text-gray font-body-small">
50
32
  {{ props.item.review?.created_at }}
51
33
  </div>
@@ -57,10 +39,7 @@
57
39
  </div>
58
40
 
59
41
  <div v-if="props.item.review?.images?.length" class="flex gap-[8px]">
60
- <DisplayImageReview
61
- :items="props.item.review?.images"
62
- @select="selectImage"
63
- />
42
+ <DisplayImageReview :items="props.item.review?.images" @select="selectImage" />
64
43
  </div>
65
44
  </div>
66
45
  <div v-if="props.item.replies">
@@ -75,12 +54,16 @@
75
54
  </div>
76
55
  </div>
77
56
  </div>
57
+
58
+ <ModalMediaView v-model="isOpen" :items="props.item.review?.images" :start-index="startIndex" title="รูปภาพรีวิว" />
78
59
  </template>
79
60
 
80
61
  <script setup>
81
62
  import { computed, ref } from "vue";
82
63
  import { useRouter } from "vue-router";
64
+ import { useConvert } from "../../composables/useConvert";
83
65
  const router = useRouter();
66
+ const { convertNumber } = useConvert();
84
67
  const isOpen = ref(false);
85
68
  const props = defineProps({
86
69
  item: { type: Object, required: true, default: () => ({
@@ -107,7 +90,9 @@ const props = defineProps({
107
90
  created_at: ""
108
91
  }
109
92
  }) },
110
- isProfile: { type: Boolean, required: true, default: false }
93
+ isProfile: { type: Boolean, required: true, default: false },
94
+ disabledLike: { type: Boolean, required: false, default: false },
95
+ disabledMenu: { type: Boolean, required: false, default: false }
111
96
  });
112
97
  const emit = defineEmits(["toggle-like", "select-image"]);
113
98
  const liked = ref(props.item.review?.liked ?? false);
@@ -127,7 +112,9 @@ function toggleLike() {
127
112
  }
128
113
  emit("toggle-like", props.item, liked.value);
129
114
  }
115
+ const startIndex = ref(0);
130
116
  const selectImage = (index) => {
117
+ startIndex.value = index;
131
118
  isOpen.value = true;
132
119
  emit("select-image", props.item, index, liked.value);
133
120
  };
@@ -2,6 +2,8 @@ import type { CardReviewProps } from "@/types/components/card/card-review";
2
2
  type __VLS_Props = {
3
3
  item: CardReviewProps;
4
4
  isProfile: boolean;
5
+ disabledLike?: boolean;
6
+ disabledMenu?: boolean;
5
7
  };
6
8
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
7
9
  "toggle-like": (item: CardReviewProps, liked: boolean) => any;
@@ -12,6 +14,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
12
14
  }>, {
13
15
  item: CardReviewProps;
14
16
  isProfile: boolean;
17
+ disabledLike: boolean;
18
+ disabledMenu: boolean;
15
19
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
20
  declare const _default: typeof __VLS_export;
17
21
  export default _default;
@@ -1,25 +1,8 @@
1
1
  import type { CarouselProps } from "@/types/components/carousel";
2
- declare var __VLS_25: {};
3
- type __VLS_Slots = {} & {
4
- default?: (props: typeof __VLS_25) => any;
5
- };
6
- declare const __VLS_base: import("vue").DefineComponent<CarouselProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
7
- "clicked-image": () => any;
8
- change: (value: number) => any;
9
- }, string, import("vue").PublicProps, Readonly<CarouselProps> & Readonly<{
10
- "onClicked-image"?: (() => any) | undefined;
11
- onChange?: ((value: number) => any) | undefined;
12
- }>, {
2
+ type __VLS_Props = Pick<CarouselProps, "items" | "selectIndex">;
3
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
13
4
  items: string[];
14
5
  selectIndex: number;
15
- fullWidth: boolean;
16
- fullHeight: boolean;
17
6
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
- declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
19
7
  declare const _default: typeof __VLS_export;
20
8
  export default _default;
21
- type __VLS_WithSlots<T, S> = T & {
22
- new (): {
23
- $slots: S;
24
- };
25
- };
@@ -1,35 +1,34 @@
1
1
  <template>
2
- <div class="relative bg-black" @mouseenter="isHovered = true" @mouseleave="isHovered = false" :style="{
3
- width: props.fullWidth ? '100%' : `${props.width}px`,
4
- height: props.fullHeight ? '100%' : `${props.height}px`
5
- }">
6
- <div v-if="props.items?.length && props.items[currentIndex]" class="flex items-center justify-center w-full h-full"
7
- @click="onClickedImage">
8
- <Image v-if="!props.items[currentIndex]?.includes('.mp4')" :src="props.items[currentIndex]"
9
- :width="props.fullWidth ? 'auto' : props.width" :height="props.fullHeight ? 'auto' : props.height"
10
- fit="contain" />
11
- <Video v-else :src="props.items[currentIndex]" fit="contain" controls full-width full-height />
12
- </div>
13
- <div v-if="props.items.length > 1 && isHovered" class="absolute top-[16px] left-1/2 transform -translate-x-1/2">
14
- <div class="rounded-full py-[4px] px-[8px] bg-black/50 w-[100px] items-center">
15
- <div class="font-body-medium w-full text-center text-white">
16
- {{ currentIndex + 1 }}/{{ props.items.length }}
17
- </div>
2
+ <div class="relative w-full h-full">
3
+ <div class="absolute top-[20px] left-1/2 transform -translate-x-1/2 z-[50]">
4
+ <div class="rounded-full py-[6px] px-[16px] bg-black/60 flex items-center justify-center">
5
+ <span class="text-white text-sm font-medium tracking-widest">
6
+ {{ currentIndex + 1 }} / {{ props.items.length }}
7
+ </span>
18
8
  </div>
19
9
  </div>
20
- <div v-if="props.items.length > 1 && currentIndex > 0 && isHovered"
21
- class="absolute left-[16px] top-1/2 transform -translate-y-1/2">
22
- <Button prependIcon="lucide:chevron-left" circle variant="solid" color="black" @click="back" :icon-size="24"
23
- :padding="0" />
24
- </div>
25
- <div v-if="props.items.length > 1 && currentIndex < props.items.length - 1 && isHovered"
26
- class="absolute right-[16px] top-1/2 transform -translate-y-1/2">
27
- <Button prependIcon="lucide:chevron-right" circle variant="solid" color="black" @click="next" :icon-size="24"
28
- :padding="0" />
29
- </div>
30
- <div class="absolute bottom-[0] w-full">
31
- <slot name="default" />
32
- </div>
10
+
11
+ <ShadCarousel
12
+ :opts="{ startIndex: props.selectIndex }"
13
+ class="carousel-media w-full h-full"
14
+ @init-api="onInitApi"
15
+ >
16
+ <ShadCarouselContent class="h-full">
17
+ <ShadCarouselItem
18
+ v-for="(item, i) in props.items"
19
+ :key="i"
20
+ class="h-full flex items-center justify-center"
21
+ >
22
+ <img
23
+ :src="item"
24
+ class="w-full h-full object-contain select-none"
25
+ draggable="false"
26
+ />
27
+ </ShadCarouselItem>
28
+ </ShadCarouselContent>
29
+ <ShadCarouselPrevious class="!left-[12px]" />
30
+ <ShadCarouselNext class="!right-[12px]" />
31
+ </ShadCarousel>
33
32
  </div>
34
33
  </template>
35
34
 
@@ -37,32 +36,23 @@
37
36
  import { ref, watch } from "vue";
38
37
  const props = defineProps({
39
38
  items: { type: Array, required: true, default: () => [] },
40
- selectIndex: { type: Number, required: false, default: 0 },
41
- width: { type: [Number, String], required: false },
42
- height: { type: [Number, String], required: false },
43
- fullWidth: { type: Boolean, required: false, default: false },
44
- fullHeight: { type: Boolean, required: false, default: false }
39
+ selectIndex: { type: Number, required: false, default: 0 }
45
40
  });
46
- const emit = defineEmits(["clicked-image", "change"]);
47
41
  const currentIndex = ref(props.selectIndex);
48
- const isHovered = ref(false);
49
- function onClickedImage() {
50
- emit("clicked-image");
51
- }
52
- function back() {
53
- if (currentIndex.value > 0) {
54
- currentIndex.value--;
55
- emit("change", currentIndex.value);
56
- }
57
- }
58
- function next() {
59
- if (currentIndex.value < props.items.length - 1) {
60
- currentIndex.value++;
61
- emit("change", currentIndex.value);
62
- }
63
- }
42
+ const api = ref();
43
+ const onInitApi = (val) => {
44
+ api.value = val;
45
+ val.on("select", () => {
46
+ currentIndex.value = val.selectedScrollSnap();
47
+ });
48
+ };
64
49
  watch(
65
50
  () => props.selectIndex,
66
- (newVal) => currentIndex.value = newVal
51
+ (newVal) => {
52
+ currentIndex.value = newVal;
53
+ if (api.value) {
54
+ api.value.scrollTo(newVal);
55
+ }
56
+ }
67
57
  );
68
58
  </script>
@@ -1,25 +1,8 @@
1
1
  import type { CarouselProps } from "@/types/components/carousel";
2
- declare var __VLS_25: {};
3
- type __VLS_Slots = {} & {
4
- default?: (props: typeof __VLS_25) => any;
5
- };
6
- declare const __VLS_base: import("vue").DefineComponent<CarouselProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
7
- "clicked-image": () => any;
8
- change: (value: number) => any;
9
- }, string, import("vue").PublicProps, Readonly<CarouselProps> & Readonly<{
10
- "onClicked-image"?: (() => any) | undefined;
11
- onChange?: ((value: number) => any) | undefined;
12
- }>, {
2
+ type __VLS_Props = Pick<CarouselProps, "items" | "selectIndex">;
3
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
13
4
  items: string[];
14
5
  selectIndex: number;
15
- fullWidth: boolean;
16
- fullHeight: boolean;
17
6
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
- declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
19
7
  declare const _default: typeof __VLS_export;
20
8
  export default _default;
21
- type __VLS_WithSlots<T, S> = T & {
22
- new (): {
23
- $slots: S;
24
- };
25
- };
@@ -1,3 +1,14 @@
1
- declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
1
+ type __VLS_Props = {
2
+ photos?: string[];
3
+ videos?: string[];
4
+ variant?: "featured" | "album";
5
+ title?: string;
6
+ };
7
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
8
+ title: string;
9
+ variant: "featured" | "album";
10
+ photos: string[];
11
+ videos: string[];
12
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
2
13
  declare const _default: typeof __VLS_export;
3
14
  export default _default;