VI. Mount‐based web components - bahrus/trans-render GitHub Wiki

Mount-based web components

Mount Count

Let's move on now to what has become the sine qua non example for web components. The counter. Now we have a rudimentary UI, so we can see how xtal-element approaches this. As always we show the optional TypeScript version. The JS version isn't that different, just remove a little sugar (or toxic chemical waste, depending on your perspective) here and there:

import {MntCfg, Mount, MountActions, MountProps} from 'trans-render/Mount.js';
import {localize} from 'trans-render/funions/Localizer.js';
import { ITransformer, UnitOfWork } from 'trans-render/types.js';

export interface DTRCounterProps {
    count: number;
} 

export interface DTRCounterMethods {
    localize(model: any, transformer: ITransformer<any, any>, uow: UnitOfWork<any, any>, matchingElement: Element): string | Partial<HTMLDataElement> | Partial<HTMLTimeElement> | undefined; 
}
const html = String.raw;
export class DTRCounter extends Mount{
    localize = localize
    static override config: MntCfg<DTRCounterProps & MountProps, DTRCounterMethods & MountActions> = {
        name: 'dtr-counter',
        shadowRootInit:{
            mode: 'open'
        },
        mainTemplate: html `
            <button part=down data-d=-1>-</button>
            <data part=count aria-live=polite></data>
            <button part=up data-d=1>+</button>`,
        propDefaults:{
            count: 30,
        },
        propInfo: {
            ...super.mntCfgMxn.propInfo,
        },
        actions:{
            ...super.mntCfgMxn.actions
        },
        xform: {
            '% count': 'localize',
            button: {
                m: {
                    on: 'click',
                    inc: 'count',
                    byAmt: '.dataset.d',
                },
            }
        },
        styles: [
            html `
<style>
    :host{
        display: block;
    }
    * {
      font-size: 200%;
    }

    span {
      width: 4rem;
      display: inline-block;
      text-align: center;
    }

    button {
      width: 4rem;
      height: 4rem;
      border: none;
      border-radius: 10px;
      background-color: seagreen;
      color: white;
    }
</style>
            `
        ]
    } 
}

await DTRCounter.bootUp();

customElements.define(DTRCounter.config.name!, DTRCounter);

Talking points, Part II

  1. We have kept the binding syntax separate from the markup syntax, similar to CSS. This is based on mount-observing transform syntax. This means migrating to something else should be easier, as the library dependencies aren't all tangled up with the actual presentation structure. Okay, maybe not such a big deal, but just saying.
  2. What I would like to impress upon you is there isn't any code (if we squint our eyes a bit)! It's mostly all JSON serializable, making it truly declarative.
  3. So using this technique, we can envision a large number of web components that can already be made declarative, even without HTML Modules -- using JSON modules, where the JSON module contains a clob or two of HTML, and a clob of CSS.

Now before you run away, justifiably repelled by the notion of editing JSON, I hear you. You and I are cut from the same cloth.

A light-touch "compiler" (or "transpiler"?) is provided by the may-it-be package. So we can edit *.mts files, and benefit from all the typing goodness TypeScript provides, or *.mjs files, and the may-it-be transpiler can output to a file for distribution, that formats the source file into the tightly constrained format that JSON requires. (The may-it-be transpiler also supports another output option -- HTML with declarative ShadowDOM, discussed later.)

<= Mount-observing transforms => Custom Element Manifesting

⚠️ **GitHub.com Fallback** ⚠️