const svgText = `<svg style="width:48px;height:48px" viewBox="0 0 24 24"> <path fill="currentColor" d="M18.5,4L19.66,8.35L18.7,8.61C18.25,7.74 17.79,6.87 17.26,6.43C16.73,6 16.11,6 15.5,6H13V16.5C13,17 13,17.5 13.33,17.75C13.67,18 14.33,18 15,18V19H9V18C9.67,18 10.33,18 10.67,17.75C11,17.5 11,17 11,16.5V6H8.5C7.89,6 7.27,6 6.74,6.43C6.21,6.87 5.75,7.74 5.3,8.61L4.34,8.35L5.5,4H18.5Z" /> </svg>`; const svgLink = `<svg style="width:48px;height:48px" viewBox="0 0 24 24"> <path fill="currentColor" d="M3.9,12C3.9,10.29 5.29,8.9 7,8.9H11V7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H11V15.1H7C5.29,15.1 3.9,13.71 3.9,12M8,13H16V11H8V13M17,7H13V8.9H17C18.71,8.9 20.1,10.29 20.1,12C20.1,13.71 18.71,15.1 17,15.1H13V17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7Z" /> </svg>`; const svgImage = `<svg style="width:48px;height:48px" viewBox="0 0 24 24"> <path fill="currentColor" d="M8.5,13.5L11,16.5L14.5,12L19,18H5M21,19V5C21,3.89 20.1,3 19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19Z" /> </svg>`; const blocks = [ { id: 'text', label: 'Text', category: 'Basic', media: svgText, activate: true, content: { type: 'text', content: 'Insert your text here', style: { padding: '10px' }, } },{ id: 'link', label: 'Link', category: 'Basic', media: svgLink, activate: true, content: { type: 'link', content: 'Insert your link here', style: { color: '#d983a6' } } }, { id: 'image', label: 'Image', category: 'Basic', media: svgImage, activate: true, content: { type: 'image' } } ]; const editor = grapesjs.init({ container: '#gjs', fromElement: true, height: '100%', storageManager: false, noticeOnUnload: false, blockManager: { custom: true, blocks, }, }); // Open the default Block Manager container const { Panels } = editor; Panels.getButton('views', 'open-sm').set('active', false); Panels.getButton('views', 'open-blocks').set('active', true); // Load the Vue app const app = new Vue({ el: '.blocks-wrp', data: { blocks: [] }, mounted() { editor.on('block:custom', this.handleBlocks); }, destroyed() { editor.off('block:custom', this.handleBlocks); }, methods: { handleBlocks(props) { this.blocks = props.blocks; this.dragStart = props.dragStart; this.dragStop = props.dragStop; // Move inside the default container if exists const cnt = props.container; cnt && cnt.appendChild(this.$el); }, onDragStart(block) { this.dragStart(block); }, onDragStop() { this.dragStop(); }, } });
<div id="gjs"> <div style="padding: 25px">Custom Block Manager</div> </div> <div style="display: none;"> <!-- Vue app --> <div class="blocks-wrp"> Custom Blocks <div class="blocks"> <div v-for="block in blocks" class="block" :key="block.getId()" @dragstart="onDragStart(block)" @dragend="onDragStop()" draggable> <div class="block-media" v-html="block.getMedia()"></div> <div class="block-label">{{ block.getLabel() }}</div> <div class="block-cat">CAT: {{ block.getCategoryLabel() }}</div> </div> </div> </div> </div>
body, html { margin: 0; height: 100%; } .block { user-select: none; min-width: 45px; padding: 1em; box-sizing: border-box; min-height: 90px; cursor: all-scroll; text-align: center; display: flex; flex-direction: column; justify-content: space-between; border: 1px solid rgba(0,0,0,.2); border-radius: 3px; margin: 10px 2.5% 5px; box-shadow: 0 1px 0 0 rgb(0 0 0 / 15%); transition: all .2s ease 0s; transition-property: color; } .block:hover { color: #d278c9; }