pukaad-ui-lib 1.246.10 → 1.247.0
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.
- package/dist/module.json +1 -1
- package/dist/module.mjs +2 -0
- package/dist/runtime/components/card/card-user-item.d.vue.ts +4 -0
- package/dist/runtime/components/card/card-user-item.vue +3 -2
- package/dist/runtime/components/card/card-user-item.vue.d.ts +4 -0
- package/dist/runtime/components/draggable.vue +14 -12
- package/dist/runtime/components/drawer/drawer-profile-network.d.vue.ts +8 -0
- package/dist/runtime/components/drawer/drawer-profile-network.vue +114 -85
- package/dist/runtime/components/drawer/drawer-profile-network.vue.d.ts +8 -0
- package/dist/runtime/components/input/input-file.vue +0 -2
- package/dist/runtime/components/modal/modal-display-image.d.vue.ts +22 -0
- package/dist/runtime/components/modal/modal-display-image.vue +68 -0
- package/dist/runtime/components/modal/modal-display-image.vue.d.ts +22 -0
- package/package.json +3 -1
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -184,11 +184,13 @@ const module$1 = defineNuxtModule({
|
|
|
184
184
|
}
|
|
185
185
|
if (css.core) {
|
|
186
186
|
const coreCssPath = resolver.resolve("./runtime/assets/css/core.css");
|
|
187
|
+
const runtimeDir = resolver.resolve("./runtime");
|
|
187
188
|
const rootDir = _nuxt.options.rootDir;
|
|
188
189
|
const template = addTemplate({
|
|
189
190
|
filename: "pukaad-ui-core.css",
|
|
190
191
|
write: true,
|
|
191
192
|
getContents: () => `@import "${coreCssPath}";
|
|
193
|
+
@source "${runtimeDir}/**/*.vue";
|
|
192
194
|
@source "${rootDir}/**/*.vue";
|
|
193
195
|
@source "${rootDir}/**/*.ts";
|
|
194
196
|
`
|
|
@@ -6,14 +6,18 @@ export interface User {
|
|
|
6
6
|
public_count?: number;
|
|
7
7
|
description?: string;
|
|
8
8
|
is_following?: boolean;
|
|
9
|
+
is_my_profile?: boolean;
|
|
9
10
|
}
|
|
10
11
|
type __VLS_ModelProps = {
|
|
11
12
|
modelValue?: User;
|
|
12
13
|
};
|
|
13
14
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
14
15
|
"update:modelValue": (value: User) => any;
|
|
16
|
+
} & {
|
|
17
|
+
"require-auth": () => any;
|
|
15
18
|
}, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
|
|
16
19
|
"onUpdate:modelValue"?: ((value: User) => any) | undefined;
|
|
20
|
+
"onRequire-auth"?: (() => any) | undefined;
|
|
17
21
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
18
22
|
declare const _default: typeof __VLS_export;
|
|
19
23
|
export default _default;
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
</div>
|
|
19
19
|
</div>
|
|
20
20
|
</div>
|
|
21
|
-
<Button :color="!modelValue?.is_following ? 'primary' : void 0" variant="outline" @click.stop="onFollowToggle">
|
|
21
|
+
<Button v-if="!modelValue?.is_my_profile" :color="!modelValue?.is_following ? 'primary' : void 0" variant="outline" @click.stop="onFollowToggle">
|
|
22
22
|
{{ modelValue?.is_following ? "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E15\u0E34\u0E14\u0E15\u0E32\u0E21" : "\u0E15\u0E34\u0E14\u0E15\u0E32\u0E21" }}
|
|
23
23
|
</Button>
|
|
24
24
|
</div>
|
|
@@ -32,6 +32,7 @@ import { useApi } from "../../composables/useApi";
|
|
|
32
32
|
const modelValue = defineModel({ type: Object, ...{
|
|
33
33
|
default: () => ({})
|
|
34
34
|
} });
|
|
35
|
+
const emit = defineEmits(["require-auth"]);
|
|
35
36
|
const router = useRouter();
|
|
36
37
|
const onClickCard = () => {
|
|
37
38
|
if (modelValue.value?.id) {
|
|
@@ -45,7 +46,7 @@ const onFollowToggle = async () => {
|
|
|
45
46
|
const { APP_TYPE } = config.public;
|
|
46
47
|
const secId = useCookie(APP_TYPE === "OFFICE" ? "OFFICE_SEC_ID" : "SEC_ID");
|
|
47
48
|
if (!secId.value) {
|
|
48
|
-
|
|
49
|
+
emit("require-auth");
|
|
49
50
|
return;
|
|
50
51
|
}
|
|
51
52
|
if (!modelValue.value?.id) return;
|
|
@@ -6,14 +6,18 @@ export interface User {
|
|
|
6
6
|
public_count?: number;
|
|
7
7
|
description?: string;
|
|
8
8
|
is_following?: boolean;
|
|
9
|
+
is_my_profile?: boolean;
|
|
9
10
|
}
|
|
10
11
|
type __VLS_ModelProps = {
|
|
11
12
|
modelValue?: User;
|
|
12
13
|
};
|
|
13
14
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
14
15
|
"update:modelValue": (value: User) => any;
|
|
16
|
+
} & {
|
|
17
|
+
"require-auth": () => any;
|
|
15
18
|
}, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
|
|
16
19
|
"onUpdate:modelValue"?: ((value: User) => any) | undefined;
|
|
20
|
+
"onRequire-auth"?: (() => any) | undefined;
|
|
17
21
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
18
22
|
declare const _default: typeof __VLS_export;
|
|
19
23
|
export default _default;
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
2
|
+
<div v-bind="$attrs">
|
|
3
|
+
<div
|
|
4
|
+
v-for="(n, i) in items"
|
|
5
|
+
:key="i"
|
|
6
|
+
class="cursor-grab active:cursor-grabbing"
|
|
7
|
+
draggable="true"
|
|
8
|
+
@dragstart="onDragStart($event, i)"
|
|
9
|
+
@dragover.prevent="onDragOver($event, i)"
|
|
10
|
+
@dragend="onDragEnd($event, i)"
|
|
11
|
+
@dragenter.prevent
|
|
12
|
+
@dragleave.prevent
|
|
13
|
+
>
|
|
14
|
+
<slot name="item" :item="n" :index="i"></slot>
|
|
15
|
+
</div>
|
|
14
16
|
</div>
|
|
15
17
|
</template>
|
|
16
18
|
|
|
@@ -9,6 +9,7 @@ export interface ProfileSummary {
|
|
|
9
9
|
export interface DrawerProfileNetworkProps {
|
|
10
10
|
profileId: string;
|
|
11
11
|
defaultTab?: "followers" | "following" | "favorites";
|
|
12
|
+
isMyProfile?: boolean;
|
|
12
13
|
}
|
|
13
14
|
type __VLS_Props = DrawerProfileNetworkProps;
|
|
14
15
|
type __VLS_ModelProps = {
|
|
@@ -19,10 +20,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
19
20
|
"update:modelValue": (value: boolean) => any;
|
|
20
21
|
} & {
|
|
21
22
|
close: () => any;
|
|
23
|
+
"require-auth": () => any;
|
|
24
|
+
"explore-profiles": () => any;
|
|
25
|
+
"explore-places": () => any;
|
|
22
26
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
23
27
|
onClose?: (() => any) | undefined;
|
|
24
28
|
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
29
|
+
"onRequire-auth"?: (() => any) | undefined;
|
|
30
|
+
"onExplore-profiles"?: (() => any) | undefined;
|
|
31
|
+
"onExplore-places"?: (() => any) | undefined;
|
|
25
32
|
}>, {
|
|
33
|
+
isMyProfile: boolean;
|
|
26
34
|
profileId: string;
|
|
27
35
|
defaultTab: "followers" | "following" | "favorites";
|
|
28
36
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -14,98 +14,126 @@
|
|
|
14
14
|
</div>
|
|
15
15
|
</template>
|
|
16
16
|
|
|
17
|
-
<
|
|
18
|
-
<
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
</ShadTabsList>
|
|
17
|
+
<ShadTabs v-model="activeTab" class="flex-1 flex flex-col h-full">
|
|
18
|
+
<ShadTabsList>
|
|
19
|
+
<ShadTabsTrigger value="followers" class="px-[16px] py-[8px]">
|
|
20
|
+
ผู้ติดตาม ({{ $convert.convertNumber(profileData?.follower_count || 0) }})
|
|
21
|
+
</ShadTabsTrigger>
|
|
22
|
+
<ShadTabsTrigger value="following" class="px-[16px] py-[8px]">
|
|
23
|
+
กำลังติดตาม ({{ $convert.convertNumber(profileData?.following_count || 0) }})
|
|
24
|
+
</ShadTabsTrigger>
|
|
25
|
+
<ShadTabsTrigger value="favorites" class="px-[16px] py-[8px]">
|
|
26
|
+
สถานที่โปรด ({{ $convert.convertNumber(profileData?.favorite_count || 0) }})
|
|
27
|
+
</ShadTabsTrigger>
|
|
28
|
+
</ShadTabsList>
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
<div class="flex-1 overflow-y-auto" @scroll="onScroll">
|
|
31
|
+
<!-- Followers -->
|
|
32
|
+
<ShadTabsContent value="followers" class="flex flex-col mt-0">
|
|
33
|
+
<template v-if="tabState.followers.loading">
|
|
34
|
+
<div class="flex justify-center py-[40px]">
|
|
35
|
+
<Icon name="lucide:loader-2" size="24" class="animate-spin text-gray" />
|
|
36
|
+
</div>
|
|
37
|
+
</template>
|
|
38
|
+
<template v-else-if="followers.length > 0">
|
|
39
|
+
<div class="flex flex-col gap-[16px]">
|
|
40
|
+
<template v-for="(user, index) in followers" :key="user.id || index">
|
|
41
|
+
<CardUserItem v-model="followers[index]" @require-auth="emit('require-auth')" />
|
|
42
|
+
<Divider v-if="index !== followers.length - 1" />
|
|
43
|
+
</template>
|
|
44
|
+
</div>
|
|
45
|
+
<div v-if="tabState.followers.loadingMore" class="flex justify-center py-[16px]">
|
|
46
|
+
<Icon name="lucide:loader-2" size="20" class="animate-spin text-gray" />
|
|
47
|
+
</div>
|
|
48
|
+
</template>
|
|
49
|
+
<template v-else>
|
|
50
|
+
<div v-if="isMyProfile" class="h-[200px] flex flex-col gap-[8px] items-center justify-center">
|
|
51
|
+
<div class="font-title-medium-prominent text-black">กำลังมองหาผู้ติดตามอยู่ใช่ไหม</div>
|
|
52
|
+
<div class="flex flex-col font-body-large text-gray items-center">
|
|
53
|
+
<div>เมื่อมีคนติดตามบัญชีนี้ ข้อมูลจะแสดงที่นี่</div>
|
|
54
|
+
<div>การโพสต์และการโต้ตอบกับผู้อื่นจะช่วยเพิ่มผู้ติดตาม</div>
|
|
37
55
|
</div>
|
|
38
|
-
</
|
|
39
|
-
<
|
|
40
|
-
<div class="
|
|
41
|
-
|
|
42
|
-
<CardUserItem v-model="followers[index]" />
|
|
43
|
-
<Divider v-if="index !== followers.length - 1" />
|
|
44
|
-
</template>
|
|
56
|
+
</div>
|
|
57
|
+
<div v-else class="h-[200px] flex flex-col gap-[8px] items-center justify-center">
|
|
58
|
+
<div class="font-title-medium-prominent text-black flex gap-[4px]">
|
|
59
|
+
{{ profileData?.name }} ยังไม่มีผู้ติดตาม
|
|
45
60
|
</div>
|
|
46
|
-
<div
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
<template v-else>
|
|
51
|
-
<div class="flex flex-col items-center justify-center py-[40px] gap-[8px]">
|
|
52
|
-
<Icon name="lucide:users" size="40" class="text-gray" />
|
|
53
|
-
<div class="font-body-medium text-gray">ไม่มีผู้ติดตาม</div>
|
|
54
|
-
</div>
|
|
55
|
-
</template>
|
|
56
|
-
</ShadTabsContent>
|
|
61
|
+
<div class="font-body-large text-gray">เมื่อมีคนติดตามบัญชีนี้ ข้อมูลจะแสดงที่นี่</div>
|
|
62
|
+
</div>
|
|
63
|
+
</template>
|
|
64
|
+
</ShadTabsContent>
|
|
57
65
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
66
|
+
<!-- Following -->
|
|
67
|
+
<ShadTabsContent value="following" class="flex flex-col mt-0">
|
|
68
|
+
<template v-if="tabState.following.loading">
|
|
69
|
+
<div class="flex justify-center py-[40px]">
|
|
70
|
+
<Icon name="lucide:loader-2" size="24" class="animate-spin text-gray" />
|
|
71
|
+
</div>
|
|
72
|
+
</template>
|
|
73
|
+
<template v-else-if="following.length > 0">
|
|
74
|
+
<div class="flex flex-col gap-[16px]">
|
|
75
|
+
<template v-for="(user, index) in following" :key="user.id || index">
|
|
76
|
+
<CardUserItem v-model="following[index]" @require-auth="emit('require-auth')" />
|
|
77
|
+
<Divider v-if="index !== following.length - 1" />
|
|
78
|
+
</template>
|
|
79
|
+
</div>
|
|
80
|
+
<div v-if="tabState.following.loadingMore" class="flex justify-center py-[16px]">
|
|
81
|
+
<Icon name="lucide:loader-2" size="20" class="animate-spin text-gray" />
|
|
82
|
+
</div>
|
|
83
|
+
</template>
|
|
84
|
+
<template v-else>
|
|
85
|
+
<div v-if="isMyProfile" class="flex flex-col gap-[24px] items-center justify-center h-[200px]">
|
|
86
|
+
<div class="flex flex-col gap-[8px] items-center">
|
|
87
|
+
<div class="font-title-medium-prominent text-black">ทันเหตุการณ์</div>
|
|
88
|
+
<div class="flex flex-col font-body-large text-gray items-center">
|
|
89
|
+
<div>การติดตามบัญชีเป็นวิธีที่ง่ายในการสร้างลำดับเหตุการณ์</div>
|
|
90
|
+
<div>ของคุณและรู้ว่ามีอะไรเกิดขึ้นบ้างกับหัวข้อและผู้ที่คุณสนใจ</div>
|
|
91
|
+
</div>
|
|
74
92
|
</div>
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
93
|
+
<Button color="primary" @click="emit('explore-profiles')">ติดตามใครดี</Button>
|
|
94
|
+
</div>
|
|
95
|
+
<div v-else class="h-[200px] flex flex-col gap-[8px] items-center justify-center">
|
|
96
|
+
<div class="font-title-medium-prominent text-black">
|
|
97
|
+
{{ profileData?.name }} ไม่ได้กำลังติดตามใคร
|
|
80
98
|
</div>
|
|
81
|
-
|
|
82
|
-
|
|
99
|
+
<div class="font-body-large text-gray">เมื่อพวกเขาติดตามบัญชี ข้อมูลจะแสดงที่นี่</div>
|
|
100
|
+
</div>
|
|
101
|
+
</template>
|
|
102
|
+
</ShadTabsContent>
|
|
83
103
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
104
|
+
<!-- Favorites -->
|
|
105
|
+
<ShadTabsContent value="favorites" class="flex flex-col mt-0">
|
|
106
|
+
<template v-if="tabState.favorites.loading">
|
|
107
|
+
<div class="flex justify-center py-[40px]">
|
|
108
|
+
<Icon name="lucide:loader-2" size="24" class="animate-spin text-gray" />
|
|
109
|
+
</div>
|
|
110
|
+
</template>
|
|
111
|
+
<template v-else-if="favorites.length > 0">
|
|
112
|
+
<div class="flex flex-col items-center justify-center p-[48px] text-gray font-body-large">
|
|
113
|
+
สถานที่โปรด (อยู่ระหว่างการพัฒนา)?
|
|
114
|
+
</div>
|
|
115
|
+
<div v-if="tabState.favorites.loadingMore" class="flex justify-center py-[16px]">
|
|
116
|
+
<Icon name="lucide:loader-2" size="20" class="animate-spin text-gray" />
|
|
117
|
+
</div>
|
|
118
|
+
</template>
|
|
119
|
+
<template v-else>
|
|
120
|
+
<div v-if="isMyProfile" class="flex flex-col gap-[24px] items-center justify-center h-[200px]">
|
|
121
|
+
<div class="flex flex-col gap-[8px] items-center">
|
|
122
|
+
<div class="font-title-medium-prominent text-black">ยังไม่มีสถานที่โปรด</div>
|
|
123
|
+
<div class="font-body-large text-gray">กดหัวใจที่สถานที่ใดก็ได้เพื่อบันทึกไว้ที่นี่</div>
|
|
89
124
|
</div>
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
125
|
+
<Button color="primary" @click="emit('explore-places')">ที่ไหนน่าสนใจ</Button>
|
|
126
|
+
</div>
|
|
127
|
+
<div v-else class="h-[200px] flex flex-col gap-[8px] items-center justify-center">
|
|
128
|
+
<div class="font-title-medium-prominent text-black">
|
|
129
|
+
@{{ profileData?.name }} ยังไม่มีสถานที่โปรด
|
|
94
130
|
</div>
|
|
95
|
-
<div
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
<Icon name="lucide:map-pin-off" size="40" class="text-gray" />
|
|
102
|
-
<div class="font-body-medium text-gray">ไม่มีสถานที่โปรด</div>
|
|
103
|
-
</div>
|
|
104
|
-
</template>
|
|
105
|
-
</ShadTabsContent>
|
|
106
|
-
</div>
|
|
107
|
-
</ShadTabs>
|
|
108
|
-
</div>
|
|
131
|
+
<div class="font-body-large text-gray">เมื่อเขาบันทึกสถานที่ไว้จะแสดงที่นี่</div>
|
|
132
|
+
</div>
|
|
133
|
+
</template>
|
|
134
|
+
</ShadTabsContent>
|
|
135
|
+
</div>
|
|
136
|
+
</ShadTabs>
|
|
109
137
|
</Drawer>
|
|
110
138
|
</template>
|
|
111
139
|
|
|
@@ -120,9 +148,10 @@ const createTabState = () => ({
|
|
|
120
148
|
});
|
|
121
149
|
const props = defineProps({
|
|
122
150
|
profileId: { type: String, required: true, default: "" },
|
|
123
|
-
defaultTab: { type: String, required: false, default: "followers" }
|
|
151
|
+
defaultTab: { type: String, required: false, default: "followers" },
|
|
152
|
+
isMyProfile: { type: Boolean, required: false, default: false }
|
|
124
153
|
});
|
|
125
|
-
const emit = defineEmits(["close"]);
|
|
154
|
+
const emit = defineEmits(["close", "explore-profiles", "explore-places", "require-auth"]);
|
|
126
155
|
const isOpen = defineModel({ type: Boolean, ...{ default: false } });
|
|
127
156
|
const activeTab = ref(props.defaultTab);
|
|
128
157
|
const profileData = ref(null);
|
|
@@ -9,6 +9,7 @@ export interface ProfileSummary {
|
|
|
9
9
|
export interface DrawerProfileNetworkProps {
|
|
10
10
|
profileId: string;
|
|
11
11
|
defaultTab?: "followers" | "following" | "favorites";
|
|
12
|
+
isMyProfile?: boolean;
|
|
12
13
|
}
|
|
13
14
|
type __VLS_Props = DrawerProfileNetworkProps;
|
|
14
15
|
type __VLS_ModelProps = {
|
|
@@ -19,10 +20,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
19
20
|
"update:modelValue": (value: boolean) => any;
|
|
20
21
|
} & {
|
|
21
22
|
close: () => any;
|
|
23
|
+
"require-auth": () => any;
|
|
24
|
+
"explore-profiles": () => any;
|
|
25
|
+
"explore-places": () => any;
|
|
22
26
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
23
27
|
onClose?: (() => any) | undefined;
|
|
24
28
|
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
29
|
+
"onRequire-auth"?: (() => any) | undefined;
|
|
30
|
+
"onExplore-profiles"?: (() => any) | undefined;
|
|
31
|
+
"onExplore-places"?: (() => any) | undefined;
|
|
25
32
|
}>, {
|
|
33
|
+
isMyProfile: boolean;
|
|
26
34
|
profileId: string;
|
|
27
35
|
defaultTab: "followers" | "following" | "favorites";
|
|
28
36
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface ModalDisplayImageProps {
|
|
2
|
+
src?: string;
|
|
3
|
+
alt?: string;
|
|
4
|
+
}
|
|
5
|
+
type __VLS_Props = ModalDisplayImageProps;
|
|
6
|
+
type __VLS_ModelProps = {
|
|
7
|
+
modelValue?: boolean;
|
|
8
|
+
};
|
|
9
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
10
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
11
|
+
"update:modelValue": (value: boolean) => any;
|
|
12
|
+
} & {
|
|
13
|
+
close: () => any;
|
|
14
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
15
|
+
onClose?: (() => any) | undefined;
|
|
16
|
+
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
17
|
+
}>, {
|
|
18
|
+
src: string;
|
|
19
|
+
alt: string;
|
|
20
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
21
|
+
declare const _default: typeof __VLS_export;
|
|
22
|
+
export default _default;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Teleport to="body">
|
|
3
|
+
<Transition
|
|
4
|
+
enter-active-class="transition-all duration-250 ease-[cubic-bezier(0.16,1,0.3,1)]"
|
|
5
|
+
leave-active-class="transition-all duration-200 ease-[cubic-bezier(0.16,1,0.3,1)]"
|
|
6
|
+
enter-from-class="opacity-0"
|
|
7
|
+
leave-to-class="opacity-0"
|
|
8
|
+
>
|
|
9
|
+
<div
|
|
10
|
+
v-if="isOpen"
|
|
11
|
+
class="fixed inset-0 z-[9999] flex items-center justify-center bg-black/95 backdrop-blur-sm outline-none"
|
|
12
|
+
@click.self="close"
|
|
13
|
+
@keydown.escape="close"
|
|
14
|
+
tabindex="0"
|
|
15
|
+
ref="overlayRef"
|
|
16
|
+
>
|
|
17
|
+
<!-- Close button -->
|
|
18
|
+
<button
|
|
19
|
+
class="absolute top-4 left-4 z-10 flex items-center justify-center size-11 border-none rounded-full bg-white/10 text-white/85 cursor-pointer transition-all duration-200 ease-in-out hover:bg-white/20 hover:text-white hover:scale-105"
|
|
20
|
+
@click="close"
|
|
21
|
+
aria-label="ปิด"
|
|
22
|
+
>
|
|
23
|
+
<Icon name="lucide:x" size="28" />
|
|
24
|
+
</button>
|
|
25
|
+
|
|
26
|
+
<!-- Image container -->
|
|
27
|
+
<div
|
|
28
|
+
class="flex items-center justify-center w-full h-full overflow-hidden"
|
|
29
|
+
>
|
|
30
|
+
<img
|
|
31
|
+
:src="props.src"
|
|
32
|
+
:alt="props.alt || '\u0E23\u0E39\u0E1B\u0E20\u0E32\u0E1E'"
|
|
33
|
+
class="max-w-[90vw] max-h-[90vh] object-contain select-none rounded-sm"
|
|
34
|
+
draggable="false"
|
|
35
|
+
/>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
</Transition>
|
|
39
|
+
</Teleport>
|
|
40
|
+
</template>
|
|
41
|
+
|
|
42
|
+
<script setup>
|
|
43
|
+
import { ref, watch, nextTick, onBeforeUnmount } from "vue";
|
|
44
|
+
const props = defineProps({
|
|
45
|
+
src: { type: String, required: false, default: "" },
|
|
46
|
+
alt: { type: String, required: false, default: "" }
|
|
47
|
+
});
|
|
48
|
+
const emits = defineEmits(["close"]);
|
|
49
|
+
const isOpen = defineModel({ type: Boolean, ...{ default: false } });
|
|
50
|
+
const overlayRef = ref(null);
|
|
51
|
+
function close() {
|
|
52
|
+
isOpen.value = false;
|
|
53
|
+
emits("close");
|
|
54
|
+
}
|
|
55
|
+
watch(isOpen, (val) => {
|
|
56
|
+
if (val) {
|
|
57
|
+
document.body.style.overflow = "hidden";
|
|
58
|
+
nextTick(() => {
|
|
59
|
+
overlayRef.value?.focus();
|
|
60
|
+
});
|
|
61
|
+
} else {
|
|
62
|
+
document.body.style.overflow = "";
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
onBeforeUnmount(() => {
|
|
66
|
+
document.body.style.overflow = "";
|
|
67
|
+
});
|
|
68
|
+
</script>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface ModalDisplayImageProps {
|
|
2
|
+
src?: string;
|
|
3
|
+
alt?: string;
|
|
4
|
+
}
|
|
5
|
+
type __VLS_Props = ModalDisplayImageProps;
|
|
6
|
+
type __VLS_ModelProps = {
|
|
7
|
+
modelValue?: boolean;
|
|
8
|
+
};
|
|
9
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
10
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
11
|
+
"update:modelValue": (value: boolean) => any;
|
|
12
|
+
} & {
|
|
13
|
+
close: () => any;
|
|
14
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
15
|
+
onClose?: (() => any) | undefined;
|
|
16
|
+
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
17
|
+
}>, {
|
|
18
|
+
src: string;
|
|
19
|
+
alt: string;
|
|
20
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
21
|
+
declare const _default: typeof __VLS_export;
|
|
22
|
+
export default _default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pukaad-ui-lib",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.247.0",
|
|
4
4
|
"description": "pukaad-ui for MeMSG",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -38,9 +38,11 @@
|
|
|
38
38
|
"@nuxt/icon": "^1.10.3",
|
|
39
39
|
"@nuxt/image": "^1.9.0",
|
|
40
40
|
"@nuxt/kit": "^4.0.0",
|
|
41
|
+
"@pinia/nuxt": "^0.11.3",
|
|
41
42
|
"@tailwindcss/vite": "^4.3.0",
|
|
42
43
|
"@tanstack/vue-table": "^8.21.3",
|
|
43
44
|
"@vee-validate/nuxt": "^4.15.0",
|
|
45
|
+
"@vee-validate/zod": "^4.15.1",
|
|
44
46
|
"@vueuse/core": "^14.2.1",
|
|
45
47
|
"@vueuse/nuxt": "^12.7.0",
|
|
46
48
|
"class-variance-authority": "^0.7.1",
|