@finema/core 2.51.0 → 2.52.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 (40) 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 +13 -13
  5. package/dist/runtime/components/Form/InputCheckbox/index.vue +18 -18
  6. package/dist/runtime/components/Form/InputComponent/index.vue +1 -1
  7. package/dist/runtime/components/Form/InputMonth/index.vue +51 -51
  8. package/dist/runtime/components/Form/InputNumber/index.vue +20 -20
  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/InputToggle/index.vue +17 -17
  13. package/dist/runtime/components/Form/InputUploadDropzone/index.vue +30 -30
  14. package/dist/runtime/components/Form/InputUploadDropzoneAuto/index.vue +50 -50
  15. package/dist/runtime/components/Form/fileState/EmptyState.vue +21 -21
  16. package/dist/runtime/components/Form/fileState/FailedState.vue +33 -33
  17. package/dist/runtime/components/Form/fileState/LoadingState.vue +24 -24
  18. package/dist/runtime/components/Form/fileState/PreviewModal.vue +23 -23
  19. package/dist/runtime/components/Form/index.vue +5 -5
  20. package/dist/runtime/components/Image.vue +28 -28
  21. package/dist/runtime/components/Log/index.vue +17 -17
  22. package/dist/runtime/components/Table/ColumnDate.vue +1 -1
  23. package/dist/runtime/components/Table/ColumnDateTime.vue +1 -1
  24. package/dist/runtime/components/Table/ColumnImage.vue +4 -4
  25. package/dist/runtime/components/Table/ColumnText.vue +1 -1
  26. package/dist/runtime/server/tsconfig.json +3 -3
  27. package/dist/runtime/theme/input.d.ts +1 -0
  28. package/dist/runtime/theme/input.js +2 -1
  29. package/dist/runtime/theme/inputNumber.d.ts +1 -0
  30. package/dist/runtime/theme/inputNumber.js +2 -1
  31. package/dist/runtime/theme/inputTags.d.ts +3 -0
  32. package/dist/runtime/theme/inputTags.js +3 -0
  33. package/dist/runtime/theme/selectMenu.d.ts +1 -1
  34. package/dist/runtime/theme/selectMenu.js +1 -1
  35. package/dist/runtime/theme/table.js +5 -5
  36. package/dist/runtime/theme/textarea.d.ts +1 -0
  37. package/dist/runtime/theme/textarea.js +2 -1
  38. package/dist/runtime/theme/uploadFileDropzone.js +5 -5
  39. package/dist/runtime/theme/wysiwyg.js +4 -4
  40. package/package.json +1 -1
@@ -1,54 +1,54 @@
1
1
  <template>
