@finema/core 3.1.0 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +1 -1
  3. package/dist/runtime/components/Form/FieldWrapper.vue +13 -13
  4. package/dist/runtime/components/Form/Fields.vue +18 -14
  5. package/dist/runtime/components/Form/InputCheckbox/index.vue +18 -18
  6. package/dist/runtime/components/Form/InputCurrency/index.vue +49 -49
  7. package/dist/runtime/components/Form/InputNumber/index.vue +20 -20
  8. package/dist/runtime/components/Form/InputSelect/index.vue +38 -38
  9. package/dist/runtime/components/Form/InputSelectMultiple/index.vue +43 -43
  10. package/dist/runtime/components/Form/InputTags/index.vue +23 -23
  11. package/dist/runtime/components/Form/InputTextarea/index.vue +18 -18
  12. package/dist/runtime/components/Form/InputTime/index.vue +38 -38
  13. package/dist/runtime/components/Form/InputToggle/index.vue +17 -17
  14. package/dist/runtime/components/Form/InputUploadDropzone/index.vue +30 -30
  15. package/dist/runtime/components/Form/InputUploadDropzoneAuto/index.vue +50 -50
  16. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/index.d.vue.ts +25 -0
  17. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/index.vue +110 -0
  18. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/index.vue.d.ts +25 -0
  19. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/types.d.ts +27 -0
  20. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/types.js +0 -0
  21. package/dist/runtime/components/Form/fileState/EmptyState.vue +21 -21
  22. package/dist/runtime/components/Form/fileState/FailedState.vue +33 -33
  23. package/dist/runtime/components/Form/fileState/LoadingState.vue +24 -24
  24. package/dist/runtime/components/Form/fileState/MultipleFilesState.d.vue.ts +30 -0
  25. package/dist/runtime/components/Form/fileState/MultipleFilesState.vue +172 -0
  26. package/dist/runtime/components/Form/fileState/MultipleFilesState.vue.d.ts +30 -0
  27. package/dist/runtime/components/Form/fileState/PreviewModal.vue +23 -23
  28. package/dist/runtime/components/Form/fileState/useUploadStateMultiple.d.ts +126 -0
  29. package/dist/runtime/components/Form/fileState/useUploadStateMultiple.js +238 -0
  30. package/dist/runtime/components/Form/index.vue +5 -5
  31. package/dist/runtime/components/Form/types.d.ts +2 -1
  32. package/dist/runtime/components/Image.vue +28 -28
  33. package/dist/runtime/components/Log/index.vue +17 -17
  34. package/dist/runtime/components/Table/ColumnDate.vue +1 -1
  35. package/dist/runtime/components/Table/ColumnDateTime.vue +1 -1
  36. package/dist/runtime/components/Table/ColumnImage.vue +4 -4
  37. package/dist/runtime/components/Table/ColumnText.vue +1 -1
  38. package/dist/runtime/components/Table/Pagination.vue +46 -46
  39. package/dist/runtime/components/Table/Simple.vue +17 -17
  40. package/dist/runtime/helpers/apiPageHelper.js +4 -4
  41. package/dist/runtime/server/tsconfig.json +3 -3
  42. package/dist/runtime/theme/uploadFileDropzone.d.ts +23 -0
  43. package/dist/runtime/theme/uploadFileDropzone.js +31 -3
  44. package/package.json +1 -1
@@ -1,32 +1,32 @@
1
1
  <template>
2
- <UseImage v-bind="$props">
3
- <template #loading>
4
- <slot name="loading">
5
- <div
6
- class="flex h-full w-full items-center justify-center"
7
- >
8
- <Loader
9
- :loading="true"
10
- />
11
- </div>
12
- </slot>
13
- </template>
14
-
15
- <template #error>
16
- <slot name="error">
17
- <div
18
- class="flex h-full w-full items-center justify-center"
19
- >
20
- <p class="text-error-400">
21
- <Icon
22
- name="i-heroicons:exclamation-circle-solid"
23
- class="text-error-400 size-8"
24
- />
25
- </p>
26
- </div>
27
- </slot>
28
- </template>
29
- </UseImage>
2
+ <UseImage v-bind="$props">
3
+ <template #loading>
4
+ <slot name="loading">
5
+ <div
6
+ class="flex h-full w-full items-center justify-center"
7
+ >
8
+ <Loader
9
+ :loading="true"
10
+ />
11
+ </div>
12
+ </slot>
13
+ </template>
14
+
15
+ <template #error>
16
+ <slot name="error">
17
+ <div
18
+ class="flex h-full w-full items-center justify-center"
19
+ >
20
+ <p class="text-error-400">
21
+ <Icon
22
+ name="i-heroicons:exclamation-circle-solid"
23
+ class="text-error-400 size-8"
24
+ />
25
+ </p>
26
+ </div>
27
+ </slot>
28
+ </template>
29
+ </UseImage>
30
30
  </template>
