export async function InitialExample() { return ( <> <h3> This is an example of various capabilities of this pattern </h3> <pre> <Loading> <AsyncExample /> </Loading> </pre> </> ) } 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; }
Renders the following output:
import { Collector } from "@virtualstate/x"; async function *ReactiveExample() { const eventCollector = new Collector(); // Replace the first parameter, don't actually collect any event const onClick = eventCollector.add.bind(eventCollector, Symbol("Click")); const button = document.createElement("button"); button.addEventListener("click", onClick); let visible = false; yield <View />; for await (const events of eventCollector) { visible = events.reduce((visible: boolean) => !visible, visible); yield <View />; // Re focus the button after the onClick, allows for toggling on and off with keyboard button.focus(); } function View() { return ( <div class="ball-container"> {visible ? <span class="ball" /> : undefined} <button type="button" getDocumentNode={() => button}>{visible ? "Grab" : "Bounce"} Ball</button> </div> ) } }
Renders the following output:
This pattern introduces a concept called tokens. A token represents some functionality that has not yet been implemented, allowing for an external consumer to replace the implementation of the token. A good example of this pattern would be a select input, where we may have a default disabled option, or provide an option
const Select = createToken( Symbol("Select"), { defaultValue: "", class: "select" }, // Default children <option disabled>No options available</option> ); // Would render // <Select defaultValue="" class="select">{defaultChildren}</Select> const DefaultSelect = <Select />; // Would render // <Select defaultValue="first" class="select">{givenChildren}</Select> const MySelect = ( <Select defaultValue="first"> <option value="first">First</option> <option value="second">Second</option> </Select> );
These examples are best seen with UI components, but tokens have more use in generic processes where the tokens are used defined data points
interface PersonUpdateOptions { firstName: string; lastName: string; } const PersonUpdateSymbol = Symbol() const PersonUpdate = createToken<typeof PersonUpdateSymbol, PersonUpdateOptions>(PersonUpdateSymbol); interface PersonUpdateFormOptions { onPersonUpdate(update: PersonUpdateOptions): void } const PersonUpdateFormSymbol = Symbol() const PersonUpdateForm = createToken<typeof PersonUpdateFormSymbol, PersonUpdateFormOptions>(PersonUpdateFormSymbol); async function *Component() { const { resolve, promise } = defer<PersonUpdateOptions>(); yield <PersonUpdateForm onPersonUpdate={resolve} /> const { firstName, lastName } = await promise; yield <PersonUpdate firstName={firstName} lastName={lastName} /> }
Currently available frontend tooling allows for JSX to be utilised to represent both web and native user interfaces.
This pattern introduces using JSX for a wide variety of use cases from boolean logic to pure business logic without requiring the use of external state management.
To fit the needs of a wide variety of applications the resulting pattern needed to: