Giter VIP home page Giter VIP logo

jquire's Introduction

jQuire Logo

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

<!-- JQuery goes here if you're want to use it as well -->
<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

// define your component
const HelloWorld = () => fragment(
    h1("Hello, World!")
)

const app = div(
    HelloWorld(),
    "Again ", HelloWorld()
)

// component with props and children
const Foo = (...props) => {
    const { childNodes, attributes } = getNodes(props)
    return div(
        "====START====",
        ...attributes,
        ...childNodes,
        "=====END====="
    )
}

Rendering Content

app.attachTo(document.body) // attaches `app` to document's body

Specifying Attributes

input(
    attr.type("number"), // set a single attribute
    attr({ value: 0, max:  100 }), // set multiple attributes
    attr.required() // single attributes without value will default to the name of the attribute
)

Styling Elements

All styles on block elements are scoped by default using unique class names. 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!")),
    // using effect function
    (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]}`),
    // using effect function
    ([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!`, // will be refreshed for every state change
    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" // warning
	
    const accent = theme == normal
        ? "darkgrey"
        : "danger"
            ? "red"
            : "info"
                ? "royalblue"
                : "orangered" // warning
	
    const style = {
        padding: "3px 5px",
        border: `1px solid ${accent}`,
        backgroundColor: primary,
        borderRadius: "5px"
    }

    // custom(tagName: a string in kebab-case, _extends: an optional HTMLElement)
    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

jquire's People

Contributors

jithujoshy avatar jithujoshyjy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

altijdshawn

jquire's Issues

functions passes as values to data attributes cannot access variables in the global scope/enclosing scope

I've kind of ran into a limitation. Functions passed as arguments to data attributes must be somewhat pure functions. They can't have references to variable/functions defined in the global or out scope. Otherwise they'll throw a ReferenceError. This is because these functions are ran inside of an eval() once they get assigned to the data attribute object. This procedure is required for binding their this value to the element in which they are are part of.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.