Начните использовать BlockBuilder с Vue3 - готовый UI и полная интеграция с Vue компонентами
Установите BlockBuilder и убедитесь, что у вас установлен Vue 3:
npm install @mushket-co/block-builderДля TypeScript добавьте типы: npm install -D @types/node
Основной Vue компонент, который предоставляет готовый UI для управления блоками
Vue компоненты, которые используются для рендеринга конкретных типов блоков
Конфигурация с доступными типами блоков, их полями и компонентами
События для отслеживания создания, обновления и удаления блоков
Создайте компонент блока и подключите BlockBuilderComponent:
Важно: Margin автоматически применяется на UI блок-обертку над компонентом. Для padding используйте CSS переменные, которые устанавливаются автоматически.
<!-- components/TextBlock.vue -->
<template>
<div class="text-block">
<div v-html="block.props.content"></div>
</div>
</template>
<script setup>
const props = defineProps({
block: {
type: Object,
required: true
}
})
</script>
<style scoped>
.text-block {
/* Используем CSS переменные для padding из spacing */
/* Переменные автоматически устанавливаются на .block-builder-block обертке */
padding-top: var(--spacing-padding-top, 1rem);
padding-bottom: var(--spacing-padding-bottom, 1rem);
/* Дополнительные стили вашего компонента */
padding-left: 1rem;
padding-right: 1rem;
}
</style><template>
<BlockBuilderComponent
:config="config"
@block-created="handleBlockCreated"
@block-updated="handleBlockUpdated"
@block-deleted="handleBlockDeleted"
/>
</template>
<script setup>
import { BlockBuilderComponent } from '@mushket-co/block-builder/vue'
import TextBlock from './components/TextBlock.vue'
const config = {
availableBlockTypes: [
{
type: 'text',
label: 'Текстовый блок',
render: {
kind: 'component',
framework: 'vue',
component: TextBlock
},
fields: [
{
name: 'content',
label: 'Содержимое',
type: 'textarea',
required: true,
defaultValue: '<p>Привет, мир!</p>'
}
],
defaultProps: {
content: '<p>Привет, мир!</p>'
},
spacingOptions: {
enabled: true,
spacingTypes: ['padding-top', 'padding-bottom', 'margin-top', 'margin-bottom']
}
}
],
}
const handleBlockCreated = (block) => {
console.log('Блок создан:', block)
}
const handleBlockUpdated = (block) => {
console.log('Блок обновлен:', block)
}
const handleBlockDeleted = (blockId) => {
console.log('Блок удален:', blockId)
}
</script>Вы можете определить несколько типов блоков с разными компонентами и полями:
<script setup>
import { BlockBuilderComponent } from '@mushket-co/block-builder/vue'
import TextBlock from './components/TextBlock.vue'
import ImageBlock from './components/ImageBlock.vue'
import ButtonBlock from './components/ButtonBlock.vue'
const config = {
availableBlockTypes: [
{
type: 'text',
label: 'Текстовый блок',
render: {
kind: 'component',
framework: 'vue',
component: TextBlock
},
fields: [
{
name: 'content',
label: 'Содержимое',
type: 'textarea',
required: true
},
{
name: 'textAlign',
label: 'Выравнивание',
type: 'select',
options: [
{ value: 'left', label: 'Слева' },
{ value: 'center', label: 'По центру' },
{ value: 'right', label: 'Справа' }
]
}
]
},
{
type: 'image',
label: 'Изображение',
render: {
kind: 'component',
framework: 'vue',
component: ImageBlock
},
fields: [
{
name: 'image',
label: 'Изображение',
type: 'image',
required: true,
imageUploadConfig: {
uploadUrl: '/api/upload',
maxFileSize: 5 * 1024 * 1024,
accept: 'image/*',
responseMapper: (response) => ({
src: response.url
})
}
},
{
name: 'alt',
label: 'Альтернативный текст',
type: 'text'
},
{
name: 'width',
label: 'Ширина',
type: 'number',
defaultValue: 100
}
]
},
{
type: 'button',
label: 'Кнопка',
render: {
kind: 'component',
framework: 'vue',
component: ButtonBlock
},
fields: [
{
name: 'text',
label: 'Текст кнопки',
type: 'text',
required: true
},
{
name: 'url',
label: 'Ссылка',
type: 'url'
},
{
name: 'variant',
label: 'Стиль',
type: 'select',
options: [
{ value: 'primary', label: 'Основной' },
{ value: 'secondary', label: 'Вторичный' },
{ value: 'outline', label: 'Обводка' }
]
}
]
}
],
}
</script>Важно: При использовании uploadUrl (загрузка через сервер API клиента) ответ сервера ОБЯЗАТЕЛЬНО должен быть объектом с полемsrc, содержащим URL изображения. Если формат ответа отличается, используйтеresponseMapper для преобразования ответа к виду объекта с вашими полями и обязательным полем src.
BlockBuilder поддерживает два режима работы. Используйте проп isEdit для управления режимом:
<template>
<!-- Режим редактирования (по умолчанию) -->
<BlockBuilderComponent
:config="config"
:isEdit="true"
/>
<!-- Режим только просмотра -->
<BlockBuilderComponent
:config="config"
:isEdit="false"
/>
</template>
<script setup>
import { BlockBuilderComponent } from '@mushket-co/block-builder/vue'
const config = {
availableBlockTypes: [
// ваша конфигурация
],
}
</script>body автоматически добавляется/удаляется CSS класс bb-is-edit-modespacingOptions.enabled: true. Margin применяется автоматически на UI блок-обертку, для padding используйте CSS переменные: --spacing-padding-top и --spacing-padding-bottomblock с полями id, type, props, settingsonSave для сохранения блоков (localStorage для разработки или API для продакшена):isEdit="false" для отображения блоков в режиме только просмотра без возможности редактирования