@meeovi/layer-shared 1.0.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/README.md +0 -0
- package/app/components/Gallery/Gallery.vue +187 -0
- package/app/components/Gallery/__tests__/Gallery.spec.ts +14 -0
- package/app/components/Heading/Heading.vue +14 -0
- package/app/components/Heading/__tests__/Heading.spec.ts +14 -0
- package/app/components/Heading/types.ts +5 -0
- package/app/components/media/audioGallery.vue +70 -0
- package/app/components/media/dragDropUpload.vue +67 -0
- package/app/components/media/fullscreenMediaModal.vue +66 -0
- package/app/components/media/imageCard.vue +65 -0
- package/app/components/media/imageGallery.vue +40 -0
- package/app/components/media/mediaCard.vue +89 -0
- package/app/components/media/mediaCarousel.vue +65 -0
- package/app/components/media/mediaFolderSidebar.vue +72 -0
- package/app/components/media/mediaPlayer.vue +40 -0
- package/app/components/media/mediaSearchBar.vue +16 -0
- package/app/components/media/videoGallery.vue +77 -0
- package/app/components/ui/AccordionItem/AccordionItem.vue +24 -0
- package/app/components/ui/AccordionItem/__tests__/AccordionItem.spec.ts +14 -0
- package/app/components/ui/AccordionItem/types.ts +5 -0
- package/app/components/ui/Alert/Alert.vue +34 -0
- package/app/components/ui/Alert/types.ts +5 -0
- package/app/components/ui/Breadcrumbs/Breadcrumbs.vue +76 -0
- package/app/components/ui/Breadcrumbs/__tests__/Breadcrumbs.spec.ts +14 -0
- package/app/components/ui/Breadcrumbs/types.ts +8 -0
- package/app/components/ui/CartProductCard/CartProductCard.vue +66 -0
- package/app/components/ui/CartProductCard/types.ts +18 -0
- package/app/components/ui/CategoryCard/CategoryCard.vue +41 -0
- package/app/components/ui/CategoryCard/types.ts +9 -0
- package/app/components/ui/Display/Display.vue +55 -0
- package/app/components/ui/Display/types.ts +12 -0
- package/app/components/ui/Divider/Divider.vue +3 -0
- package/app/components/ui/Divider/__tests__/Divider.spec.tsx +10 -0
- package/app/components/ui/Footer.vue +92 -0
- package/app/components/ui/Form/FormHelperText.vue +5 -0
- package/app/components/ui/Form/FormLabel.vue +5 -0
- package/app/components/ui/Form/FormPasswordInput.vue +15 -0
- package/app/components/ui/Form/__tests__/FormHelperText.spec.ts +10 -0
- package/app/components/ui/Form/__tests__/FormLabel.spec.ts +10 -0
- package/app/components/ui/Hero/Hero.vue +44 -0
- package/app/components/ui/Hero/types.ts +10 -0
- package/app/components/ui/Modal/Modal.vue +19 -0
- package/app/components/ui/Modal/types.ts +8 -0
- package/app/components/ui/Motionable.vue +45 -0
- package/app/components/ui/NavbarBottom.vue +63 -0
- package/app/components/ui/NavbarTop.vue +25 -0
- package/app/components/ui/Overlay/Overlay.vue +14 -0
- package/app/components/ui/Overlay/__tests__/Overlay.spec.ts +14 -0
- package/app/components/ui/Overlay/types.ts +3 -0
- package/app/components/ui/PageBuilder.vue +39 -0
- package/app/components/ui/PageContainer.vue +5 -0
- package/app/components/ui/Pagination/Pagination.vue +151 -0
- package/app/components/ui/Pagination/__tests__/Pagination.spec.ts +17 -0
- package/app/components/ui/Pagination/types.ts +6 -0
- package/app/components/ui/ProductCard/ProductCard.vue +55 -0
- package/app/components/ui/ProductCard/__tests__/ProductCard.spec.ts +16 -0
- package/app/components/ui/ProductCard/types.ts +12 -0
- package/app/components/ui/ProductCardHorizontal/ProductCardHorizontal.vue +34 -0
- package/app/components/ui/ProductCardHorizontal/__tests__/ProductCardHorizontal.spec.ts +36 -0
- package/app/components/ui/ProductCardHorizontal/types.ts +8 -0
- package/app/components/ui/PurchaseCard/PurchaseCard.vue +109 -0
- package/app/components/ui/PurchaseCard/__tests__/PurchaseCard.spec.ts +15 -0
- package/app/components/ui/PurchaseCard/types.ts +5 -0
- package/app/components/ui/QuantitySelector/QuantitySelector.vue +69 -0
- package/app/components/ui/QuantitySelector/__tests__/QuantitySelector.spec.ts +15 -0
- package/app/components/ui/QuantitySelector/types.ts +5 -0
- package/app/components/ui/RadialProgress.vue +44 -0
- package/app/components/ui/Review/Review.vue +57 -0
- package/app/components/ui/Review/__tests__/Review.spec.ts +15 -0
- package/app/components/ui/Review/types.ts +5 -0
- package/app/components/ui/ScrollTop.vue +82 -0
- package/app/components/ui/Search.vue +54 -0
- package/app/components/ui/Tag/Tag.vue +38 -0
- package/app/components/ui/Tag/__tests__/Tag.spec.ts +10 -0
- package/app/components/ui/Tag/types.ts +16 -0
- package/app/components/ui/VsfLogo.vue +7 -0
- package/app/components/ui/forms/BooleanInput.vue +34 -0
- package/app/components/ui/forms/DateTime.vue +44 -0
- package/app/components/ui/forms/DirectusFormElement.vue +60 -0
- package/app/components/ui/forms/DynamicTableElement.vue +57 -0
- package/app/components/ui/forms/FileInput.vue +85 -0
- package/app/components/ui/forms/FormField.vue +34 -0
- package/app/components/ui/forms/RelationSelect.vue +63 -0
- package/app/components/ui/forms/RepeaterInput.vue +121 -0
- package/app/components/ui/forms/SelectInput.vue +65 -0
- package/app/components/ui/forms/TextArea.vue +59 -0
- package/app/components/ui/forms/TextInput.vue +42 -0
- package/app/components/ui/forms/TiptapEditor.vue +136 -0
- package/app/components/ui/forms/[collection].vue +22 -0
- package/app/components/ui/studio/builder.vue +57 -0
- package/app/components/ui/studio/document.vue +69 -0
- package/app/components/ui/studio/email.vue +57 -0
- package/app/composables/globals/uploadFiles.js +41 -0
- package/app/composables/globals/useAdminTable.ts +12 -0
- package/app/composables/globals/useCustomFetch.ts +13 -0
- package/app/composables/globals/useDirectusField.ts +144 -0
- package/app/composables/globals/useDirectusForm.ts +70 -0
- package/app/composables/globals/useDirectusSchema.js +9 -0
- package/app/composables/globals/useFileManager.ts +76 -0
- package/app/composables/globals/useLivePreview.ts +17 -0
- package/app/composables/globals/useLoading.ts +23 -0
- package/app/composables/globals/useNavigation.js +19 -0
- package/app/composables/globals/useNotifications.ts +153 -0
- package/app/composables/globals/usePages.js +36 -0
- package/app/composables/globals/useRichText.ts +33 -0
- package/app/composables/globals/useServerRootMixin.ts +19 -0
- package/app/composables/globals/useVisualEditing.ts +38 -0
- package/app/composables/media/useFile.ts +6 -0
- package/app/composables/media/useMediaCenter.ts +353 -0
- package/app/composables/media/useVideojs.ts +45 -0
- package/app/composables/registry.ts +13 -0
- package/app/composables/types.ts +12 -0
- package/app/composables/useContent.ts +13 -0
- package/app/composables/useDirectusRequest.ts +32 -0
- package/app/stores/index.ts +0 -0
- package/app/types/api/global-search.ts +8 -0
- package/app/types/blocks/block-button-group.ts +7 -0
- package/app/types/blocks/block-button.ts +14 -0
- package/app/types/blocks/block-column.ts +20 -0
- package/app/types/blocks/block-cta.ts +10 -0
- package/app/types/blocks/block-divider.ts +4 -0
- package/app/types/blocks/block-faq.ts +12 -0
- package/app/types/blocks/block-form.ts +8 -0
- package/app/types/blocks/block-gallery.ts +14 -0
- package/app/types/blocks/block-hero.ts +12 -0
- package/app/types/blocks/block-html.ts +4 -0
- package/app/types/blocks/block-logocloud.ts +14 -0
- package/app/types/blocks/block-quote.ts +11 -0
- package/app/types/blocks/block-richtext.ts +7 -0
- package/app/types/blocks/block-steps.ts +22 -0
- package/app/types/blocks/block-team.ts +6 -0
- package/app/types/blocks/block-testimonial.ts +14 -0
- package/app/types/blocks/block-video.ts +10 -0
- package/app/types/blocks/block.ts +49 -0
- package/app/types/blocks/index.ts +18 -0
- package/app/types/componentMap.ts +15 -0
- package/app/types/content/category.ts +11 -0
- package/app/types/content/form.ts +20 -0
- package/app/types/content/index.ts +6 -0
- package/app/types/content/page.ts +76 -0
- package/app/types/content/post.ts +39 -0
- package/app/types/content/team.ts +16 -0
- package/app/types/content/testimonial.ts +19 -0
- package/app/types/directus.d.ts +47 -0
- package/app/types/env.d.ts +8 -0
- package/app/types/help/index.ts +53 -0
- package/app/types/index.d.ts +9 -0
- package/app/types/index.ts +7 -0
- package/app/types/meta/analytics.ts +18 -0
- package/app/types/meta/config.ts +21 -0
- package/app/types/meta/globals.ts +30 -0
- package/app/types/meta/index.ts +6 -0
- package/app/types/meta/navigation.ts +32 -0
- package/app/types/meta/redirect.ts +13 -0
- package/app/types/meta/seo.ts +19 -0
- package/app/types/os/contact.ts +23 -0
- package/app/types/os/conversation.ts +25 -0
- package/app/types/os/index.ts +16 -0
- package/app/types/os/organization.ts +54 -0
- package/app/types/os/os-activity.ts +28 -0
- package/app/types/os/os-deal.ts +45 -0
- package/app/types/os/os-expense.ts +22 -0
- package/app/types/os/os-invoice.ts +48 -0
- package/app/types/os/os-item.ts +18 -0
- package/app/types/os/os-payment.ts +29 -0
- package/app/types/os/os-project.ts +47 -0
- package/app/types/os/os-proposal.ts +84 -0
- package/app/types/os/os-settings.ts +19 -0
- package/app/types/os/os-subscription.ts +12 -0
- package/app/types/os/os-task.ts +34 -0
- package/app/types/os/os-tax-rate.ts +13 -0
- package/app/types/pageComponentMap.ts +8 -0
- package/app/types/schema.d.ts +39 -0
- package/app/types/schema.ts +151 -0
- package/app/types/system/file.ts +46 -0
- package/app/types/system/folder.ts +8 -0
- package/app/types/system/index.ts +4 -0
- package/app/types/system/role.ts +21 -0
- package/app/types/system/user.ts +56 -0
- package/app/utils/Timer.js +44 -0
- package/app/utils/billing-address.ts +24 -0
- package/app/utils/color.ts +14 -0
- package/app/utils/currency.ts +29 -0
- package/app/utils/embed.ts +57 -0
- package/app/utils/errors.ts +9 -0
- package/app/utils/fieldRegistry.js +89 -0
- package/app/utils/fonts.ts +24 -0
- package/app/utils/formkit.ts +75 -0
- package/app/utils/icons.ts +62 -0
- package/app/utils/index.js +0 -0
- package/app/utils/links.ts +28 -0
- package/app/utils/lodash.ts +33 -0
- package/app/utils/markdown.ts +9 -0
- package/app/utils/math.ts +25 -0
- package/app/utils/navigation.ts +11 -0
- package/app/utils/objects.ts +11 -0
- package/app/utils/paths.ts +21 -0
- package/app/utils/relations.ts +33 -0
- package/app/utils/strings.ts +113 -0
- package/app/utils/time.ts +148 -0
- package/app/utils/url.ts +22 -0
- package/app/utils/user-name.ts +21 -0
- package/app/utils/video/README.md +51 -0
- package/app/utils/video/playlist.js +0 -0
- package/dist/api/global-search.d.ts +8 -0
- package/dist/api/global-search.js +1 -0
- package/dist/blocks/block-button-group.d.ts +6 -0
- package/dist/blocks/block-button-group.js +1 -0
- package/dist/blocks/block-button.d.ts +13 -0
- package/dist/blocks/block-button.js +1 -0
- package/dist/blocks/block-column.d.ts +18 -0
- package/dist/blocks/block-column.js +1 -0
- package/dist/blocks/block-cta.d.ts +11 -0
- package/dist/blocks/block-cta.js +1 -0
- package/dist/blocks/block-divider.d.ts +4 -0
- package/dist/blocks/block-divider.js +1 -0
- package/dist/blocks/block-faq.d.ts +11 -0
- package/dist/blocks/block-faq.js +1 -0
- package/dist/blocks/block-form.d.ts +7 -0
- package/dist/blocks/block-form.js +1 -0
- package/dist/blocks/block-gallery.d.ts +13 -0
- package/dist/blocks/block-gallery.js +1 -0
- package/dist/blocks/block-hero.d.ts +11 -0
- package/dist/blocks/block-hero.js +1 -0
- package/dist/blocks/block-html.d.ts +4 -0
- package/dist/blocks/block-html.js +1 -0
- package/dist/blocks/block-logocloud.d.ts +13 -0
- package/dist/blocks/block-logocloud.js +1 -0
- package/dist/blocks/block-quote.d.ts +10 -0
- package/dist/blocks/block-quote.js +1 -0
- package/dist/blocks/block-richtext.d.ts +7 -0
- package/dist/blocks/block-richtext.js +1 -0
- package/dist/blocks/block-steps.d.ts +21 -0
- package/dist/blocks/block-steps.js +1 -0
- package/dist/blocks/block-team.d.ts +6 -0
- package/dist/blocks/block-team.js +1 -0
- package/dist/blocks/block-testimonial.d.ts +13 -0
- package/dist/blocks/block-testimonial.js +1 -0
- package/dist/blocks/block-video.d.ts +9 -0
- package/dist/blocks/block-video.js +1 -0
- package/dist/blocks/block.d.ts +17 -0
- package/dist/blocks/block.js +1 -0
- package/dist/blocks/index.d.ts +18 -0
- package/dist/blocks/index.js +1 -0
- package/dist/componentMap.d.ts +6 -0
- package/dist/componentMap.js +8 -0
- package/dist/content/category.d.ts +10 -0
- package/dist/content/category.js +1 -0
- package/dist/content/form.d.ts +21 -0
- package/dist/content/form.js +1 -0
- package/dist/content/index.d.ts +6 -0
- package/dist/content/index.js +1 -0
- package/dist/content/page.d.ts +38 -0
- package/dist/content/page.js +1 -0
- package/dist/content/post.d.ts +38 -0
- package/dist/content/post.js +1 -0
- package/dist/content/team.d.ts +17 -0
- package/dist/content/team.js +1 -0
- package/dist/content/testimonial.d.ts +18 -0
- package/dist/content/testimonial.js +1 -0
- package/dist/help/index.d.ts +51 -0
- package/dist/help/index.js +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +1 -0
- package/dist/meta/analytics.d.ts +21 -0
- package/dist/meta/analytics.js +1 -0
- package/dist/meta/config.d.ts +22 -0
- package/dist/meta/config.js +1 -0
- package/dist/meta/globals.d.ts +33 -0
- package/dist/meta/globals.js +1 -0
- package/dist/meta/index.d.ts +6 -0
- package/dist/meta/index.js +1 -0
- package/dist/meta/navigation.d.ts +31 -0
- package/dist/meta/navigation.js +1 -0
- package/dist/meta/redirect.d.ts +12 -0
- package/dist/meta/redirect.js +1 -0
- package/dist/meta/seo.d.ts +19 -0
- package/dist/meta/seo.js +1 -0
- package/dist/os/contact.d.ts +22 -0
- package/dist/os/contact.js +1 -0
- package/dist/os/conversation.d.ts +23 -0
- package/dist/os/conversation.js +1 -0
- package/dist/os/index.d.ts +16 -0
- package/dist/os/index.js +1 -0
- package/dist/os/organization.d.ts +51 -0
- package/dist/os/organization.js +1 -0
- package/dist/os/os-activity.d.ts +26 -0
- package/dist/os/os-activity.js +1 -0
- package/dist/os/os-deal.d.ts +42 -0
- package/dist/os/os-deal.js +1 -0
- package/dist/os/os-expense.d.ts +21 -0
- package/dist/os/os-expense.js +1 -0
- package/dist/os/os-invoice.d.ts +46 -0
- package/dist/os/os-invoice.js +1 -0
- package/dist/os/os-item.d.ts +17 -0
- package/dist/os/os-item.js +1 -0
- package/dist/os/os-payment.d.ts +27 -0
- package/dist/os/os-payment.js +1 -0
- package/dist/os/os-project.d.ts +45 -0
- package/dist/os/os-project.js +1 -0
- package/dist/os/os-proposal.d.ts +61 -0
- package/dist/os/os-proposal.js +1 -0
- package/dist/os/os-settings.d.ts +17 -0
- package/dist/os/os-settings.js +1 -0
- package/dist/os/os-subscription.d.ts +12 -0
- package/dist/os/os-subscription.js +1 -0
- package/dist/os/os-task.d.ts +32 -0
- package/dist/os/os-task.js +1 -0
- package/dist/os/os-tax-rate.d.ts +12 -0
- package/dist/os/os-tax-rate.js +1 -0
- package/dist/pageComponentMap.d.ts +2 -0
- package/dist/pageComponentMap.js +7 -0
- package/dist/schema.d.ts +78 -0
- package/dist/schema.js +1 -0
- package/dist/system/file.d.ts +47 -0
- package/dist/system/file.js +1 -0
- package/dist/system/folder.d.ts +8 -0
- package/dist/system/folder.js +1 -0
- package/dist/system/index.d.ts +4 -0
- package/dist/system/index.js +1 -0
- package/dist/system/role.d.ts +20 -0
- package/dist/system/role.js +1 -0
- package/dist/system/user.d.ts +57 -0
- package/dist/system/user.js +1 -0
- package/nuxt.config.ts +5 -0
- package/package.json +42 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :style="'width: ' + fieldWidth + '; display:flex; align-items:flex-start; gap:8px'">
|
|
3
|
+
<client-only>
|
|
4
|
+
<tiptap-editor :name="field" v-model="textAreaValue" rows="12" :required="required" :label="label" style="flex:1" />
|
|
5
|
+
</client-only>
|
|
6
|
+
<span v-if="props.autoGenerated" class="auto-badge">Auto</span>
|
|
7
|
+
</div>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script setup lang="ts">
|
|
11
|
+
import {
|
|
12
|
+
computed
|
|
13
|
+
} from 'vue'
|
|
14
|
+
import TiptapEditor from './TiptapEditor.vue'
|
|
15
|
+
|
|
16
|
+
const props = withDefaults(defineProps < {
|
|
17
|
+
defaultValue ? : string
|
|
18
|
+
label ? : string
|
|
19
|
+
width ? : string | null
|
|
20
|
+
field: string
|
|
21
|
+
required ? : boolean
|
|
22
|
+
options ? : Record < string,
|
|
23
|
+
any > | null
|
|
24
|
+
modelValue ? : string
|
|
25
|
+
autoGenerated ? : boolean
|
|
26
|
+
} > (), {
|
|
27
|
+
required: false,
|
|
28
|
+
options: null,
|
|
29
|
+
width: null,
|
|
30
|
+
autoGenerated: false,
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const emit = defineEmits(['update:modelValue'])
|
|
34
|
+
|
|
35
|
+
const fieldWidth = props.width === 'full' ? '100%' : '50%'
|
|
36
|
+
|
|
37
|
+
const textAreaValue = computed({
|
|
38
|
+
get() {
|
|
39
|
+
return props.modelValue || props.defaultValue || ''
|
|
40
|
+
},
|
|
41
|
+
set(value) {
|
|
42
|
+
emit('update:modelValue', value)
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<style scoped>
|
|
48
|
+
.auto-badge {
|
|
49
|
+
font-size: 12px;
|
|
50
|
+
padding: 4px 6px;
|
|
51
|
+
border-radius: 4px;
|
|
52
|
+
background: #eee;
|
|
53
|
+
color: #333
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
textarea {
|
|
57
|
+
width: 100%
|
|
58
|
+
}
|
|
59
|
+
</style>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const props = withDefaults(defineProps<{
|
|
3
|
+
defaultValue?: string
|
|
4
|
+
label?: string
|
|
5
|
+
options?: Record<string, any> | null
|
|
6
|
+
width?: string | null
|
|
7
|
+
field: string
|
|
8
|
+
required?: boolean
|
|
9
|
+
modelValue?: string
|
|
10
|
+
autoGenerated?: boolean
|
|
11
|
+
}>(), {
|
|
12
|
+
required: false,
|
|
13
|
+
options: null,
|
|
14
|
+
width: null,
|
|
15
|
+
autoGenerated: false,
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const emit = defineEmits(['update:modelValue'])
|
|
19
|
+
|
|
20
|
+
const fieldWidth = props.width === 'full' ? '100%' : '50%'
|
|
21
|
+
|
|
22
|
+
const inputValue = computed({
|
|
23
|
+
get() {
|
|
24
|
+
return props.modelValue || props.defaultValue || ''
|
|
25
|
+
},
|
|
26
|
+
set(value) {
|
|
27
|
+
emit('update:modelValue', value)
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<template>
|
|
33
|
+
<div :style="'width: ' + fieldWidth + '; display:flex; align-items:center; gap:8px'">
|
|
34
|
+
<v-text-field :name="field" v-model="inputValue" type="text" :label="label" :required="required" style="flex:1" />
|
|
35
|
+
<span v-if="props.autoGenerated" class="auto-badge">Auto</span>
|
|
36
|
+
</div>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<style scoped>
|
|
40
|
+
.auto-badge{font-size:12px;padding:4px 6px;border-radius:4px;background:#eee;color:#333}
|
|
41
|
+
input {width:100%;}
|
|
42
|
+
</style>
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<div v-if="editor">
|
|
4
|
+
<button
|
|
5
|
+
@click="editor.chain().focus().toggleBold().run()"
|
|
6
|
+
:disabled="!editor.can().chain().focus().toggleBold().run()"
|
|
7
|
+
:class="{ 'is-active': editor.isActive('bold') }"
|
|
8
|
+
>
|
|
9
|
+
bold
|
|
10
|
+
</button>
|
|
11
|
+
<button
|
|
12
|
+
@click="editor.chain().focus().toggleItalic().run()"
|
|
13
|
+
:disabled="!editor.can().chain().focus().toggleItalic().run()"
|
|
14
|
+
:class="{ 'is-active': editor.isActive('italic') }"
|
|
15
|
+
>
|
|
16
|
+
italic
|
|
17
|
+
</button>
|
|
18
|
+
<button
|
|
19
|
+
@click="editor.chain().focus().toggleStrike().run()"
|
|
20
|
+
:disabled="!editor.can().chain().focus().toggleStrike().run()"
|
|
21
|
+
:class="{ 'is-active': editor.isActive('strike') }"
|
|
22
|
+
>
|
|
23
|
+
strike
|
|
24
|
+
</button>
|
|
25
|
+
<button
|
|
26
|
+
@click="editor.chain().focus().toggleCode().run()"
|
|
27
|
+
:disabled="!editor.can().chain().focus().toggleCode().run()"
|
|
28
|
+
:class="{ 'is-active': editor.isActive('code') }"
|
|
29
|
+
>
|
|
30
|
+
code
|
|
31
|
+
</button>
|
|
32
|
+
<button @click="editor.chain().focus().unsetAllMarks().run()">
|
|
33
|
+
clear marks
|
|
34
|
+
</button>
|
|
35
|
+
<button @click="editor.chain().focus().clearNodes().run()">
|
|
36
|
+
clear nodes
|
|
37
|
+
</button>
|
|
38
|
+
<button
|
|
39
|
+
@click="editor.chain().focus().setParagraph().run()"
|
|
40
|
+
:class="{ 'is-active': editor.isActive('paragraph') }"
|
|
41
|
+
>
|
|
42
|
+
paragraph
|
|
43
|
+
</button>
|
|
44
|
+
<button
|
|
45
|
+
@click="editor.chain().focus().toggleHeading({ level: 1 }).run()"
|
|
46
|
+
:class="{ 'is-active': editor.isActive('heading', { level: 1 }) }"
|
|
47
|
+
>
|
|
48
|
+
h1
|
|
49
|
+
</button>
|
|
50
|
+
<button
|
|
51
|
+
@click="editor.chain().focus().toggleHeading({ level: 2 }).run()"
|
|
52
|
+
:class="{ 'is-active': editor.isActive('heading', { level: 2 }) }"
|
|
53
|
+
>
|
|
54
|
+
h2
|
|
55
|
+
</button>
|
|
56
|
+
<button
|
|
57
|
+
@click="editor.chain().focus().toggleHeading({ level: 3 }).run()"
|
|
58
|
+
:class="{ 'is-active': editor.isActive('heading', { level: 3 }) }"
|
|
59
|
+
>
|
|
60
|
+
h3
|
|
61
|
+
</button>
|
|
62
|
+
<button
|
|
63
|
+
@click="editor.chain().focus().toggleHeading({ level: 4 }).run()"
|
|
64
|
+
:class="{ 'is-active': editor.isActive('heading', { level: 4 }) }"
|
|
65
|
+
>
|
|
66
|
+
h4
|
|
67
|
+
</button>
|
|
68
|
+
<button
|
|
69
|
+
@click="editor.chain().focus().toggleHeading({ level: 5 }).run()"
|
|
70
|
+
:class="{ 'is-active': editor.isActive('heading', { level: 5 }) }"
|
|
71
|
+
>
|
|
72
|
+
h5
|
|
73
|
+
</button>
|
|
74
|
+
<button
|
|
75
|
+
@click="editor.chain().focus().toggleHeading({ level: 6 }).run()"
|
|
76
|
+
:class="{ 'is-active': editor.isActive('heading', { level: 6 }) }"
|
|
77
|
+
>
|
|
78
|
+
h6
|
|
79
|
+
</button>
|
|
80
|
+
<button
|
|
81
|
+
@click="editor.chain().focus().toggleBulletList().run()"
|
|
82
|
+
:class="{ 'is-active': editor.isActive('bulletList') }"
|
|
83
|
+
>
|
|
84
|
+
bullet list
|
|
85
|
+
</button>
|
|
86
|
+
<button
|
|
87
|
+
@click="editor.chain().focus().toggleOrderedList().run()"
|
|
88
|
+
:class="{ 'is-active': editor.isActive('orderedList') }"
|
|
89
|
+
>
|
|
90
|
+
ordered list
|
|
91
|
+
</button>
|
|
92
|
+
<button
|
|
93
|
+
@click="editor.chain().focus().toggleCodeBlock().run()"
|
|
94
|
+
:class="{ 'is-active': editor.isActive('codeBlock') }"
|
|
95
|
+
>
|
|
96
|
+
code block
|
|
97
|
+
</button>
|
|
98
|
+
<button
|
|
99
|
+
@click="editor.chain().focus().toggleBlockquote().run()"
|
|
100
|
+
:class="{ 'is-active': editor.isActive('blockquote') }"
|
|
101
|
+
>
|
|
102
|
+
blockquote
|
|
103
|
+
</button>
|
|
104
|
+
<button @click="editor.chain().focus().setHorizontalRule().run()">
|
|
105
|
+
horizontal rule
|
|
106
|
+
</button>
|
|
107
|
+
<button @click="editor.chain().focus().setHardBreak().run()">
|
|
108
|
+
hard break
|
|
109
|
+
</button>
|
|
110
|
+
<button
|
|
111
|
+
@click="editor.chain().focus().undo().run()"
|
|
112
|
+
:disabled="!editor.can().chain().focus().undo().run()"
|
|
113
|
+
>
|
|
114
|
+
undo
|
|
115
|
+
</button>
|
|
116
|
+
<button
|
|
117
|
+
@click="editor.chain().focus().redo().run()"
|
|
118
|
+
:disabled="!editor.can().chain().focus().redo().run()"
|
|
119
|
+
>
|
|
120
|
+
redo
|
|
121
|
+
</button>
|
|
122
|
+
</div>
|
|
123
|
+
<TiptapEditorContent :editor="editor" />
|
|
124
|
+
</div>
|
|
125
|
+
</template>
|
|
126
|
+
|
|
127
|
+
<script setup>
|
|
128
|
+
const editor = useEditor({
|
|
129
|
+
content: "<p>Type something here. 🎉</p>",
|
|
130
|
+
extensions: [TiptapStarterKit],
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
onBeforeUnmount(() => {
|
|
134
|
+
unref(editor).destroy();
|
|
135
|
+
});
|
|
136
|
+
</script>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import AutoForm from '~/components/forms/DynamicForm.vue'
|
|
3
|
+
import { useDirectusSchema } from '@/layers/ui-app/app/composables/globals/useDirectusSchema.js'
|
|
4
|
+
|
|
5
|
+
const route = useRoute()
|
|
6
|
+
const collection = route.params.collection
|
|
7
|
+
|
|
8
|
+
const { data: schema } = await useAsyncData(
|
|
9
|
+
`schema-${collection}`,
|
|
10
|
+
() => useDirectusSchema(collection)
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
const formData = ref({})
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<template>
|
|
17
|
+
<div>
|
|
18
|
+
<h1>Dynamic Form for {{ collection }}</h1>
|
|
19
|
+
<AutoForm :schema="schema" v-model="formData" />
|
|
20
|
+
<pre>{{ formData }}</pre>
|
|
21
|
+
</div>
|
|
22
|
+
</template>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="cnt">
|
|
3
|
+
<div class="cnt-nav">Meeovi Studio</div>
|
|
4
|
+
<div class="cnt-body">
|
|
5
|
+
<div class="editor" ref="editorEl"></div>
|
|
6
|
+
</div>
|
|
7
|
+
</div>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script setup lang="ts">
|
|
11
|
+
import createStudioEditor from '@grapesjs/studio-sdk';
|
|
12
|
+
import '@grapesjs/studio-sdk/dist/style.css';
|
|
13
|
+
|
|
14
|
+
const editorEl = ref(null);
|
|
15
|
+
|
|
16
|
+
onMounted(() => {
|
|
17
|
+
createStudioEditor({
|
|
18
|
+
root: editorEl.value,
|
|
19
|
+
plugins: [(editor) => console.log('editor created!', editor)],
|
|
20
|
+
licenseKey: 'YOUR_LICENSE_KEY',
|
|
21
|
+
project: {
|
|
22
|
+
default: {
|
|
23
|
+
pages: [
|
|
24
|
+
{
|
|
25
|
+
name: 'Home',
|
|
26
|
+
component: `<h1 style="padding: 2rem; text-align: center">
|
|
27
|
+
Hello Studio 👋
|
|
28
|
+
</h1>`,
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<style>
|
|
38
|
+
body {
|
|
39
|
+
margin: 0;
|
|
40
|
+
}
|
|
41
|
+
.cnt {
|
|
42
|
+
display: flex;
|
|
43
|
+
flex-direction: column;
|
|
44
|
+
height: 100dvh;
|
|
45
|
+
}
|
|
46
|
+
.cnt-nav {
|
|
47
|
+
padding: 10px;
|
|
48
|
+
background-color: #020420;
|
|
49
|
+
color: #00dc82;
|
|
50
|
+
}
|
|
51
|
+
.cnt-body {
|
|
52
|
+
flex-grow: 1;
|
|
53
|
+
}
|
|
54
|
+
.editor {
|
|
55
|
+
height: 100%;
|
|
56
|
+
}
|
|
57
|
+
</style>
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="cnt">
|
|
3
|
+
<div class="cnt-nav">Meeovi Studio</div>
|
|
4
|
+
<div class="cnt-body">
|
|
5
|
+
<div class="editor" ref="editorEl"></div>
|
|
6
|
+
</div>
|
|
7
|
+
</div>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script setup lang="ts">
|
|
11
|
+
import createStudioEditor from '@grapesjs/studio-sdk';
|
|
12
|
+
import '@grapesjs/studio-sdk/dist/style.css';
|
|
13
|
+
import { presetPrintable, canvasFullSize } from '@grapesjs/studio-sdk-plugins';
|
|
14
|
+
|
|
15
|
+
const editorEl = ref(null);
|
|
16
|
+
|
|
17
|
+
onMounted(() => {
|
|
18
|
+
createStudioEditor({
|
|
19
|
+
root: editorEl.value,
|
|
20
|
+
plugins: [
|
|
21
|
+
presetPrintable,
|
|
22
|
+
canvasFullSize, // Optional
|
|
23
|
+
],
|
|
24
|
+
licenseKey: 'YOUR_LICENSE_KEY',
|
|
25
|
+
project: {
|
|
26
|
+
type: 'document', // Ensure the project type is set to 'document'
|
|
27
|
+
default: {
|
|
28
|
+
pages: [{
|
|
29
|
+
name: 'Invoice',
|
|
30
|
+
component: `<!DOCTYPE html>
|
|
31
|
+
<html>
|
|
32
|
+
<body style="padding: 40px; font-family: Arial, Helvetica, sans-serif">
|
|
33
|
+
<h1>New Document</h1>
|
|
34
|
+
<p>Content of the document.</p>
|
|
35
|
+
</body>
|
|
36
|
+
<html>
|
|
37
|
+
`,
|
|
38
|
+
}],
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<style>
|
|
46
|
+
body {
|
|
47
|
+
margin: 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.cnt {
|
|
51
|
+
display: flex;
|
|
52
|
+
flex-direction: column;
|
|
53
|
+
height: 100dvh;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.cnt-nav {
|
|
57
|
+
padding: 10px;
|
|
58
|
+
background-color: #020420;
|
|
59
|
+
color: #00dc82;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.cnt-body {
|
|
63
|
+
flex-grow: 1;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.editor {
|
|
67
|
+
height: 100%;
|
|
68
|
+
}
|
|
69
|
+
</style>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="cnt">
|
|
3
|
+
<div class="cnt-nav">Meeovi Studio</div>
|
|
4
|
+
<div class="cnt-body">
|
|
5
|
+
<div class="editor" ref="editorEl"></div>
|
|
6
|
+
</div>
|
|
7
|
+
</div>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script setup lang="ts">
|
|
11
|
+
import createStudioEditor from '@grapesjs/studio-sdk';
|
|
12
|
+
import '@grapesjs/studio-sdk/dist/style.css';
|
|
13
|
+
|
|
14
|
+
const editorEl = ref(null);
|
|
15
|
+
|
|
16
|
+
onMounted(() => {
|
|
17
|
+
createStudioEditor({
|
|
18
|
+
root: editorEl.value,
|
|
19
|
+
plugins: [(editor) => console.log('editor created!', editor)],
|
|
20
|
+
licenseKey: 'YOUR_LICENSE_KEY',
|
|
21
|
+
project: {
|
|
22
|
+
type: 'email',
|
|
23
|
+
default: {
|
|
24
|
+
pages: [{
|
|
25
|
+
component: '<mjml><mj-body><mj-section><mj-column><mj-text>My email</mj-text></mj-column></mj-section></mj-body></mjml>'
|
|
26
|
+
}, ],
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<style>
|
|
34
|
+
body {
|
|
35
|
+
margin: 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.cnt {
|
|
39
|
+
display: flex;
|
|
40
|
+
flex-direction: column;
|
|
41
|
+
height: 100dvh;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.cnt-nav {
|
|
45
|
+
padding: 10px;
|
|
46
|
+
background-color: #020420;
|
|
47
|
+
color: #00dc82;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.cnt-body {
|
|
51
|
+
flex-grow: 1;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.editor {
|
|
55
|
+
height: 100%;
|
|
56
|
+
}
|
|
57
|
+
</style>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { uploadFiles } from '@meeovi/directus-client';
|
|
2
|
+
|
|
3
|
+
export default async function uploadFile({ imageFile, documentFile, videoFile, audioFile }) {
|
|
4
|
+
const { $directus } = useNuxtApp();
|
|
5
|
+
const uploadedFiles = {};
|
|
6
|
+
|
|
7
|
+
try {
|
|
8
|
+
if (imageFile) {
|
|
9
|
+
const formDataImage = new FormData();
|
|
10
|
+
formDataImage.append('file', imageFile);
|
|
11
|
+
const uploadedImage = await $directus.request(uploadFiles(formDataImage));
|
|
12
|
+
uploadedFiles.imageId = uploadedImage.id;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (documentFile) {
|
|
16
|
+
const formDataDocument = new FormData();
|
|
17
|
+
formDataDocument.append('file', documentFile);
|
|
18
|
+
const uploadedDocument = await $directus.request(uploadFiles(formDataDocument));
|
|
19
|
+
uploadedFiles.documentId = uploadedDocument.id;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (videoFile) {
|
|
23
|
+
const formDataVideo = new FormData();
|
|
24
|
+
formDataVideo.append('file', videoFile);
|
|
25
|
+
const uploadedVideo = await $directus.request(uploadFiles(formDataVideo));
|
|
26
|
+
uploadedFiles.videoId = uploadedVideo.id;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (audioFile) {
|
|
30
|
+
const formDataAudio = new FormData();
|
|
31
|
+
formDataAudio.append('file', audioFile);
|
|
32
|
+
const uploadedAudio = await $directus.request(uploadFiles(formDataAudio));
|
|
33
|
+
uploadedFiles.audioId = uploadedAudio.id;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return uploadedFiles;
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.error('Error uploading files:', error);
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AdminTable } from '#components'
|
|
2
|
+
import type { ComponentExposed } from 'vue-component-type-helpers'
|
|
3
|
+
|
|
4
|
+
export function useAdminTable(refName: string = 'table') {
|
|
5
|
+
const adminTableRef = useTemplateRef<ComponentExposed<typeof AdminTable>>(refName)
|
|
6
|
+
const refresh = () => {
|
|
7
|
+
adminTableRef.value?.fetchTableData()
|
|
8
|
+
}
|
|
9
|
+
return {
|
|
10
|
+
refresh
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { UseFetchOptions } from '#imports'
|
|
2
|
+
|
|
3
|
+
export function useCustomFetch<T>(
|
|
4
|
+
url: string | Request | Ref<string | Request> | (() => string | Request),
|
|
5
|
+
options: UseFetchOptions<T> = {}
|
|
6
|
+
) {
|
|
7
|
+
return {
|
|
8
|
+
...useFetch(url, {
|
|
9
|
+
...options,
|
|
10
|
+
$fetch: useNuxtApp().$customFetch
|
|
11
|
+
})
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { ref, computed, watch } from "vue"
|
|
2
|
+
import Input from "~/components/ui/forms/TextInput.vue"
|
|
3
|
+
import TextArea from "~/components/ui/forms/TextArea.vue"
|
|
4
|
+
import Select from "~/components/ui/forms/SelectInput.vue"
|
|
5
|
+
import DateTime from "~/components/ui/forms/DateTime.vue"
|
|
6
|
+
import FileInput from "~/components/ui/forms/FileInput.vue"
|
|
7
|
+
import BooleanInput from "~/components/ui/forms/BooleanInput.vue"
|
|
8
|
+
import RelationSelect from "~/components/ui/forms/RelationSelect.vue"
|
|
9
|
+
import RepeaterInput from "~/components/ui/forms/RepeaterInput.vue"
|
|
10
|
+
import TiptapEditor from "~/components/ui/forms/TiptapEditor.vue"
|
|
11
|
+
|
|
12
|
+
export function useDirectusField(field: any, modelValue: any, emit: any, formContext?: any) {
|
|
13
|
+
const internalValue = computed({
|
|
14
|
+
get: () => modelValue,
|
|
15
|
+
set: (v) => emit("update:modelValue", v),
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const previousAuto = ref<string | null>(null)
|
|
19
|
+
const internalAuto = computed(() => {
|
|
20
|
+
return previousAuto.value != null && internalValue.value === previousAuto.value
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
const slugify = (val: string) =>
|
|
24
|
+
String(val || "")
|
|
25
|
+
.toLowerCase()
|
|
26
|
+
.normalize("NFKD")
|
|
27
|
+
.replace(/\s+/g, "-")
|
|
28
|
+
.replace(/[^a-z0-9\-]/g, "")
|
|
29
|
+
.replace(/-+/g, "-")
|
|
30
|
+
.replace(/^-|-$/g, "")
|
|
31
|
+
|
|
32
|
+
const isAliasField = computed(() => {
|
|
33
|
+
const meta = field?.meta ?? {}
|
|
34
|
+
return (
|
|
35
|
+
meta.interface === "alias" ||
|
|
36
|
+
(meta.options && (meta.options.source || meta.options.from))
|
|
37
|
+
)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
if (isAliasField.value && formContext && formContext.form) {
|
|
41
|
+
const meta = field?.meta ?? {}
|
|
42
|
+
let sourceField: string | null = meta?.options?.source ?? meta?.options?.from ?? null
|
|
43
|
+
|
|
44
|
+
if (!sourceField && formContext.fields) {
|
|
45
|
+
const candidates = ["name", "title"]
|
|
46
|
+
sourceField =
|
|
47
|
+
candidates.find((c: string) =>
|
|
48
|
+
formContext.fields.value.some((f: any) => f.field === c)
|
|
49
|
+
) ?? null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (sourceField) {
|
|
53
|
+
watch(
|
|
54
|
+
() => formContext.form.value?.[sourceField as string],
|
|
55
|
+
(newVal) => {
|
|
56
|
+
const target = field.field
|
|
57
|
+
const current = formContext.form.value?.[target] ?? ""
|
|
58
|
+
const generated = slugify(String(newVal ?? ""))
|
|
59
|
+
|
|
60
|
+
if (!generated) return
|
|
61
|
+
|
|
62
|
+
// Case 1: Empty or previously auto‑generated → regenerate
|
|
63
|
+
if (!current || current === previousAuto.value) {
|
|
64
|
+
formContext.form.value[target] = generated
|
|
65
|
+
internalValue.value = generated
|
|
66
|
+
previousAuto.value = generated
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{ immediate: true }
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
// Watch the target itself: if cleared, regenerate
|
|
73
|
+
watch(
|
|
74
|
+
() => formContext.form.value?.[field.field],
|
|
75
|
+
(newVal) => {
|
|
76
|
+
if (!newVal) {
|
|
77
|
+
const sourceVal = formContext.form.value?.[sourceField as string] ?? ""
|
|
78
|
+
const regenerated = slugify(String(sourceVal))
|
|
79
|
+
if (regenerated) {
|
|
80
|
+
formContext.form.value[field.field] = regenerated
|
|
81
|
+
internalValue.value = regenerated
|
|
82
|
+
previousAuto.value = regenerated
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// --- Label prettifier ---
|
|
91
|
+
const prettify = (s: string) =>
|
|
92
|
+
s.replace(/_/g, " ")
|
|
93
|
+
.split(" ")
|
|
94
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
95
|
+
.join(" ")
|
|
96
|
+
|
|
97
|
+
const label = computed(() => {
|
|
98
|
+
const raw = field?.meta?.field ?? field?.field ?? ""
|
|
99
|
+
return prettify(raw)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
// --- Field lookup ---
|
|
103
|
+
const fieldLookup = computed(() => {
|
|
104
|
+
const iface = field?.meta?.interface
|
|
105
|
+
const name = String(iface ?? "").toLowerCase()
|
|
106
|
+
|
|
107
|
+
if (["input", "string"].includes(name)) return Input
|
|
108
|
+
if (
|
|
109
|
+
["textarea", "wysiwyg", "rich-text", "input-multiline", "input-rich-text", "input-rich-text-md"].includes(name)
|
|
110
|
+
)
|
|
111
|
+
return TiptapEditor
|
|
112
|
+
if (["select", "select-dropdown", "select-multiple"].includes(name)) return Select
|
|
113
|
+
if (name === "datetime") return DateTime
|
|
114
|
+
if (["file", "files", "file-image"].includes(name)) return FileInput
|
|
115
|
+
if (name === "boolean") return BooleanInput
|
|
116
|
+
if (name.includes("many") || name.includes("one") || name.includes("to")) return RelationSelect
|
|
117
|
+
return Input
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
const required = computed(() => {
|
|
121
|
+
const meta = field?.meta ?? {}
|
|
122
|
+
return Boolean(meta?.validation?.required ?? meta?.required ?? false)
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
const safeOptions = computed(() => field?.meta?.options ?? null)
|
|
126
|
+
const defaultValue = computed(() => field?.schema?.default_value ?? null)
|
|
127
|
+
const isMultiple = computed(() => {
|
|
128
|
+
const name = String(field?.meta?.interface ?? "").toLowerCase()
|
|
129
|
+
if (name === "select-multiple") return true
|
|
130
|
+
if (name.includes("many")) return true
|
|
131
|
+
return Boolean(field?.meta?.options?.multiple || false)
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
internalValue,
|
|
136
|
+
internalAuto,
|
|
137
|
+
label,
|
|
138
|
+
fieldLookup,
|
|
139
|
+
required,
|
|
140
|
+
safeOptions,
|
|
141
|
+
defaultValue,
|
|
142
|
+
isMultiple,
|
|
143
|
+
}
|
|
144
|
+
}
|