31
31
 
32
32
  <script setup>
@@ -1,21 +1,21 @@
1
1
  <template>
2
- <DevOnly>
3
- <TeleportSafe
4
- to="#dev-logs"
5
- >
6
- <LogItem
7
- v-if="typeof data !== 'undefined'"
8
- :data="data"
9
- :title="title"
10
- />
11
- <LogItem
12
- v-for="(item, index) in dataItems"
13
- :key="index"
14
- :data="item"
15
- :title="`${title} #${index + 1}`"
16
- />
17
- </TeleportSafe>
18
- </DevOnly>
2
+ <DevOnly>
3
+ <TeleportSafe
4
+ to="#dev-logs"
5
+ >
6
+ <LogItem
7
+ v-if="typeof data !== 'undefined'"
8
+ :data="data"
9
+ :title="title"
10
+ />
11
+ <LogItem
12
+ v-for="(item, index) in dataItems"
13
+ :key="index"
14
+ :data="item"
15
+ :title="`${title} #${index + 1}`"
16
+ />
17
+ </TeleportSafe>
18
+ </DevOnly>
19
19
  </template>
20
20
 
21
21
  <script setup>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- {{ getValue || "-" }}
2
+ {{ getValue || "-" }}
3
3
  </template>
4
4
 
5
5
  <script setup>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- {{ getValue || "-" }}
2
+ {{ getValue || "-" }}
3
3
  </template>
4
4
 
5
5
  <script setup>
@@ -1,8 +1,8 @@
1
1
  <template>
2
- <Image
3
- class="h-12 rounded"
4
- :src="getValue"
5
- />
2
+ <Image
3
+ class="h-12 rounded"
4
+ :src="getValue"
5
+ />
6
6
  </template>
7
7
 
8
8
  <script setup>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- {{ getValue }}
2
+ {{ getValue }}
3
3
  </template>
4
4
 
5
5
  <script setup>
@@ -1,70 +1,70 @@
1
1
  <template>
2
- <div
2
+ <div
3
3
  :class="
4
4
  theme.paginationContainer({
5
5
  class: [ui?.paginationContainer]
6
6
  })
7
- "
8
- >
9
- <div
7
+ "
8
+ >
9
+ <div
10
10
  :class="
11
11
  theme.paginationInfoWrapper({
12
12
  class: [ui?.paginationInfoWrapper]
13
13
  })
14
- "
15
- >
16
- <USelect
17
- v-if="options.pageOptions && !options.isHideLimitSelect"
18
- size="lg"
19
- trailing="รายการ"
14
+ "
15
+ >
16
+ <USelect
17
+ v-if="options.pageOptions && !options.isHideLimitSelect"
18
+ size="lg"
19
+ trailing="รายการ"
20
20
  :class="
21
21
  theme.paginationLimitSelect({
22
22
  class: [ui?.paginationLimitSelect, 'cursor-pointer']
23
23
  })
24
- "
25
- :items="pageLimitItems"
26
- :model-value="pageLimit"
27
- @update:modelValue="emits('pageLimitChange', $event)"
28
- >
29
- <template #default="{ modelValue }">
30
- <p
24
+ "
25
+ :items="pageLimitItems"
26
+ :model-value="pageLimit"
27
+ @update:modelValue="emits('pageLimitChange', $event)"
28
+ >
29
+ <template #default="{ modelValue }">
30
+ <p
31
31
  :class="
32
32
  theme.paginationLimitSelectLabel({
33
33
  class: [ui?.paginationLimitSelectLabel]
34
34
  })
35
- "
36
- >
37
- {{ modelValue }} รายการ
38
- </p>
39
- </template>
40
- </USelect>
41
- <p
35
+ "
36
+ >
37
+ {{ modelValue }} รายการ
38
+ </p>
39
+ </template>
40
+ </USelect>
41
+ <p
42
42
  :class="
43
43
  theme.paginationInfo({
44
44
  class: [ui?.paginationInfo, '']
45
45
  })
