Canvas Spots
by artur_arseniev
HTML
<script src="https://unpkg.com/grapesjs"></script>
<script src="https://unpkg.com/grapesjs-blocks-basic"></script>
<link rel="stylesheet" href="https://unpkg.com/grapesjs/dist/css/grapes.min.css">
<div id="gjs">
</div>
<div class="canvas-spots">
<div v-for="spot in spots" v-if="isSpotToShow(spot)" :key="spot.id" :class="{spot: 1, 'spot-hover': isHoverSpot(spot) }" :style="spot.getStyle()">
<button v-if="isTextSelectedSpot(spot)" class="spot-text-btn" type="button" @click="onBtnAdd">
+ Add
</button>
<span v-if="isHoverSpot(spot)" class="spot-hover-tag">
Name: {{ spot.component.getName() }}
</span>
</div>
</div>
SCSS
body, html {
height: 100%;
margin: 0;
}
.spot-text-btn {
background-color: #3b97e3;
border: none;
color: white;
padding: 4px 8px;
border-radius: 3px;
cursor: pointer;
position: absolute;
left: 50%;
bottom: 0;
translate: -50% 120%;
pointer-events: auto;
}
.spot-hover {
border: 2px solid #d23be3;
}
.spot-hover-tag {
background-color: #d23be3;
color: white;
padding: 4px 8px;
position: absolute;
left: 0;
bottom: 0;
translate: 0% 100%;
white-space: nowrap;
}
Babel + JSX
const editor = grapesjs.init({
container: '#gjs',
height: '100%',
storageManager: false,
components: `
<div style="padding: 25px; margin: 10px">Custom Canvas Spots</div>
<div style="padding: 25px; margin: 10px">Custom Canvas Spots</div>
<div style="padding: 25px; margin: 10px">Custom Canvas Spots</div>
`,
plugins: ['gjs-blocks-basic'],
canvas: {
customSpots: { hover: true },
},
});
const { Canvas } = editor;
const app = new Vue({
el: '.canvas-spots',
data: {
spots: [],
customSpotType: 'my-text-spot',
},
mounted() {
const { customSpotType } = this;
// Catch-all event for any spot update
editor.on('canvas:spot', this.onCanvasSpot);
// Add a new custom canvas spot for the last selected text component.
editor.on('component:toggled', (component) => {
// Remove all spots related to our custom type
Canvas.removeSpots({ type: customSpotType });
if (component === editor.getSelected() && component.is('text')) {
Canvas.addSpot({ type: customSpotType, component });
}
});
editor.onReady(() => {
// Once the editor is ready, append our custom elements to GrapesJS spots container
Canvas.getSpotsEl().appendChild(this.$el);
});
},
methods: {
onCanvasSpot() {
this.spots = Canvas.getSpots();
},
onBtnAdd() {
const selected = editor.getSelected();
const parent = selected.parent();
if (parent) {
parent.append(
{ type: 'text', components: 'New text component' },
{ at: selected.index() + 1 }
)
}
},
isTextSelectedSpot(spot) {
return spot.type === this.customSpotType;
},
isHoverSpot(spot) {
return spot.type === 'hover';
},
isSpotToShow(spot) {
return this.isTextSelectedSpot(spot) || this.isHoverSpot(spot);
},
}
});