lifeart / glimmer-next

GXT is `glimmer-vm` runtime alternative, only 7kb gzipped
https://g-next.netlify.app
MIT License
29 stars 3 forks source link
compiler dom-manipulation glimmer-js glimmer-next glimmer-vm gxt handlebars handlebars-js reactive-framework template ui vite

GXT Netlify Status

<img align="right" width="95" height="95" alt="Philosopherโ€™s stone, logo of PostCSS" src="./public/logo.png">

GXT is a cutting-edge, compilable runtime environment designed as glimmer-vm alternative, showcasing the power and flexibility of modern web component development. This repo includes a live example of how GXT can be used in real-world applications, providing developers with a practical and interactive experience. Explore our sample at netlify.

Benefits

Development tools for VS Code

Quick Links

Component sample

Based on template imports RFC

import { RemoveIcon } from "./RemoveIcon.gts";
import type { Item } from "@/utils/data";
import { type Cell, cellFor, Component } from "@lifeart/gxt";

type RowArgs = {
  Args: {
    item: Item;
    selectedCell: Cell<number>;
    onRemove: (item: Item) => void;
  };
};

export class Row extends Component<RowArgs> {
  get labelCell() {
    return cellFor(this.args.item, "label");
  }
  get id() {
    return this.args.item.id;
  }
  get selected() {
    return this.args.selectedCell.value;
  }
  set selected(value: number) {
    this.args.selectedCell.value = value;
  }
  get isSelected() {
    return this.selected === this.id;
  }
  get className() {
    return this.isSelected ? "danger" : "";
  }
  onClick = () => {
    this.selected = this.isSelected ? 0 : this.id;
  };
  onClickRemove = (e: Event) => {
    this.args.onRemove(this.args.item);
  };
  <template>
    <tr class={{this.className}}>
      <td class="col-md-1">{{this.id}}</td>
      <td class="col-md-4">
        <a {{on "click" this.onClick}} data-test-select>{{this.labelCell}}</a>
      </td>
      <td class="col-md-1">
        <a {{on "click" this.onClickRemove}} data-test-remove>
          <RemoveIcon />
        </a>
      </td>
      <td class="col-md-6"></td>
    </tr>
  </template>
}

Key Features

Simple and Expressive Component Model

Reactive Primitives

Benefits and Use Cases

gNext serves as a powerful tool for web developers looking to harness the capabilities of Glimmer-VM in a real-world setting. Its benefits and use cases include:

gNext is not just a library; it's a gateway to building modern, efficient, and reactive web applications using Glimmer-VM. Whether you are building dynamic user interfaces, complex single-page applications, or just experimenting with new front-end technologies, gNext provides the tools and capabilities to bring your ideas to life.

Explore gNext and elevate your web development experience!

Notes

#

function modifier(element: Element, ...args: Args) {
    return () => {
        // destructor
    }
}
function helper(...args: Args): string | boolean | number | null {
  // helper logic
  return 3 + 2;
}

Reactive primitives

formula could be used to create derived state from Cell's. It's autotrack dependencies and update when any of them changed.

scope function is used to suspend ts error about unused variables. It's not required for runtime, but required for ts compilation.

destructors supported.

import { registerDestructor, hbs, scope } from "@lifeart/gxt";

export function Icon() {
  registerDestructor(this, () => {
    console.log("destructor");
  });

  return hbs`<i class="glyphicon glyphicon-remove"></i>`;
}

Setup

Start project from this template: https://github.com/lifeart/template-gxt

or

pnpm create vite my-app --template vanilla-ts
pnpm install @lifeart/gxt

Edit vite.config.mts to import compiler:

import { defineConfig } from "vite";
import { compiler } from "@lifeart/gxt/compiler";

export default defineConfig(({ mode }) => ({
  plugins: [compiler(mode)],
}));

To render root component, use renderComponent function.

import { renderComponent } from "@lifeart/gxt";
import App from "./App.gts";

const Instance = renderComponent(
  new App().template(),
  document.getElementById("app"),
);

To destroy component, use destroyElement function.

import { destroyElement } from "@lifeart/gxt";

destroyElement(Instance);