2
- <FieldWrapper v-bind="wrapperProps">
3
- <div
4
- ref="dropzoneRef"
5
- :class="theme.base()"
6
- >
7
- <div :class="theme.wrapper()">
8
- <!-- Empty State -->
9
- <EmptyState
10
- v-if="uploadState.isEmpty.value"
11
- :theme="theme"
12
- :select-file-label="selectFileLabel"
13
- :select-file-sub-label="selectFileSubLabel"
14
- :placeholder="placeholder"
15
- @open-file="uploadState.handleOpenFile"
16
- />
17
-
18
- <!-- Loading State -->
19
- <LoadingState
20
- v-if="uploadState.isUploading.value"
21
- :theme="theme"
22
- :selected-file="uploadState.selectedFile.value"
23
- :percent="uploadState.percent.value"
24
- :uploading-label="uploadingLabel"
25
- />
26
-
27
- <!-- Success State -->
28
- <SuccessState
29
- v-if="uploadState.isSuccess.value"
30
- :theme="theme"
31
- :value="value"
32
- :disabled="wrapperProps.disabled"
33
- :readonly="wrapperProps.readonly"
34
- @preview="uploadState.handlePreview"
35
- @download="handleDownloadFile"
36
- @delete="uploadState.handleDeleteFile"
37
- />
38
-
39
- <!-- Failed State -->
40
- <FailedState
41
- v-if="uploadState.isError.value"
42
- :theme="theme"
43
- :selected-file="uploadState.selectedFile.value"
44
- :upload-failed-label="uploadFailedLabel"
45
- :retry-label="retryLabel"
46
- @retry="uploadState.handleRetryUpload"
47
- @delete="uploadState.handleDeleteFile"
48
- />
49
- </div>
50
- </div>
51
- </FieldWrapper>
2
+ <FieldWrapper v-bind="wrapperProps">
3
+ <div
4
+ ref="dropzoneRef"
5
+ :class="theme.base()"
6
+ >
7
+ <div :class="theme.wrapper()">
8
+ <!-- Empty State -->
9
+ <EmptyState
10
+ v-if="uploadState.isEmpty.value"
11
+ :theme="theme"
12
+ :select-file-label="selectFileLabel"
13
+ :select-file-sub-label="selectFileSubLabel"
14
+ :placeholder="placeholder"
15
+ @open-file="uploadState.handleOpenFile"
16
+ />
17
+
18
+ <!-- Loading State -->
19
+ <LoadingState
20
+ v-if="uploadState.isUploading.value"
21
+ :theme="theme"
22
+ :selected-file="uploadState.selectedFile.value"
23
+ :percent="uploadState.percent.value"
24
+ :uploading-label="uploadingLabel"
25
+ />
26
+
27
+ <!-- Success State -->
28
+ <SuccessState
29
+ v-if="uploadState.isSuccess.value"
30
+ :theme="theme"
31
+ :value="value"
32
+ :disabled="wrapperProps.disabled"
33
+ :readonly="wrapperProps.readonly"
34
+ @preview="uploadState.handlePreview"
35
+ @download="handleDownloadFile"
36
+ @delete="uploadState.handleDeleteFile"
37
+ />
38
+
39
+ <!-- Failed State -->
40
+ <FailedState
41
+ v-if="uploadState.isError.value"
42
+ :theme="theme"
43
+ :selected-file="uploadState.selectedFile.value"
44
+ :upload-failed-label="uploadFailedLabel"
45
+ :retry-label="retryLabel"
46
+ @retry="uploadState.handleRetryUpload"
47
+ @delete="uploadState.handleDeleteFile"
48
+ />
49
+ </div>
50
+ </div>
51
+ </FieldWrapper>
52
52
  </template>
53
53
 
54
54
  <script setup>
@@ -1,25 +1,25 @@
1
1
  <template>
2
- <div :class="theme.placeholderWrapper()">
3
- <Icon
4
- :name="icons.uploadIcon"
5
- :class="theme.labelIcon()"
6
- />
7
- <div :class="theme.labelWrapper()">
8
- <p
9
- class="text-primary cursor-pointer font-bold"
10
- @click="$emit('openFile')"
11
- >
12
- {{ selectFileLabel }}
13
- </p>
14
- <p>{{ selectFileSubLabel }}</p>
15
- </div>
16
- <p
17
- v-if="placeholder"
18
- :class="theme.placeholder()"
19
- >
20
- {{ placeholder }}
21
- </p>
22
- </div>
2
+ <div :class="theme.placeholderWrapper()">
3
+ <Icon
4
+ :name="icons.uploadIcon"
5
+ :class="theme.labelIcon()"
6
+ />
7
+ <div :class="theme.labelWrapper()">
8
+ <p
9
+ class="text-primary cursor-pointer font-bold"
10
+ @click="$emit('openFile')"
11
+ >
12
+ {{ selectFileLabel }}
13
+ </p>
14
+ <p>{{ selectFileSubLabel }}</p>
15
+ </div>
16
+ <p
17
+ v-if="placeholder"
18
+ :class="theme.placeholder()"
19
+ >
20
+ {{ placeholder }}
21
+ </p>
22
+ </div>
23
23
  </template>
24
24
 
25
25
  <script setup>
@@ -1,37 +1,37 @@
1
1
  <template>
