pukaad-ui-lib 1.29.0 → 1.31.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pukaad-ui-lib",
3
3
  "configKey": "pukaadUI",
4
- "version": "1.29.0",
4
+ "version": "1.31.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
@@ -0,0 +1,55 @@
1
+ export interface DataListProps {
2
+ items?: Record<string, any>[];
3
+ height?: number | string;
4
+ maxHeight?: number | string;
5
+ fullHeight?: boolean;
6
+ disabledPagination?: boolean;
7
+ totalPage?: number;
8
+ }
9
+ type __VLS_Props = DataListProps;
10
+ type __VLS_ModelProps = {
11
+ "page"?: number;
12
+ };
13
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
14
+ declare var __VLS_6: {
15
+ items: Record<string, any>[];
16
+ }, __VLS_26: {
17
+ item: Record<string, any>;
18
+ index: number;
19
+ }, __VLS_28: {}, __VLS_35: {};
20
+ type __VLS_Slots = {} & {
21
+ body?: (props: typeof __VLS_6) => any;
22
+ } & {
23
+ item?: (props: typeof __VLS_26) => any;
24
+ } & {
25
+ empty?: (props: typeof __VLS_28) => any;
26
+ } & {
27
+ 'empty-content'?: (props: typeof __VLS_35) => any;
28
+ };
29
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
30
+ "update:page": (value: number) => any;
31
+ } & {
32
+ "select-page": (value: number) => any;
33
+ "change-page": (value: number) => any;
34
+ "click-row": (item: Record<string, any>, index: number) => any;
35
+ "change-item-per-page": (value: number) => any;
36
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
37
+ "onSelect-page"?: ((value: number) => any) | undefined;
38
+ "onChange-page"?: ((value: number) => any) | undefined;
39
+ "onClick-row"?: ((item: Record<string, any>, index: number) => any) | undefined;
40
+ "onChange-item-per-page"?: ((value: number) => any) | undefined;
41
+ "onUpdate:page"?: ((value: number) => any) | undefined;
42
+ }>, {
43
+ items: Record<string, any>[];
44
+ fullHeight: boolean;
45
+ disabledPagination: boolean;
46
+ totalPage: number;
47
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
48
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
49
+ declare const _default: typeof __VLS_export;
50
+ export default _default;
51
+ type __VLS_WithSlots<T, S> = T & {
52
+ new (): {
53
+ $slots: S;
54
+ };
55
+ };
@@ -0,0 +1,78 @@
1
+ <script setup>
2
+ import {
3
+ Table as ShadTable,
4
+ TableBody as ShadTableBody,
5
+ TableRow as ShadTableRow,
6
+ TableCell as ShadTableCell,
7
+ TableEmpty as ShadTableEmpty
8
+ } from "@/runtime/components/ui/table";
9
+ const emit = defineEmits(["select-page", "change-page", "click-row", "change-item-per-page"]);
10
+ const props = defineProps({
11
+ items: { type: Array, required: false, default: () => [] },
12
+ height: { type: [Number, String], required: false },
13
+ maxHeight: { type: [Number, String], required: false },
14
+ fullHeight: { type: Boolean, required: false, default: false },
15
+ disabledPagination: { type: Boolean, required: false, default: false },
16
+ totalPage: { type: Number, required: false, default: 1 }
17
+ });
18
+ const page = defineModel("page", { type: Number, ...{
19
+ default: 1
20
+ } });
21
+ </script>
22
+
23
+ <template>
24
+ <div class="bg-white rounded-lg flex flex-col">
25
+ <!-- List Container -->
26
+ <div
27
+ class="flex-1 overflow-auto"
28
+ :style="{
29
+ height: props.fullHeight ? '100%' : props.height ? `${props.height}px` : 'auto',
30
+ maxHeight: props.maxHeight ? `${props.maxHeight}px` : void 0
31
+ }"
32
+ >
33
+ <ShadTable>
34
+ <slot name="body" :items="props.items">
35
+ <ShadTableBody>
36
+ <template v-if="props.items.length > 0">
37
+ <ShadTableRow
38
+ v-for="(item, index) in props.items"
39
+ :key="index"
40
+ class="cursor-pointer"
41
+ @click="emit('click-row', item, index)"
42
+ >
43
+ <ShadTableCell class="w-full">
44
+ <slot name="item" :item="item" :index="index">
45
+ {{ item }}
46
+ </slot>
47
+ </ShadTableCell>
48
+ </ShadTableRow>
49
+ </template>
50
+
51
+ <!-- Empty State -->
52
+ <template v-else>
53
+ <slot name="empty">
54
+ <ShadTableEmpty :colspan="1">
55
+ <slot name="empty-content" />
56
+ </ShadTableEmpty>
57
+ </slot>
58
+ </template>
59
+ </ShadTableBody>
60
+ </slot>
61
+ </ShadTable>
62
+ </div>
63
+
64
+ <!-- Pagination -->
65
+ <div
66
+ v-if="props.items.length > 0 && !props.disabledPagination"
67
+ class="p-4 flex justify-center items-center border-t"
68
+ >
69
+ <Pagination
70
+ :totalPage="props.totalPage"
71
+ v-model="page"
72
+ @change-item-per-page="
73
+ (val) => emit('change-item-per-page', val)
74
+ "
75
+ />
76
+ </div>
77
+ </div>
78
+ </template>
@@ -0,0 +1,55 @@
1
+ export interface DataListProps {
2
+ items?: Record<string, any>[];
3
+ height?: number | string;
4
+ maxHeight?: number | string;
5
+ fullHeight?: boolean;
6
+ disabledPagination?: boolean;
7
+ totalPage?: number;
8
+ }
9
+ type __VLS_Props = DataListProps;
10
+ type __VLS_ModelProps = {
11
+ "page"?: number;
12
+ };
13
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
14
+ declare var __VLS_6: {
15
+ items: Record<string, any>[];
16
+ }, __VLS_26: {
17
+ item: Record<string, any>;
18
+ index: number;
19
+ }, __VLS_28: {}, __VLS_35: {};
20
+ type __VLS_Slots = {} & {
21
+ body?: (props: typeof __VLS_6) => any;
22
+ } & {
23
+ item?: (props: typeof __VLS_26) => any;
24
+ } & {
25
+ empty?: (props: typeof __VLS_28) => any;
26
+ } & {
27
+ 'empty-content'?: (props: typeof __VLS_35) => any;
28
+ };
29
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
30
+ "update:page": (value: number) => any;
31
+ } & {
32
+ "select-page": (value: number) => any;
33
+ "change-page": (value: number) => any;
34
+ "click-row": (item: Record<string, any>, index: number) => any;
35
+ "change-item-per-page": (value: number) => any;
36
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
37
+ "onSelect-page"?: ((value: number) => any) | undefined;
38
+ "onChange-page"?: ((value: number) => any) | undefined;
39
+ "onClick-row"?: ((item: Record<string, any>, index: number) => any) | undefined;
40
+ "onChange-item-per-page"?: ((value: number) => any) | undefined;
41
+ "onUpdate:page"?: ((value: number) => any) | undefined;
42
+ }>, {
43
+ items: Record<string, any>[];
44
+ fullHeight: boolean;
45
+ disabledPagination: boolean;
46
+ totalPage: number;
47
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
48
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
49
+ declare const _default: typeof __VLS_export;
50
+ export default _default;
51
+ type __VLS_WithSlots<T, S> = T & {
52
+ new (): {
53
+ $slots: S;
54
+ };
55
+ };
@@ -58,13 +58,13 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
58
58
  }>, {
59
59
  items: Record<string, any>[];
60
60
  fullHeight: boolean;
61
+ disabledPagination: boolean;
62
+ totalPage: number;
61
63
  itemHeader: TableHeader[];
62
64
  headerAlinement: TableHeaderAlignment;
63
65
  cellAlinement: TableHeaderAlignment;
64
66
  disabledHeader: boolean;
65
67
  disabledSort: boolean;
66
- disabledPagination: boolean;
67
- totalPage: number;
68
68
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
69
69
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
70
70
  declare const _default: typeof __VLS_export;
@@ -58,13 +58,13 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
58
58
  }>, {
59
59
  items: Record<string, any>[];
60
60
  fullHeight: boolean;
61
+ disabledPagination: boolean;
62
+ totalPage: number;
61
63
  itemHeader: TableHeader[];
62
64
  headerAlinement: TableHeaderAlignment;
63
65
  cellAlinement: TableHeaderAlignment;
64
66
  disabledHeader: boolean;
65
67
  disabledSort: boolean;
66
- disabledPagination: boolean;
67
- totalPage: number;
68
68
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
69
69
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
70
70
  declare const _default: typeof __VLS_export;
@@ -64,7 +64,6 @@ 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
67
  responsive: boolean;
69
68
  restore: boolean;
70
69
  checkCrossOrigin: boolean;
@@ -73,6 +72,7 @@ declare const __VLS_export: import("vue").DefineComponent<ImageCropperProps, {
73
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,7 +64,6 @@ 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
67
  responsive: boolean;
69
68
  restore: boolean;
70
69
  checkCrossOrigin: boolean;
@@ -73,6 +72,7 @@ declare const __VLS_export: import("vue").DefineComponent<ImageCropperProps, {
73
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;
@@ -37,8 +37,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
37
37
  name: string;
38
38
  placeholder: string;
39
39
  description: string;
40
- options: AutocompleteOption[] | string[] | number[];
41
40
  limit: number;
41
+ options: AutocompleteOption[] | string[] | number[];
42
42
  disabledErrorMessage: boolean;
43
43
  disabledBorder: boolean;
44
44
  showCounter: boolean;
@@ -37,8 +37,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
37
37
  name: string;
38
38
  placeholder: string;
39
39
  description: string;
40
- options: AutocompleteOption[] | string[] | number[];
41
40
  limit: number;
41
+ options: AutocompleteOption[] | string[] | number[];
42
42
  disabledErrorMessage: boolean;
43
43
  disabledBorder: boolean;
44
44
  showCounter: boolean;
@@ -1,25 +1,23 @@
1
1
  <template>
2
2
  <Modal
3
3
  :title="props.item ? '\u0E41\u0E01\u0E49\u0E44\u0E02\u0E1A\u0E31\u0E15\u0E23\u0E1B\u0E23\u0E30\u0E0A\u0E32\u0E0A\u0E19' : '\u0E2D\u0E31\u0E1B\u0E42\u0E2B\u0E25\u0E14\u0E1A\u0E31\u0E15\u0E23\u0E1B\u0E23\u0E30\u0E0A\u0E32\u0E0A\u0E19'"
4
- width="499"
5
- divider
6
- :gap="imageFile ? 0 : 16"
4
+ class="lg:max-w-[512px] gap-[24px]"
7
5
  @close="onCancel"
8
6
  v-model="isOpenModal"
9
7
  >
10
- <div v-if="!imageFile" class="flex flex-col gap-[16px]">
11
- <div class="px-[16px]">
12
- <ul
13
- class="list-disc list-inside flex flex-col gap-[8px] font-body-medium-prominent text-gray"
14
- >
15
- <li>จัดวางรูปหน้าและตราครุฑตรงช่องกรอบ</li>
16
- <li>ต้องชัดเจน อ่านง่าย ไม่เบลอ</li>
17
- <li>มีแสงสว่างเพียงพอ และไม่มีแสงสะท้อน</li>
18
- <li>ไม่มีนิ้วมือมาปิดบังบัตรประชาชน</li>
19
- <li>บัตรประชาชนต้องไม่หมดอายุ</li>
20
- </ul>
21
- </div>
22
- <div v-if="props.item" class="px-[16px]">
8
+ <template #description v-if="!imageFile">
9
+ <ul
10
+ class="list-disc list-inside flex flex-col gap-[8px] font-body-medium-prominent text-gray"
11
+ >
12
+ <li>จัดวางรูปหน้าและตราครุฑตรงช่องกรอบ</li>
13
+ <li>ต้องชัดเจน อ่านง่าย ไม่เบลอ</li>
14
+ <li>มีแสงสว่างเพียงพอ และไม่มีแสงสะท้อน</li>
15
+ <li>ไม่มีนิ้วมือมาปิดบังบัตรประชาชน</li>
16
+ <li>บัตรประชาชนต้องไม่หมดอายุ</li>
17
+ </ul>
18
+ </template>
19
+ <div v-if="!imageFile" class="flex flex-col">
20
+ <div v-if="props.item">
23
21
  <div class="relative w-[467px] h-[263px]">
24
22
  <Image
25
23
  :src="props.item"
@@ -47,7 +45,7 @@
47
45
  </div>
48
46
  </div>
49
47
  </div>
50
- <div v-else class="px-[16px]">
48
+ <div v-else>
51
49
  <input
52
50
  ref="fileInputRef"
53
51
  type="file"
@@ -112,20 +110,13 @@
112
110
  </div>
113
111
  </div>
114
112
  <div class="p-[16px] flex gap-[40px] items-center">
115
- <div class="flex gap-[16px] items-center">
113
+ <div class="flex gap-[8px] items-center">
116
114
  <div>
117
115
  <Icon name="lucide:zoom-in" :size="20" />
118
116
  </div>
119
- <Button
120
- variant="text"
121
- disabled-padding
122
- :disabled="!imageFile"
123
- @click="onZoomOut"
124
- >
125
- <div>
126
- <Icon name="f7:minus" :size="16" />
127
- </div>
128
- </Button>
117
+ <div class="cursor-pointer" @click="onZoomOut">
118
+ <Icon name="f7:minus" :size="20" />
119
+ </div>
129
120
  <InputSlider
130
121
  :thumb-size="16"
131
122
  :min="isZoomMin"
@@ -135,31 +126,17 @@
135
126
  full-width
136
127
  v-model="isZoom"
137
128
  />
138
- <Button
139
- variant="text"
140
- disabled-padding
141
- :disabled="!imageFile"
142
- @click="onZoomIn"
143
- >
144
- <div>
145
- <Icon name="f7:plus" :size="16" />
146
- </div>
147
- </Button>
129
+ <div class="cursor-pointer" @click="onZoomIn">
130
+ <Icon name="f7:plus" :size="20" />
131
+ </div>
148
132
  </div>
149
- <div class="flex gap-[16px] items-center">
133
+ <div class="flex gap-[8px] items-center">
150
134
  <div>
151
135
  <Icon name="lucide:refresh-cw" :size="20" />
152
136
  </div>
153
- <Button
154
- variant="text"
155
- disabled-padding
156
- :disabled="!imageFile"
157
- @click="onRotateLeft"
158
- >
159
- <div>
160
- <Icon name="f7:minus" size="16" />
161
- </div>
162
- </Button>
137
+ <div class="cursor-pointer" @click="onRotateLeft">
138
+ <Icon name="f7:minus" :size="20" />
139
+ </div>
163
140
  <InputSlider
164
141
  :thumb-size="16"
165
142
  :min="isRotateMin"
@@ -169,24 +146,20 @@
169
146
  full-width
170
147
  v-model="isRotate"
171
148
  />
172
- <Button
173
- variant="text"
174
- disabled-padding
175
- :disabled="!imageFile"
176
- @click="onRotateRight"
177
- aria-label="หมุนขวา"
178
- >
179
- <Icon name="f7:plus" :size="16" />
180
- </Button>
149
+ <div class="cursor-pointer" @click="onRotateRight">
150
+ <Icon name="f7:plus" :size="20" />
151
+ </div>
181
152
  </div>
182
153
  </div>
183
154
  </div>
184
155
  <template #footer>
185
- <div class="flex gap-[16px] w-full">
186
- <Button variant="outline" full-width @click="onCancel">ยกเลิก</Button>
156
+ <div class="flex gap-[16px]">
157
+ <Button variant="outline" class="w-[224px]" @click="onCancel"
158
+ >ยกเลิก</Button
159
+ >
187
160
  <Button
188
161
  color="primary"
189
- full-width
162
+ class="w-[224px]"
190
163
  :disabled="!imageFile"
191
164
  @click="onCropImage"
192
165
  >
@@ -11,29 +11,31 @@ type __VLS_ModelProps = {
11
11
  modelValue?: boolean;
12
12
  };
13
13
  type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
14
- declare var __VLS_20: {}, __VLS_27: {}, __VLS_34: {}, __VLS_36: {
14
+ declare var __VLS_21: {}, __VLS_28: {}, __VLS_35: {}, __VLS_37: {
15
15
  meta: any;
16
- }, __VLS_43: {
16
+ }, __VLS_44: {
17
17
  meta: any;
18
18
  };
19
19
  type __VLS_Slots = {} & {
20
- header?: (props: typeof __VLS_20) => any;
20
+ header?: (props: typeof __VLS_21) => any;
21
21
  } & {
22
- title?: (props: typeof __VLS_27) => any;
22
+ title?: (props: typeof __VLS_28) => any;
23
23
  } & {
24
- description?: (props: typeof __VLS_34) => any;
24
+ description?: (props: typeof __VLS_35) => any;
25
25
  } & {
26
- default?: (props: typeof __VLS_36) => any;
26
+ default?: (props: typeof __VLS_37) => any;
27
27
  } & {
28
- footer?: (props: typeof __VLS_43) => any;
28
+ footer?: (props: typeof __VLS_44) => any;
29
29
  };
30
30
  declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
31
31
  "update:modelValue": (value: boolean) => any;
32
32
  } & {
33
33
  submit: () => any;
34
+ close: () => any;
34
35
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
35
36
  onSubmit?: (() => any) | undefined;
36
37
  "onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
38
+ onClose?: (() => any) | undefined;
37
39
  }>, {
38
40
  disabledCloseBtn: boolean;
39
41
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -5,6 +5,7 @@
5
5
  :disabled-close-btn="props.disabledCloseBtn"
6
6
  v-slot="{ meta }"
7
7
  @submit="onSubmit"
8
+ @close="onClose"
8
9
  >
9
10
  <ShadDialogHeader>
10
11
  <slot name="header">
@@ -29,7 +30,7 @@
29
30
  </template>
30
31
 
31
32
  <script setup>
32
- const emits = defineEmits(["submit"]);
33
+ const emits = defineEmits(["submit", "close"]);
33
34
  const props = defineProps({
34
35
  class: { type: null, required: false },
35
36
  title: { type: String, required: false },
@@ -43,4 +44,7 @@ const isOpen = defineModel({ type: Boolean, ...{
43
44
  const onSubmit = (e) => {
44
45
  emits("submit");
45
46
  };
47
+ const onClose = () => {
48
+ emits("close");
49
+ };
46
50
  </script>
@@ -11,29 +11,31 @@ type __VLS_ModelProps = {
11
11
  modelValue?: boolean;
12
12
  };
13
13
  type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
14
- declare var __VLS_20: {}, __VLS_27: {}, __VLS_34: {}, __VLS_36: {
14
+ declare var __VLS_21: {}, __VLS_28: {}, __VLS_35: {}, __VLS_37: {
15
15
  meta: any;
16
- }, __VLS_43: {
16
+ }, __VLS_44: {
17
17
  meta: any;
18
18
  };
19
19
  type __VLS_Slots = {} & {
20
- header?: (props: typeof __VLS_20) => any;
20
+ header?: (props: typeof __VLS_21) => any;
21
21
  } & {
22
- title?: (props: typeof __VLS_27) => any;
22
+ title?: (props: typeof __VLS_28) => any;
23
23
  } & {
24
- description?: (props: typeof __VLS_34) => any;
24
+ description?: (props: typeof __VLS_35) => any;
25
25
  } & {
26
- default?: (props: typeof __VLS_36) => any;
26
+ default?: (props: typeof __VLS_37) => any;
27
27
  } & {
28
- footer?: (props: typeof __VLS_43) => any;
28
+ footer?: (props: typeof __VLS_44) => any;
29
29
  };
30
30
  declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
31
31
  "update:modelValue": (value: boolean) => any;
32
32
  } & {
33
33
  submit: () => any;
34
+ close: () => any;
34
35
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
35
36
  onSubmit?: (() => any) | undefined;
36
37
  "onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
38
+ onClose?: (() => any) | undefined;
37
39
  }>, {
38
40
  disabledCloseBtn: boolean;
39
41
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -14,73 +14,93 @@
14
14
  </label>
15
15
 
16
16
  <Modal
17
- title="ปรับแต่งรูปภาพหน้าปก"
18
- width="500"
19
- title-position="left"
20
- divider-header
21
- divider-footer
22
- disabled-padding-content
17
+ title="ปรับแต่งรูปภาพหน้าโปรไฟล์"
18
+ class="lg:max-w-[512px] gap-[24px]"
23
19
  v-model="isOpenModal"
24
20
  >
25
- <div
26
- class="h-[500px] flex justify-center items-center overflow-hidden circular-cropper-container"
27
- >
28
- <ImageCropper
29
- v-if="imageFile"
30
- ref="cropperRef"
31
- dragMode="move"
32
- :container-style="{
21
+ <div class="flex flex-col gap-[16px]">
22
+ <div
23
+ class="flex justify-center items-center overflow-hidden circular-cropper-container"
24
+ >
25
+ <ImageCropper
26
+ v-if="imageFile"
27
+ ref="cropperRef"
28
+ dragMode="move"
29
+ :container-style="{
33
30
  width: '320px',
34
31
  height: '320px',
35
32
  overflow: 'visible',
36
33
  position: 'relative'
37
34
  }"
38
- :img-style="{ display: 'block', maxWidth: '100%', maxHeight: '100%' }"
39
- :src="imageUrl"
40
- :aspect-ratio="1"
41
- :initial-aspect-ratio="1"
42
- :view-mode="3"
43
- :guides="false"
44
- :movable="true"
45
- :crop-box-movable="false"
46
- :crop-box-resizable="false"
47
- :background="false"
48
- :center="false"
49
- :min-crop-box-width="320"
50
- :min-crop-box-height="320"
51
- :min-canvas-width="320"
52
- :min-canvas-height="320"
53
- :auto-crop-area="1"
54
- :responsive="true"
55
- :zoom-on-wheel="false"
56
- :zoom-on-touch="false"
57
- @zoom="onZoom"
58
- />
59
- </div>
60
-
61
- <div class="p-[16px] flex gap-[16px] items-center text-mercury">
62
- <Button variant="text" disabled-padding @click="onZoomOut">
63
- <Icon name="f7:minus" size="16" />
64
- </Button>
65
- <InputSlider
66
- thumb-size="16"
67
- :min="isZoomMin"
68
- :max="isZoomMax"
69
- :step="isZoomStep"
70
- full-width
71
- v-model="isZoom"
72
- />
73
- <Button variant="text" disabled-padding @click="onZoomIn">
74
- <Icon name="f7:plus" size="16" />
75
- </Button>
35
+ :img-style="{ display: 'block', maxWidth: '100%', maxHeight: '100%' }"
36
+ :src="imageUrl"
37
+ :aspect-ratio="1"
38
+ :initial-aspect-ratio="1"
39
+ :view-mode="3"
40
+ :guides="false"
41
+ :movable="true"
42
+ :crop-box-movable="false"
43
+ :crop-box-resizable="false"
44
+ :background="false"
45
+ :center="false"
46
+ :min-crop-box-width="320"
47
+ :min-crop-box-height="320"
48
+ :min-canvas-width="320"
49
+ :min-canvas-height="320"
50
+ :auto-crop-area="1"
51
+ :responsive="true"
52
+ :zoom-on-wheel="false"
53
+ :zoom-on-touch="false"
54
+ @zoom="onZoom"
55
+ />
56
+ </div>
57
+ <div class="flex gap-[40px] items-center p-[16px]">
58
+ <div class="flex gap-[8px] items-center w-full">
59
+ <Icon name="lucide:zoom-in" size="20" />
60
+ <div @click="onZoomOut">
61
+ <Icon name="f7:minus" size="20" />
62
+ </div>
63
+ <InputSlider
64
+ thumb-size="16"
65
+ :min="isZoomMin"
66
+ :max="isZoomMax"
67
+ :step="isZoomStep"
68
+ full-width
69
+ v-model="isZoom"
70
+ />
71
+ <div @click="onZoomIn">
72
+ <Icon name="f7:plus" size="20" />
73
+ </div>
74
+ </div>
75
+ <div class="flex gap-[8px] items-center w-full">
76
+ <Icon name="lucide:rotate-cw" size="20" />
77
+ <div @click="onRotateLeft" class="cursor-pointer">
78
+ <Icon name="f7:minus" size="20" />
79
+ </div>
80
+ <InputSlider
81
+ thumb-size="16"
82
+ :min="isRotateMin"
83
+ :max="isRotateMax"
84
+ :step="isRotateStep"
85
+ full-width
86
+ v-model="isRotate"
87
+ />
88
+ <div @click="onRotateRight" class="cursor-pointer">
89
+ <Icon name="f7:plus" size="20" />
90
+ </div>
91
+ </div>
92
+ </div>
76
93
  </div>
77
-
78
94
  <template #footer>
79
- <div class="flex items-center gap-[16px]">
80
- <Button variant="outline" full-width @click="isOpenModal = false">
95
+ <div class="flex items-center gap-[16px] w-[464px]">
96
+ <Button
97
+ variant="outline"
98
+ class="w-[224px]"
99
+ @click="isOpenModal = false"
100
+ >
81
101
  ยกเลิก
82
102
  </Button>
83
- <Button color="primary" full-width @click="onCropImage">
103
+ <Button color="primary" class="w-[224px]" @click="onCropImage">
84
104
  บันทึก
85
105
  </Button>
86
106
  </div>
@@ -99,6 +119,10 @@ const isZoom = ref(0);
99
119
  const isZoomMin = 0;
100
120
  const isZoomMax = 5;
101
121
  const isZoomStep = 1;
122
+ const isRotate = ref(0);
123
+ const isRotateMin = -180;
124
+ const isRotateMax = 180;
125
+ const isRotateStep = 15;
102
126
  const fileCrop = defineModel({ type: null });
103
127
  const onTriggerFileInput = (event) => {
104
128
  event.preventDefault();
@@ -114,6 +138,16 @@ const onZoomIn = () => {
114
138
  isZoom.value += isZoomStep;
115
139
  }
116
140
  };
141
+ const onRotateLeft = () => {
142
+ if (isRotate.value > isRotateMin) {
143
+ isRotate.value -= isRotateStep;
144
+ }
145
+ };
146
+ const onRotateRight = () => {
147
+ if (isRotate.value < isRotateMax) {
148
+ isRotate.value += isRotateStep;
149
+ }
150
+ };
117
151
  const onChange = (event) => {
118
152
  const input = event.target;
119
153
  if (input.files && input.files.length > 0) {
@@ -165,8 +199,17 @@ watch(
165
199
  }
166
200
  }
167
201
  );
202
+ watch(
203
+ () => isRotate.value,
204
+ (newRotate) => {
205
+ if (cropperRef.value) {
206
+ const cropper = cropperRef.value;
207
+ cropper.rotateTo(newRotate);
208
+ }
209
+ }
210
+ );
168
211
  </script>
169
212
 
170
213
  <style>
171
- .circular-cropper-container .cropper-view-box{border:2px solid var(--color-primary)!important;border-radius:50%!important}.circular-cropper-container .cropper-face,.circular-cropper-container .cropper-modal{background-color:transparent!important}.circular-cropper-container .cropper-wrap-box{opacity:.25!important;overflow:visible!important}
214
+ .circular-cropper-container .cropper-view-box{border:2px solid var(--color-transparent)!important;border-radius:50%!important}.circular-cropper-container .cropper-face,.circular-cropper-container .cropper-modal{background-color:transparent!important}.circular-cropper-container .cropper-wrap-box{opacity:.25!important;overflow:visible!important}.circular-cropper-container .cropper-view-box{outline-color:transparent!important}.circular-cropper-container .cropper-line,.circular-cropper-container .cropper-point{background-color:transparent!important}
172
215
  </style>
@@ -41,11 +41,11 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
41
41
  }>, {
42
42
  items: Record<string, any>[];
43
43
  fullHeight: false;
44
+ totalPage: number;
44
45
  itemHeader: TableHeader[];
45
46
  headerAlinement: "start" | "center" | "end";
46
47
  disabledHeader: false;
47
48
  disabledSort: false;
48
- totalPage: number;
49
49
  paginationVisible: number;
50
50
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
51
51
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -41,11 +41,11 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
41
41
  }>, {
42
42
  items: Record<string, any>[];
43
43
  fullHeight: false;
44
+ totalPage: number;
44
45
  itemHeader: TableHeader[];
45
46
  headerAlinement: "start" | "center" | "end";
46
47
  disabledHeader: false;
47
48
  disabledSort: false;
48
- totalPage: number;
49
49
  paginationVisible: number;
50
50
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
51
51
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -12,6 +12,7 @@ type __VLS_Slots = {} & {
12
12
  };
13
13
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
14
14
  submit: (event: Event) => any;
15
+ close: (event: Event) => any;
15
16
  escapeKeyDown: (event: KeyboardEvent) => any;
16
17
  pointerDownOutside: (event: import("reka-ui").PointerDownOutsideEvent) => any;
17
18
  focusOutside: (event: import("reka-ui").FocusOutsideEvent) => any;
@@ -20,6 +21,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {},
20
21
  closeAutoFocus: (event: Event) => any;
21
22
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
22
23
  onSubmit?: ((event: Event) => any) | undefined;
24
+ onClose?: ((event: Event) => any) | undefined;
23
25
  onEscapeKeyDown?: ((event: KeyboardEvent) => any) | undefined;
24
26
  onPointerDownOutside?: ((event: import("reka-ui").PointerDownOutsideEvent) => any) | undefined;
25
27
  onFocusOutside?: ((event: import("reka-ui").FocusOutsideEvent) => any) | undefined;
@@ -18,6 +18,7 @@
18
18
  <DialogClose
19
19
  v-if="!props.disabledCloseBtn"
20
20
  class="absolute top-4 right-4 rounded-xs opacity-70 cursor-pointer transition-opacity hover:opacity-100 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-6"
21
+ @click="onClose"
21
22
  >
22
23
  <Icon name="lucide:x" size="24" />
23
24
  <span class="sr-only">Close</span>
@@ -45,7 +46,7 @@ const props = defineProps({
45
46
  class: { type: null, required: false },
46
47
  disabledCloseBtn: { type: Boolean, required: false, default: false }
47
48
  });
48
- const emits = defineEmits(["submit", "escapeKeyDown", "pointerDownOutside", "focusOutside", "interactOutside", "openAutoFocus", "closeAutoFocus"]);
49
+ const emits = defineEmits(["submit", "close", "escapeKeyDown", "pointerDownOutside", "focusOutside", "interactOutside", "openAutoFocus", "closeAutoFocus"]);
49
50
  const delegatedProps = reactiveOmit(props, "class");
50
51
  const forwarded = useForwardPropsEmits(delegatedProps, emits);
51
52
  const onOutSideClick = (e) => {
@@ -54,4 +55,7 @@ const onOutSideClick = (e) => {
54
55
  const onSubmit = (e) => {
55
56
  emits("submit", e);
56
57
  };
58
+ const onClose = (e) => {
59
+ emits("close", e);
60
+ };
57
61
  </script>
@@ -12,6 +12,7 @@ type __VLS_Slots = {} & {
12
12
  };
13
13
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
14
14
  submit: (event: Event) => any;
15
+ close: (event: Event) => any;
15
16
  escapeKeyDown: (event: KeyboardEvent) => any;
16
17
  pointerDownOutside: (event: import("reka-ui").PointerDownOutsideEvent) => any;
17
18
  focusOutside: (event: import("reka-ui").FocusOutsideEvent) => any;
@@ -20,6 +21,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {},
20
21
  closeAutoFocus: (event: Event) => any;
21
22
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
22
23
  onSubmit?: ((event: Event) => any) | undefined;
24
+ onClose?: ((event: Event) => any) | undefined;
23
25
  onEscapeKeyDown?: ((event: KeyboardEvent) => any) | undefined;
24
26
  onPointerDownOutside?: ((event: import("reka-ui").PointerDownOutsideEvent) => any) | undefined;
25
27
  onFocusOutside?: ((event: import("reka-ui").FocusOutsideEvent) => any) | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pukaad-ui-lib",
3
- "version": "1.29.0",
3
+ "version": "1.31.0",
4
4
  "description": "pukaad-ui for MeMSG",
5
5
  "repository": {
6
6
  "type": "git",