@finema/core 1.4.187 → 1.4.189

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 (63) hide show
  1. package/README.md +60 -60
  2. package/dist/module.d.mts +1 -1
  3. package/dist/module.d.ts +1 -1
  4. package/dist/module.json +1 -1
  5. package/dist/module.mjs +1 -1
  6. package/dist/runtime/components/Alert.vue +48 -48
  7. package/dist/runtime/components/Avatar.vue +27 -27
  8. package/dist/runtime/components/Badge.vue +11 -11
  9. package/dist/runtime/components/Breadcrumb.vue +44 -44
  10. package/dist/runtime/components/Button/Group.vue +37 -37
  11. package/dist/runtime/components/Button/index.vue +75 -75
  12. package/dist/runtime/components/Card.vue +38 -38
  13. package/dist/runtime/components/Core.vue +45 -45
  14. package/dist/runtime/components/Dialog/index.vue +108 -108
  15. package/dist/runtime/components/Dropdown/index.vue +70 -70
  16. package/dist/runtime/components/FlexDeck/Base.vue +143 -143
  17. package/dist/runtime/components/FlexDeck/index.vue +68 -68
  18. package/dist/runtime/components/Form/FieldWrapper.vue +23 -23
  19. package/dist/runtime/components/Form/Fields.vue +230 -230
  20. package/dist/runtime/components/Form/InputCheckbox/index.vue +28 -28
  21. package/dist/runtime/components/Form/InputDateTime/index.vue +61 -61
  22. package/dist/runtime/components/Form/InputDateTimeRange/index.vue +83 -83
  23. package/dist/runtime/components/Form/InputNumber/index.vue +27 -27
  24. package/dist/runtime/components/Form/InputRadio/index.vue +27 -27
  25. package/dist/runtime/components/Form/InputSelect/index.vue +45 -45
  26. package/dist/runtime/components/Form/InputSelectMultiple/index.vue +54 -54
  27. package/dist/runtime/components/Form/InputStatic/index.vue +16 -16
  28. package/dist/runtime/components/Form/InputTags/index.vue +141 -141
  29. package/dist/runtime/components/Form/InputText/index.vue +68 -68
  30. package/dist/runtime/components/Form/InputTextarea/index.vue +25 -25
  31. package/dist/runtime/components/Form/InputToggle/index.vue +27 -27
  32. package/dist/runtime/components/Form/InputUploadDropzone/index.vue +206 -206
  33. package/dist/runtime/components/Form/InputUploadDropzoneAuto/index.vue +342 -342
  34. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/ItemUpload.vue +241 -241
  35. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/ItemView.vue +89 -89
  36. package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/index.vue +172 -172
  37. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/ItemUpload.vue +161 -161
  38. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/ItemView.vue +64 -64
  39. package/dist/runtime/components/Form/InputUploadDropzoneImageAutoMultiple/index.vue +172 -172
  40. package/dist/runtime/components/Form/InputUploadFileClassic/index.vue +95 -95
  41. package/dist/runtime/components/Form/InputUploadFileClassicAuto/index.vue +151 -151
  42. package/dist/runtime/components/Form/InputUploadImageAuto/index.vue +219 -219
  43. package/dist/runtime/components/Form/InputWYSIWYG/index.vue +215 -56
  44. package/dist/runtime/components/Form/index.vue +6 -6
  45. package/dist/runtime/components/Icon.vue +23 -23
  46. package/dist/runtime/components/Image.vue +36 -36
  47. package/dist/runtime/components/Loader.vue +27 -27
  48. package/dist/runtime/components/Modal/index.vue +146 -146
  49. package/dist/runtime/components/QRCode.vue +22 -22
  50. package/dist/runtime/components/SimplePagination.vue +96 -96
  51. package/dist/runtime/components/Slideover/index.vue +110 -110
  52. package/dist/runtime/components/Table/Base.vue +160 -150
  53. package/dist/runtime/components/Table/ColumnDate.vue +16 -16
  54. package/dist/runtime/components/Table/ColumnDateTime.vue +18 -18
  55. package/dist/runtime/components/Table/ColumnImage.vue +15 -15
  56. package/dist/runtime/components/Table/ColumnNumber.vue +14 -14
  57. package/dist/runtime/components/Table/ColumnText.vue +29 -29
  58. package/dist/runtime/components/Table/Simple.vue +69 -69
  59. package/dist/runtime/components/Table/index.vue +65 -65
  60. package/dist/runtime/components/Table/types.d.ts +1 -0
  61. package/dist/runtime/components/Tabs/index.vue +64 -64
  62. package/dist/runtime/components/TeleportSafe.vue +40 -40
  63. package/package.json +101 -94
@@ -1,57 +1,216 @@
1
- <template>
2
- <FieldWrapper v-bind="wrapperProps">
3
- <ClientOnly>
4
- <QuillEditor
5
- v-model:content="value"
6
- :placeholder="placeholder ?? label"
7
- :autofocus="autoFocus"
8
- :disabled="isDisabled || isReadonly"
9
- :name="name"
10
- class="ql-snow focus:ring-primary-500 min-h-[300px] rounded-b-md bg-white ring-1 ring-inset ring-gray-300 focus:ring-2"
11
- content-type="html"
12
- :options="options"
13
- />
14
- </ClientOnly>
15
- </FieldWrapper>
16
- </template>
17
- <script lang="ts" setup>
18
- import { useFieldHOC } from '#core/composables/useForm'
19
- import FieldWrapper from '#core/components/Form/FieldWrapper.vue'
20
- import '@vueup/vue-quill/dist/vue-quill.snow.css'
21
- import type { IWYSIWYGFieldProps } from '#core/components/Form/InputWYSIWYG/types'
22
-
23
- const props = withDefaults(defineProps<IWYSIWYGFieldProps>(), {})
24
- const { value, wrapperProps } = useFieldHOC<string>(props)
25
-
26
- const options = {
27
- modules: {
28
- toolbar: [
29
- // [{ size: ['small', false, 'large', 'huge'] }], // custom dropdown
30
- ['bold', 'italic', 'underline'], // toggled buttons
31
- // ['blockquote', 'code-block'],
32
-
33
- ['link'],
34
-
35
- // [{ header: 1 }, { header: 2 }], // custom button values
36
- [{ list: 'ordered' }, { list: 'bullet' }],
37
- // [{ script: 'sub' }, { script: 'super' }], // superscript/subscript
38
- [{ indent: '-1' }, { indent: '+1' }], // outdent/indent
39
- // [{ direction: 'rtl' }], // text direction
40
- [{ align: [] }],
41
-
42
- // [{ header: [1, 2, 3, 4, 5, 6, false] }],
43
-
44
- [{ color: [] }], // dropdown with defaults from theme
45
- ['link', 'image', 'video'], // link and image, video
46
-
47
- // [{ font: [] }],
48
-
49
- ['clean'], // remove formatting button
50
- ],
51
- },
52
- theme: 'snow',
53
- }
54
- </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>
55
214
  <style>
56
- .ql-toolbar.ql-snow{@apply rounded-t-md border-b-0 bg-white}.ql-container.ql-snow,.ql-snow{@apply border-0}
57
- </style>
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>
@@ -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>