2
- <div :class="theme.onFailedWrapper()">
3
- <div :class="theme.onFailedFailedImgWrapper()">
4
- <Icon
5
- :name="getFileIcon(selectedFile)"
6
- :class="theme.onFailedFailedIconClass()"
7
- />
8
- </div>
9
- <div :class="theme.onFailedTextWrapper()">
10
- <div class="truncate">
11
- <h1 class="truncate font-bold">
12
- {{ selectedFile.name }}
13
- </h1>
14
- <p class="text-error truncate font-light">
15
- {{ uploadFailedLabel }}
16
- </p>
17
- <Button
18
- variant="link"
19
- :icon="icons.actionRetryIcon"
20
- :class="theme.actionRetryBtnClass()"
21
- color="primary"
22
- @click="$emit('retry')"
23
- >
24
- {{ retryLabel }}
25
- </Button>
26
- </div>
27
- <Icon
28
- :name="icons.actionDeleteIcon"
29
- :class="theme.actionDeleteIconClass()"
30
- title="ลบไฟล์"
31
- @click="$emit('delete')"
32
- />
33
- </div>
34
- </div>
2
+ <div :class="theme.onFailedWrapper()">
3
+ <div :class="theme.onFailedFailedImgWrapper()">
4
+ <Icon
5
+ :name="getFileIcon(selectedFile)"
6
+ :class="theme.onFailedFailedIconClass()"
7
+ />
8
+ </div>
9
+ <div :class="theme.onFailedTextWrapper()">
10
+ <div class="truncate">
11
+ <h1 class="truncate font-bold">
12
+ {{ selectedFile.name }}
13
+ </h1>
14
+ <p class="text-error truncate font-light">
15
+ {{ uploadFailedLabel }}
16
+ </p>
17
+ <Button
18
+ variant="link"
19
+ :icon="icons.actionRetryIcon"
20
+ :class="theme.actionRetryBtnClass()"
21
+ color="primary"
22
+ @click="$emit('retry')"
23
+ >
24
+ {{ retryLabel }}
25
+ </Button>
26
+ </div>
27
+ <Icon
28
+ :name="icons.actionDeleteIcon"
29
+ :class="theme.actionDeleteIconClass()"
30
+ title="ลบไฟล์"
31
+ @click="$emit('delete')"
32
+ />
33
+ </div>
34
+ </div>
35
35
  </template>
36
36
 
37
37
  <script setup>
@@ -1,28 +1,28 @@
1
1
  <template>
2
- <div :class="theme.onLoadingWrapper()">
3
- <div :class="theme.onLoadingPlaceholderWrapper()">
4
- <Icon
5
- :name="getFileIcon(selectedFile)"
6
- :class="theme.onLoadingPlaceholderIconClass()"
7
- />
8
- </div>
9
- <div :class="theme.onLoadingTextWrapper()">
10
- <div class="truncate">
11
- <h1 class="truncate font-bold">
12
- {{ selectedFile.name }}
13
- </h1>
14
- <p class="truncate font-light text-gray-400">
15
- {{ getFileSize(selectedFile) }} - {{ percent }}% {{ uploadingLabel }}
16
- </p>
17
- </div>
18
- <div>
19
- <Icon
20
- :name="icons.loadingIcon"
21
- :class="theme.onLoadingLoadingIconClass()"
22
- />
23
- </div>
24
- </div>
25
- </div>
2
+ <div :class="theme.onLoadingWrapper()">
3
+ <div :class="theme.onLoadingPlaceholderWrapper()">
4
+ <Icon
5
+ :name="getFileIcon(selectedFile)"
6
+ :class="theme.onLoadingPlaceholderIconClass()"
7
+ />
8
+ </div>
9
+ <div :class="theme.onLoadingTextWrapper()">
10
+ <div class="truncate">
11
+ <h1 class="truncate font-bold">
12
+ {{ selectedFile.name }}
13
+ </h1>
14
+ <p class="truncate font-light text-gray-400">
15
+ {{ getFileSize(selectedFile) }} - {{ percent }}% {{ uploadingLabel }}
16
+ </p>
17
+ </div>
18
+ <div>
19
+ <Icon
20
+ :name="icons.loadingIcon"
21
+ :class="theme.onLoadingLoadingIconClass()"
22
+ />
23
+ </div>
24
+ </div>
25
+ </div>
26
26
  </template>
27
27
 
28
28
  <script setup>
@@ -1,29 +1,29 @@
1
1
  <template>
2
- <Modal
3
- :close="{ onClick: () => emits('close', false) }"
4
- :dismissible="false"
5
- :title="value?.name"
2
+ <Modal
3
+ :close="{ onClick: () => emits('close', false) }"
4
+ :dismissible="false"
5
+ :title="value?.name"
6
6
  :ui="{
7
7
  content: 'max-w-3xl'
