Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VvvebJS React

VvvebJS wrapper for React.

Example React router dashboard example.

Installation

npm i vvvebjs @vvvebjs/react

Example

This is a simple example that loads and saves pages from local storage,

import { useRef, useEffect, useState, useCallback } from 'react';
import VvvebJs from '@vvvebjs/react';

function Builder() {
	let pages = {
		"page1": {
			name: "page1",
			filename: null,
			file: null,
			url: null,
			title: "Page 1",
			folder: null,
			description: "Page 1 description"
		},
	};
	
	// starter templates for new page modal
	let startTemplates = {
		"template1": {
			name: "template1",
			html:`<html>
				<head><link href="https://cdn.jsdelivr.net/npm/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"></head>
				<body><div class="container my-3"><h1>Template 1</h1></div></body>
				</html>`
		},
		"template2": {
			name: "template2",
			html:`<html>
				<head><link href="https://cdn.jsdelivr.net/npm/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"></head>
				<body>
					<div class="container my-3">
						<h2>Template 2</h2>
						<p class="lead">Lorem ipsum</p>
					</div>
				</body>
				</html>`
		},
	};
		
	if (localStorage.getItem('vvveb.pages')) {
		pages = JSON.parse(localStorage.getItem('vvveb.pages'));
	}
	
	//add custom sections
	const sections = () => {
		Vvveb.SectionsGroup['Custom'] =
		["custom/section-1", "custom/section-2"];


		Vvveb.Sections.add("custom/section-1", {
			name: "Custom section 1",
			dragHtml: '<img src="' + Vvveb.baseUrl + 'icons/image.svg">',        
			image: Vvveb.baseUrl + 'icons/image.svg',
			html:`
		<section data-name="section-1">    
		  <div class="container">
			<h2>Custom section 1</h2>
		  </div>
		</section>`});
		
		Vvveb.Sections.add("custom/section-2", {
			name: "Custom section 1",
			dragHtml: '<img src="' + Vvveb.baseUrl + 'icons/image.svg">',        
			image: Vvveb.baseUrl + 'icons/image.svg',
			html:`
		<section data-name="section-2">    
		  <div class="container">
			<h2>Custom section 2</h2>
		  </div>
		</section>`});
	}
	
	//add custom blocks
	const blocks = () => {
		Vvveb.BlocksGroup['Custom'] =
		["custom/block-1", "custom/block-2"];


		Vvveb.Blocks.add("custom/block-1", {
			name: "Custom block 1",
			image: Vvveb.baseUrl + 'icons/image.svg',
			html: `
				<div class="container">
					<h2>Custom block 1</h2>
				</div>`
		});
		
		Vvveb.Blocks.add("custom/block-2", {
			name: "Custom block 1",
			image: Vvveb.baseUrl + 'icons/image.svg',
			html: `
				<div class="container">
					<h2>Custom block 2</h2>
				</div>`
		});
		
	}

	//add custom components
	const components = () => {
			
		Vvveb.ComponentsGroup['Custom'] = [	
		"custom/myelement",
		];

		Vvveb.Components.extend("_base","custom/myelement", {
			nodes: ["myelement"],
			name: "MyElement",
			image: "icons/image.svg",
			resizable:true,
			html: `<myelement>
				  <img src="${Vvveb.baseUrl}icons/image.svg" alt="Desc">
				  <h1>Bane</h1>
				  <p>Description</p>
				</myelement>`,
				
			resizable:true,//show select box resize handlers
			
			properties: [{
				name: "Image",
				key: "src",
				child:"img",
				htmlAttr: "src",
				inputtype: ImageInput
			},{
				name: "Width",
				key: "width",
				child:"img",
				htmlAttr: "width",
				inputtype: CssUnitInput
			},{
				name: "Height",
				key: "height",
				child:"img",
				htmlAttr: "height",
				inputtype: CssUnitInput
			},{
				name: "Alt",
				key: "alt",
				child:"img",
				htmlAttr: "alt",
				inputtype: TextInput
			},{
				name: "Caption",
				key: "caption",
				child:"figcaption",
				htmlAttr: "innerHTML",
				inputtype: TextareaInput
			}]    
		});
			
	}
	
	const ready = (Vvveb) => {
		sections();
		components();
		blocks();
		
		//disable new page form sumission
		document.querySelector("#new-page-modal form").action = "";
	}

	const init = (Vvveb) => {
		//set media path
		//window.mediaPath = '';
		window.mediaPath = Vvveb.baseUrl + '../../media';
		
		//set media handlers
		window.uploadUrl = '/upload-endpoint';
		window.deleteUrl = '/delete-endpoint';
		window.renameUrl = '/rename-endpoint';
	
		Vvveb.MediaModal.setResponse([{
		"name": "",
		"type": "folder",
		"path": "",
		"items": [
			{
				"name": "15.jpg",
				"type": "file",
				"path": "\/15.jpg",
				"size": 135553
			},
			{
				"name": "2.jpg",
				"type": "file",
				"path": "\/2.jpg",
				"size": 87295
			},
			{
				"name": "4.jpg",
				"type": "file",
				"path": "\/4.jpg",
				"size": 225688
			},
			{
				"name": "5.jpg",
				"type": "file",
				"path": "\/5.jpg",
				"size": 158339
			},
			{
				"name": "6.jpg",
				"type": "file",
				"path": "\/6.jpg",
				"size": 149161
			},
			{
				"name": "7.jpg",
				"type": "file",
				"path": "\/7.jpg",
				"size": 57618
			},
			{
				"name": "mountains",
				"type": "folder",
				"path": "\/mountains",
				"items": [
					{
						"name": "1.jpg",
						"type": "file",
						"path": "\/mountains\/1.jpg",
						"size": 72587
					},
					{
						"name": "12.jpg",
						"type": "file",
						"path": "\/mountains\/12.jpg",
						"size": 130542
					},
					{
						"name": "3.jpg",
						"type": "file",
						"path": "\/mountains\/3.jpg",
						"size": 126297
					}
				]
			},
			{
				"name": "sample.webm",
				"type": "file",
				"path": "\/sample.webm",
				"size": 663407
			},
			{
				"name": "sample.webp",
				"type": "file",
				"path": "\/sample.webp",
				"size": 5138
			}]}]);
	}
	
	const editor = (Vvveb) => console.log(Vvveb);
	
	window.addEventListener("Vvveb.FileManager.deletePage", (e) => {
		let data = e.detail;
		delete pages[data.name];
		localStorage.setItem('vvveb.pages', JSON.stringify(pages));
	});
	
	window.addEventListener("Vvveb.FileManager.renamePage", (e) => {
		let data = e.detail;
		console.log(e, 'renamePage', data);
	});
	
	window.addEventListener("Vvveb.FileManager.addPage", (e) => {
		let data = e.detail;
		console.log(e, 'addPage', data);
	});
	
	window.addEventListener("Vvveb.FileManager.loadPage", (e) => {
		let data = e.detail;
		if (localStorage.hasOwnProperty('vvveb.content')) {
			let content = JSON.parse(localStorage.getItem('vvveb.content'));
			
			if (content.hasOwnProperty(data.name)) {
				return Vvveb.Builder.loadHtml(content[data.name]);
			}
		}
	
		Vvveb.Builder.loadHtml(`<html>
				<head><link href="https://cdn.jsdelivr.net/npm/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"></head>
				<body><div class="m-5"><h1>${data.name}</h1></div></body>
				</html>`);
	});
	
	window.addEventListener("Vvveb.Builder.save", (e) => {
		let data = e.detail;
		pages[data.name] = data;
		localStorage.setItem('vvveb.pages', JSON.stringify(pages));

		let content = {};
		if (localStorage.hasOwnProperty('vvveb.content')) {
			content = JSON.parse(localStorage.getItem('vvveb.content'));
		}
		
		if (data.startTemplateUrl) {
			//new page use selected template
			content[data.name] = startTemplates[data.startTemplateUrl]["html"];
		} else {
			//existing page
			content[data.name] = data.html;//Vvveb.Builder.getHtml();
		}
		
		localStorage.setItem('vvveb.content', JSON.stringify(content));
		
		displayToast("success", "Save", "Page saved!");
	});
	


 return (
		<VvvebJs pages={pages} startTemplates={startTemplates} onEditor={editor} onReady={ready} onInit={init}/>
	);
}

export default Builder;

License

Apache 2

Morty Proxy This is a proxified and sanitized view of the page, visit original site.