@finema/core 1.4.189 → 1.4.190

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 (61) hide show
  1. package/README.md +60 -60
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +1 -1
  4. package/dist/runtime/components/Alert.vue +48 -48
  5. package/dist/runtime/components/Avatar.vue +27 -27
  6. package/dist/runtime/components/Badge.vue +11 -11
  7. package/dist/runtime/components/Breadcrumb.vue +44 -44
  8. package/dist/runtime/components/Button/Group.vue +37 -37
  9. package/dist/runtime/components/Button/index.vue +75 -75
  10. package/dist/runtime/components/Card.vue +38 -38
  11. package/dist/runtime/components/Core.vue +45 -45
  12. package/dist/runtime/components/Dialog/index.vue +108 -108
  13. package/dist/runtime/components/Dropdown/index.vue +70 -70
  14. package/dist/runtime/components/FlexDeck/Base.vue +153 -143
  15. package/dist/runtime/components/FlexDeck/index.vue +68 -68
  16. package/dist/runtime/components/FlexDeck/types.d.ts +1 -0
  17. package/dist/runtime/components/Form/FieldWrapper.vue +23 -23
  18. package/dist/runtime/components/Form/Fields.vue +230 -230
  19. package/dist/runtime/components/Form/InputCheckbox/index.vue +28 -28
  20. package/dist/runtime/components/Form/InputDateTime/index.vue +61 -61
  21. package/dist/runtime/components/Form/InputDateTimeRange/index.vue +83 -83
  22. package/dist/runtime/components/Form/InputNumber/index.vue +27 -27
  23. package/dist/runtime/components/Form/InputRadio/index.vue +27 -27
  24. package/dist/runtime/components/Form/InputSelect/index.vue +45 -45
  25. package/dist/runtime/components/Form/InputSelectMultiple/index.vue +54 -54
  26. package/dist/runtime/components/Form/InputStatic/index.vue +16 -16
  27. package/dist/runtime/components/Form/InputTags/index.vue +141 -141
  28. package/dist/runtime/components/Form/InputText/index.vue +68 -68
  29. package/dist/runtime/components/Form/InputTextarea/index.vue +25 -25
  30. package/dist/runtime/components/Form/InputToggle/index.vue +27 -27
  31. package/dist/runtime/components/Form/InputUploadDropzone/index.vue +206 -206
  32. package/dist/runtime/components/Form/InputUploadDropzoneAuto/index.vue +342 -342
  33. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/ItemUpload.vue +241 -241
  34. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/ItemView.vue +89 -89
  35. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/index.vue +172 -172
  36. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/ItemUpload.vue +161 -161
  37. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/ItemView.vue +64 -64
  38. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/index.vue +172 -172
  39. package/dist/runtime/components/Form/InputUploadFileClassic/index.vue +95 -95
  40. package/dist/runtime/components/Form/InputUploadFileClassicAuto/index.vue +151 -151
  41. package/dist/runtime/components/Form/InputUploadImageAuto/index.vue +219 -219
  42. package/dist/runtime/components/Form/InputWYSIWYG/index.vue +214 -214
  43. package/dist/runtime/components/Form/index.vue +6 -6
  44. package/dist/runtime/components/Icon.vue +23 -23
  45. package/dist/runtime/components/Image.vue +36 -36
  46. package/dist/runtime/components/Loader.vue +27 -27
  47. package/dist/runtime/components/Modal/index.vue +146 -146
  48. package/dist/runtime/components/QRCode.vue +22 -22
  49. package/dist/runtime/components/SimplePagination.vue +96 -96
  50. package/dist/runtime/components/Slideover/index.vue +110 -110
  51. package/dist/runtime/components/Table/Base.vue +160 -160
  52. package/dist/runtime/components/Table/ColumnDate.vue +16 -16
  53. package/dist/runtime/components/Table/ColumnDateTime.vue +18 -18
  54. package/dist/runtime/components/Table/ColumnImage.vue +15 -15
  55. package/dist/runtime/components/Table/ColumnNumber.vue +14 -14
  56. package/dist/runtime/components/Table/ColumnText.vue +29 -29
  57. package/dist/runtime/components/Table/Simple.vue +69 -69
  58. package/dist/runtime/components/Table/index.vue +65 -65
  59. package/dist/runtime/components/Tabs/index.vue +64 -64
  60. package/dist/runtime/components/TeleportSafe.vue +40 -40
  61. package/package.json +101 -101
