pukaad-ui-lib 1.37.0 → 1.39.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/runtime/assets/css/main.css +1 -1
- package/dist/runtime/components/drawer/drawer.d.vue.ts +7 -5
- package/dist/runtime/components/drawer/drawer.vue +3 -0
- package/dist/runtime/components/drawer/drawer.vue.d.ts +7 -5
- package/dist/runtime/components/image/image-cropper.d.vue.ts +2 -2
- package/dist/runtime/components/image/image-cropper.vue.d.ts +2 -2
- package/dist/runtime/components/input/input-address.d.vue.ts +74 -1
- package/dist/runtime/components/input/input-address.vue +480 -75
- package/dist/runtime/components/input/input-address.vue.d.ts +74 -1
- package/dist/runtime/components/input/input-autocomplete.vue +44 -13
- package/dist/runtime/components/input/input-combobox.vue +1 -1
- package/dist/runtime/components/input/input-text-field.d.vue.ts +1 -1
- package/dist/runtime/components/input/input-text-field.vue.d.ts +1 -1
- package/dist/runtime/components/input/input-textarea.d.vue.ts +1 -1
- package/dist/runtime/components/input/input-textarea.vue.d.ts +1 -1
- package/dist/runtime/components/loading.d.vue.ts +10 -0
- package/dist/runtime/components/loading.vue +24 -0
- package/dist/runtime/components/loading.vue.d.ts +10 -0
- package/dist/runtime/components/modal/modal.d.vue.ts +9 -7
- package/dist/runtime/components/modal/modal.vue +4 -1
- package/dist/runtime/components/modal/modal.vue.d.ts +9 -7
- package/dist/runtime/components/ui/input-group/InputGroupButton.d.vue.ts +1 -1
- package/dist/runtime/components/ui/input-group/InputGroupButton.vue.d.ts +1 -1
- package/dist/runtime/components/ui/input-group/index.d.ts +1 -1
- package/package.json +1 -1
package/dist/module.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@import "tailwindcss";@import "tw-animate-css";@import "./system.css";@import "./fonts/Anuphan.css";@import "./fonts/Sarabun.css";@import "./scroll-bar.css";@import "quill/dist/quill.snow.css";@custom-variant dark (&:is(.dark *));@theme inline{--radius-sm:calc(var(--radius) - 4px);--radius-md:calc(var(--radius) - 2px);--radius-lg:var(--radius);--radius-xl:calc(var(--radius) + 4px);--color-background:var(--background);--color-foreground:var(--foreground);--color-card:var(--card);--color-card-foreground:var(--card-foreground);--color-popover:var(--popover);--color-popover-foreground:var(--popover-foreground);--color-primary-foreground:var(--primary-foreground);--color-secondary-foreground:var(--secondary-foreground);--color-muted:var(--muted);--color-muted-foreground:var(--muted-foreground);--color-accent:var(--accent);--color-accent-foreground:var(--accent-foreground);--color-destructive:var(--destructive);--color-destructive-foreground:var(--destructive-foreground);--color-border:var(--border);--color-input:var(--input);--color-ring:var(--ring);--color-chart-1:var(--chart-1);--color-chart-2:var(--chart-2);--color-chart-3:var(--chart-3);--color-chart-4:var(--chart-4);--color-chart-5:var(--chart-5);--color-sidebar:var(--sidebar);--color-sidebar-foreground:var(--sidebar-foreground);--color-sidebar-primary:var(--sidebar-primary);--color-sidebar-primary-foreground:var(--sidebar-primary-foreground);--color-sidebar-accent:var(--sidebar-accent);--color-sidebar-accent-foreground:var(--sidebar-accent-foreground);--color-sidebar-border:var(--sidebar-border);--color-sidebar-ring:var(--sidebar-ring);--color-red:var(--red);--color-error:var(--error);--color-success:var(--success);--color-green:var(--green);--color-warning:var(--warning);--color-yellow:var(--yellow);--color-primary:var(--primary);--color-secondary:var(--secondary);--color-info:var(--info);--color-black:var(--black);--color-dark:var(--dark);--color-gray:var(--gray);--color-cloud:var(--cloud);--color-mercury:var(--mercury);--color-green-light:var(--green-light);--color-red-light:var(--red-light);--color-yellow-light:var(--yellow-light);--color-bright:var(--bright);--color-silver:var(--silver);--color-smoke:var(--smoke);--z-index-announce-tool:10;--z-index-dropdown:11;--z-index-overlay:12;--z-index-loading:13;--z-index-drawer:14;--z-index-modal:15;--z-index-toast:99998;--z-index-loading-page:99999}:root{--radius:0.625rem;--red:#b71c1c;--success:#43a047;--green:#1b5e20;--warning:#f9a825;--yellow:#fbc02d;--info:#e3f2fd;--black:#212121;--dark:#424242;--gray:#616161;--cloud:#c4c4c4;--mercury:#e0e0e0;--green-light:#e3f5e3;--red-light:#fde3e3;--yellow-light:#fef3c7;--bright:#f5f5f5;--silver:#f7f7f7;--smoke:#fafafa;--white:#fff;--background:var(--white);--foreground:var(--black);--card:var(--background);--card-foreground:var(--foreground);--popover:var(--background);--popover-foreground:var(--foreground);--primary:#1976b8;--primary-foreground:var(--white);--secondary:#22a7ef;--secondary-foreground:var(--white);--muted:oklch(0.97 0 0);--muted-foreground:var(--
|
|
1
|
+
@import "tailwindcss";@import "tw-animate-css";@import "./system.css";@import "./fonts/Anuphan.css";@import "./fonts/Sarabun.css";@import "./scroll-bar.css";@import "quill/dist/quill.snow.css";@custom-variant dark (&:is(.dark *));@theme inline{--radius-sm:calc(var(--radius) - 4px);--radius-md:calc(var(--radius) - 2px);--radius-lg:var(--radius);--radius-xl:calc(var(--radius) + 4px);--color-background:var(--background);--color-foreground:var(--foreground);--color-card:var(--card);--color-card-foreground:var(--card-foreground);--color-popover:var(--popover);--color-popover-foreground:var(--popover-foreground);--color-primary-foreground:var(--primary-foreground);--color-secondary-foreground:var(--secondary-foreground);--color-muted:var(--muted);--color-muted-foreground:var(--muted-foreground);--color-accent:var(--accent);--color-accent-foreground:var(--accent-foreground);--color-destructive:var(--destructive);--color-destructive-foreground:var(--destructive-foreground);--color-border:var(--border);--color-input:var(--input);--color-ring:var(--ring);--color-chart-1:var(--chart-1);--color-chart-2:var(--chart-2);--color-chart-3:var(--chart-3);--color-chart-4:var(--chart-4);--color-chart-5:var(--chart-5);--color-sidebar:var(--sidebar);--color-sidebar-foreground:var(--sidebar-foreground);--color-sidebar-primary:var(--sidebar-primary);--color-sidebar-primary-foreground:var(--sidebar-primary-foreground);--color-sidebar-accent:var(--sidebar-accent);--color-sidebar-accent-foreground:var(--sidebar-accent-foreground);--color-sidebar-border:var(--sidebar-border);--color-sidebar-ring:var(--sidebar-ring);--color-red:var(--red);--color-error:var(--error);--color-success:var(--success);--color-green:var(--green);--color-warning:var(--warning);--color-yellow:var(--yellow);--color-primary:var(--primary);--color-secondary:var(--secondary);--color-info:var(--info);--color-black:var(--black);--color-dark:var(--dark);--color-gray:var(--gray);--color-cloud:var(--cloud);--color-mercury:var(--mercury);--color-green-light:var(--green-light);--color-red-light:var(--red-light);--color-yellow-light:var(--yellow-light);--color-bright:var(--bright);--color-silver:var(--silver);--color-smoke:var(--smoke);--z-index-announce-tool:10;--z-index-dropdown:11;--z-index-overlay:12;--z-index-loading:13;--z-index-drawer:14;--z-index-modal:15;--z-index-toast:99998;--z-index-loading-page:99999}:root{--radius:0.625rem;--red:#b71c1c;--success:#43a047;--green:#1b5e20;--warning:#f9a825;--yellow:#fbc02d;--info:#e3f2fd;--black:#212121;--dark:#424242;--gray:#616161;--cloud:#c4c4c4;--mercury:#e0e0e0;--green-light:#e3f5e3;--red-light:#fde3e3;--yellow-light:#fef3c7;--bright:#f5f5f5;--silver:#f7f7f7;--smoke:#fafafa;--white:#fff;--background:var(--white);--foreground:var(--black);--card:var(--background);--card-foreground:var(--foreground);--popover:var(--background);--popover-foreground:var(--foreground);--primary:#1976b8;--primary-foreground:var(--white);--secondary:#22a7ef;--secondary-foreground:var(--white);--muted:oklch(0.97 0 0);--muted-foreground:var(--cloud);--accent:oklch(0.97 0 0);--accent-foreground:oklch(0.205 0 0);--destructive:#d32f2f;--destructive-foreground:var(--white);--border:var(--color-mercury);--input:var(--color-mercury);--ring:var(--mercury);--chart-1:oklch(0.646 0.222 41.116);--chart-2:oklch(0.6 0.118 184.704);--chart-3:oklch(0.398 0.07 227.392);--chart-4:oklch(0.828 0.189 84.429);--chart-5:oklch(0.769 0.188 70.08);--sidebar:oklch(0.985 0 0);--sidebar-foreground:var(--foreground);--sidebar-primary:oklch(0.205 0 0);--sidebar-primary-foreground:oklch(0.985 0 0);--sidebar-accent:oklch(0.97 0 0);--sidebar-accent-foreground:oklch(0.205 0 0);--sidebar-border:var(--color-mercury);--sidebar-ring:var(--color-mercury)}.dark{--background:oklch(0.145 0 0);--foreground:oklch(0.985 0 0);--card:oklch(0.145 0 0);--card-foreground:oklch(0.985 0 0);--popover:oklch(0.145 0 0);--popover-foreground:oklch(0.985 0 0);--primary:oklch(0.985 0 0);--primary-foreground:oklch(0.205 0 0);--secondary:oklch(0.269 0 0);--secondary-foreground:oklch(0.985 0 0);--muted:oklch(0.269 0 0);--muted-foreground:oklch(0.708 0 0);--accent:oklch(0.269 0 0);--accent-foreground:oklch(0.985 0 0);--destructive:oklch(0.396 0.141 25.723);--destructive-foreground:oklch(0.637 0.237 25.331);--border:oklch(0.269 0 0);--input:oklch(0.269 0 0);--ring:oklch(0.439 0 0);--chart-1:oklch(0.488 0.243 264.376);--chart-2:oklch(0.696 0.17 162.48);--chart-3:oklch(0.769 0.188 70.08);--chart-4:oklch(0.627 0.265 303.9);--chart-5:oklch(0.645 0.246 16.439);--sidebar:oklch(0.205 0 0);--sidebar-foreground:oklch(0.985 0 0);--sidebar-primary:oklch(0.488 0.243 264.376);--sidebar-primary-foreground:oklch(0.985 0 0);--sidebar-accent:oklch(0.269 0 0);--sidebar-accent-foreground:oklch(0.985 0 0);--sidebar-border:oklch(0.269 0 0);--sidebar-ring:oklch(0.439 0 0)}@layer base{*{@apply border-border outline-ring/50}body{@apply bg-background text-foreground}}
|
|
@@ -2,23 +2,25 @@ import type { SheetContentProps } from "@/runtime/components/ui/sheet/SheetConte
|
|
|
2
2
|
export interface DrawerProps extends SheetContentProps {
|
|
3
3
|
title?: string;
|
|
4
4
|
description?: string;
|
|
5
|
+
isLoading?: boolean;
|
|
6
|
+
loadingText?: string;
|
|
5
7
|
}
|
|
6
8
|
type __VLS_Props = DrawerProps;
|
|
7
9
|
type __VLS_ModelProps = {
|
|
8
10
|
modelValue?: boolean;
|
|
9
11
|
};
|
|
10
12
|
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
11
|
-
declare var
|
|
13
|
+
declare var __VLS_27: {}, __VLS_41: {
|
|
12
14
|
meta: any;
|
|
13
|
-
},
|
|
15
|
+
}, __VLS_49: {
|
|
14
16
|
meta: any;
|
|
15
17
|
};
|
|
16
18
|
type __VLS_Slots = {} & {
|
|
17
|
-
header?: (props: typeof
|
|
19
|
+
header?: (props: typeof __VLS_27) => any;
|
|
18
20
|
} & {
|
|
19
|
-
default?: (props: typeof
|
|
21
|
+
default?: (props: typeof __VLS_41) => any;
|
|
20
22
|
} & {
|
|
21
|
-
footer?: (props: typeof
|
|
23
|
+
footer?: (props: typeof __VLS_49) => any;
|
|
22
24
|
};
|
|
23
25
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
24
26
|
"update:modelValue": (value: boolean) => any;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<ShadSheet v-model:open="isOpen">
|
|
3
3
|
<ShadSheetContent v-bind="props" v-slot="{ meta }" @submit="onSubmit">
|
|
4
|
+
<Loading :is-loading="props.isLoading" :text="props.loadingText" />
|
|
4
5
|
<ShadSheetHeader class="flex-shrink-0">
|
|
5
6
|
<slot name="header">
|
|
6
7
|
<ShadSheetTitle>{{ props.title }}</ShadSheetTitle>
|
|
@@ -23,6 +24,8 @@
|
|
|
23
24
|
const props = defineProps({
|
|
24
25
|
title: { type: String, required: false },
|
|
25
26
|
description: { type: String, required: false },
|
|
27
|
+
isLoading: { type: Boolean, required: false },
|
|
28
|
+
loadingText: { type: String, required: false },
|
|
26
29
|
class: { type: null, required: false },
|
|
27
30
|
side: { type: String, required: false },
|
|
28
31
|
forceMount: { type: Boolean, required: false },
|
|
@@ -2,23 +2,25 @@ import type { SheetContentProps } from "@/runtime/components/ui/sheet/SheetConte
|
|
|
2
2
|
export interface DrawerProps extends SheetContentProps {
|
|
3
3
|
title?: string;
|
|
4
4
|
description?: string;
|
|
5
|
+
isLoading?: boolean;
|
|
6
|
+
loadingText?: string;
|
|
5
7
|
}
|
|
6
8
|
type __VLS_Props = DrawerProps;
|
|
7
9
|
type __VLS_ModelProps = {
|
|
8
10
|
modelValue?: boolean;
|
|
9
11
|
};
|
|
10
12
|
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
11
|
-
declare var
|
|
13
|
+
declare var __VLS_27: {}, __VLS_41: {
|
|
12
14
|
meta: any;
|
|
13
|
-
},
|
|
15
|
+
}, __VLS_49: {
|
|
14
16
|
meta: any;
|
|
15
17
|
};
|
|
16
18
|
type __VLS_Slots = {} & {
|
|
17
|
-
header?: (props: typeof
|
|
19
|
+
header?: (props: typeof __VLS_27) => any;
|
|
18
20
|
} & {
|
|
19
|
-
default?: (props: typeof
|
|
21
|
+
default?: (props: typeof __VLS_41) => any;
|
|
20
22
|
} & {
|
|
21
|
-
footer?: (props: typeof
|
|
23
|
+
footer?: (props: typeof __VLS_49) => any;
|
|
22
24
|
};
|
|
23
25
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
24
26
|
"update:modelValue": (value: boolean) => any;
|
|
@@ -64,15 +64,15 @@ declare const __VLS_export: import("vue").DefineComponent<ImageCropperProps, {
|
|
|
64
64
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ImageCropperProps> & Readonly<{}>, {
|
|
65
65
|
center: boolean;
|
|
66
66
|
src: string;
|
|
67
|
-
background: boolean;
|
|
68
|
-
modal: boolean;
|
|
69
67
|
responsive: boolean;
|
|
70
68
|
restore: boolean;
|
|
71
69
|
checkCrossOrigin: boolean;
|
|
72
70
|
checkOrientation: boolean;
|
|
73
71
|
crossorigin: "" | "anonymous" | "use-credentials";
|
|
72
|
+
modal: boolean;
|
|
74
73
|
guides: boolean;
|
|
75
74
|
highlight: boolean;
|
|
75
|
+
background: boolean;
|
|
76
76
|
autoCrop: boolean;
|
|
77
77
|
movable: boolean;
|
|
78
78
|
rotatable: boolean;
|
|
@@ -64,15 +64,15 @@ declare const __VLS_export: import("vue").DefineComponent<ImageCropperProps, {
|
|
|
64
64
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ImageCropperProps> & Readonly<{}>, {
|
|
65
65
|
center: boolean;
|
|
66
66
|
src: string;
|
|
67
|
-
background: boolean;
|
|
68
|
-
modal: boolean;
|
|
69
67
|
responsive: boolean;
|
|
70
68
|
restore: boolean;
|
|
71
69
|
checkCrossOrigin: boolean;
|
|
72
70
|
checkOrientation: boolean;
|
|
73
71
|
crossorigin: "" | "anonymous" | "use-credentials";
|
|
72
|
+
modal: boolean;
|
|
74
73
|
guides: boolean;
|
|
75
74
|
highlight: boolean;
|
|
75
|
+
background: boolean;
|
|
76
76
|
autoCrop: boolean;
|
|
77
77
|
movable: boolean;
|
|
78
78
|
rotatable: boolean;
|
|
@@ -1,3 +1,76 @@
|
|
|
1
|
-
|
|
1
|
+
interface Province {
|
|
2
|
+
code: number;
|
|
3
|
+
name_th: string;
|
|
4
|
+
name_en: string;
|
|
5
|
+
}
|
|
6
|
+
interface District {
|
|
7
|
+
code: number;
|
|
8
|
+
name_th: string;
|
|
9
|
+
name_en: string;
|
|
10
|
+
province_code: number;
|
|
11
|
+
}
|
|
12
|
+
interface SubDistrict {
|
|
13
|
+
code: number;
|
|
14
|
+
name_th: string;
|
|
15
|
+
name_en: string;
|
|
16
|
+
district_code: number;
|
|
17
|
+
zip_code: number;
|
|
18
|
+
}
|
|
19
|
+
export interface InputAddressValue {
|
|
20
|
+
province?: Province;
|
|
21
|
+
district?: District;
|
|
22
|
+
subDistrict?: SubDistrict;
|
|
23
|
+
zipCode?: number;
|
|
24
|
+
detail?: string;
|
|
25
|
+
fullAddress?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface InputAddressProps {
|
|
28
|
+
name?: string;
|
|
29
|
+
label?: string;
|
|
30
|
+
placeholder?: string;
|
|
31
|
+
labelDetail?: string;
|
|
32
|
+
placeholderDetail?: string;
|
|
33
|
+
required?: boolean;
|
|
34
|
+
requiredDetail?: boolean;
|
|
35
|
+
rules?: object | string | Function;
|
|
36
|
+
provinces?: Province[];
|
|
37
|
+
districts?: District[];
|
|
38
|
+
subDistricts?: SubDistrict[];
|
|
39
|
+
}
|
|
40
|
+
type __VLS_Props = InputAddressProps;
|
|
41
|
+
type __VLS_ModelProps = {
|
|
42
|
+
modelValue?: InputAddressValue;
|
|
43
|
+
};
|
|
44
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
45
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
46
|
+
validate: () => Promise<boolean>;
|
|
47
|
+
setErrors: (errMsg: string[]) => void;
|
|
48
|
+
reset: () => void;
|
|
49
|
+
addressFieldRef: import("vue").Ref<any, any>;
|
|
50
|
+
detailFieldRef: import("vue").Ref<any, any>;
|
|
51
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
52
|
+
"update:modelValue": (value: InputAddressValue) => any;
|
|
53
|
+
} & {
|
|
54
|
+
change: (value: InputAddressValue) => any;
|
|
55
|
+
selectProvince: (province: Province) => any;
|
|
56
|
+
selectDistrict: (district: District) => any;
|
|
57
|
+
selectSubDistrict: (subDistrict: SubDistrict) => any;
|
|
58
|
+
selectZipCode: (zipCode: number) => any;
|
|
59
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
60
|
+
onChange?: ((value: InputAddressValue) => any) | undefined;
|
|
61
|
+
"onUpdate:modelValue"?: ((value: InputAddressValue) => any) | undefined;
|
|
62
|
+
onSelectProvince?: ((province: Province) => any) | undefined;
|
|
63
|
+
onSelectDistrict?: ((district: District) => any) | undefined;
|
|
64
|
+
onSelectSubDistrict?: ((subDistrict: SubDistrict) => any) | undefined;
|
|
65
|
+
onSelectZipCode?: ((zipCode: number) => any) | undefined;
|
|
66
|
+
}>, {
|
|
67
|
+
label: string;
|
|
68
|
+
required: boolean;
|
|
69
|
+
name: string;
|
|
70
|
+
placeholder: string;
|
|
71
|
+
labelDetail: string;
|
|
72
|
+
placeholderDetail: string;
|
|
73
|
+
requiredDetail: boolean;
|
|
74
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
2
75
|
declare const _default: typeof __VLS_export;
|
|
3
76
|
export default _default;
|
|
@@ -1,87 +1,492 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
v-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
:key="i_pro"
|
|
26
|
-
class="p-2 border-b-[1px] border-mercury cursor-pointer"
|
|
27
|
-
@click="onSelectProvince(pro)"
|
|
2
|
+
<div class="space-y-4">
|
|
3
|
+
<!-- Address Selector (Province, District, Sub-district, Zip code) -->
|
|
4
|
+
<ShadFormField
|
|
5
|
+
ref="addressFieldRef"
|
|
6
|
+
:name="props.name"
|
|
7
|
+
:rules="props.rules || defaultRules"
|
|
8
|
+
v-slot="{ componentField }"
|
|
9
|
+
v-model="addressValue"
|
|
10
|
+
>
|
|
11
|
+
<ShadFormItem>
|
|
12
|
+
<ShadFormLabel v-if="props.label" class="w-full">
|
|
13
|
+
<div class="flex-1">
|
|
14
|
+
{{ props.label }}
|
|
15
|
+
<span v-if="props.required" class="text-destructive">*</span>
|
|
16
|
+
</div>
|
|
17
|
+
</ShadFormLabel>
|
|
18
|
+
<ShadPopover v-model:open="popoverOpen" v-bind="componentField">
|
|
19
|
+
<ShadPopoverTrigger as-child>
|
|
20
|
+
<ShadFormControl>
|
|
21
|
+
<ShadButton
|
|
22
|
+
variant="outline"
|
|
23
|
+
role="combobox"
|
|
24
|
+
class="w-full justify-between text-start"
|
|
28
25
|
>
|
|
29
|
-
{
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
<span :class="{ 'text-cloud': !addressValue }">
|
|
27
|
+
{{ addressValue || props.placeholder }}
|
|
28
|
+
</span>
|
|
29
|
+
<Icon name="lucide:chevron-down" class="h-4 w-4" />
|
|
30
|
+
</ShadButton>
|
|
31
|
+
</ShadFormControl>
|
|
32
|
+
</ShadPopoverTrigger>
|
|
33
|
+
<ShadPopoverContent class="w-[400px] p-0">
|
|
34
|
+
<ShadCommand>
|
|
35
|
+
<ShadCommandInput
|
|
36
|
+
v-model="searchQuery"
|
|
37
|
+
placeholder="ค้นหาที่อยู่"
|
|
38
|
+
/>
|
|
39
|
+
<ShadTabs v-model="currentTab" class="w-full">
|
|
40
|
+
<ShadTabsList class="w-full grid grid-cols-4 rounded-none">
|
|
41
|
+
<ShadTabsTrigger value="province" class="rounded-none">
|
|
42
|
+
จังหวัด
|
|
43
|
+
</ShadTabsTrigger>
|
|
44
|
+
<ShadTabsTrigger
|
|
45
|
+
value="district"
|
|
46
|
+
:disabled="!selectedProvince"
|
|
47
|
+
class="rounded-none"
|
|
48
|
+
>
|
|
49
|
+
อำเภอ/เขต
|
|
50
|
+
</ShadTabsTrigger>
|
|
51
|
+
<ShadTabsTrigger
|
|
52
|
+
value="subDistrict"
|
|
53
|
+
:disabled="!selectedDistrict"
|
|
54
|
+
class="rounded-none"
|
|
55
|
+
>
|
|
56
|
+
ตำบล/แขวง
|
|
57
|
+
</ShadTabsTrigger>
|
|
58
|
+
<ShadTabsTrigger
|
|
59
|
+
value="zipCode"
|
|
60
|
+
:disabled="!selectedSubDistrict"
|
|
61
|
+
class="rounded-none"
|
|
62
|
+
>
|
|
63
|
+
รหัสไปรษณีย์
|
|
64
|
+
</ShadTabsTrigger>
|
|
65
|
+
</ShadTabsList>
|
|
33
66
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
67
|
+
<!-- Province Tab -->
|
|
68
|
+
<ShadTabsContent value="province" class="m-0">
|
|
69
|
+
<ShadCommandList class="max-h-64">
|
|
70
|
+
<ShadCommandGroup>
|
|
71
|
+
<ShadCommandItem
|
|
72
|
+
v-for="province in filteredProvinces"
|
|
73
|
+
:key="province.code"
|
|
74
|
+
:value="province.name_th"
|
|
75
|
+
@select="onSelectProvince(province)"
|
|
76
|
+
>
|
|
77
|
+
{{ province.name_th }}
|
|
78
|
+
<Icon
|
|
79
|
+
v-if="selectedProvince?.code === province.code"
|
|
80
|
+
name="lucide:check"
|
|
81
|
+
class="ml-auto h-4 w-4"
|
|
82
|
+
/>
|
|
83
|
+
</ShadCommandItem>
|
|
84
|
+
</ShadCommandGroup>
|
|
85
|
+
<ShadCommandEmpty>ไม่พบจังหวัด</ShadCommandEmpty>
|
|
86
|
+
</ShadCommandList>
|
|
87
|
+
</ShadTabsContent>
|
|
46
88
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
89
|
+
<!-- District Tab -->
|
|
90
|
+
<ShadTabsContent value="district" class="m-0">
|
|
91
|
+
<ShadCommandList class="max-h-64">
|
|
92
|
+
<ShadCommandGroup>
|
|
93
|
+
<ShadCommandItem
|
|
94
|
+
v-for="district in filteredDistricts"
|
|
95
|
+
:key="district.code"
|
|
96
|
+
:value="district.name_th"
|
|
97
|
+
@select="onSelectDistrict(district)"
|
|
98
|
+
>
|
|
99
|
+
{{ district.name_th }}
|
|
100
|
+
<Icon
|
|
101
|
+
v-if="selectedDistrict?.code === district.code"
|
|
102
|
+
name="lucide:check"
|
|
103
|
+
class="ml-auto h-4 w-4"
|
|
104
|
+
/>
|
|
105
|
+
</ShadCommandItem>
|
|
106
|
+
</ShadCommandGroup>
|
|
107
|
+
<ShadCommandEmpty>ไม่พบอำเภอ/เขต</ShadCommandEmpty>
|
|
108
|
+
</ShadCommandList>
|
|
109
|
+
</ShadTabsContent>
|
|
61
110
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
111
|
+
<!-- Sub-district Tab -->
|
|
112
|
+
<ShadTabsContent value="subDistrict" class="m-0">
|
|
113
|
+
<ShadCommandList class="max-h-64">
|
|
114
|
+
<ShadCommandGroup>
|
|
115
|
+
<ShadCommandItem
|
|
116
|
+
v-for="subDistrict in filteredSubDistricts"
|
|
117
|
+
:key="subDistrict.code"
|
|
118
|
+
:value="subDistrict.name_th"
|
|
119
|
+
@select="onSelectSubDistrict(subDistrict)"
|
|
120
|
+
>
|
|
121
|
+
{{ subDistrict.name_th }}
|
|
122
|
+
<Icon
|
|
123
|
+
v-if="selectedSubDistrict?.code === subDistrict.code"
|
|
124
|
+
name="lucide:check"
|
|
125
|
+
class="ml-auto h-4 w-4"
|
|
126
|
+
/>
|
|
127
|
+
</ShadCommandItem>
|
|
128
|
+
</ShadCommandGroup>
|
|
129
|
+
<ShadCommandEmpty>ไม่พบตำบล/แขวง</ShadCommandEmpty>
|
|
130
|
+
</ShadCommandList>
|
|
131
|
+
</ShadTabsContent>
|
|
132
|
+
|
|
133
|
+
<!-- Zip Code Tab -->
|
|
134
|
+
<ShadTabsContent value="zipCode" class="m-0">
|
|
135
|
+
<ShadCommandList class="max-h-64">
|
|
136
|
+
<ShadCommandGroup>
|
|
137
|
+
<ShadCommandItem
|
|
138
|
+
v-if="selectedSubDistrict"
|
|
139
|
+
:value="selectedSubDistrict.zip_code.toString()"
|
|
140
|
+
@select="onSelectZipCode"
|
|
141
|
+
>
|
|
142
|
+
{{ selectedSubDistrict.zip_code }}
|
|
143
|
+
<Icon name="lucide:check" class="ml-auto h-4 w-4" />
|
|
144
|
+
</ShadCommandItem>
|
|
145
|
+
</ShadCommandGroup>
|
|
146
|
+
<ShadCommandEmpty>ไม่พบรหัสไปรษณีย์</ShadCommandEmpty>
|
|
147
|
+
</ShadCommandList>
|
|
148
|
+
</ShadTabsContent>
|
|
149
|
+
</ShadTabs>
|
|
150
|
+
</ShadCommand>
|
|
151
|
+
</ShadPopoverContent>
|
|
152
|
+
</ShadPopover>
|
|
153
|
+
<ShadFormMessage />
|
|
154
|
+
</ShadFormItem>
|
|
155
|
+
</ShadFormField>
|
|
156
|
+
|
|
157
|
+
<!-- Address Detail (House number, Soi, Moo, Road) -->
|
|
75
158
|
<InputTextField
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
:
|
|
79
|
-
:
|
|
159
|
+
ref="detailFieldRef"
|
|
160
|
+
:name="`${props.name}-detail`"
|
|
161
|
+
:label="props.labelDetail"
|
|
162
|
+
:placeholder="props.placeholderDetail"
|
|
163
|
+
:disabled="!addressValue"
|
|
164
|
+
:required="props.requiredDetail"
|
|
80
165
|
v-model="addressDetailValue"
|
|
81
166
|
/>
|
|
82
|
-
</div>
|
|
167
|
+
</div>
|
|
83
168
|
</template>
|
|
84
169
|
|
|
85
170
|
<script setup>
|
|
86
|
-
|
|
171
|
+
import { ref, computed, watch } from "vue";
|
|
172
|
+
import InputTextField from "./input-text-field.vue";
|
|
173
|
+
const props = defineProps({
|
|
174
|
+
name: { type: String, required: false, default: "address" },
|
|
175
|
+
label: { type: String, required: false, default: "\u0E08\u0E31\u0E07\u0E2B\u0E27\u0E31\u0E14, \u0E2D\u0E33\u0E40\u0E20\u0E2D/\u0E40\u0E02\u0E15, \u0E15\u0E33\u0E1A\u0E25/\u0E41\u0E02\u0E27\u0E07, \u0E23\u0E2B\u0E31\u0E2A\u0E44\u0E1B\u0E23\u0E29\u0E13\u0E35\u0E22\u0E4C" },
|
|
176
|
+
placeholder: { type: String, required: false, default: "\u0E08\u0E31\u0E07\u0E2B\u0E27\u0E31\u0E14, \u0E2D\u0E33\u0E40\u0E20\u0E2D/\u0E40\u0E02\u0E15, \u0E15\u0E33\u0E1A\u0E25/\u0E41\u0E02\u0E27\u0E07, \u0E23\u0E2B\u0E31\u0E2A\u0E44\u0E1B\u0E23\u0E29\u0E13\u0E35\u0E22\u0E4C" },
|
|
177
|
+
labelDetail: { type: String, required: false, default: "\u0E1A\u0E49\u0E32\u0E19\u0E40\u0E25\u0E02\u0E17\u0E35\u0E48, \u0E0B\u0E2D\u0E22, \u0E2B\u0E21\u0E39\u0E48, \u0E16\u0E19\u0E19" },
|
|
178
|
+
placeholderDetail: { type: String, required: false, default: "\u0E1A\u0E49\u0E32\u0E19\u0E40\u0E25\u0E02\u0E17\u0E35\u0E48, \u0E0B\u0E2D\u0E22, \u0E2B\u0E21\u0E39\u0E48, \u0E16\u0E19\u0E19" },
|
|
179
|
+
required: { type: Boolean, required: false, default: false },
|
|
180
|
+
requiredDetail: { type: Boolean, required: false, default: false },
|
|
181
|
+
rules: { type: [Object, String, Function], required: false },
|
|
182
|
+
provinces: { type: Array, required: false },
|
|
183
|
+
districts: { type: Array, required: false },
|
|
184
|
+
subDistricts: { type: Array, required: false }
|
|
185
|
+
});
|
|
186
|
+
const emits = defineEmits(["selectProvince", "selectDistrict", "selectSubDistrict", "selectZipCode", "change"]);
|
|
187
|
+
const modelValue = defineModel({ type: Object, ...{
|
|
188
|
+
default: () => ({})
|
|
189
|
+
} });
|
|
190
|
+
const popoverOpen = ref(false);
|
|
191
|
+
const currentTab = ref("province");
|
|
192
|
+
const searchQuery = ref("");
|
|
193
|
+
const addressFieldRef = ref();
|
|
194
|
+
const detailFieldRef = ref();
|
|
195
|
+
const selectedProvince = ref(null);
|
|
196
|
+
const selectedDistrict = ref(null);
|
|
197
|
+
const selectedSubDistrict = ref(null);
|
|
198
|
+
const addressValue = computed(() => {
|
|
199
|
+
const parts = [];
|
|
200
|
+
if (selectedProvince.value) parts.push(selectedProvince.value.name_th);
|
|
201
|
+
if (selectedDistrict.value) parts.push(selectedDistrict.value.name_th);
|
|
202
|
+
if (selectedSubDistrict.value) parts.push(selectedSubDistrict.value.name_th);
|
|
203
|
+
if (selectedSubDistrict.value)
|
|
204
|
+
parts.push(selectedSubDistrict.value.zip_code.toString());
|
|
205
|
+
return parts.join(", ");
|
|
206
|
+
});
|
|
207
|
+
const addressDetailValue = ref("");
|
|
208
|
+
const mockProvinces = props.provinces || [
|
|
209
|
+
{ code: 10, name_th: "\u0E01\u0E23\u0E38\u0E07\u0E40\u0E17\u0E1E\u0E21\u0E2B\u0E32\u0E19\u0E04\u0E23", name_en: "Bangkok" },
|
|
210
|
+
{ code: 11, name_th: "\u0E2A\u0E21\u0E38\u0E17\u0E23\u0E1B\u0E23\u0E32\u0E01\u0E32\u0E23", name_en: "Samut Prakan" },
|
|
211
|
+
{ code: 12, name_th: "\u0E19\u0E19\u0E17\u0E1A\u0E38\u0E23\u0E35", name_en: "Nonthaburi" },
|
|
212
|
+
{ code: 13, name_th: "\u0E1B\u0E17\u0E38\u0E21\u0E18\u0E32\u0E19\u0E35", name_en: "Pathum Thani" },
|
|
213
|
+
{ code: 14, name_th: "\u0E1E\u0E23\u0E30\u0E19\u0E04\u0E23\u0E28\u0E23\u0E35\u0E2D\u0E22\u0E38\u0E18\u0E22\u0E32", name_en: "Phra Nakhon Si Ayutthaya" },
|
|
214
|
+
{ code: 20, name_th: "\u0E0A\u0E25\u0E1A\u0E38\u0E23\u0E35", name_en: "Chon Buri" },
|
|
215
|
+
{ code: 50, name_th: "\u0E40\u0E0A\u0E35\u0E22\u0E07\u0E43\u0E2B\u0E21\u0E48", name_en: "Chiang Mai" }
|
|
216
|
+
];
|
|
217
|
+
const mockDistricts = props.districts || [
|
|
218
|
+
// กรุงเทพมหานคร
|
|
219
|
+
{
|
|
220
|
+
code: 1001,
|
|
221
|
+
name_th: "\u0E40\u0E02\u0E15\u0E1E\u0E23\u0E30\u0E19\u0E04\u0E23",
|
|
222
|
+
name_en: "Phra Nakhon",
|
|
223
|
+
province_code: 10
|
|
224
|
+
},
|
|
225
|
+
{ code: 1002, name_th: "\u0E40\u0E02\u0E15\u0E14\u0E38\u0E2A\u0E34\u0E15", name_en: "Dusit", province_code: 10 },
|
|
226
|
+
{
|
|
227
|
+
code: 1003,
|
|
228
|
+
name_th: "\u0E40\u0E02\u0E15\u0E2B\u0E19\u0E2D\u0E07\u0E08\u0E2D\u0E01",
|
|
229
|
+
name_en: "Nong Chok",
|
|
230
|
+
province_code: 10
|
|
231
|
+
},
|
|
232
|
+
{ code: 1004, name_th: "\u0E40\u0E02\u0E15\u0E1A\u0E32\u0E07\u0E23\u0E31\u0E01", name_en: "Bang Rak", province_code: 10 },
|
|
233
|
+
{ code: 1005, name_th: "\u0E40\u0E02\u0E15\u0E1A\u0E32\u0E07\u0E40\u0E02\u0E19", name_en: "Bang Khen", province_code: 10 },
|
|
234
|
+
{
|
|
235
|
+
code: 1006,
|
|
236
|
+
name_th: "\u0E40\u0E02\u0E15\u0E1A\u0E32\u0E07\u0E01\u0E30\u0E1B\u0E34",
|
|
237
|
+
name_en: "Bang Kapi",
|
|
238
|
+
province_code: 10
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
code: 1007,
|
|
242
|
+
name_th: "\u0E40\u0E02\u0E15\u0E1B\u0E17\u0E38\u0E21\u0E27\u0E31\u0E19",
|
|
243
|
+
name_en: "Pathum Wan",
|
|
244
|
+
province_code: 10
|
|
245
|
+
},
|
|
246
|
+
// สมุทรปราการ
|
|
247
|
+
{
|
|
248
|
+
code: 1101,
|
|
249
|
+
name_th: "\u0E2D\u0E33\u0E40\u0E20\u0E2D\u0E40\u0E21\u0E37\u0E2D\u0E07\u0E2A\u0E21\u0E38\u0E17\u0E23\u0E1B\u0E23\u0E32\u0E01\u0E32\u0E23",
|
|
250
|
+
name_en: "Mueang Samut Prakan",
|
|
251
|
+
province_code: 11
|
|
252
|
+
},
|
|
253
|
+
{ code: 1102, name_th: "\u0E2D\u0E33\u0E40\u0E20\u0E2D\u0E1A\u0E32\u0E07\u0E1A\u0E48\u0E2D", name_en: "Bang Bo", province_code: 11 },
|
|
254
|
+
// นนทบุรี
|
|
255
|
+
{
|
|
256
|
+
code: 1201,
|
|
257
|
+
name_th: "\u0E2D\u0E33\u0E40\u0E20\u0E2D\u0E40\u0E21\u0E37\u0E2D\u0E07\u0E19\u0E19\u0E17\u0E1A\u0E38\u0E23\u0E35",
|
|
258
|
+
name_en: "Mueang Nonthaburi",
|
|
259
|
+
province_code: 12
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
code: 1202,
|
|
263
|
+
name_th: "\u0E2D\u0E33\u0E40\u0E20\u0E2D\u0E1A\u0E32\u0E07\u0E01\u0E23\u0E27\u0E22",
|
|
264
|
+
name_en: "Bang Kruai",
|
|
265
|
+
province_code: 12
|
|
266
|
+
}
|
|
267
|
+
];
|
|
268
|
+
const mockSubDistricts = props.subDistricts || [
|
|
269
|
+
// เขตพระนคร
|
|
270
|
+
{
|
|
271
|
+
code: 100101,
|
|
272
|
+
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E1E\u0E23\u0E30\u0E1A\u0E23\u0E21\u0E21\u0E2B\u0E32\u0E23\u0E32\u0E0A\u0E27\u0E31\u0E07",
|
|
273
|
+
name_en: "Phra Borom Maha Ratchawang",
|
|
274
|
+
district_code: 1001,
|
|
275
|
+
zip_code: 10200
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
code: 100102,
|
|
279
|
+
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E27\u0E31\u0E07\u0E1A\u0E39\u0E23\u0E1E\u0E32\u0E20\u0E34\u0E23\u0E21\u0E22\u0E4C",
|
|
280
|
+
name_en: "Wang Burapha Phirom",
|
|
281
|
+
district_code: 1001,
|
|
282
|
+
zip_code: 10200
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
code: 100103,
|
|
286
|
+
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E27\u0E31\u0E14\u0E23\u0E32\u0E0A\u0E1A\u0E1E\u0E34\u0E18",
|
|
287
|
+
name_en: "Wat Ratchabophit",
|
|
288
|
+
district_code: 1001,
|
|
289
|
+
zip_code: 10200
|
|
290
|
+
},
|
|
291
|
+
// เขตดุสิต
|
|
292
|
+
{
|
|
293
|
+
code: 100201,
|
|
294
|
+
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E14\u0E38\u0E2A\u0E34\u0E15",
|
|
295
|
+
name_en: "Dusit",
|
|
296
|
+
district_code: 1002,
|
|
297
|
+
zip_code: 10300
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
code: 100202,
|
|
301
|
+
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E27\u0E0A\u0E34\u0E23\u0E1E\u0E22\u0E32\u0E1A\u0E32\u0E25",
|
|
302
|
+
name_en: "Wachiraphayaban",
|
|
303
|
+
district_code: 1002,
|
|
304
|
+
zip_code: 10300
|
|
305
|
+
},
|
|
306
|
+
// เขตบางรัก
|
|
307
|
+
{
|
|
308
|
+
code: 100401,
|
|
309
|
+
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E21\u0E2B\u0E32\u0E1E\u0E24\u0E12\u0E32\u0E23\u0E32\u0E21",
|
|
310
|
+
name_en: "Maha Phruettharam",
|
|
311
|
+
district_code: 1004,
|
|
312
|
+
zip_code: 10500
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
code: 100402,
|
|
316
|
+
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E2A\u0E35\u0E25\u0E21",
|
|
317
|
+
name_en: "Si Lom",
|
|
318
|
+
district_code: 1004,
|
|
319
|
+
zip_code: 10500
|
|
320
|
+
},
|
|
321
|
+
// เขตปทุมวัน
|
|
322
|
+
{
|
|
323
|
+
code: 100701,
|
|
324
|
+
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E23\u0E2D\u0E07\u0E40\u0E21\u0E37\u0E2D\u0E07",
|
|
325
|
+
name_en: "Rong Mueang",
|
|
326
|
+
district_code: 1007,
|
|
327
|
+
zip_code: 10330
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
code: 100702,
|
|
331
|
+
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E27\u0E31\u0E07\u0E43\u0E2B\u0E21\u0E48",
|
|
332
|
+
name_en: "Wang Mai",
|
|
333
|
+
district_code: 1007,
|
|
334
|
+
zip_code: 10330
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
code: 100703,
|
|
338
|
+
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E1B\u0E17\u0E38\u0E21\u0E27\u0E31\u0E19",
|
|
339
|
+
name_en: "Pathum Wan",
|
|
340
|
+
district_code: 1007,
|
|
341
|
+
zip_code: 10330
|
|
342
|
+
},
|
|
343
|
+
// อำเภอเมืองสมุทรปราการ
|
|
344
|
+
{
|
|
345
|
+
code: 110101,
|
|
346
|
+
name_th: "\u0E15\u0E33\u0E1A\u0E25\u0E1B\u0E32\u0E01\u0E19\u0E49\u0E33",
|
|
347
|
+
name_en: "Pak Nam",
|
|
348
|
+
district_code: 1101,
|
|
349
|
+
zip_code: 10270
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
code: 110102,
|
|
353
|
+
name_th: "\u0E15\u0E33\u0E1A\u0E25\u0E2A\u0E33\u0E42\u0E23\u0E07\u0E40\u0E2B\u0E19\u0E37\u0E2D",
|
|
354
|
+
name_en: "Samrong Nuea",
|
|
355
|
+
district_code: 1101,
|
|
356
|
+
zip_code: 10270
|
|
357
|
+
},
|
|
358
|
+
// อำเภอเมืองนนทบุรี
|
|
359
|
+
{
|
|
360
|
+
code: 120101,
|
|
361
|
+
name_th: "\u0E15\u0E33\u0E1A\u0E25\u0E2A\u0E27\u0E19\u0E43\u0E2B\u0E0D\u0E48",
|
|
362
|
+
name_en: "Suan Yai",
|
|
363
|
+
district_code: 1201,
|
|
364
|
+
zip_code: 11e3
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
code: 120102,
|
|
368
|
+
name_th: "\u0E15\u0E33\u0E1A\u0E25\u0E15\u0E25\u0E32\u0E14\u0E02\u0E27\u0E31\u0E0D",
|
|
369
|
+
name_en: "Talat Khwan",
|
|
370
|
+
district_code: 1201,
|
|
371
|
+
zip_code: 11e3
|
|
372
|
+
}
|
|
373
|
+
];
|
|
374
|
+
const filteredProvinces = computed(() => {
|
|
375
|
+
if (!searchQuery.value) return mockProvinces;
|
|
376
|
+
const query = searchQuery.value.toLowerCase();
|
|
377
|
+
return mockProvinces.filter(
|
|
378
|
+
(p) => p.name_th.toLowerCase().includes(query) || p.name_en.toLowerCase().includes(query)
|
|
379
|
+
);
|
|
380
|
+
});
|
|
381
|
+
const filteredDistricts = computed(() => {
|
|
382
|
+
if (!selectedProvince.value) return [];
|
|
383
|
+
const districts = mockDistricts.filter(
|
|
384
|
+
(d) => d.province_code === selectedProvince.value?.code
|
|
385
|
+
);
|
|
386
|
+
if (!searchQuery.value) return districts;
|
|
387
|
+
const query = searchQuery.value.toLowerCase();
|
|
388
|
+
return districts.filter(
|
|
389
|
+
(d) => d.name_th.toLowerCase().includes(query) || d.name_en.toLowerCase().includes(query)
|
|
390
|
+
);
|
|
391
|
+
});
|
|
392
|
+
const filteredSubDistricts = computed(() => {
|
|
393
|
+
if (!selectedDistrict.value) return [];
|
|
394
|
+
const subDistricts = mockSubDistricts.filter(
|
|
395
|
+
(s) => s.district_code === selectedDistrict.value?.code
|
|
396
|
+
);
|
|
397
|
+
if (!searchQuery.value) return subDistricts;
|
|
398
|
+
const query = searchQuery.value.toLowerCase();
|
|
399
|
+
return subDistricts.filter(
|
|
400
|
+
(s) => s.name_th.toLowerCase().includes(query) || s.name_en.toLowerCase().includes(query)
|
|
401
|
+
);
|
|
402
|
+
});
|
|
403
|
+
const onSelectProvince = (province) => {
|
|
404
|
+
selectedProvince.value = province;
|
|
405
|
+
selectedDistrict.value = null;
|
|
406
|
+
selectedSubDistrict.value = null;
|
|
407
|
+
searchQuery.value = "";
|
|
408
|
+
currentTab.value = "district";
|
|
409
|
+
emits("selectProvince", province);
|
|
410
|
+
updateModelValue();
|
|
411
|
+
};
|
|
412
|
+
const onSelectDistrict = (district) => {
|
|
413
|
+
selectedDistrict.value = district;
|
|
414
|
+
selectedSubDistrict.value = null;
|
|
415
|
+
searchQuery.value = "";
|
|
416
|
+
currentTab.value = "subDistrict";
|
|
417
|
+
emits("selectDistrict", district);
|
|
418
|
+
updateModelValue();
|
|
419
|
+
};
|
|
420
|
+
const onSelectSubDistrict = (subDistrict) => {
|
|
421
|
+
selectedSubDistrict.value = subDistrict;
|
|
422
|
+
searchQuery.value = "";
|
|
423
|
+
currentTab.value = "zipCode";
|
|
424
|
+
emits("selectSubDistrict", subDistrict);
|
|
425
|
+
updateModelValue();
|
|
426
|
+
};
|
|
427
|
+
const onSelectZipCode = () => {
|
|
428
|
+
if (selectedSubDistrict.value) {
|
|
429
|
+
emits("selectZipCode", selectedSubDistrict.value.zip_code);
|
|
430
|
+
popoverOpen.value = false;
|
|
431
|
+
currentTab.value = "province";
|
|
432
|
+
updateModelValue();
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
const updateModelValue = () => {
|
|
436
|
+
const value = {
|
|
437
|
+
province: selectedProvince.value || void 0,
|
|
438
|
+
district: selectedDistrict.value || void 0,
|
|
439
|
+
subDistrict: selectedSubDistrict.value || void 0,
|
|
440
|
+
zipCode: selectedSubDistrict.value?.zip_code,
|
|
441
|
+
detail: addressDetailValue.value || void 0,
|
|
442
|
+
fullAddress: buildFullAddress()
|
|
443
|
+
};
|
|
444
|
+
modelValue.value = value;
|
|
445
|
+
emits("change", value);
|
|
446
|
+
};
|
|
447
|
+
const buildFullAddress = () => {
|
|
448
|
+
const parts = [];
|
|
449
|
+
if (addressDetailValue.value) parts.push(addressDetailValue.value);
|
|
450
|
+
if (selectedSubDistrict.value) parts.push(selectedSubDistrict.value.name_th);
|
|
451
|
+
if (selectedDistrict.value) parts.push(selectedDistrict.value.name_th);
|
|
452
|
+
if (selectedProvince.value) parts.push(selectedProvince.value.name_th);
|
|
453
|
+
if (selectedSubDistrict.value)
|
|
454
|
+
parts.push(selectedSubDistrict.value.zip_code.toString());
|
|
455
|
+
return parts.join(" ");
|
|
456
|
+
};
|
|
457
|
+
watch(addressDetailValue, () => {
|
|
458
|
+
updateModelValue();
|
|
459
|
+
});
|
|
460
|
+
const defaultRules = (v) => {
|
|
461
|
+
if (!v && props.required) {
|
|
462
|
+
return "\u0E01\u0E23\u0E38\u0E13\u0E32\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E17\u0E35\u0E48\u0E2D\u0E22\u0E39\u0E48";
|
|
463
|
+
}
|
|
464
|
+
if (v && v.split(", ").length < 4 && props.required) {
|
|
465
|
+
return "\u0E01\u0E23\u0E38\u0E13\u0E32\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E17\u0E35\u0E48\u0E2D\u0E22\u0E39\u0E48\u0E43\u0E2B\u0E49\u0E04\u0E23\u0E1A\u0E16\u0E49\u0E27\u0E19";
|
|
466
|
+
}
|
|
467
|
+
return true;
|
|
468
|
+
};
|
|
469
|
+
const validate = async () => {
|
|
470
|
+
const addressValid = await addressFieldRef.value?.validate();
|
|
471
|
+
const detailValid = await detailFieldRef.value?.validate?.();
|
|
472
|
+
return addressValid?.valid !== false && detailValid !== false;
|
|
473
|
+
};
|
|
474
|
+
const setErrors = (errMsg) => {
|
|
475
|
+
addressFieldRef.value?.setErrors(errMsg);
|
|
476
|
+
};
|
|
477
|
+
const reset = () => {
|
|
478
|
+
selectedProvince.value = null;
|
|
479
|
+
selectedDistrict.value = null;
|
|
480
|
+
selectedSubDistrict.value = null;
|
|
481
|
+
addressDetailValue.value = "";
|
|
482
|
+
currentTab.value = "province";
|
|
483
|
+
updateModelValue();
|
|
484
|
+
};
|
|
485
|
+
defineExpose({
|
|
486
|
+
validate,
|
|
487
|
+
setErrors,
|
|
488
|
+
reset,
|
|
489
|
+
addressFieldRef,
|
|
490
|
+
detailFieldRef
|
|
491
|
+
});
|
|
87
492
|
</script>
|
|
@@ -1,3 +1,76 @@
|
|
|
1
|
-
|
|
1
|
+
interface Province {
|
|
2
|
+
code: number;
|
|
3
|
+
name_th: string;
|
|
4
|
+
name_en: string;
|
|
5
|
+
}
|
|
6
|
+
interface District {
|
|
7
|
+
code: number;
|
|
8
|
+
name_th: string;
|
|
9
|
+
name_en: string;
|
|
10
|
+
province_code: number;
|
|
11
|
+
}
|
|
12
|
+
interface SubDistrict {
|
|
13
|
+
code: number;
|
|
14
|
+
name_th: string;
|
|
15
|
+
name_en: string;
|
|
16
|
+
district_code: number;
|
|
17
|
+
zip_code: number;
|
|
18
|
+
}
|
|
19
|
+
export interface InputAddressValue {
|
|
20
|
+
province?: Province;
|
|
21
|
+
district?: District;
|
|
22
|
+
subDistrict?: SubDistrict;
|
|
23
|
+
zipCode?: number;
|
|
24
|
+
detail?: string;
|
|
25
|
+
fullAddress?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface InputAddressProps {
|
|
28
|
+
name?: string;
|
|
29
|
+
label?: string;
|
|
30
|
+
placeholder?: string;
|
|
31
|
+
labelDetail?: string;
|
|
32
|
+
placeholderDetail?: string;
|
|
33
|
+
required?: boolean;
|
|
34
|
+
requiredDetail?: boolean;
|
|
35
|
+
rules?: object | string | Function;
|
|
36
|
+
provinces?: Province[];
|
|
37
|
+
districts?: District[];
|
|
38
|
+
subDistricts?: SubDistrict[];
|
|
39
|
+
}
|
|
40
|
+
type __VLS_Props = InputAddressProps;
|
|
41
|
+
type __VLS_ModelProps = {
|
|
42
|
+
modelValue?: InputAddressValue;
|
|
43
|
+
};
|
|
44
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
45
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
46
|
+
validate: () => Promise<boolean>;
|
|
47
|
+
setErrors: (errMsg: string[]) => void;
|
|
48
|
+
reset: () => void;
|
|
49
|
+
addressFieldRef: import("vue").Ref<any, any>;
|
|
50
|
+
detailFieldRef: import("vue").Ref<any, any>;
|
|
51
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
52
|
+
"update:modelValue": (value: InputAddressValue) => any;
|
|
53
|
+
} & {
|
|
54
|
+
change: (value: InputAddressValue) => any;
|
|
55
|
+
selectProvince: (province: Province) => any;
|
|
56
|
+
selectDistrict: (district: District) => any;
|
|
57
|
+
selectSubDistrict: (subDistrict: SubDistrict) => any;
|
|
58
|
+
selectZipCode: (zipCode: number) => any;
|
|
59
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
60
|
+
onChange?: ((value: InputAddressValue) => any) | undefined;
|
|
61
|
+
"onUpdate:modelValue"?: ((value: InputAddressValue) => any) | undefined;
|
|
62
|
+
onSelectProvince?: ((province: Province) => any) | undefined;
|
|
63
|
+
onSelectDistrict?: ((district: District) => any) | undefined;
|
|
64
|
+
onSelectSubDistrict?: ((subDistrict: SubDistrict) => any) | undefined;
|
|
65
|
+
onSelectZipCode?: ((zipCode: number) => any) | undefined;
|
|
66
|
+
}>, {
|
|
67
|
+
label: string;
|
|
68
|
+
required: boolean;
|
|
69
|
+
name: string;
|
|
70
|
+
placeholder: string;
|
|
71
|
+
labelDetail: string;
|
|
72
|
+
placeholderDetail: string;
|
|
73
|
+
requiredDetail: boolean;
|
|
74
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
2
75
|
declare const _default: typeof __VLS_export;
|
|
3
76
|
export default _default;
|
|
@@ -1,27 +1,54 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<ShadPopover v-model:open="open" :modal="false">
|
|
3
3
|
<ShadPopoverAnchor as-child>
|
|
4
|
-
<InputTextField
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
:
|
|
4
|
+
<InputTextField
|
|
5
|
+
ref="fieldRef"
|
|
6
|
+
v-model="searchText"
|
|
7
|
+
:label="props.label"
|
|
8
|
+
:name="props.name"
|
|
9
|
+
:rules="props.rules"
|
|
10
|
+
:required="props.required"
|
|
11
|
+
:description="props.description"
|
|
12
|
+
:placeholder="props.placeholder"
|
|
13
|
+
:disabled-border="props.disabledBorder"
|
|
14
|
+
:disabled-error-message="props.disabledErrorMessage"
|
|
15
|
+
autocomplete="off"
|
|
16
|
+
@focus="open = true"
|
|
17
|
+
@click="console.log('click')"
|
|
18
|
+
@blur="handleBlur"
|
|
19
|
+
:show-counter="props.showCounter"
|
|
20
|
+
:limit="props.limit"
|
|
21
|
+
>
|
|
9
22
|
<template #append>
|
|
10
|
-
<Icon
|
|
11
|
-
|
|
23
|
+
<Icon
|
|
24
|
+
@mousedown.stop.prevent="handleIconMouseDown"
|
|
25
|
+
:name="modelValue ? 'lucide:x' : 'lucide:search'"
|
|
26
|
+
size="16"
|
|
27
|
+
class="cursor-pointer"
|
|
28
|
+
/>
|
|
12
29
|
</template>
|
|
13
30
|
</InputTextField>
|
|
14
31
|
</ShadPopoverAnchor>
|
|
15
|
-
<ShadPopoverContent
|
|
16
|
-
|
|
17
|
-
|
|
32
|
+
<ShadPopoverContent
|
|
33
|
+
@openAutoFocus.prevent
|
|
34
|
+
@closeAutoFocus.prevent
|
|
35
|
+
align="start"
|
|
36
|
+
class="max-h-[312px] overflow-auto"
|
|
37
|
+
>
|
|
38
|
+
<div
|
|
39
|
+
v-if="filteredOptions.length === 0"
|
|
40
|
+
class="flex flex-col gap-[8px] items-center justify-center h-[192px]"
|
|
41
|
+
>
|
|
18
42
|
<Icon name="pukaad:page-not-found" class="w-[77px] h-[64px]" />
|
|
19
43
|
<div class="font-body-medium text-center text-gray">ไม่พบข้อมูล</div>
|
|
20
44
|
</div>
|
|
21
45
|
<div v-else>
|
|
22
|
-
<div
|
|
46
|
+
<div
|
|
47
|
+
v-for="option in filteredOptions"
|
|
48
|
+
:key="option.value"
|
|
23
49
|
class="cursor-pointer hover:bg-smoke flex items-center gap-[8px] px-[8px] py-[6px]"
|
|
24
|
-
@mousedown.prevent="selectOption(option)"
|
|
50
|
+
@mousedown.prevent="selectOption(option)"
|
|
51
|
+
>
|
|
25
52
|
<div class="flex flex-col gap-[4px] w-full">
|
|
26
53
|
<div class="font-body-medium">
|
|
27
54
|
{{ option.label }}
|
|
@@ -30,7 +57,11 @@
|
|
|
30
57
|
{{ option.description }}
|
|
31
58
|
</div>
|
|
32
59
|
</div>
|
|
33
|
-
<Icon
|
|
60
|
+
<Icon
|
|
61
|
+
v-if="modelValue === option.value"
|
|
62
|
+
name="lucide:check"
|
|
63
|
+
size="16"
|
|
64
|
+
/>
|
|
34
65
|
</div>
|
|
35
66
|
</div>
|
|
36
67
|
</ShadPopoverContent>
|
|
@@ -55,10 +55,10 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
55
55
|
name: string;
|
|
56
56
|
disabled: boolean;
|
|
57
57
|
limit: number;
|
|
58
|
+
readonly: boolean;
|
|
58
59
|
disabledErrorMessage: boolean;
|
|
59
60
|
disabledBorder: boolean;
|
|
60
61
|
showCounter: boolean;
|
|
61
|
-
readonly: boolean;
|
|
62
62
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
63
63
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
64
64
|
declare const _default: typeof __VLS_export;
|
|
@@ -55,10 +55,10 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
55
55
|
name: string;
|
|
56
56
|
disabled: boolean;
|
|
57
57
|
limit: number;
|
|
58
|
+
readonly: boolean;
|
|
58
59
|
disabledErrorMessage: boolean;
|
|
59
60
|
disabledBorder: boolean;
|
|
60
61
|
showCounter: boolean;
|
|
61
|
-
readonly: boolean;
|
|
62
62
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
63
63
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
64
64
|
declare const _default: typeof __VLS_export;
|
|
@@ -45,10 +45,10 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
45
45
|
name: string;
|
|
46
46
|
disabled: boolean;
|
|
47
47
|
limit: number;
|
|
48
|
+
readonly: boolean;
|
|
48
49
|
disabledErrorMessage: boolean;
|
|
49
50
|
disabledBorder: boolean;
|
|
50
51
|
showCounter: boolean;
|
|
51
|
-
readonly: boolean;
|
|
52
52
|
resize: "none" | "both" | "horizontal" | "vertical";
|
|
53
53
|
rows: number;
|
|
54
54
|
heightScroll: boolean;
|
|
@@ -45,10 +45,10 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
45
45
|
name: string;
|
|
46
46
|
disabled: boolean;
|
|
47
47
|
limit: number;
|
|
48
|
+
readonly: boolean;
|
|
48
49
|
disabledErrorMessage: boolean;
|
|
49
50
|
disabledBorder: boolean;
|
|
50
51
|
showCounter: boolean;
|
|
51
|
-
readonly: boolean;
|
|
52
52
|
resize: "none" | "both" | "horizontal" | "vertical";
|
|
53
53
|
rows: number;
|
|
54
54
|
heightScroll: boolean;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface LoadingProps {
|
|
2
|
+
isLoading?: boolean;
|
|
3
|
+
text?: string;
|
|
4
|
+
}
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<LoadingProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<LoadingProps> & Readonly<{}>, {
|
|
6
|
+
text: string;
|
|
7
|
+
isLoading: boolean;
|
|
8
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
|
+
declare const _default: typeof __VLS_export;
|
|
10
|
+
export default _default;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Transition name="loading-fade">
|
|
3
|
+
<div
|
|
4
|
+
v-if="isLoading"
|
|
5
|
+
class="absolute inset-0 opacity-50 z-50 flex items-center justify-center backdrop-blur-2xl"
|
|
6
|
+
>
|
|
7
|
+
<div class="flex flex-col items-center gap-3">
|
|
8
|
+
<div class="loading-spinner"></div>
|
|
9
|
+
<span v-if="text" class="text-sm text-cloud">{{ text }}</span>
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
</Transition>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<script setup>
|
|
16
|
+
defineProps({
|
|
17
|
+
isLoading: { type: Boolean, required: false, default: false },
|
|
18
|
+
text: { type: String, required: false, default: "" }
|
|
19
|
+
});
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<style scoped>
|
|
23
|
+
.loading-spinner{animation:spin .8s linear infinite;border:6px solid rgba(0,0,0,.1);border-radius:50%;border-top-color:#3b82f6;height:64px;width:64px}@keyframes spin{to{transform:rotate(1turn)}}.loading-fade-enter-active,.loading-fade-leave-active{transition:opacity .2s ease}.loading-fade-enter-from,.loading-fade-leave-to{opacity:0}
|
|
24
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface LoadingProps {
|
|
2
|
+
isLoading?: boolean;
|
|
3
|
+
text?: string;
|
|
4
|
+
}
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<LoadingProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<LoadingProps> & Readonly<{}>, {
|
|
6
|
+
text: string;
|
|
7
|
+
isLoading: boolean;
|
|
8
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
|
+
declare const _default: typeof __VLS_export;
|
|
10
|
+
export default _default;
|
|
@@ -5,27 +5,29 @@ export interface ModalProps {
|
|
|
5
5
|
description?: string;
|
|
6
6
|
footer?: string;
|
|
7
7
|
disabledCloseBtn?: boolean;
|
|
8
|
+
isLoading?: boolean;
|
|
9
|
+
loadingText?: string;
|
|
8
10
|
}
|
|
9
11
|
type __VLS_Props = ModalProps;
|
|
10
12
|
type __VLS_ModelProps = {
|
|
11
13
|
modelValue?: boolean;
|
|
12
14
|
};
|
|
13
15
|
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
14
|
-
declare var
|
|
16
|
+
declare var __VLS_28: {}, __VLS_36: {}, __VLS_44: {}, __VLS_46: {
|
|
15
17
|
meta: any;
|
|
16
|
-
},
|
|
18
|
+
}, __VLS_54: {
|
|
17
19
|
meta: any;
|
|
18
20
|
};
|
|
19
21
|
type __VLS_Slots = {} & {
|
|
20
|
-
header?: (props: typeof
|
|
22
|
+
header?: (props: typeof __VLS_28) => any;
|
|
21
23
|
} & {
|
|
22
|
-
title?: (props: typeof
|
|
24
|
+
title?: (props: typeof __VLS_36) => any;
|
|
23
25
|
} & {
|
|
24
|
-
description?: (props: typeof
|
|
26
|
+
description?: (props: typeof __VLS_44) => any;
|
|
25
27
|
} & {
|
|
26
|
-
default?: (props: typeof
|
|
28
|
+
default?: (props: typeof __VLS_46) => any;
|
|
27
29
|
} & {
|
|
28
|
-
footer?: (props: typeof
|
|
30
|
+
footer?: (props: typeof __VLS_54) => any;
|
|
29
31
|
};
|
|
30
32
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
31
33
|
"update:modelValue": (value: boolean) => any;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
@submit="onSubmit"
|
|
8
8
|
@close="onClose"
|
|
9
9
|
>
|
|
10
|
+
<Loading :is-loading="props.isLoading" :text="props.loadingText" />
|
|
10
11
|
<ShadDialogHeader>
|
|
11
12
|
<slot name="header">
|
|
12
13
|
<ShadDialogTitle>
|
|
@@ -36,7 +37,9 @@ const props = defineProps({
|
|
|
36
37
|
title: { type: String, required: false },
|
|
37
38
|
description: { type: String, required: false },
|
|
38
39
|
footer: { type: String, required: false },
|
|
39
|
-
disabledCloseBtn: { type: Boolean, required: false, default: false }
|
|
40
|
+
disabledCloseBtn: { type: Boolean, required: false, default: false },
|
|
41
|
+
isLoading: { type: Boolean, required: false },
|
|
42
|
+
loadingText: { type: String, required: false }
|
|
40
43
|
});
|
|
41
44
|
const isOpen = defineModel({ type: Boolean, ...{
|
|
42
45
|
default: false
|
|
@@ -5,27 +5,29 @@ export interface ModalProps {
|
|
|
5
5
|
description?: string;
|
|
6
6
|
footer?: string;
|
|
7
7
|
disabledCloseBtn?: boolean;
|
|
8
|
+
isLoading?: boolean;
|
|
9
|
+
loadingText?: string;
|
|
8
10
|
}
|
|
9
11
|
type __VLS_Props = ModalProps;
|
|
10
12
|
type __VLS_ModelProps = {
|
|
11
13
|
modelValue?: boolean;
|
|
12
14
|
};
|
|
13
15
|
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
14
|
-
declare var
|
|
16
|
+
declare var __VLS_28: {}, __VLS_36: {}, __VLS_44: {}, __VLS_46: {
|
|
15
17
|
meta: any;
|
|
16
|
-
},
|
|
18
|
+
}, __VLS_54: {
|
|
17
19
|
meta: any;
|
|
18
20
|
};
|
|
19
21
|
type __VLS_Slots = {} & {
|
|
20
|
-
header?: (props: typeof
|
|
22
|
+
header?: (props: typeof __VLS_28) => any;
|
|
21
23
|
} & {
|
|
22
|
-
title?: (props: typeof
|
|
24
|
+
title?: (props: typeof __VLS_36) => any;
|
|
23
25
|
} & {
|
|
24
|
-
description?: (props: typeof
|
|
26
|
+
description?: (props: typeof __VLS_44) => any;
|
|
25
27
|
} & {
|
|
26
|
-
default?: (props: typeof
|
|
28
|
+
default?: (props: typeof __VLS_46) => any;
|
|
27
29
|
} & {
|
|
28
|
-
footer?: (props: typeof
|
|
30
|
+
footer?: (props: typeof __VLS_54) => any;
|
|
29
31
|
};
|
|
30
32
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
31
33
|
"update:modelValue": (value: boolean) => any;
|
|
@@ -5,7 +5,7 @@ type __VLS_Slots = {} & {
|
|
|
5
5
|
};
|
|
6
6
|
declare const __VLS_base: import("vue").DefineComponent<InputGroupButtonProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<InputGroupButtonProps> & Readonly<{}>, {
|
|
7
7
|
variant: "default" | "outline" | "ghost" | "link" | "text" | "icon" | null;
|
|
8
|
-
size: "
|
|
8
|
+
size: "icon-xs" | "sm" | "icon-sm" | "xs" | null;
|
|
9
9
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
10
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
11
11
|
declare const _default: typeof __VLS_export;
|
|
@@ -5,7 +5,7 @@ type __VLS_Slots = {} & {
|
|
|
5
5
|
};
|
|
6
6
|
declare const __VLS_base: import("vue").DefineComponent<InputGroupButtonProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<InputGroupButtonProps> & Readonly<{}>, {
|
|
7
7
|
variant: "default" | "outline" | "ghost" | "link" | "text" | "icon" | null;
|
|
8
|
-
size: "
|
|
8
|
+
size: "icon-xs" | "sm" | "icon-sm" | "xs" | null;
|
|
9
9
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
10
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
11
11
|
declare const _default: typeof __VLS_export;
|
|
@@ -12,7 +12,7 @@ export declare const inputGroupAddonVariants: (props?: ({
|
|
|
12
12
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
13
13
|
export type InputGroupVariants = VariantProps<typeof inputGroupAddonVariants>;
|
|
14
14
|
export declare const inputGroupButtonVariants: (props?: ({
|
|
15
|
-
size?: "
|
|
15
|
+
size?: "icon-xs" | "sm" | "icon-sm" | "xs" | null | undefined;
|
|
16
16
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
17
17
|
export type InputGroupButtonVariants = VariantProps<typeof inputGroupButtonVariants>;
|
|
18
18
|
export interface InputGroupButtonProps {
|