@virtualstate/x

nycrc config on GitHub 87.99%25 lines covered 87.99%25 statements covered 67.61%25 functions covered 83.31%25 branches covered

If you want to get started, fork or clone the virtualstate.dev repository for an already set up project.

Running Examples

To run the examples located at packages/examples see:

Running examples with Deno

deno run \                                                                                                                                                                                             *[main] 
  --import-map=https://cdn.skypack.dev/@virtualstate/deno/import-map.json \
  --allow-net \
  https://cdn.skypack.dev/@virtualstate/examples/lib/log.js

Running examples with Node

git clone https://github.com/virtualstate/x.git 
cd x 
yarn
yarn build
yarn examples:log

Running examples with npx

npx @virtualstate/examples@^2.14.10 

h

Demo Usage

import { h, createFragment } from "@virtualstate/x";

async function AsyncExample() {
  return await new Promise(
    resolve => setTimeout(resolve, 1500, `Async result: ${Math.random()}`)
  );
}

async function *Loading(options: unknown, child: VNode) {
  yield <>Loading!</>;
  yield child;
}

export async function InitialExample() {
  return (
    <div class="output">
      <h3>
        This is an example of various
        capabilities of this pattern
      </h3>
      <pre>
        <Loading>
          <AsyncExample />
        </Loading>
      </pre>
    </div>
  )
}

Working with a virtual node

Related Blog Post

The returned of h is a VNode:

export interface VNode {
  source: unknown;
  options?: object;
  children?: AsyncIterable<VNode[]>;
}

Scalar nodes created with h will be returned directly

import { h } from "@virtualstate/x";

const node = h(1);
const { source: one } = node;
console.log({ one }); // Logs { one: 1 }

Any scalar nodes with h that have children can be read using for await

const first = h("first");
const second = h("second");
const third = h("third");
const node = h("result", {}, first, second, third);

const { source: result, children } = node;
console.log({ result }); // Logs { result: "result" }

if (!children) throw new Error("Expected children");

for await (const results of children) {
  // Eventually Logs { results: ["first", "second", "third" ] }
  console.log({ results: results.map(node => node.source) });
}

Any function type can be used as a virtual node

import { h } from "@virtualstate/x";

function Fn() {
  return "Function ✨";
}
async function AsyncFn() {
  await new Promise<void>(queueMicrotask);
  return "Async Function 💡";
}
function *GeneratorFn() {
  yield "GeneratorFn Loading";
  yield "GeneratorFn 💥";
}
async function *AsyncGeneratorFn() {
  yield "AsyncGeneratorFn Loading";
  yield "AsyncGeneratorFn 🔥";
}
function Fns() {
  return [
    h(Fn),
    h(AsyncFn),
    h(GeneratorFn),
    h(AsyncGeneratorFn)
  ]
    .map(node => f("fn", { name: node.source.name }, node.source.name, node));
}

const { children } = f(Fns);

if (!children) throw new Error("Expected children");

for await (const results of children) {
  // Eventually Logs { results: ["Fn", "AsyncFn", "GeneratorFn", "AsyncGeneratorFn" ] }
  console.log({ results: results.map(node => node.options.name) });
}

union

import { union } from "@virtualstate/x";

async function wait(ms = 10) {
  await new Promise((resolve) => setTimeout(resolve, ms));
}

async function* left() {
  yield "Left 1";
  await wait(19);
  yield "Left 2";
  await wait(401);
  yield "Left 3";
}

function* middle() {
  yield "Middle 1";
  yield "Middle 2";
  yield "Middle 3";
}

async function* right() {
  yield "Right 1";
  await wait(401);
  yield "Right 2";
  yield "Right 3";
  await wait(19);
  yield "Right 4";
}

for await (const [leftResult, middleResult, rightResult] of union([
  left(),
  middle(),
  right()
])) {
  const result = { leftResult, middleResult, rightResult };
  console.log(result);
  document.body.innerHTML = JSON.stringify(result, undefined, "  ");
}

Discord

Interested in talking more about the project? Find us on Discord

Contributing

Please see Contributing

Code of Conduct

This project and everyone participating in it is governed by the Code of Conduct listed here. By participating, you are expected to uphold this code. Please report unacceptable behavior to conduct@fabiancook.dev.

Licence

This repository is licensed under the MIT license.