Replies: 3 comments 5 replies
-
There is an example here showing you exactly what you're asking. |
Beta Was this translation helpful? Give feedback.
2 replies
-
Hi, this is my code in React. This is the code from the documentation, I converted it to Next.js React. Hope it helps import { useEditor } from "@grapesjs/react";
import { CanvasSpot, Component } from "grapesjs";
import { useEffect, useState } from "react";
import './canvas-spot.css';
const CanvasSpots = () => {
const editor = useEditor();
const { Canvas } = editor;
const [spots, setSpots] = useState<CanvasSpot[]>([]);
const customSpotType = 'my-text-spot';
useEffect(() => {
const onCanvasSpot = () => {
setSpots(Canvas.getSpots());
};
const onComponentToggled = (component: 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 });
}
};
const onEditorReady = () => {
// Once the editor is ready, append our custom elements to GrapesJS spots container
Canvas.getSpotsEl()?.appendChild(document.querySelector('.canvas-spots') as HTMLElement);
console.log('Canvas spots container appended to GrapesJS spots container');
};
// Catch-all event for any spot update
editor.on('canvas:spot', onCanvasSpot);
// Add a new custom canvas spot for the last selected text component.
editor.on('component:toggled', onComponentToggled);
// Editor ready event
editor.onReady(onEditorReady);
// Cleanup listeners on unmount
return () => {
editor.off('canvas:spot', onCanvasSpot);
editor.off('component:toggled', onComponentToggled);
// editor.onReady(onEditorReady);
};
}, [customSpotType]);
const onBtnAdd = () => {
const selected = editor.getSelected();
if (!selected) return;
const parent = selected.parent();
if (parent) {
parent.append(
{ type: 'text', components: 'New text component' },
{ at: selected.index() + 1 }
);
}
};
const isTextSelectedSpot = (spot: CanvasSpot) => {
return spot.type === customSpotType;
};
const isHoverSpot = (spot: CanvasSpot) => {
return spot.type === 'hover';
};
const isSpotToShow = (spot: CanvasSpot) => {
return isTextSelectedSpot(spot) || isHoverSpot(spot);
};
return (
<div className="canvas-spots">
{spots.map((spot) => (
isSpotToShow(spot) && (
<div
key={spot.id}
className={`spot ${isHoverSpot(spot) ? 'spot-hover' : ''}`}
style={spot.getStyle() as any}
>
{isTextSelectedSpot(spot) && (
<button className="spot-text-btn" type="button" onClick={onBtnAdd}>
+ Add
</button>
)}
{isHoverSpot(spot) && (
<span className="spot-hover-tag">
Name: {spot.component?.getName()}
</span>
)}
</div>
)
))}
</div>
);
};
export default CanvasSpots; the CSS should be .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;
} |
Beta Was this translation helpful? Give feedback.
1 reply
-
Beta Was this translation helpful? Give feedback.
2 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Hi there, I want to add a button in between every
<section>
that says (+ Add Section).I know I should be able to do this with Canvas Spots, but I can't get the button to show up.
Beta Was this translation helpful? Give feedback.
All reactions