46
- "
47
- >
48
- <span v-if="options.pageOptions">{{ pageBetween }} จากทั้งหมด {{ totalCountWithComma }}</span>
49
- <span v-else>ทั้งหมด {{ options.rawData.length }} รายการ</span>
50
- </p>
51
- </div>
52
-
53
- <UPagination
54
- v-if="options.pageOptions && options.pageOptions.totalPage > 1"
55
- :page="page"
56
- :default-page="options.pageOptions?.currentPage || 1"
57
- :items-per-page="options.pageOptions.limit"
58
- :total="options.pageOptions.totalCount"
59
- :to="options.isRouteChange ? to : void 0"
60
- show-edges
61
- variant="outline"
62
- color="neutral"
63
- active-color="neutral"
64
- active-variant="subtle"
65
- @update:page="emits('pageChange', $event)"
66
- />
67
- </div>
46
+ "
47
+ >
48
+ <span v-if="options.pageOptions">{{ pageBetween }} จากทั้งหมด {{ totalCountWithComma }}</span>
49
+ <span v-else>ทั้งหมด {{ options.rawData.length }} รายการ</span>
50
+ </p>
51
+ </div>
52
+
53
+ <UPagination
54
+ v-if="options.pageOptions && options.pageOptions.totalPage > 1"
55
+ :page="page"
56
+ :default-page="options.pageOptions?.currentPage || 1"
57
+ :items-per-page="options.pageOptions.limit"
58
+ :total="options.pageOptions.totalCount"
59
+ :to="options.isRouteChange ? to : void 0"
60
+ show-edges
61
+ variant="outline"
62
+ color="neutral"
63
+ active-color="neutral"
64
+ active-variant="subtle"
65
+ @update:page="emits('pageChange', $event)"
66
+ />
67
+ </div>
68
68
  </template>
69
69
 
70
70
  <script setup>
@@ -1,25 +1,25 @@
1
1
  <template>
2
- <Base
3
- v-bind="$attrs"
2
+ <Base
3
+ v-bind="$attrs"
4
4
  :options="{
5
5
  ...options,
6
6
  pageOptions,
7
7
  isHideLimitSelect: true
8
- }"
9
- :ui="ui"
10
- :raw-data="itemsByPage"
11
- @page-change="onPageChange"
12
- >
13
- <template
14
- v-for="(_, slot) of $slots"
15
- #[slot]="slotProps"
16
- >
17
- <slot
18
- :name="slot"
19
- v-bind="slotProps || {}"
20
- />
21
- </template>
22
- </Base>
8
+ }"
9
+ :ui="ui"
10
+ :raw-data="itemsByPage"
11
+ @page-change="onPageChange"
12
+ >
13
+ <template
14
+ v-for="(_, slot) of $slots"
15
+ #[slot]="slotProps"
16
+ >
17
+ <slot
18
+ :name="slot"
19
+ v-bind="slotProps || {}"
20
+ />
21
+ </template>
22
+ </Base>
23
23
  </template>
24
24
 
25
25
  <script setup>
@@ -162,21 +162,21 @@ export const apiFetchHelper = async (state, onUpdateStatus, onUpdateOptions, onU
162
162
  ...moreOptions
163
163
  } = response;
164
164
  onUpdateItems(items);
165
- onUpdateOptions({
165
+ onUpdateOptions(JSON.parse(JSON.stringify({
166
166
  ...getOptions(moreOptions),
167
167
  _timestamp: Date.now(),
168
168
  _status: status,
169
169
  request: requestOptions
170
- });
170
+ })));
171
171
  onUpdateStatus(updateLoaderState.setSuccess(state().status));
172
172
  },
173
173
  onError: (error) => {
174
174
  onUpdateStatus(updateLoaderState.setError(state().status, error));
175
- onUpdateOptions({
175
+ onUpdateOptions(JSON.parse(JSON.stringify({
176
176
  ...state().options,
177
177
  _status: error.response?.status,
178
178
  request: requestOptions
179
- });
179
+ })));
180
180
  },
