Releases: hstd-dev/hstd
0.1.40 - Task
📝 Task
Self-resolvable Promise provides phase handling which triggered by user.
import { $, h as html, io, Task } from "hstd";
const Iterated = async function*() {
const
user = $(''),
next = Task() // returns self-resolvable Promise.
;
yield html`
<label>Show user <input ${{ [io.value]: user }}/></label>
<button ${{ [on.click]: () => next(user.$) }}>submit</button>
`;
const finalUser = await next();
yield html`
<label>Loading...</label>
`;
const { name, age, link } = await fetch(`/api/user/${finalUser}`).then(res => res.json());
yield html`
<div>
<label>${name}</label>
<label>${age}</label>
<label>${link}</label>
</div>
`;
}0.1.37 - Exposing Cores
⚙ Exposing Core Features
in 0.1.37, we added exports which contains some parts of hstd's core:
Pointer()
Module Pointer is the unwrapped edition of $.
import { $, Pointer } from "hstd";
const count = Pointer(0);
++count.$; // "1"This module does not support some few features, such as producing pointer from template:
$`count is ${count}`; // "count is 1"
Pointer`count is ${count}`; // TypeErrorand processing global property:
$.console.log(count); // show log from "count" changes
Pointer.console.log(count); // TypeError...which is slightly faster than wrapped $.
Memo()
Module Memo uses Map or WeakMap to eliminate additional, unnecessary computation like React's useMemo().
this is used in various scene, from TemplateStringsArray validation layer to Pointer's binding strategy.
import { Memo } from "hstd";
const sum = Memo((input) => {
console.log("computing...");
return input + 1
});
sum(1); // returns "2"
// console: "computing..."
sum(1); // returns "2"
// nothing appears at console, which shows the callback was not executed.the second arguments of Memo defines which method should be use between WeakMap or Map:
const resolveTemplate = Memo((template) => {
console.log(`analyzing template... ${template.join("[value]")}`)
const processedTemplate = // analyzing process continues...
return (values) => processedTemplate(values);
}, true); // put "true" here when you want to use WeakMap for caching keys instead of Map.
const temp = (a, ...b) => resolveTemplate(a)(b);
const factory = () => temp`Hello world at ${performance.now()}`;
factory(); // returns: Hello world at 1187.437022
// console: "analyzing template... Hello world at [value]"
factory(); // returns: Hello world at 1196.921623
// nothing appears at console, which shows the first callback was not executed.Prop()
Module Prop generates proxied stackable prop, which used in our on and css:
import { h as html, Prop } from "hstd";
const myStackable = Prop(
(key) => (value, ref) => ref[key] = value;
);
document.body.append(...html`
<video ${{ [myStackableProp.src]: "cat.webp" }}></video>
<audio ${{
[myStackableProp]: {
src: "cat.opus"
}
}}></audio>
`)0.1.31 - from()
import { $ } from 'hstd';
const $innerWidth = $(innerWidth).from(resolve => {
addEventListener("resize", () => resolve(innerWidth), { passive: true })
});
$innerWidth.watch($ => console.log($)); // shows current innerWidth!0.1.28 - Async Iterator Support
💫 Async Iterator Support
For customized complex fallbacks:
import { $, h as html } from "hstd";
async function* UserProfile(userId: string): AsyncGenerator<HSTDFragment> {
const
loadingDots: $<number> = $(0, $ => $ % 3),
loadingDotsInterval: string = setInterval(() => loadingDots.$++, 700)
;
yield html`
<span>Loading${$`.`.repeat(loadingDots.into($ => $ + 1))}</span>
`;
const { name, age, link } = await fetch(`/api/user/${userId}`).then(res => res.json());
clearInterval(loadingDotsInterval);
yield html`
<div>
<label>${name}</label>
<label>${age}</label>
<label>${link}</label>
</div>
`;
}
document.body.append(...html`${UserProfile("ihasq")}`);or write your own Suspense:
async function* Suspense({ fallback }, main) {
yield* fallback;
yield* await main;
}
document.body.append(...html`
${Suspense({ fallback: html`<label>Loading...</label>` },
User({ id: "ihasq" })
)}
`)0.1.22
Added:
🦖 Asyncified - HyperStandard now supports Promise
async function WithFetch() {
const { name, age, gender } = await fetch("/api/user/ihasq").then(res => res.json());
return html`
<h1>${name}</h1>
<h2>Age: ${age}</h2>
<h2>Gender: ${gender}</h2>
`
}
document.body.append(...html`${WithFetch()}`) // without "await" !!