8
- }"
9
- >
10
- <template #body>
11
- <div class="flex justify-center">
12
- <img
13
- v-if="value && isImageFromPath(value.path)"
14
- :src="value.url"
15
- alt="img-preview"
16
- class="max-h-96 max-w-full rounded-lg"
17
- />
18
- <video
19
- v-else-if="value && isVideoFromPath(value.path)"
20
- :src="value.url"
21
- controls
22
- class="max-h-96 max-w-full"
23
- />
24
- </div>
25
- </template>
26
- </Modal>
8
+ }"
9
+ >
10
+ <template #body>
11
+ <div class="flex justify-center">
12
+ <img
13
+ v-if="value && isImageFromPath(value.path)"
14
+ :src="value.url"
15
+ alt="img-preview"
16
+ class="max-h-96 max-w-full rounded-lg"
17
+ />
18
+ <video
19
+ v-else-if="value && isVideoFromPath(value.path)"
20
+ :src="value.url"
21
+ controls
22
+ class="max-h-96 max-w-full"
23
+ />
24
+ </div>
25
+ </template>
26
+ </Modal>
27
27
  </template>
28
28
 
29
29
  <script setup>
@@ -1,5 +1,5 @@
1
- <template>
2
- <form class="form">
3
- <slot />
4
- </form>
5
- </template>
1
+ <template>
2
+ <form class="form">
3
+ <slot />
4
+ </form>
5
+ </template>
@@ -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,3 +1,3 @@
1
- {
2
- "extends": "../../../.nuxt/tsconfig.server.json",
3
- }
1
+ {
2
+ "extends": "../../../.nuxt/tsconfig.server.json",
3
+ }
@@ -1,6 +1,7 @@
1
1
  export declare const inputTheme: {
2
2
  slots: {
3
3
  root: string;
4
+ base: string[];
4
5
  suggestionsContainer: string;
5
6
  suggestionItem: string;
6
7
  suggestionItemActive: string;
@@ -1,7 +1,8 @@
1
1
  export const inputTheme = {
2
2
  slots: {
3
3
  root: "w-full",
4
- suggestionsContainer: "w-full bg-white max-h-60 overflow-y-auto rounded-md",
4
+ base: ["rounded-lg"],
5
+ suggestionsContainer: "w-full bg-white max-h-60 overflow-y-auto rounded-lg",
5
6
  suggestionItem: "px-3 py-3 text-sm cursor-pointer hover:bg-(--ui-color-primary-100) truncate",
6
7
  suggestionItemActive: "bg-(--ui-color-primary-100)"
7
8
  },
@@ -1,6 +1,7 @@
1
1
  export declare const inputNumberTheme: {
2
2
  slots: {
3
3
  root: string;
4
+ base: string[];
4
5
  };
5
6
  variants: {
6
7
  size: {
@@ -1,6 +1,7 @@
1
1
  export const inputNumberTheme = {
2
2
  slots: {
3
- root: "w-full"
3
+ root: "w-full",
4
+ base: ["rounded-lg"]
4
5
  },
5
6
  variants: {
6
7
  size: {
@@ -1,4 +1,7 @@
1
1
  export declare const inputTagsTheme: {
2
+ slots: {
3
+ base: string[];
4
+ };
2
5
  variants: {
3
6
  size: {
4
7
  xl: {
@@ -1,4 +1,7 @@
1
1
  export const inputTagsTheme = {
2
+ slots: {
3
+ base: ["rounded-lg"]
4
+ },
2
5
  variants: {
3
6
  size: {
4
7
  xl: {
@@ -1,6 +1,6 @@
1
1
  export declare const selectMenuTheme: {
2
2
  slots: {
3
- base: string;
3
+ base: string[];
4
4
  trailingIcon: string;
5
5
  selectedWrapper: string;
6
6
  selectedLabel: string;
@@ -1,6 +1,6 @@
1
1
  export const selectMenuTheme = {
2
2
  slots: {
3
- base: "cursor-pointer w-full",
3
+ base: ["cursor-pointer w-full rounded-lg"],
4
4
  trailingIcon: "group-data-[state=open]:rotate-180 transition-transform duration-200",
5
5
  selectedWrapper: "flex w-full items-center justify-between",
6
6
  selectedLabel: "truncate",
@@ -1,7 +1,7 @@
1
1
  export const tableTheme = {
2
2
  slots: {
3
- root: "bg-white",
4
- rootWrapper: "rounded-t-lg rounded-b-lg border-1 border-[#EAECF0]",
3
+ root: "",
4
+ rootWrapper: "rounded-t-lg rounded-b-lg border-1 border-[#EAECF0] bg-white",
5
5
  searchContainer: "mb-4 flex justify-end",
6
6
  captionContainer: "hidden mb-4 text-gray-500",
7
7
  captionBoldText: "font-bold",
@@ -11,8 +11,8 @@ export const tableTheme = {
11
11
  paginationInfo: "text-sm font-bold text-gray-600",
12
12
  paginationLimitSelect: "max-sm:!hidden min-w-[120px]",
13
13
  paginationLimitSelectLabel: "font-bold text-gray-600",
14
- thead: "bg-primary",
15
- th: "text-[#475467] bg-white whitespace-nowrap font-medium text-xs",
14
+ thead: "",
15
+ th: "text-[#475467] whitespace-nowrap font-medium text-xs",
16
16
  td: "text-[#475467]"
17
17
  },
18
18
  variants: {
@@ -24,7 +24,7 @@ export const tableTheme = {
24
24
  },
25
25
  sticky: {
26
26
  true: {
27
- thead: "sticky top-0 inset-x-0 bg-primary z-[1] backdrop-blur",
27
+ thead: "sticky top-0 inset-x-0 z-[1] backdrop-blur",
28
28
  tfoot: "sticky bottom-0 inset-x-0 bg-white z-[1] backdrop-blur"
29
29
  }
30
30
  }
@@ -1,6 +1,7 @@
1
1
  export declare const textareaTheme: {
2
2
  slots: {
3
3
  root: string;
4
+ base: string[];
4
5
  };
5
6
  variants: {
6
7
  size: {
@@ -1,6 +1,7 @@
1
1
  export const textareaTheme = {
2
2
  slots: {
3
- root: "w-full"
3
+ root: "w-full",
4
+ base: ["rounded-lg"]
4
5
  },
5
6
  variants: {
6
7
  size: {
@@ -11,7 +11,7 @@ export const uploadFileDropzoneTheme = {
11
11
  actionRetryIcon: "stash:arrow-retry"
12
12
  },
13
13
  slots: {
14
- base: "relative w-full text-base p-4 transition rounded-md flex items-center justify-center ring-1 bg-white ring-gray-300",
14
+ base: "relative w-full text-base p-4 transition rounded-lg flex items-center justify-center ring-1 bg-white ring-accented",
15
15
  wrapper: "flex flex-col items-center w-full",
16
16
  disabled: "bg-gray-100 border-none grayscale cursor-not-allowed",
17
17
  failed: "border-error",
@@ -26,14 +26,14 @@ export const uploadFileDropzoneTheme = {
26
26
  onLoadingTextWrapper: "flex-1 min-w-0 flex items-center justify-between",
27
27
  onLoadingLoadingIconClass: "size-10 text-primary animate-spin",
28
28
  // Preview state
29
- onPreviewWrapper: "flex items-center space-x-4 rounded-md w-full",
30
- onPreviewImgWrapper: "flex-shrink-0 w-16 h-16 flex justify-center items-center rounded-md overflow-hidden bg-gray-100",
29
+ onPreviewWrapper: "flex items-center space-x-4 rounded-lg w-full",
30
+ onPreviewImgWrapper: "flex-shrink-0 w-16 h-16 flex justify-center items-center rounded-lg overflow-hidden bg-gray-100",
31
31
  onPreviewImgClass: "w-full h-full object-cover",
32
- onPreviewFileWrapper: "flex-shrink-0 w-16 h-16 flex justify-center items-center rounded-md overflow-hidden",
32
+ onPreviewFileWrapper: "flex-shrink-0 w-16 h-16 flex justify-center items-center rounded-lg overflow-hidden",
33
33
  onPreviewFileClass: "size-8 text-gray-400 m-auto",
34
34
  onPreviewTextWrapper: "flex-1 min-w-0 flex items-center justify-between",
35
35
  // Failed state
36
- onFailedWrapper: "flex items-start space-x-4 w-full rounded-md",
36
+ onFailedWrapper: "flex items-start space-x-4 w-full rounded-lg",
37
37
  onFailedFailedImgWrapper: "flex-shrink-0",
38
38
  onFailedFailedIconClass: "size-12",
39
39
  onFailedTextWrapper: "flex-1 min-w-0 flex items-start justify-between",