@@ -1,216 +1,216 @@
1
- <template>
2
- <FieldWrapper v-bind="wrapperProps">
3
- <ClientOnly>
4
- <div
5
- class="form-textarea focus:ring-primary-500 dark:focus:ring-primary-400 relative block w-full resize-none rounded-md border-0 bg-white p-0 pb-3 text-sm text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:outline-none focus:ring-2 disabled:cursor-not-allowed disabled:opacity-75 dark:bg-gray-900 dark:text-white dark:ring-gray-700 dark:placeholder:text-gray-500"
6
- >
7
- <div class="tiptap-menu-bar">
8
- <div
9
- v-for="(items, index) in menuItems"
10
- :key="index"
11
- class="flex items-center border-r border-gray-200 pr-2"
12
- >
13
- <button
14
- v-for="item in items"
15
- :key="item.name"
16
- :class="{ 'is-active': item.isActive?.() }"
17
- class="menu-item"
18
- type="button"
19
- :title="item.title"
20
- @click="item.action"
21
- >
22
- <Icon :name="item.icon" class="size-5" />
23
- </button>
24
- </div>
25
- </div>
26
- <EditorContent
27
- :editor="editor"
28
- :placeholder="placeholder ?? label"
29
- :autofocus="autoFocus"
30
- :disabled="isDisabled || isReadonly"
31
- :name="name"
32
- />
33
- </div>
34
- </ClientOnly>
35
- </FieldWrapper>
36
- </template>
37
- <script lang="ts" setup>
38
- import { useFieldHOC } from '#core/composables/useForm'
39
- import FieldWrapper from '#core/components/Form/FieldWrapper.vue'
40
- import { EditorContent, useEditor } from '@tiptap/vue-3'
41
- import type { IWYSIWYGFieldProps } from '#core/components/Form/InputWYSIWYG/types'
42
- import StarterKit from '@tiptap/starter-kit'
43
- import Underline from '@tiptap/extension-underline'
44
- import TextAlign from '@tiptap/extension-text-align'
45
- import Link from '@tiptap/extension-link'
46
- import Image from '@tiptap/extension-image'
47
- import Youtube from '@tiptap/extension-youtube'
48
- import { computed, watch } from 'vue'
49
-
50
- const props = withDefaults(defineProps<IWYSIWYGFieldProps>(), {})
51
- const { value, wrapperProps } = useFieldHOC<string>(props)
52
- const editor = useEditor({
53
- content: value.value,
54
- extensions: [
55
- StarterKit,
56
- Underline,
57
- TextAlign.configure({
58
- types: ['heading', 'paragraph'],
59
- }),
60
- Link.configure({
61
- openOnClick: false,
62
- }),
63
- Image,
64
- Youtube,
65
- ],
66
- editorProps: {
67
- attributes: {
68
- class: 'prose m-4 focus:outline-none',
69
- },
70
- },
71
- onUpdate: ({ editor }) => {
72
- value.value = editor.getHTML()
73
- },
74
- })
75
-
76
- watch(value, (newValue) => {
77
- if (editor.value && newValue !== editor.value.getHTML()) {
78
- editor.value.commands.setContent(newValue)
79
- }
80
- })
81
-
82
- const menuItems = computed(() => [
83
- [
84
- {
85
- name: 'bold',
86
- icon: 'ph:text-b-bold',
87
- action: () => editor.value!.chain().focus().toggleBold().run(),
88
- isActive: () => editor.value!.isActive('bold'),
89
- title: 'Bold',
90
- },
91
- {
92
- name: 'italic',
93
- icon: 'ph:text-italic',
94
- action: () => editor.value!.chain().focus().toggleItalic().run(),
95
- isActive: () => editor.value!.isActive('italic'),
96
- title: 'Italic',
97
- },
98
- {
99
- name: 'underline',
100
- icon: 'ph:text-underline',
101
- action: () => editor.value!.chain().focus().toggleUnderline().run(),
102
- isActive: () => editor.value!.isActive('underline'),
103
- title: 'Underline',
104
- },
105
- ],
106
- [
107
- {
108
- name: 'bullet-list',
109
- icon: 'ph:list-bullets',
110
- action: () => editor.value!.chain().focus().toggleBulletList().run(),
111
- isActive: () => editor.value!.isActive('bulletList'),
112
- title: 'Bullet List',
113
- },
114
- {
115
- name: 'ordered-list',
116
- icon: 'ph:list-numbers',
117
- action: () => editor.value!.chain().focus().toggleOrderedList().run(),
118
- isActive: () => editor.value!.isActive('orderedList'),
119
- title: 'Ordered List',
120
- },
121
- ],
122
- [
123
- {
124
- name: 'align-left',
125
- icon: 'ph:text-align-left',
126
- action: () => editor.value!.chain().focus().setTextAlign('left').run(),
127
- isActive: () => editor.value!.isActive({ textAlign: 'left' }),
128
- title: 'Align Left',
129
- },
130
- {
131
- name: 'align-center',
132
- icon: 'ph:text-align-center',
133
- action: () => editor.value!.chain().focus().setTextAlign('center').run(),
134
- isActive: () => editor.value!.isActive({ textAlign: 'center' }),
135
- title: 'Align Center',
136
- },
137
- {
138
- name: 'align-right',
139
- icon: 'ph:text-align-right',
140
- action: () => editor.value!.chain().focus().setTextAlign('right').run(),
141
- isActive: () => editor.value!.isActive({ textAlign: 'right' }),
142
- title: 'Align Right',
143
- },
144
- ],
145
- [
146
- {
147
- name: 'link',
148
- icon: 'ph:link-simple',
149
- action: () => {
150
- const url = window.prompt('URL')
151
-
152
- if (url) {
153
- editor.value!.chain().focus().setLink({ href: url }).run()
154
- }
155
- },
156
- isActive: () => editor.value!.isActive('link'),
157
- title: 'Insert Link',
158
- },
159
- {
160
- name: 'image',
161
- icon: 'ph:image',
162
- action: () => {
163
- const url = window.prompt('Image URL')
164
-
165
- if (url) {
166
- editor.value!.chain().focus().setImage({ src: url }).run()
167
- }
168
- },
169
- title: 'Insert Image',
170
- },
171
- {
172
- name: 'video',
173
- icon: 'ph:video-camera',
174
- action: () => {
175
- const url = window.prompt('Video URL')
176
-
177
- if (url) {
178
- editor.value!.chain().focus().setYoutubeVideo({ src: url }).run()
179
- }
180
- },
181
- title: 'Insert Video',
182
- },
183
- ],
184
- [
185
- {
186
- name: 'hardBreak',
187
- icon: 'ri:text-wrap',
188
- action: () => editor.value!.chain().focus().setHardBreak().run(),
189
- title: 'Hard Break',
190
- },
191
- {
192
- name: 'clear',
193
- icon: 'ri:format-clear',
194
- action: () => editor.value!.chain().focus().clearNodes().unsetAllMarks().run(),
195
- title: 'Clear',
196
- },
197
- ],
198
- [
199
- {
200
- name: 'undo',
201
- icon: 'ph:arrow-counter-clockwise',
202
- action: () => editor.value!.chain().focus().undo().run(),
203
- title: 'Undo',
204
- },
205
- {
206
- name: 'redo',
207
- icon: 'ph:arrow-clockwise',
208
- action: () => editor.value!.chain().focus().redo().run(),
209
- title: 'Redo',
210
- },
211
- ],
212
- ])
213
- </script>
1
+ <template>
2
+ <FieldWrapper v-bind="wrapperProps">
3
+ <ClientOnly>
4
+ <div
5
+ class="form-textarea focus:ring-primary-500 dark:focus:ring-primary-400 relative block w-full resize-none rounded-md border-0 bg-white p-0 pb-3 text-sm text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:outline-none focus:ring-2 disabled:cursor-not-allowed disabled:opacity-75 dark:bg-gray-900 dark:text-white dark:ring-gray-700 dark:placeholder:text-gray-500"
6
+ >
7
+ <div class="tiptap-menu-bar">
8
+ <div
9
+ v-for="(items, index) in menuItems"
10
+ :key="index"
11
+ class="flex items-center border-r border-gray-200 pr-2"
12
+ >
13
+ <button
14
+ v-for="item in items"
15
+ :key="item.name"
16
+ :class="{ 'is-active': item.isActive?.() }"
17
+ class="menu-item"
18
+ type="button"
19
+ :title="item.title"
20
+ @click="item.action"
21
+ >
22
+ <Icon :name="item.icon" class="size-5" />
23
+ </button>
24
+ </div>
25
+ </div>
26
+ <EditorContent
27
+ :editor="editor"
28
+ :placeholder="placeholder ?? label"
29
+ :autofocus="autoFocus"
30
+ :disabled="isDisabled || isReadonly"
31
+ :name="name"
32
+ />
33
+ </div>
34
+ </ClientOnly>
35
+ </FieldWrapper>
36
+ </template>
37
+ <script lang="ts" setup>
38
+ import { useFieldHOC } from '#core/composables/useForm'
39
+ import FieldWrapper from '#core/components/Form/FieldWrapper.vue'
40
+ import { EditorContent, useEditor } from '@tiptap/vue-3'
41
+ import type { IWYSIWYGFieldProps } from '#core/components/Form/InputWYSIWYG/types'
42
+ import StarterKit from '@tiptap/starter-kit'
43
+ import Underline from '@tiptap/extension-underline'
44
+ import TextAlign from '@tiptap/extension-text-align'
45
+ import Link from '@tiptap/extension-link'
46
+ import Image from '@tiptap/extension-image'
47
+ import Youtube from '@tiptap/extension-youtube'
48
+ import { computed, watch } from 'vue'
49
+
50
+ const props = withDefaults(defineProps<IWYSIWYGFieldProps>(), {})
51
+ const { value, wrapperProps } = useFieldHOC<string>(props)
52
+ const editor = useEditor({
53
+ content: value.value,
54
+ extensions: [
55
+ StarterKit,
56
+ Underline,
57
+ TextAlign.configure({
58
+ types: ['heading', 'paragraph'],
59
+ }),
60
+ Link.configure({
61
+ openOnClick: false,
62
+ }),
63
+ Image,
64
+ Youtube,
65
+ ],
66
+ editorProps: {
67
+ attributes: {
68
+ class: 'prose m-4 focus:outline-none',
69
+ },
70
+ },
71
+ onUpdate: ({ editor }) => {
72
+ value.value = editor.getHTML()
73
+ },
74
+ })
75
+
76
+ watch(value, (newValue) => {
77
+ if (editor.value && newValue !== editor.value.getHTML()) {
78
+ editor.value.commands.setContent(newValue)
79
+ }
80
+ })
81
+
82
+ const menuItems = computed(() => [
83
+ [
84
+ {
85
+ name: 'bold',
86
+ icon: 'ph:text-b-bold',
87
+ action: () => editor.value!.chain().focus().toggleBold().run(),
88
+ isActive: () => editor.value!.isActive('bold'),
89
+ title: 'Bold',
90
+ },
91
+ {
92
+ name: 'italic',
93
+ icon: 'ph:text-italic',
94
+ action: () => editor.value!.chain().focus().toggleItalic().run(),
95
+ isActive: () => editor.value!.isActive('italic'),
96
+ title: 'Italic',
97
+ },
98
+ {
99
+ name: 'underline',
100
+ icon: 'ph:text-underline',
101
+ action: () => editor.value!.chain().focus().toggleUnderline().run(),
102
+ isActive: () => editor.value!.isActive('underline'),
103
+ title: 'Underline',
104
+ },
105
+ ],
106
+ [
107
+ {
108
+ name: 'bullet-list',
109
+ icon: 'ph:list-bullets',
110
+ action: () => editor.value!.chain().focus().toggleBulletList().run(),
111
+ isActive: () => editor.value!.isActive('bulletList'),
112
+ title: 'Bullet List',
113
+ },
114
+ {
115
+ name: 'ordered-list',
116
+ icon: 'ph:list-numbers',
117
+ action: () => editor.value!.chain().focus().toggleOrderedList().run(),
118
+ isActive: () => editor.value!.isActive('orderedList'),
119
+ title: 'Ordered List',
120
+ },
121
+ ],
122
+ [
123
+ {
124
+ name: 'align-left',
125
+ icon: 'ph:text-align-left',
126
+ action: () => editor.value!.chain().focus().setTextAlign('left').run(),
127
+ isActive: () => editor.value!.isActive({ textAlign: 'left' }),
128
+ title: 'Align Left',
129
+ },
130
+ {
131
+ name: 'align-center',
132
+ icon: 'ph:text-align-center',
133
+ action: () => editor.value!.chain().focus().setTextAlign('center').run(),
134
+ isActive: () => editor.value!.isActive({ textAlign: 'center' }),
135
+ title: 'Align Center',
136
+ },
137
+ {
138
+ name: 'align-right',
139
+ icon: 'ph:text-align-right',
140
+ action: () => editor.value!.chain().focus().setTextAlign('right').run(),
141
+ isActive: () => editor.value!.isActive({ textAlign: 'right' }),
142
+ title: 'Align Right',
143
+ },
144
+ ],
145
+ [
146
+ {
147
+ name: 'link',
148
+ icon: 'ph:link-simple',
149
+ action: () => {
150
+ const url = window.prompt('URL')
151
+
152
+ if (url) {
153
+ editor.value!.chain().focus().setLink({ href: url }).run()
154
+ }
155
+ },
156
+ isActive: () => editor.value!.isActive('link'),
157
+ title: 'Insert Link',
158
+ },
159
+ {
160
+ name: 'image',
161
+ icon: 'ph:image',
162
+ action: () => {
163
+ const url = window.prompt('Image URL')
164
+
165
+ if (url) {
166
+ editor.value!.chain().focus().setImage({ src: url }).run()
167
+ }
168
+ },
169
+ title: 'Insert Image',
170
+ },
171
+ {
172
+ name: 'video',
173
+ icon: 'ph:video-camera',
174
+ action: () => {
175
+ const url = window.prompt('Video URL')
176
+
177
+ if (url) {
178
+ editor.value!.chain().focus().setYoutubeVideo({ src: url }).run()
179
+ }
180
+ },
181
+ title: 'Insert Video',
182
+ },
183
+ ],
184
+ [
185
+ {
186
+ name: 'hardBreak',
187
+ icon: 'ri:text-wrap',
188
+ action: () => editor.value!.chain().focus().setHardBreak().run(),
189
+ title: 'Hard Break',
190
+ },
191
+ {
192
+ name: 'clear',
193
+ icon: 'ri:format-clear',
194
+ action: () => editor.value!.chain().focus().clearNodes().unsetAllMarks().run(),
195
+ title: 'Clear',
196
+ },
197
+ ],
198
+ [
199
+ {
200
+ name: 'undo',
201
+ icon: 'ph:arrow-counter-clockwise',
202
+ action: () => editor.value!.chain().focus().undo().run(),
203
+ title: 'Undo',
204
+ },
205
+ {
206
+ name: 'redo',
207
+ icon: 'ph:arrow-clockwise',
208
+ action: () => editor.value!.chain().focus().redo().run(),
209
+ title: 'Redo',
210
+ },
211
+ ],
212
+ ])
213
+ </script>
214
214
  <style>
