jQuire
jQuery UI Reciter
This project began as an experiment, stretching what's possible with JavaScript.
After a great deal of trouble, refactoring and a lot of sleepless nights, I think I've come up with something that I can be proud of!
I wouldn't advise it to be used in real applications but you're welcome to experiment with it and provide constructive criticism.
website
Installation and Imports
npm install jquire
you can also use a cdn if you like
<script type="module" src="https://cdn.jsdelivr.net/npm/jquire@latest/src/jquire.min.js"></script>
after installation 👇
import {
natives, nodes, when,
on, state, watch, each, paths,
getNodes, animate, css
} from "./node_modules/jquire/dist/jquire.min.js"
After you specify all the required imports you can either destructure each html element creator function from natives
proxy object.
const {
div, input, button,
form, dialog, img,
main, nav, a, br, h1,
footer, template, span
} = natives
const { attr, text, fragment } = nodes
Or, you can populate all the valid html element creators into the globalThis
object and make them available in the global scope.
natives.globalize()
Create a component
const HelloWorld = () => fragment(
h1("Hello, World!")
)
const app = div(
HelloWorld(),
"Again ", HelloWorld()
)
const Foo = (...props) => {
const { childNodes, attributes } = getNodes(props)
return div(
"====START====",
...attributes,
...childNodes,
"=====END====="
)
}
Rendering Content
app.attachTo(document.body)
Specifying Attributes
input(
attr.type("number"),
attr({ value: 0, max: 100 }),
attr.required()
)
Styling Elements
All styles on block elements are scoped by default using ShadowRoot. You can even specify css rules in them.
CSS Properties
div(
css.height("50px"),
css({ backgroundColor: "lightblue" })
)
Specifying styles for child elements
div(
css("button.abc")({
backgroundColor: "violet",
borderRadius: "5px",
border: "none",
padding: "5px 15px",
fontVariant: "small-caps"
}),
button(
attr.class("abc"),
"click me!"
)
)
Pseudo Classes, Pseudo Elements and CSS Rules
button(
"click me!",
css(":hover")({
backgroundColor: "teal"
}),
css("::before")({
content: "",
border: "1px solid fuchsia",
display: "inline-block",
width: "25px",
height: "25px"
}),
css("@keyframes", "press")({
"100%": {
transform: "scale(1.15)"
}
}),
css("@media screen and (max-width: 500px)")(
css(":host")({
borderColor: "cyan"
})
)
)
Animating Elements
div(
animate({ height: "500px" })
)
Handling Events
button(
"click me!",
on.click(event => console.log("clicked!")),
(event = on("click")) => console.log("effecive click!")
)
Creating elements from an Iterable
const fruits = ["apple", "orange", "banana"]
const fruitEmojis = ['🍎', '🍊', '🍌']
ul(
fruits.map((fruit, i) => `${fruit} - ${fruitEmojis[i]}`),
([fruit, i] = each(fruits)) => `${fruit} - ${fruitEmojis[i]}`
)
Reactive Data and Element Reference
You can use the state()
function to store reactive objects.
Then using the watch()
effect function, update the elements to be in sync with the state object.
const person = {
name: "John",
age: 26,
profession: "Artist"
}
const personST = state({ person })
div(
([person] = watch(personST)) =>
`John is ${person.age} years old!`,
button(
"increment age",
(_ = on("click")) => personST.age++
)
)
Conditional Rendering
You can choose to render or not to render certain elements based on a condition using when()
effect function.
const age = 50
div(
(_ = when(age > 200)) => span("Invalid age: Greater than 200.")
)
Custom Elements
jQuire supports HTML5 Custom Elements out of the box.You can use them like any other component and they are brought into scope using the custom()
function.
const MyButton = (label = '', theme = "normal") => {
const primary = theme == "normal"
? "lightgrey"
: "danger"
? "palevioletred"
: "info"
? "cornflowerblue"
: "coral"
const accent = theme == normal
? "darkgrey"
: "danger"
? "red"
: "info"
? "royalblue"
: "orangered"
const style = {
padding: "3px 5px",
border: `1px solid ${accent}`,
backgroundColor: primary,
borderRadius: "5px"
}
return custom("my-btn", HTMLButtonElement)(
css(style),
label
)
}
You can also create custom elements by specifying them as properties of custom()
function.
const { HelloWorld } = custom
HelloWorld("hello world!")
Lifecycle Effects
These are events that let you run code when an element is attached or detached from DOM using attach()
and detach()
effect functions respectively.
const sidebarST = state({ clicked: false })
div(
button("⊞", (_ = on("click")) => sidebarST.clicked = !sidebarST.clicked),
(_ = watch(sidebarST)) => (_ = when(sidebarST.clicked)) =>
aside(
(_ = attach()) => console.log("sidebar visible"),
(_ = detach()) => console.log("sidebar hidden")
),
)
More ideas on the horizon...
stay tuned for more