Skip to content

Repository files navigation

Webfx

Web UI framework and utilities.

It was originally created for MusicCloud.

npm

Demos

Project Structure

  • buildDOM.ts - View and DOM builder
  • view.ts - The core of View
  • packages/
  • views/ - Some built-in Views and helpers
    • Basics
    • ListView
    • Dialog
    • Menu
    • Overlay
    • Toast
    • LoadingIndicator
    • Section
  • style.css - CSS for the built-in views
  • dist/ - Bundles
    • webfx.js - UMD bundle for browsers (+ .min.js version)
    • webfxcore.min.js - UMD bundle without the viewlib and style
    • webfx.esm.js - ESM bundle

Installation

Import from modules

Install the module locally using npm:

npm install @yuuza/webfx

Import from ES modules:

import{View,ButtonView}from"@yuuza/webfx";

Load into the browser directly

Add webfx to your web page:

<scriptsrc="https://cdn.jsdelivr.net/npm/@yuuza/webfx@1.9.12/dist/webfx.min.js"></script>

Or if you don't need the viewlib:

<scriptsrc="https://cdn.jsdelivr.net/npm/@yuuza/webfx@1.9.12/dist/webfxcore.min.js"></script>

Then the module can be accessed from global variable webfx:

const{ View, ButtonView, mountView }=webfx;

Usage

A basic view component

// Define a very basic view classclassHelloextendsView{createDom(){// Returns a DOM expression object for rendering.return{tag: "p.text.bold#hello",text: "hello webfx",};}}// Create an instance of the view and mount it onto the <body>.mountView(document.body,newHello());

Renders:

<pclass="text bold" id="hello">hello webfx</p>

Note: You can omit the createDom() can be omited if you want an empty <div>.

DOM Expression

A DOM Expression is an object of type BuildDomNode, or a View object, a string, a number, or a function that returns a string or number.

typeBuildDomNode={tag?: BuildDomTag;// A string that indicates a DOM tag name, class names, and id, similar to a CSS selector.child?: BuildDomExpr[]|BuildDomExpr;// One or more DOM expressions as the children.text?: FuncOrVal<string>;// A shortcut for `textContent`. It can be a function, see below.hidden?: FuncOrVal<boolean>;// The `hidden` property, but can be a function, see below.init?: Action<HTMLElement>;// A callback that is called when the DOM is created.update?: Action<HTMLElement>;// A callback that is called when the view is updated.// ...internal properties omitted...};

The text and hidden callbacks will be called in updateDom().

Properties and Child Elements

Webfx does not have states; they are just properties.

You can use the child key in the DOM expression for child elements.

// Inject Webfx CSS.webfx.injectWebfxCss();classCounterextendsView{constructor(){super();this.count=0;}createDom(){return{tag: "div.counter",child: ["Count: ",()=>this.count,{tag: "br"},newButtonView({text: "Click me",onActive: ()=>{this.updateWith({count: this.count+1});},}),],};}}// Mount the view onto the body element.mountView(document.body,newCounter());

Renders:

<divclass="counter">
Count: 9
<br/><divclass="btn" tabindex="0">Click me</div></div>

Hook Methods

Webfx provides two hook methods:

  • postCreateDom(): called when the DOM is just created.
  • updateDom(): called after postCreateDom(). Can also be called manually by updateDom().

updateWith() is a shortcut for changing properties and calling updateDom().

Note: When overriding these methods, call the super method.

webfx.injectWebfxCss();classCounterextendsView{constructor(){super();this.count=0;}createDom(){return{tag: "div.counter",child: ["Count: ",{tag: "span",text: ()=>this.count,init: (dom)=>{console.info("the <span> DOM is created",dom);},update: (dom)=>{dom.style.fontSize=`${14+this.count}px`;},},{tag: "br"},newButtonView({text: "Click me",onActive: ()=>{this.updateWith({count: this.count+1});},}),],};}postCreateDom(){super.postCreateDom();console.info("the counter DOM is created",this.dom);}updateDom(){super.updateDom();console.info("the counter DOM is updated",this.dom);}}// Mount the view onto the body element.mountView(document.body,newCounter());

ListView

(TBD)

Using JSX/TSX

Before using JSX/TSX, make sure to set jsx() as the JSX factory in the transpiler.

You can do this in one of two ways:

  • Set "jsxFactory": "jsx" in tsconfig.json.
  • Use /** @jsx jsx */ in your source code.
/** @jsx jsx */import{View,ButtonView,jsx}from"@yuuza/webfx";webfx.injectWebfxCss();classCounterextendsView{constructor(){super();this.count=0;}createDom(){return(<divclass="counter">
Count: {()=>this.count}<br/><ButtonViewonActive={()=>{this.updateWith({count: this.count+1});}}>
Click me
</ButtonView></div>);}}// Mount the view onto the body element.mountView(document.body,newCounter());

Todos

  • Implement functional DOM tree updating.
  • Add React-like function components with hooks.

(TBD)

Releases

Packages

Used by

Contributors

Languages