GrapeJS Web Builder
Installation
Créer un nouveau projet
Fonctionnalités
- Introduction
- Graph REST API
- Les listes
Plugins SPFx
- Créer son plugin SharePoint
- spfx-list-migration
- GrapeJS Web Builder
GrapeJS Web Builder
Installation
Liens utiles
Getting started : https://grapesjs.com/docs/getting-started.html
Installer Grapejs
npm install grapejs
Ci-dessous est une suggestion d’organisation de la structure du projet.
.
|
└── src
├── index.ts
├── styles
│ ├── dist
│ │ └── tailwind.css
│ ├── grape-container.css
│ ├── postcss.config.js
│ └── tailwind.css
└── webparts
└── monSuperSite
├── MonSuperSiteWebPart.ts
├── grapejs // Regroupe toute la logique du Builder Grapejs
│ ├── components // Regroupe les plugins des composants grapejs
│ │ ├── Counter
│ │ │ └── Counter.tsx
│ └── index.tsx // Fichier de configuration du Builder
├── components // Regroupe les composants React
│ ├── Counter
│ │ └── Counter.tsx
│ ├── MonSuperSite.tsx
│ ├── Page // Rendu des pages à partir des données GrapeJS
│ │ └── Page.tsx
│ └── Wrapper // Rendu des composants à partir des données des composants GrapeJS
│ └── Wrapper.tsx
└── pnpjsConfig.ts
Les composants GrapeJS ne sont pas des composants React mais des plugins à ajouter dans la configuration de l’éditeur GrapeJS. Ils peuvent utiliser des composants React en les convertissant en HTML à travers ReactDOM.
Pour le code complet, voir le gitlab.
Initialisation de l’éditeur
Dans un fichier src/webparts/monSuperSite/grapejs/index.tsx :
import grapesjs from 'grapesjs';
import 'grapesjs/dist/css/grapes.min.css';
import "../../../styles/dist/tailwind.css"; // N'est pas requis pour GrapeJS, mais utile.
export default function GrapeContainer({}: IGrapeContainerProps): ReactElement<IGrapeContainerProps> {
const editorRef = useRef<any>(null);
useEffect(() => {
editorRef.current = grapesjs.init({
// Indicate where to init the editor. You can also pass an HTMLElement
container: '#gjs',
// Get the content for the canvas directly from the element
fromElement: true,
// Size of the editor
width: 'auto',
canvas: {
styles: [ // Injection des styles dont on a besoin dans l'éditeur
"https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css"
]
},
// Avoid any default panel
blockManager: {
appendTo: '#blocks',
blocks: [
{
id: 'text',
label: 'Text', // You can use HTML/SVG inside labels - ex: <b>Text</b>
content: '<div data-gjs-type="text">Insert your text here</div>', // Composant Built-in
category: "Basic Blocks"
},
{
id: "counter", //
label: "Counter",
select: true,
content: { type: 'counter-type' }, // Composant Custom
activate: true,
category: "Custom Blocks"
},
]
},
layerManager: {
appendTo: '.layers-container'
},
panels: { // Configuration des Panels
defaults: [
{
id: 'blocks', // id du Panel
el: '.panel__left', // Sélecteur de l'élément HTML où injecter le Panel
// Make the panel resizable
resizable: {
maxDim: 350,
minDim: 200,
tc: false, // Top handler
cl: true, // Left handler
cr: true, // Right handler
bc: false, // Bottom handler
// Being a flex child we need to change `flex-basis` property
// instead of the `width` (default)
keyWidth: 'flex-basis',
},
},
{
id: 'blocks-actions', // id du Panel
el: ".pannel__blocks-actions", // Sélecteur de l'élément HTML où injecter le Panel
buttons: [ // Boutons du Panel
{
id: 'show-blocks', // ID unique de l'élément HTML où injecter le bouton
active: true,
label: '+',
command: 'show-blocks', // Commande Custom ou Built-in
togglable: true,
},
]
},
// ...
]
},
selectorManager: { // Configuration du Manager des sélecteurs des classes, états...
appendTo: '.styles-container'
},
styleManager: { // Configuration du Manager des styles
appendTo: '.styles-container',
sectors: [{
name: 'Dimension',
open: false,
// Use built-in properties
buildProps: ['width', 'min-height', 'padding'],
// Use `properties` to define/override single property
properties: [
{
// Type of the input,
// options: integer | radio | select | color | slider | file | composite | stack
type: 'integer',
name: 'The width', // Label for the property
property: 'width', // CSS property (if buildProps contains it will be extended)
units: ['px', '%'], // Units, available only for 'integer' types
defaults: 'auto', // Default value
min: 0, // Min value, available only for 'integer' types
}
]
},
// ...
]
},
storageManager: { // Configuration du manager de gestion des données du projets
type: "remote-local", // Dans ce cas, c'est un manager personnalisé
autosave: true,
autoload: true,
stepsBeforeSave: 1, // À augmenter selon les préférences : nombre d'étapes avant la sauvegarde
},
traitManager: { // Configuration du manager de gestion d'attributs des Components GrapeJS
appendTo: '.traits-container',
},
deviceManager: { // Configuration du manager responsive
devices: [{
name: 'Desktop',
width: '', // default size
}, {
name: 'Mobile',
width: '320px', // this value will be used on canvas width
widthMedia: '480px', // this value will be used in CSS @media
}]
},
pageManager: { // Configration du manager des pages
pages: [
{
id: "first-page", // ID unique de la page
component: "<div id='first-page'>First page</div>" // Composant par défaut
},
// ...
]
}
});
return () => {
// Suppression de la ref de l'éditeur GrapeJS
editorRef.current && editorRef.current.destroy();
};
}, []);
return(
<>
{/* Panel Top : regroupe des des boutons liés à des commandes GrapJS au-dessus du Canvas */}
<div className="panel__top">
<div className="panel__basic-actions"></div>
<div className="panel__devices"></div>
<div className="panel__switcher"></div>
</div>
<div className="editor-row">
{/* Panel Top : regroupe des des boutons liés à des commandes GrapJS à gauche du Canvas */}
<div className="panel__left">
<div className='relative w-full flex'>
<div className='pannel__blocks-actions !relative'></div>
</div>
<div>
<div className="blocks-container" id="blocks"></div>
</div>
</div>
{/* Conteneur du Canvas *}
<div className="editor-canvas">
{/* GrapeJS injecte l'éditeur dans la div suivante via l'id 'gjs' */}
<div id="gjs" className='max-h-full overflow-y-scroll'></div>
</div>
{/* Panel Top : regroupe des des boutons liés à des commandes GrapJS à droite du Canvas */}
<div className="panel__right">
<div className="layers-container"></div>
<div className="styles-container"></div>
<div className="traits-container"></div>
</div>
</div>
</>
);
}