215
215
  .tiptap-menu-bar{@apply flex flex-wrap border-b py-2 px-2 gap-1}.menu-item{@apply px-1 py-1 rounded hover:bg-gray-100 transition-colors flex justify-center items-center}.menu-item.is-active{@apply bg-primary-100 text-primary-600}
216
- </style>
216
+ </style>
@@ -1,6 +1,6 @@
1
- <template>
2
- <form class="form">
3
- <slot />
4
- </form>
5
- </template>
6
- <script lang="ts" setup></script>
1
+ <template>
2
+ <form class="form">
3
+ <slot />
4
+ </form>
5
+ </template>
6
+ <script lang="ts" setup></script>
@@ -1,23 +1,23 @@
1
- <template>
2
- <UIcon :name="name" :dynamic="dynamicValue" />
3
- </template>
4
-
5
- <script lang="ts" setup>
6
- import { computed, useUiConfig } from '#imports'
7
- import { icon } from '#core/ui.config'
8
-
9
- const props = defineProps({
10
- name: {
11
- type: String,
12
- required: true,
13
- },
14
- dynamic: {
15
- type: Boolean,
16
- default: false,
17
- },
18
- })
19
-
20
- const config = useUiConfig<typeof icon>(icon, 'icon')
21
-
22
- const dynamicValue = computed(() => props.dynamic || config.dynamic)
23
- </script>
1
+ <template>
2
+ <UIcon :name="name" :dynamic="dynamicValue" />
3
+ </template>
4
+
5
+ <script lang="ts" setup>
6
+ import { computed, useUiConfig } from '#imports'
7
+ import { icon } from '#core/ui.config'
8
+
9
+ const props = defineProps({
10
+ name: {
11
+ type: String,
12
+ required: true,
13
+ },
14
+ dynamic: {
15
+ type: Boolean,
16
+ default: false,
17
+ },
18
+ })
19
+
20
+ const config = useUiConfig<typeof icon>(icon, 'icon')
21
+
22
+ const dynamicValue = computed(() => props.dynamic || config.dynamic)
23
+ </script>
@@ -1,36 +1,36 @@
1
- <template>
2
- <img :src="getSrc" />
3
- </template>
4
- <script lang="ts" setup>
5
- import { useImage } from '@vueuse/core'
6
- import { computed } from 'vue'
7
-
8
- const props = defineProps({
9
- src: {
10
- type: String,
11
- required: true,
12
- },
13
- loadingSrc: {
14
- type: String,
15
- default: '',
16
- },
17
- errorSrc: {
18
- type: String,
19
- default: '',
20
- },
21
- })
22
-
23
- const { isLoading, error } = useImage({ src: props.src })
24
-
25
- const getSrc = computed(() => {
26
- if (isLoading.value) {
27
- return props.loadingSrc
28
- }
29
-
30
- if (error.value) {
31
- return props.errorSrc
32
- }
33
-
34
- return props.src
35
- })
36
- </script>
1
+ <template>
2
+ <img :src="getSrc" />
3
+ </template>
4
+ <script lang="ts" setup>
5
+ import { useImage } from '@vueuse/core'
6
+ import { computed } from 'vue'
7
+
8
+ const props = defineProps({
9
+ src: {
10
+ type: String,
11
+ required: true,
12
+ },
13
+ loadingSrc: {
14
+ type: String,
15
+ default: '',
16
+ },
17
+ errorSrc: {
18
+ type: String,
19
+ default: '',
20
+ },
21
+ })
22
+
23
+ const { isLoading, error } = useImage({ src: props.src })
24
+
25
+ const getSrc = computed(() => {
26
+ if (isLoading.value) {
27
+ return props.loadingSrc
28
+ }
29
+
30
+ if (error.value) {
31
+ return props.errorSrc
32
+ }
33
+
34
+ return props.src
35
+ })
36
+ </script>
@@ -1,27 +1,27 @@
1
- <template>
2
- <div
3
- v-if="isLoading"
4
- :class="[
5
- 'flex w-full items-center justify-center',
6
- $attrs.class,
7
- {
8
- 'min-h-[200px]': !$attrs.class,
9
- },
10
- ]"
11
- >
12
- <UIcon name="i-svg-spinners:180-ring-with-bg" class="text-primary text-4xl" dynamic />
13
- </div>
14
- <slot v-else />
15
- </template>
16
- <script lang="ts" setup>
17
- defineOptions({
18
- inheritAttrs: false,
19
- })
20
-
21
- defineProps({
22
- isLoading: {
23
- type: Boolean,
24
- default: true,
25
- },
26
- })
27
- </script>
1
+ <template>
2
+ <div
3
+ v-if="isLoading"
4
+ :class="[
5
+ 'flex w-full items-center justify-center',
6
+ $attrs.class,
7
+ {
8
+ 'min-h-[200px]': !$attrs.class,
9
+ },
10
+ ]"
11
+ >
12
+ <UIcon name="i-svg-spinners:180-ring-with-bg" class="text-primary text-4xl" dynamic />
13
+ </div>
14
+ <slot v-else />
15
+ </template>
16
+ <script lang="ts" setup>
17
+ defineOptions({
18
+ inheritAttrs: false,
19
+ })
20
+
21
+ defineProps({
22
+ isLoading: {
23
+ type: Boolean,
24
+ default: true,
25
+ },
26
+ })
27
+ </script>