181
181
  onComplete: () => {
182
182
  onUpdateStatus(updateLoaderState.setComplete(state().status));
@@ -1,3 +1,3 @@
1
- {
2
- "extends": "../../../.nuxt/tsconfig.server.json",
3
- }
1
+ {
2
+ "extends": "../../../.nuxt/tsconfig.server.json",
3
+ }
@@ -9,6 +9,7 @@ export declare const uploadFileDropzoneTheme: {
9
9
  actionDownloadIcon: string;
10
10
  actionDeleteIcon: string;
11
11
  actionRetryIcon: string;
12
+ errorIcon: string;
12
13
  };
13
14
  slots: {
14
15
  base: string;
@@ -38,6 +39,28 @@ export declare const uploadFileDropzoneTheme: {
38
39
  actionIconClass: string;
39
40
  actionDeleteIconClass: string;
40
41
  actionRetryBtnClass: string;
42
+ multipleFilesWrapper: string;
43
+ fileItemWrapper: string;
44
+ uploadingItemWrapper: string;
45
+ uploadingIconWrapper: string;
46
+ uploadingIconClass: string;
47
+ uploadingTextWrapper: string;
48
+ progressBarWrapper: string;
49
+ progressBarFill: string;
50
+ successItemWrapper: string;
51
+ successImgWrapper: string;
52
+ successImgClass: string;
53
+ successFileWrapper: string;
54
+ successFileClass: string;
55
+ successTextWrapper: string;
56
+ errorItemWrapper: string;
57
+ errorIconWrapper: string;
58
+ errorIconClass: string;
59
+ errorTextWrapper: string;
60
+ errorActionWrapper: string;
61
+ addMoreWrapper: string;
62
+ addMoreButton: string;
63
+ addMoreIcon: string;
41
64
  };
42
65
  variants: {
43
66
  dragover: {
@@ -8,7 +8,8 @@ export const uploadFileDropzoneTheme = {
8
8
  actionPreviewIcon: "ic:outline-remove-red-eye",
9
9
  actionDownloadIcon: "material-symbols:download",
10
10
  actionDeleteIcon: "material-symbols:delete",
11
- actionRetryIcon: "stash:arrow-retry"
11
+ actionRetryIcon: "stash:arrow-retry",
12
+ errorIcon: "i-heroicons:exclamation-circle-solid"
12
13
  },
13
14
  slots: {
14
15
  base: "relative w-full text-base p-4 transition rounded-lg flex items-center justify-center ring-1 bg-white ring-accented",
@@ -28,7 +29,7 @@ export const uploadFileDropzoneTheme = {
28
29
  // Preview state
29
30
  onPreviewWrapper: "flex items-center space-x-4 rounded-lg w-full",
30
31
  onPreviewImgWrapper: "flex-shrink-0 w-16 h-16 flex justify-center items-center rounded-lg overflow-hidden bg-gray-100",
31
- onPreviewImgClass: "w-full h-full object-cover",
32
+ onPreviewImgClass: "w-full h-full object-fit",
32
33
  onPreviewFileWrapper: "flex-shrink-0 w-16 h-16 flex justify-center items-center rounded-lg overflow-hidden",
33
34
  onPreviewFileClass: "size-8 text-gray-400 m-auto",
34
35
  onPreviewTextWrapper: "flex-1 min-w-0 flex items-center justify-between",
@@ -41,7 +42,34 @@ export const uploadFileDropzoneTheme = {
41
42
  actionWrapper: "flex items-center space-x-2",
42
43
  actionIconClass: "size-6 text-dimmed hover:text-dimmed-600 cursor-pointer transition-colors",
43
44
  actionDeleteIconClass: "size-6 text-(--ui-color-error-500) hover:text-(--ui-color-error-600) cursor-pointer transition-colors",
44
- actionRetryBtnClass: "px-0"
45
+ actionRetryBtnClass: "px-0",
46
+ // Multiple files
47
+ multipleFilesWrapper: "flex flex-col gap-3 w-full mt-4",
48
+ fileItemWrapper: "w-full ring-1 bg-white ring-accented rounded-lg p-3",
49
+ // Uploading item
50
+ uploadingItemWrapper: "flex items-center space-x-4 w-full",
51
+ uploadingIconWrapper: "flex-shrink-0",
52
+ uploadingIconClass: "size-12 text-gray-400",
53
+ uploadingTextWrapper: "flex-1 min-w-0",
54
+ progressBarWrapper: "w-full bg-gray-200 rounded-full h-2 overflow-hidden",
55
+ progressBarFill: "bg-primary h-full transition-all duration-300",
56
+ // Success item
57
+ successItemWrapper: "flex items-center space-x-4 rounded-lg w-full",
58
+ successImgWrapper: "flex-shrink-0 w-16 h-16 flex justify-center items-center rounded-lg overflow-hidden bg-gray-100",
59
+ successImgClass: "w-full h-full object-fit",
60
+ successFileWrapper: "flex-shrink-0 w-16 h-16 flex justify-center items-center rounded-lg overflow-hidden",
61
+ successFileClass: "size-8 text-gray-400 m-auto",
62
+ successTextWrapper: "flex-1 min-w-0 flex items-center justify-between",
63
+ // Error item
64
+ errorItemWrapper: "flex items-center space-x-4 w-full rounded-lg bg-(--ui-color-error-50) p-3",
65
+ errorIconWrapper: "flex-shrink-0",
66
+ errorIconClass: "size-12 text-(--ui-color-error-500)",
67
+ errorTextWrapper: "flex-1 min-w-0",
68
+ errorActionWrapper: "flex items-center space-x-2",
69
+ // Add more button
70
+ addMoreWrapper: "w-full mt-3 pt-3 border-t border-gray-200",
71
+ addMoreButton: "w-full flex items-center justify-center gap-2 px-4 py-2 text-sm text-primary border border-primary rounded-lg hover:bg-primary-50 transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
72
+ addMoreIcon: "size-4"
45
73
  },
46
74
  variants: {
47
75
  dragover: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finema/core",
3
- "version": "3.1.0",
3
+ "version": "3.2.1",
4
4
  "repository": "https://gitlab.finema.co/finema/ui-kit",
5
5
  "license": "MIT",
6
6
  "author": "Finema Dev Core Team",