Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/retrohacker/template
A simple framework for webapps
https://github.com/retrohacker/template
Last synced: 19 days ago
JSON representation
A simple framework for webapps
- Host: GitHub
- URL: https://github.com/retrohacker/template
- Owner: retrohacker
- License: other
- Created: 2023-02-07T22:21:28.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-04-01T22:24:51.000Z (8 months ago)
- Last Synced: 2024-11-11T10:42:41.787Z (about 1 month ago)
- Language: TypeScript
- Size: 46.9 KB
- Stars: 480
- Watchers: 9
- Forks: 9
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-github-star - template
README
# Template
Template is a simple JS framework for creating interactive applications.
It focuses on using web-native patterns.
Calling it a framework is a bit of an exaggeration, it's a single `class` that
manages HTML ``s.The entire "framework" is here: [./template.ts](./template.ts)
# Usage
Your Hello World example:
```html
import Template from "./template.js";
// Create an HTMLTemplateElement from the text representation of HTML
const html = Template.createElement(
'<div><h1 class="message">Hello Template</h2></div>'
);
// Create an HTMLStyleElement from the text representation of a style node
const css = Template.createStyle("<style></style>");
class HelloWorld extends Template {
constructor() {
super(html, css);
}
setMessage(msg) {
// We can use getElement to query for child nodes, in this case: class="message"
// Anything you want to update during runtime should be stored on "this"
const message = this.getElement(".message");
// Update the content of <h1 class="message">
message.innerText = msg;
}
}
// Get the div we want to mount into
const app = document.getElementById("app");
// Create an instance of our HelloWorld component
const helloworld = new HelloWorld();
// Mount our component into the dom
helloworld.mount(app);
// Set our message
helloworld.setMessage("Hello Template!");
```
# How it works
Template uses HTML
[``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template)
to create reusable components.We then "mount" a `` into an element on the page by creating a
[shadow DOM](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM).The shadow DOM encapsulates the reusable components making sure that the CSS and
JS from one component can not interfere with another.Using `.addChild(selector: string, child: Template)` allows us to nest these
components. The parent keeps track of all mounted children. When we unmount the
parent, it will recursively unmount all children.We follow React's philosophy of state flowing down. Our components manage their
own children, configuring the child's state. Children manage updating their own
DOM to reflect changes in state.We also follow React's philosophy of state bubbling up. When a user interacts
with a child node, the child node emits an event. The parent receives the event
and decides what to do.State management, event propogation, etc. are still early and need more thought.
# Build process
You'll want to use a bundler like `vite`
For example:
`index.html`
```html
````index.css`
```css
.WelcomeComponent {
background-color: hsla(0, 0%, 100%, 1);
border-radius: 5px;
display: flex;
flex-direction: row;
}
.button {
padding: 1em;
margin: 0.5em;
cursor: pointer;
background-color: inherit;
transition: background-color linear 0.1s;
border-radius: inherit;
}
.button:hover {
background-color: hsla(0, 0%, 90%, 1);
transition: background-color linear 0.1s;
}
````index.ts`
```typescript
import Template from "template";
import Feather from "feather-icons";
import html from "./index.html?raw";
import css from "./index.css?raw";const template = Template.createElement(html);
const style = Template.createStyle(css);class Welcome extends Template {
constructor() {
super(template, style);
}
mount(host: HTMLElement) {
super.mount(host);
this.getElement(".new > .icon").innerHTML =
Feather.icons["user-plus"].toSvg();
this.getElement(".new").addEventListener("click", () => {
this.emit("new");
});
this.getElement(".pair > .icon").innerHTML =
Feather.icons["smartphone"].toSvg();
this.getElement(".pair").addEventListener("click", () => {
this.emit("pair");
});
return this;
}
}export default Welcome;
```