Build Powerful ⚡ Web Apps with Ease
Explore the 🎙️ docs »
Join Community
.
Report Bug
.
Request Feature
const Cradova = new Comp(function () {
const [year, setYear] = useState(3, this);
return h1("Cradova is " + year + " yrs old in ", {
onclick() {
setYear((lastYear) => {
return lastYear + 1;
});
},
});
});
document.body.appendChild(Cradova.render());
import { div, h1, $if, $ifelse, $case, $switch } from "cradova";
function Hello({ name }) {
return div(
$if(name === "john", h1("Hello john")),
$if(name === "paul", h1("Goodbye paul")),
$ifelse(name === "john", h1("Hello john"), h1("Hello Paul"))
);
}
const html = div(Hello("john"), Hello("paul"));
function whatsAllowed({ age }) {
return div(
$switch(
age,
$case(12, h1("too young")),
$case(26, h1("you are welcome")),
$case(52, h1("too old"))
)
);
}
document.body.append(html, whatsAllowed({ age: 26 }));
Cradova is a web development framework for building Single Page Applications and PWAs.
Cradova follows the VJS specification
Fast and simple with and fewer abstractions and yet easily composable.
Cradova is not built on virtual DOM or diff algorithms. Instead, State management is done in a way that is simple, easy and fast.
Undoubtedly, this provides a significant advantage.
npm i cradova
<!-- unpkg -->
<script src="https://unpkg.com/cradova/dist/index.js"></script>
<!-- js deliver -->
<script src="https://cdn.jsdelivr.net/npm/cradova/dist/index.js"></script>
Some aspects of Cradova are not reflected in the following example. More functionality will be entailed in future docs.
import { div, h1 } from "cradova";
function Hello(name) {
return h1("Hello " + name, {
className: "title",
style: {
color: "grey",
},
});
}
const html = div(Hello("peter"), Hello("joe"));
document.body.append(html);
This a collection of basic examples that can give you some ideas
import {
button,
createSignal,
Comp,
reference,
h1,
br,
div,
useRef,
} from "cradova";
const count = new Comp(function () {
const [count, setCounter] = useState(0, this);
setTimeout(() => {
setCounter(count + 1);
}, 1000);
return h1(" count: " + count);
});
// hello message
function HelloMessage() {
return div("Click to get a greeting", {
onclick() {
const name = prompt("what are your names");
this.innerText = name ? "hello " + name : "Click to get a greeting";
},
});
}
// using CradovaRef
const nameRef = new Comp(function () {
const [name, setName] = (useState < string) | (undefined > (undefined, this));
return div(name ? "hello " + name : "Click to get a second greeting", {
onclick() {
const name = prompt();
if (name) {
setName(name);
} else {
alert("Please provide a valid name");
}
},
});
});
// reference (not state)
function typingExample() {
const ref = useRef();
return div(
input({
oninput() {
ref.current("text").innerText = this.value;
},
placeholder: "typing simulation",
}),
p(" no thing typed yet!", { reference: ref.bindAs("text") })
);
}
function App() {
return div(count, typingExample, HelloMessage, nameRef);
}
document.body.append(App());
Let's see a simple TodoList example
import {
button,
createSignal,
useState,
div,
input,
main,
p,
Comp,
h1,
useRef,
} from "../dist/index.js";
function TodoList() {
// can be used to hold multiple references
const referenceSet = useRef();
// creating a store
const todoStore = new createSignal([
"take bath",
"code coded",
"take a break",
]);
// create actions
todoStore.createAction("add-todo", function (todo) {
this.set([...this.value, todo]);
});
todoStore.createAction("remove-todo", function (todo) {
const ind = this.value.indexOf(todo);
this.value.splice(ind, 1);
this.set(this.value);
});
// bind Comp to Signal
todoStore.bindRef(todoList);
// markup
return main(
p(`|Todo List`),
div(
input({
placeholder: "type in todo",
reference: referenceSet.bindAs("todoInput"),
}),
button("Add todo", {
onclick() {
todoStore.fireAction(
"add-todo",
referenceSet.current("todoInput").value
);
referenceSet.current("todoInput").value = "";
},
})
),
todoList.render
);
}
const todoList = new Comp(function () {
const self = this;
return div(
self.Signal.value.map((item) =>
p(item, {
title: "click to remove",
onclick() {
self.Signal.fireAction("remove-todo", item);
},
})
)
);
});
document.body.appendChild(TodoList());
Unlike just appending stuff to the DOM, a better to build apps is to use a routing system.
Cradova Router is a module that allows you do the following:
Create specified routes in you application help you handle navigation render a page on a route listen to Navigation changes create error boundary at page level apart from Comp level.
let's try an example.
import { Page, Router } from "cradova";
// Comp can be used as page template this way
const template = new Comp(function (name) {
// an effect run once after page renders
const self = this;
self.effect(() => {
const name = new Promise((res) => {
res("john doe");
});
setTimeout(async () => {
self.recall(await name);
}, 1000);
});
// effects can be used to make api calls needed for the page
return div(name ? ">>>>>>>> Hello " + name : " loading...");
});
const home = new Page({
name: "home page", // page title
template: () => div(template),
});
// in your routes.ts file
Router.BrowserRoutes({
// Ways to use paths and Pages
"*": home,
"/home": home,
"/home?": home,
"/home/:name": home,
// will be lazy loaded
"/lazy-loaded-home": async () => await import("./home"),
});
// creates these routes
Router.navigate("/home", data);
// navigates to that page
Router.onPageEvent((lastRoute, newRoute) => {
console.log(lastRoute, newRoute);
});
// listen for navigation changes
More info on Cradova Router
Every Cradova app mounts on a div with attribute data-wrapper="app"
if it already exist Cradova will use it instead.
Cradova will create a div with data-wrapper="app" if it doesn't exists already.
so if you want to use your own mount point then create a div with data-wrapper="app".
More info on Cradova pages
Cradova pages has onActivate() and onDeactivate() methods which is also available in the component function on the this variable bound to it.
this allow you manage rendering circle for each page in your app
More info on Cradova Comp
Cradova Comp is a dynamic component class, which ships simple abstractions like:
- recall
- useEffect
- useState
- useRef
- preRender
these behaviors allow you manage rendering circle for Comps in your app
More info on Cradova createSignal
Cradova Signals allows you to create powerful data stores.
with ability to:
- create store
- create actions and fire them
- bind a Comp
- listen to changes
- persist changes to localStorage
- update a Comp and bindings automatically
With these simple and easy abstractions, you can write datastores with so much convenience.
At the moment, we're in the process of creating a documentation website for Cradova, and we have limited resources. If you're interested in lending a hand, we invite you to join our community, gain firsthand experience, and contribute to the advancement of Cradova.
To get further insights and help on Cradova, visit the Discord and Telegram Community Chats.
We are currently working to set up the following:
- building Cradova CLI (in progress)
- Cradova Documentation Website
- UI component libraries for cradova (The Sacho Project)
- Sample projects
- maintenance and promotion
██████╗ ██████╗ █████═╗ ███████╗ ███████╗ ██╗ ██╗ █████╗
██╔════╝ ██╔══██╗ ██╔═╗██║ █ ██ ██╔═════╝█ ██║ ██║ ██╔═╗██
██║ ██████╔╝ ███████║ █ ██ ██║ ██ ██║ ██║ ██████╗
██║ ██╔══██╗ ██║ ██║ █ ██ ██║ ██ ╚██╗ ██╔╝ ██║ ██╗
╚██████╗ ██║ ██║ ██║ ██║ ███████╔╝ ████████ ╚███╔╝ ██║ ██║
╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚════╝ ╚══╝ ╚═╝ ╚═╝
Opensourced And Free.
Join Us on telegram.
If you contribute code to this project, you are implicitly allowing your code to be distributed under same license. You are also implicitly verifying that all code is your original work.
Your Support is a good force for change anytime you do it, you can ensure Our projects, growth, Cradova, Cradova, JetPath etc, growth and improvement by making a re-occuring or fixed sponsorship to github sponsors:
Support via cryptos -
- BTC:
bc1q228fnx44ha9y5lvtku70pjgaeh2jj3f867nwye
- ETH:
0xd067560fDed3B1f3244d460d5E3011BC42C4E5d7
- LTC:
ltc1quvc04rpmsurvss6ll54fvdgyh95p5kf74wppa6
- TRX:
THag6WuG4EoiB911ce9ELgN3p7DibtS6vP
Build Powerful ⚡ Web Apps with Ease.