Paradox is just a simple vanilla javascript library for DOM manipulation.
Hopefully it will ease your development while learning
·
Report Bugs
·
Request Features
IMPORTANT: Things are changing a lot right now, so please be patient, this is a work in progress
- Table of Contents
- About The Project
- Getting Started
- Documentation
- Contributing
- License
- Contact
- Roadmap
- Acknowledgements
Working on cool stuff to say here. stay tuned and please be patient, this is a work in progress.
Contributions are welcome thogh xd, please start a discussion to discuss what you would like to change, add or remove and we can figure it out together.
Link to the npm package
Paradox is a simple vanilla javascript library for DOM manipulation that also provides a simple router and PubSub implementation.
- Node.js >= v16.16.0 (For development mode)
- Clone the repo
git clone git@github.com:ProjectPenrose/paradox.git
- Install NPM packages
cd penrose-paradox npm install
Now things can change depending on what you want to do, so here are some options:
You can use paradox in a project that uses npm, all you need before getting started is to have webpack set with babel loader.
Then you can install it like this:
npm i penrose-paradox
Then you can import it like this:
import Paradox from "penrose-paradox";
Now you'll have access to all the paradox features in your node projects.
Here's an example of a project structure that uses paradox:
. # root
├── app
│ ├── index.js
│ └── index.html
├── dist
│ ├── css
│ │ └── main.css
│ └── js
│ └── bundle.js
├── node_modules
├── package.json
├── package-lock.json
├── server
│ └── index.js
├── scss
│ └── main.scss
└── webpack.config.js
- The
app
folder contains the html project and the javascript entry point file where you can import paradox. - The
dist
folder contains the built project and it's generated by webpack. - The
node_modules
folder contains the npm packages for the project. - The
package.json
file contains the project info and the npm scripts. - The
package-lock.json
file contains the npm packages info. - The
server
folder contains a simple Nodejs server that serves thedist
folder and redirects all the requests to theindex.html
file. - The
scss
folder contains a simplemain.scss
and it should be compiled todist/css/main.css
. - The
webpack.config.js
file contains the webpack config.
const path = require("path");
module.exports = {
entry: {
"js/bundle": "./app/index.js",
},
target: "web",
mode: "development",
output: {
filename: "[name].js",
path: path.resolve(__dirname, "dist"),
},
module: {
rules: [
{
test: /\.(js)$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
}
},
],
},
// ... other config
}
If you want to use it as a module in a simple HTML project, you should import it in your script like this:
<script type="module">
import Paradox from "./path/to/penrose-paradox/build/index.js";
</script>
Paradox includes the following features:
Paradox provides a simple way to build an element with the buildElement
function that takes the element name and an object with the element properties as arguments.
Properties:
Property | Type | Description |
---|---|---|
id | string | The element id |
classList | string | The element class list separated by spaces |
attributes | object | The element attributes (e.g. type, value, etc.) |
events | object | The element events (e.g. click, change, etc.) |
style | object | The element style (e.g. backgroundColor, color, etc.) |
text | string | The element text |
children | array | The element children |
import Paradox from "penrose-paradox";
function handleButtonClick() {
alert("Hello World!");
}
const myButton = {
id: "myButton",
classList: "btn btn-primary",
attributes: {
type: "button",
},
events: {
click: handleButtonClick,
},
style: {
backgroundColor: "red",
},
text: "Click me!",
children: [
{
tag: "i",
options: {
id: "myButtonIcon",
classList: "fas fa-hand-pointer",
}
},
],
}
document.body.appendChild(Paradox.buildElement("button", myButton));
NOTES:
- The
buildElement
function will return aHTMLElement
object. - The
children
property is an array of objects with thetag
andoptions
properties. Thetag
property is the element name and theoptions
property is the object with the element properties. - The
options
property is optional, so you can pass just thetag
property and it will return an element with no properties.
Paradox provides a simple router to handle the navigation between pages.
import Paradox from "penrose-paradox";
function Home(props) {
const { root } = props;
root.append(Paradox.buildElement("div", {
id: "home",
text: "Welcome to Paradox!",
}));
}
function About(props) {
const { name, root } = props;
root.append(Paradox.buildElement("div", {
id: "about",
text: `Paradox is a simple vanilla javascript library for DOM manipulation. This is the ${name} page.`,
}));
}
const root = document.getElementById("root");
const routes = [
{
path: "/",
component: Home,
props: {
root,
},
},
{
path: "/about",
component: About,
props: {
name: "About",
root,
},
},
];
const router = new Paradox.Router(routes);
router.init()
.then((path) => {
console.info(`The current path is: ${path}`);
})
.catch((error) => {
console.error(error);
});
NOTES:
- The router will look for the
#
in the url to handle the navigation. For example, if the url ishttp://localhost:8080/#/about
, the router will navigate to the/about
path. - The router will inject the
props
object into the component function as an argument and it will contain, besides the properties that you pass, the following properties:queryString
: A string with the query parameters. For example, if the url ishttp://localhost:8080/about?name=Paradox
, thequeryString
will be?name=Paradox
.params
: An object with the path parameters. For example, if the url ishttp://localhost:8080/about/Paradox
, and the path is/about/:name
, theparams
object will be{ name: "Paradox" }
.query
: An object with the query parameters. For example, if the url ishttp://localhost:8080/about?name=Paradox
, thequery
object will be{ name: "Paradox" }
.baseUrl
: A string with the base url. For example, if the url ishttp://localhost:8080/about?name=Paradox
, thebaseUrl
will behttp://localhost:8080
.
Paradox provides a simple PubSub implementation to handle the communication between components.
In case you're not familiar, PubSub is a popular messaging pattern in software architecture. It stands for Publish-Subscribe pattern and is used for communication between different parts of an application or between different applications.
In the PubSub pattern, publishers send messages without knowing who the subscribers are. Subscribers, on the other hand, express interest in one or more events and only receive messages that are of interest, without knowing who sent them.
This pattern is widely used in event-driven programming and can help to decouple the components of an application, leading to code that is easier to maintain and extend. In the context of Paradox, it allows components to communicate with each other in a decoupled manner.
import Paradox from "penrose-paradox";
Paradox.pubsub.subscribe("myEvent", (data) => {
console.log(data);
});
Paradox.pubsub.publish("myEvent", "Hello World!");
NOTES:
- You can use pubsub to communicate between components, for example, you can publish an event in a component and subscribe to it in another component. This way you can pass data between components without having to use props.
- Subscriptions are not persistent, so if you subscribe to an event and then navigate to another page, the subscription will be lost.
- You can use the
Paradox.pubsub.unsubscribe
method to unsubscribe from an event. - You can not publish an event before subscribing to it xd.
You can find some examples in the examples
folder.
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated.
Distributed under the MIT License. See LICENSE
for more information.
Santiago Rincon - @alexsc6955
See the ROADMAP.md for a list of proposed features (and known issues).
If you have any ideas, please start a discussion and we can figure it out together.
- K2 - For not letting me use React in their projects xd.