simplified

This commit is contained in:
Geoff Doty 2024-05-05 09:07:17 -04:00
parent 6b00b9ed2b
commit 5b9b2c2624
4 changed files with 22 additions and 39 deletions

View File

@ -2,24 +2,23 @@
> Minimal Javascript UI Library > Minimal Javascript UI Library
This is an experimental composable ui library that takes ideas from Elm Architecture, but without the doctrine - this is Javascript! This is an experimental composable ui builder that takes ideas from Elm Architecture, but without the doctrine - this is Javascript!
## Features ## Features
- No Virtual Dom - No Virtual Dom
- No Build System - No Build System
- No Over Engineering - No Over Engineering
- ~100 lines of code - ~1kb minified
- Totally inefficient rendering (at scale) - Totally INEFFICIENT rendering (at scale)
## Overview ## Overview
the `app` builder takes an `opts` object that expects it to include: the `app` builder takes an `opts` object that expects:
- `state` as initial data `{object}` - `state` as initial data `{object}`
- `actions` as `{object}` with functions definitions - `actions` as `{object}` with functions definitions
- `view` as `{function}` that returns valid dom - `view` as `{function}` that returns valid dom
- `mount` as querySelector compatible `{string}`
and a querySelector compatible `selector` to mount the ui.
`app` returns: `app` returns:
@ -30,7 +29,7 @@ and a querySelector compatible `selector` to mount the ui.
```html ```html
<script type="module"> <script type="module">
import {app, h} from "./tagged.js"; import {app, h} from "./tagged.min.js";
const myapp = app({ const myapp = app({
state: {name: "[Your Name Here]", job: "Developer"}, state: {name: "[Your Name Here]", job: "Developer"},
@ -54,11 +53,8 @@ and a querySelector compatible `selector` to mount the ui.
### Inspired By ### Inspired By
- hyperapp - hyperapp
- mithril
- Elm Architecture - Elm Architecture
## Todo ## Notes
- Actions Example
> WORK-IN-PROGRESS > WORK-IN-PROGRESS

2
dist/tagged.min.js vendored
View File

@ -1,3 +1,3 @@
/*! Tagged v:0.1 | MIT LICENSE | https://github.com/n2geoff/tagged */ /*! Tagged v:0.1 | MIT LICENSE | https://github.com/n2geoff/tagged */
function tag(tag,...args){const el=document.createElement(tag);return args.forEach((arg=>{"string"==typeof arg||"number"==typeof arg?el.appendChild(document.createTextNode(arg)):Array.isArray(arg)?el.append(...arg):Object.assign(el,arg)})),el}function app(opts,selector="body"){let data={},view=()=>null,actions={};const $=document.querySelector.bind(document),state=state=>("object"==typeof state&&(data={...data,...state}),update(),data),update=()=>{$(selector).replaceChildren(view(data,actions))};return opts.view&&"function"==typeof opts.view&&(view=opts?.view),opts.state&&"object"==typeof opts.state&&(data=state(opts.state)),opts.actions&&"object"==typeof opts.actions&&(actions=opts.actions),opts.view&&selector&&update(),{state:state,actions:actions}}const h=tag;export{app,h}; function tag(tag,...args){const el=document.createElement(tag);return args.forEach((arg=>{"string"==typeof arg||"number"==typeof arg?el.appendChild(document.createTextNode(arg)):Array.isArray(arg)?el.append(...arg):Object.assign(el,arg)})),el}function app(opts){let data=check(opts.state,{}),view=check(opts.view,(()=>null)),actions=check(opts.actions,{}),mount=opts.mount||"body";function check(value,type){return typeof value==typeof type?value:type}const update=()=>{document.querySelector(mount).replaceChildren(view(data,actions))};return opts.view&&mount&&update(),{state:state=>("object"==typeof state&&(data={...data,...state}),update(),data),actions:actions}}const h=tag;export{app,h};
//# sourceMappingURL=true //# sourceMappingURL=true

View File

@ -1 +1 @@
{"version":3,"names":["tag","args","el","document","createElement","forEach","arg","appendChild","createTextNode","Array","isArray","append","Object","assign","app","opts","selector","data","view","actions","$","querySelector","bind","state","update","replaceChildren","h"],"sources":["dist/tagged.js"],"mappings":"AAQA,SAASA,IAAIA,OAAQC,MACjB,MAAMC,GAAKC,SAASC,cAAcJ,KAYlC,OAVAC,KAAKI,SAASC,MACS,iBAARA,KAAmC,iBAARA,IAClCJ,GAAGK,YAAYJ,SAASK,eAAeF,MAChCG,MAAMC,QAAQJ,KACrBJ,GAAGS,UAAUL,KAEbM,OAAOC,OAAOX,GAAII,IACtB,IAGGJ,EACX,CAEA,SAASY,IAAIC,KAAMC,SAAW,QAE1B,IAAIC,KAAO,CAAC,EACRC,KAAO,IAAM,KACbC,QAAU,CAAC,EAGf,MAAMC,EAAIjB,SAASkB,cAAcC,KAAKnB,UAGhCoB,MAASA,QACS,iBAAVA,QACNN,KAAO,IAAIA,QAASM,QAIxBC,SAGOP,MAGLO,OAAS,KACXJ,EAAEJ,UAAUS,gBAAgBP,KAAKD,KAAME,SAAS,EAwBpD,OApBIJ,KAAKG,MAA6B,mBAAdH,KAAKG,OACzBA,KAAOH,MAAMG,MAIbH,KAAKQ,OAA+B,iBAAfR,KAAKQ,QAE1BN,KAAOM,MAAMR,KAAKQ,QAIlBR,KAAKI,SAAmC,iBAAjBJ,KAAKI,UAC5BA,QAAUJ,KAAKI,SAIfJ,KAAKG,MAAQF,UACbQ,SAGG,CACHD,YACAJ,gBAER,CAEA,MAAMO,EAAI1B,WAEDc,IAAKY","ignoreList":[]} {"version":3,"names":["tag","args","el","document","createElement","forEach","arg","appendChild","createTextNode","Array","isArray","append","Object","assign","app","opts","data","check","state","view","actions","mount","value","type","update","querySelector","replaceChildren","h"],"sources":["dist/tagged.js"],"mappings":"AAQA,SAASA,IAAIA,OAAQC,MACjB,MAAMC,GAAKC,SAASC,cAAcJ,KAYlC,OAVAC,KAAKI,SAASC,MACS,iBAARA,KAAmC,iBAARA,IAClCJ,GAAGK,YAAYJ,SAASK,eAAeF,MAChCG,MAAMC,QAAQJ,KACrBJ,GAAGS,UAAUL,KAEbM,OAAOC,OAAOX,GAAII,IACtB,IAGGJ,EACX,CAEA,SAASY,IAAIC,MAET,IAAIC,KAAUC,MAAMF,KAAKG,MAAO,CAAC,GAC7BC,KAAUF,MAAMF,KAAKI,MAAM,IAAM,OACjCC,QAAUH,MAAMF,KAAKK,QAAS,CAAC,GAC/BC,MAAUN,KAAKM,OAAS,OAG5B,SAASJ,MAAMK,MAAOC,MAClB,cAAcD,cAAiBC,KAAOD,MAAQC,IAClD,CAGA,MAYMC,OAAS,KACXrB,SAASsB,cAAcJ,OAAOK,gBAAgBP,KAAKH,KAAMI,SAAS,EAQtE,OAJIL,KAAKI,MAAQE,OACbG,SAGG,CACHN,MAtBWA,QACS,iBAAVA,QACNF,KAAO,IAAIA,QAASE,QAIxBM,SAGOR,MAcPI,gBAER,CAEA,MAAMO,EAAI3B,WAEDc,IAAKa","ignoreList":[]}

View File

@ -1,11 +1,14 @@
export default function app(opts, selector = "body") { export default function app(opts) {
// initial setup // initial setup
let data = {}; let data = check(opts.state, {});
let view = () => null; let view = check(opts.view, () => null);
let actions = {}; let actions = check(opts.actions, {});
let mount = opts.mount || "body";
// query helper // check set or default
const $ = document.querySelector.bind(document); function check(value, type) {
return typeof value === typeof type ? value : type;
}
// state helper // state helper
const state = (state) => { const state = (state) => {
@ -21,32 +24,16 @@ export default function app(opts, selector = "body") {
} }
const update = () => { const update = () => {
$(selector).replaceChildren(view(data, actions)); document.querySelector(mount).replaceChildren(view(data, actions));
}
// setup view function
if (opts.view && typeof opts.view === "function") {
view = opts?.view;
}
// setup data object
if (opts.state && typeof opts.state === "object") {
// wrap data in state object
data = state(opts.state);
}
// setup actions object
if (opts.actions && typeof opts.actions === "object") {
actions = opts.actions;
} }
// mount view // mount view
if (opts.view && selector) { if (opts.view && mount) {
update(); update();
} }
return { return {
state, state,
actions, actions,
}; }
} }