0.0.16 • Published 8 months ago

van-jsx v0.0.16

Weekly downloads
-
License
MIT
Repository
github
Last release
8 months ago

van-jsx

GitHub npm bundlejs

A small ~1kb JSX libs for building Vanilla App.

  • Control JSX with vanilla-js.
  • SSR Ready.
  • TypeScript support out of the box.
  • No virtual-dom.
  • Router with SSR support.
  • Helmet with SSR support.

Starter

Client App

npx degit herudi/van-jsx-starter my-app

cd my-app

// install deps
npm install

// run dev
npm run dev

// build
npm run build

SSR App

Coming Soon...

Install

Npm

npm i van-jsx

Deno

import {...} from "https://deno.land/x/van_jsx/mod.ts";

Usage

/* @jsx h */

import { createHost, h, render } from "van-jsx";

const Counter = () => {
  const state = { count: 0 };
  const Host = createHost();

  Host.controller = ({ btn, count }) => {
    btn.onclick = () => {
      count.innerText = (state.count += 1).toString();
    };
  };

  return (
    <Host>
      <button ref="btn">Click Me</button>
      <h1 ref="count">{state.count}</h1>
    </Host>
  );
};

render(<Counter />, document.getElementById("root"));

// No problem
// render(
//   <>
//     <Counter />
//     <Counter />
//     <Counter />
//   </>,
//   document.getElementById("root"),
// );

SSR

/* @jsx h */

import { h } from "van-jsx";
import App from "./app.tsx";

// example using express
app.get("/", (req, res) => {
  const html = (
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <title>My App</title>
      </head>
      <body>
        <div id="root">
          <App />
        </div>
        <script src="/client.js"></script>
      </body>
    </html>
  );
  res.send(html);
});

// on the client interactive
hydrate(<App />, document.getElementById("root"));

Router

import { createRouter, Link } from "van-jsx/router";

const App = () => {
  const Route = createRouter();
  return (
    <>
      <nav>
        <Link href="/">Home</Link>
        <Link href="/about">About</Link>
      </nav>
      <Route path="/" component={() => <Home />} />
      <Route path="/about" component={() => <About />} />
    </>
  );
};

Helmet

import { Helmet } from "van-jsx/helmet";

const App = () => {
  return (
    <Host>
      <Helmet>
        <title>Hello App</title>
        <script>{`console.log("hello from head")`}</script>
      </Helmet>
      <Helmet footer>
        <script>{`console.log("hello from body")`}</script>
      </Helmet>
      <div>
        <h1>Hello App</h1>
      </div>
    </Host>
  );
};

Helmet SSR

import { Helmet } from "van-jsx/helmet";

// example using express
app.get("/", (req, res) => {
  const { head, attr, body, footer } = Helmet.rewind(<App />);
  const html = (
    <html lang="en" {...attr.html.toJSON()}>
      <head>
        <meta charset="utf-8" />
        {head}
      </head>
      <body {...attr.body.toJSON()}>
        <div id="root">
          {body}
        </div>
        <script src="/client.js"></script>
        {footer}
      </body>
    </html>
  );
  res.send(html);
});

Host

Just Fragment to control jsx with vanilla-js.

const MyComp = () => {
  const Host = createHost();

  Host.controller = ({ my_text }) => {
    // my_text is a ref="my_text"

    my_text.innerText = "Bar";
  };

  return (
    <Host>
      <h1 ref="my_text">Foo</h1>
    </Host>
  );
};

// Dom updated.
// <h1>Bar</h1>

Options Hook

Options.elem

Attach where element is created.

options.elem = (data) => {
  console.log(data);
};

Options.fc

Attach where FunctionComponent is created.

options.fc = (data) => {
  console.log(data);
};

Lazy

const Home = lazy(() => import("./home.tsx"));

Lazy SSR

const Home = await lazySSR(() => import("./home.tsx"));

Example Todo App

const Item: FC<{ name: string }> = (props) => {
  // create Host as li
  const Host = createHost("li");

  Host.controller = ({ item, remove }) => {
    remove.onclick = () => item.remove();
  };

  return (
    <Host ref="item">
      <span>{props.name}</span>
      <button ref="remove">remove</button>
    </Host>
  );
};
const Todo: FC<{ data: string[] }> = (props) => {
  // inital state from server
  const state = { todos: props.data };

  const Host = createHost();

  Host.controller = ({ form, input, list }) => {
    form.onsubmit = (e) => {
      e.preventDefault();
      list.append(<Item name={input.value} />);
      input.value = "";
      input.focus();
    };
  };

  return (
    <Host>
      <h1>Welcome Todo</h1>
      <form ref="form">
        <input ref="input" placeholder="text..." />
        <button type="submit">Submit</button>
      </form>
      <div ref="list">{state.todos.map((name) => <Item name={name} />)}</div>
    </Host>
  );
};

License

MIT

0.0.16

8 months ago

0.0.15

9 months ago

0.0.14

10 months ago

0.0.13

10 months ago

0.0.12

10 months ago

0.0.11

10 months ago

0.0.10

10 months ago

0.0.9

10 months ago

0.0.8

10 months ago

0.0.7

10 months ago

0.0.6

10 months ago

0.0.5

10 months ago

0.0.4

10 months ago

0.0.3

10 months ago

0.0.2

10 months ago

0.0.1

11 months ago