zenith 0.0.1 → 1.0.0-beta.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Daniel Barber / Aleph1 Technologies Inc
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # Zenith
2
+
3
+ Zenith is a tiny yet powerful reactive JavaScript framework that is under 2.5kb minified and gzipped, and 2.25kb minified and brotlified.
4
+
5
+ Its virtual dom and diffing algorithm function on an entire page or on specific nodes — especially useful in cases where you know that only a portion of the (v)dom tree will change. It allows for granular control over components that need to govern themselves and their own content, such as canvas, WebGL, or SVG. Additionally, it includes an opt-in object pool to minimize garbage collection.
6
+
7
+ Zenith is fast, flexible, fully tested, and doesn’t require a build step. It wouldn’t exist without [Mithril.js](https://github.com/MithrilJS/mithril.js).
8
+
9
+ **The current release release is alpha. It is used in production, but is still rapidly evolving. Consider the API relatively safe.**
10
+
11
+ ## Installation
12
+
13
+ For now, use the .js files in /dist/.
14
+
15
+ Will be available on npm soon.
16
+
17
+ ## Additional Information
18
+
19
+ WIP: [Zenith site](https://aleph-1.com/zenith)
20
+
21
+ Documentation coming soon.
22
+
23
+ ## Simple Use Case
24
+
25
+ ```html
26
+ <!DOCTYPE html>
27
+ <html lang="en">
28
+ <head>
29
+ </head>
30
+ <body>
31
+ <main id="app"></main>
32
+ <script src="js/zenith.min.js"></script>
33
+ <script>
34
+ let counter = 0;
35
+ const CounterDef = z.compDef({
36
+ draw: vNode => z.elem('div', z.text(`Counter: {$counter}`)),
37
+ tick: vNode => {
38
+ counter++;
39
+ vNode.redraw();
40
+ }
41
+ });
42
+ z.mount(document.querySelector('#app'), z.comp(CounterDef));
43
+ </script>
44
+ </body>
45
+ </html>
46
+ ```
47
+
48
+ ## License
49
+
50
+ [MIT](LICENSE.md)
@@ -0,0 +1,152 @@
1
+ /*! Zenith Helpers v1.0.0-beta.13 | MIT License | © 2022-2025 Daniel Barber */
2
+ import { node, draw } from './zenith.js';
3
+
4
+ const keep = () => true;
5
+
6
+ const VNODE_ELEM = 1;
7
+ const VNODE_TEXT = 2;
8
+ const VNODE_COMP = 3;
9
+ const VNODE_NODE = 4;
10
+ const VNODE_COMPDEF = 5;
11
+
12
+ const is = {
13
+ elem: VNODE_ELEM,
14
+ text: VNODE_TEXT,
15
+ comp: VNODE_COMP,
16
+ node: VNODE_NODE,
17
+ compDef: VNODE_COMPDEF
18
+ };
19
+
20
+ const cls = (...args) => args.filter(Boolean).join(" ");
21
+
22
+ const slot = (content, attrs) => {
23
+ if (content) {
24
+ if (typeof content === "function") return content(attrs);
25
+ return content;
26
+ }
27
+ };
28
+
29
+ const html = (value) => {
30
+ const container = document.createElement("div");
31
+ container.innerHTML = value + "";
32
+ const nodes = [...container.childNodes].map((child) => node(child));
33
+ return nodes.length === 1 ? nodes[0] : nodes;
34
+ };
35
+
36
+ const closest = (vNode, predicate) => {
37
+ for (let current = vNode.up; current; current = current.up) {
38
+ if (predicate(current)) return current;
39
+ }
40
+ };
41
+
42
+ const inject = (vNode, ...keys) => {
43
+ const result = {};
44
+ const needed = new Set(keys);
45
+ for (let current = vNode.up; current && needed.size > 0; current = current.up) {
46
+ if (current.is === is.comp && current.provide) {
47
+ for (const key of needed) {
48
+ if (current.provide[key] !== void 0) {
49
+ result[key] = current.provide[key];
50
+ needed.delete(key);
51
+ }
52
+ }
53
+ }
54
+ }
55
+ return result;
56
+ };
57
+
58
+ const signal = (val) => {
59
+ let _val = val;
60
+ const _fns = /* @__PURE__ */ new Set();
61
+ const notify = () => {
62
+ for (const fn of _fns) fn(_val);
63
+ };
64
+ return {
65
+ get val() {
66
+ return _val;
67
+ },
68
+ set val(newVal) {
69
+ if (_val !== newVal) {
70
+ _val = newVal;
71
+ notify();
72
+ }
73
+ },
74
+ sub(fn) {
75
+ _fns.add(fn);
76
+ return () => _fns.delete(fn);
77
+ },
78
+ notify
79
+ };
80
+ };
81
+
82
+ const derived = (fn, deps) => {
83
+ const computed = signal(fn());
84
+ const cleanups = deps.map((dep) => dep.sub(() => {
85
+ computed.val = fn();
86
+ }));
87
+ computed.destroy = () => {
88
+ for (const cleanup of cleanups) cleanup();
89
+ cleanups.length = 0;
90
+ };
91
+ return computed;
92
+ };
93
+
94
+ const router = (routes, options = {}) => {
95
+ const isHistory = options.mode === "history";
96
+ const eventType = isHistory ? "popstate" : "hashchange";
97
+ const getPath = () => isHistory ? location.pathname : location.hash.slice(1) || "/";
98
+ const compiled = [];
99
+ const matchRoute = (path) => {
100
+ for (const route of compiled) {
101
+ const match = path.match(route.regex);
102
+ if (match) {
103
+ const params = {};
104
+ for (let i = 0; i < route.keys.length; i++) {
105
+ params[route.keys[i]] = match[i + 1];
106
+ }
107
+ return { component: route.component, params };
108
+ }
109
+ }
110
+ return { component: routes["*"] || null, params: {} };
111
+ };
112
+ for (const pattern in routes) {
113
+ const keys = [];
114
+ const regexPattern = pattern.replace(/:[^/]+/g, (match) => {
115
+ keys.push(match.slice(1));
116
+ return "([^/]+)";
117
+ }).replace(/\*/g, "(.*)");
118
+ compiled.push({
119
+ regex: new RegExp(`^${regexPattern}$`),
120
+ keys,
121
+ component: routes[pattern]
122
+ });
123
+ }
124
+ return {
125
+ init(vNode) {
126
+ const matched = matchRoute(getPath());
127
+ vNode.route = matched.component;
128
+ vNode.params = matched.params;
129
+ vNode.onroute = () => {
130
+ const matched2 = matchRoute(getPath());
131
+ vNode.route = matched2.component;
132
+ vNode.params = matched2.params;
133
+ draw(vNode, true);
134
+ };
135
+ window.addEventListener(eventType, vNode.onroute);
136
+ },
137
+ draw: (vNode) => {
138
+ var _a;
139
+ return (_a = vNode.route) == null ? void 0 : _a.call(vNode, vNode.params);
140
+ },
141
+ removed(vNode) {
142
+ window.removeEventListener(eventType, vNode.onroute);
143
+ }
144
+ };
145
+ };
146
+
147
+ const Portal = {
148
+ to: (vNode) => typeof vNode.attrs.to === "string" ? document.querySelector(vNode.attrs.to) : vNode.attrs.to,
149
+ draw: (vNode) => vNode.attrs.children
150
+ };
151
+
152
+ export { Portal, closest, cls, derived, html, inject, is, keep, router, signal, slot };
@@ -0,0 +1,2 @@
1
+ /*! Zenith Helpers v1.0.0-beta.13 | MIT License | © 2022-2025 Daniel Barber */
2
+ !function(e){"use strict";const is={elem:1,text:2,comp:3,node:4,compDef:5},signal=e=>{let t=e;const o=new Set,n=()=>{for(const e of o)e(t)};return{get val(){return t},set val(e){t!==e&&(t=e,n())},sub:e=>(o.add(e),()=>o.delete(e)),notify:n}};window.zh={keep:()=>!0,is:is,cls:(...e)=>e.filter(Boolean).join(" "),slot:(e,t)=>{if(e)return"function"==typeof e?e(t):e},html:t=>{const o=document.createElement("div");o.innerHTML=t+"";const n=[...o.childNodes].map(t=>e.node(t));return 1===n.length?n[0]:n},closest:(e,t)=>{for(let o=e.up;o;o=o.up)if(t(o))return o},inject:(e,...t)=>{const o={},n=new Set(t);for(let t=e.up;t&&n.size>0;t=t.up)if(t.is===is.comp&&t.provide)for(const e of n)void 0!==t.provide[e]&&(o[e]=t.provide[e],n.delete(e));return o},signal:signal,derived:(e,t)=>{const o=signal(e()),n=t.map(t=>t.sub(()=>{o.val=e()}));return o.destroy=()=>{for(const e of n)e();n.length=0},o},router:(t,o={})=>{const n="history"===o.mode,r=n?"popstate":"hashchange",s=()=>n?location.pathname:location.hash.slice(1)||"/",c=[],a=e=>{for(const t of c){const o=e.match(t.regex);if(o){const e={};for(let n=0;t.keys.length>n;n++)e[t.keys[n]]=o[n+1];return{component:t.component,params:e}}}return{component:t["*"]||null,params:{}}};for(const e in t){const o=[],n=e.replace(/:[^/]+/g,e=>(o.push(e.slice(1)),"([^/]+)")).replace(/\*/g,"(.*)");c.push({regex:RegExp(`^${n}$`),keys:o,component:t[e]})}return{init(t){const o=a(s());t.route=o.component,t.params=o.params,t.onroute=()=>{const o=a(s());t.route=o.component,t.params=o.params,e.draw(t,!0)},window.addEventListener(r,t.onroute)},draw:e=>{var t;return null==(t=e.route)?void 0:t.call(e,e.params)},removed(e){window.removeEventListener(r,e.onroute)}}},Portal:{to:e=>"string"==typeof e.attrs.to?document.querySelector(e.attrs.to):e.attrs.to,draw:e=>e.attrs.children}}}(z);
@@ -0,0 +1,2 @@
1
+ /*! Zenith Helpers v1.0.0-beta.13 | MIT License | © 2022-2025 Daniel Barber */
2
+ import{node as e,draw as t}from"./zenith.js";const keep=()=>!0,is={elem:1,text:2,comp:3,node:4,compDef:5},cls=(...e)=>e.filter(Boolean).join(" "),slot=(e,t)=>{if(e)return"function"==typeof e?e(t):e},html=t=>{const o=document.createElement("div");o.innerHTML=t+"";const n=[...o.childNodes].map(t=>e(t));return 1===n.length?n[0]:n},closest=(e,t)=>{for(let o=e.up;o;o=o.up)if(t(o))return o},inject=(e,...t)=>{const o={},n=new Set(t);for(let t=e.up;t&&n.size>0;t=t.up)if(3===t.is&&t.provide)for(const e of n)void 0!==t.provide[e]&&(o[e]=t.provide[e],n.delete(e));return o},signal=e=>{let t=e;const o=new Set,n=()=>{for(const e of o)e(t)};return{get val(){return t},set val(e){t!==e&&(t=e,n())},sub:e=>(o.add(e),()=>o.delete(e)),notify:n}},derived=(e,t)=>{const o=signal(e()),n=t.map(t=>t.sub(()=>{o.val=e()}));return o.destroy=()=>{for(const e of n)e();n.length=0},o},router=(e,o={})=>{const n="history"===o.mode,r=n?"popstate":"hashchange",s=()=>n?location.pathname:location.hash.slice(1)||"/",a=[],c=t=>{for(const e of a){const o=t.match(e.regex);if(o){const t={};for(let n=0;e.keys.length>n;n++)t[e.keys[n]]=o[n+1];return{component:e.component,params:t}}}return{component:e["*"]||null,params:{}}};for(const t in e){const o=[],n=t.replace(/:[^/]+/g,e=>(o.push(e.slice(1)),"([^/]+)")).replace(/\*/g,"(.*)");a.push({regex:RegExp(`^${n}$`),keys:o,component:e[t]})}return{init(e){const o=c(s());e.route=o.component,e.params=o.params,e.onroute=()=>{const o=c(s());e.route=o.component,e.params=o.params,t(e,!0)},window.addEventListener(r,e.onroute)},draw:e=>{var t;return null==(t=e.route)?void 0:t.call(e,e.params)},removed(e){window.removeEventListener(r,e.onroute)}}},Portal={to:e=>"string"==typeof e.attrs.to?document.querySelector(e.attrs.to):e.attrs.to,draw:e=>e.attrs.children};export{Portal,closest,cls,derived,html,inject,is,keep,router,signal,slot};
@@ -0,0 +1,536 @@
1
+ /*! Zenith v1.0.0-beta.13 | MIT License | © 2022-2025 Daniel Barber */
2
+ const VNODE_ELEM = 1;
3
+ const VNODE_TEXT = 2;
4
+ const VNODE_COMP = 3;
5
+ const VNODE_NODE = 4;
6
+ const VNODE_COMPDEF = 5;
7
+
8
+ const boundNodes = /* @__PURE__ */ new Map();
9
+ const redrawQueue = /* @__PURE__ */ new Set();
10
+ const ns = {
11
+ math: "http://www.w3.org/1998/Math/MathML",
12
+ svg: "http://www.w3.org/2000/svg"
13
+ };
14
+ const FLAG_IS_DEFINED = 1;
15
+ const FLAG_IS_STALE = 2;
16
+ const FLAG_IS_REMOVING = 4;
17
+ const FLAG_HAS_LIFECYCLE = 8;
18
+ const FLAG_HAS_REMOVE = 16;
19
+ const FLAG_HAS_REMOVED = 32;
20
+ const FLAG_REMOVE_CALLED = 64;
21
+ const DIFF_NONE = 1;
22
+ const DIFF_SELF = 2;
23
+ const DIFF_NODES = 4;
24
+ const DIFF_ALL = DIFF_SELF | DIFF_NODES;
25
+ const diff = {
26
+ none: DIFF_NONE,
27
+ self: DIFF_SELF,
28
+ nodes: DIFF_NODES,
29
+ all: DIFF_ALL
30
+ };
31
+ const ALWAYS_EMPTY_ARRAY = Object.freeze([]) ;
32
+ const ALWAYS_EMPTY_OBJECT = Object.freeze({}) ;
33
+ const ALWAYS_EMPTY_MAP = /* @__PURE__ */ new Map();
34
+ const sync = () => {
35
+ let remaining = redrawQueue.size;
36
+ let targetEl;
37
+ if (remaining) {
38
+ const active = document.activeElement;
39
+ for (const redrawNode of redrawQueue) {
40
+ targetEl = boundNodes.has(redrawNode.el) ? redrawNode.el : redrawNode.attrs && redrawNode.attrs.to || redrawNode.el && redrawNode.el.parentNode || redrawNode.up && redrawNode.up.el;
41
+ redrawQueue.delete(redrawNode);
42
+ if (targetEl) {
43
+ _redrawComponent(redrawNode, targetEl);
44
+ }
45
+ if (!--remaining) break;
46
+ }
47
+ if (redrawQueue.size) Promise.resolve().then(sync);
48
+ if (active && active !== document.activeElement && typeof active.focus === "function") {
49
+ active.focus();
50
+ }
51
+ }
52
+ };
53
+ const draw = (vNode, surgical) => {
54
+ if (surgical) {
55
+ if (vNode.is === VNODE_COMP) {
56
+ vNode.$tag |= FLAG_IS_STALE;
57
+ }
58
+ redrawQueue.add(vNode);
59
+ } else {
60
+ let current;
61
+ for (current = vNode; current.up; current = current.up) ;
62
+ redrawQueue.add(current);
63
+ for (current = vNode; current.up; current = current.up) {
64
+ if (current.is === VNODE_COMP) {
65
+ if (current.$tag & FLAG_IS_STALE) break;
66
+ current.$tag |= FLAG_IS_STALE;
67
+ }
68
+ }
69
+ }
70
+ if (redrawQueue.size === 1) {
71
+ Promise.resolve().then(sync);
72
+ }
73
+ };
74
+ const _flattenReusableArray = [];
75
+ const _flatten = (nodes, offset = 0, arr = []) => {
76
+ let node2;
77
+ if (!(nodes && typeof nodes === "object" && nodes.length != null)) {
78
+ _flattenReusableArray[0] = nodes;
79
+ nodes = _flattenReusableArray;
80
+ }
81
+ for (offset; offset < nodes.length; offset++) {
82
+ node2 = nodes[offset];
83
+ if (Array.isArray(node2)) {
84
+ _flatten(node2, 0, arr);
85
+ } else if (node2 != null) {
86
+ if (node2.is) {
87
+ if (arr.$keys === void 0) {
88
+ arr.$keys = node2.attrs && "$key" in node2.attrs ? ALWAYS_EMPTY_MAP : null;
89
+ } else if (!arr.$keys !== !(node2.attrs && "$key" in node2.attrs)) {
90
+ throw new Error("Children have mixed keys..." );
91
+ }
92
+ arr.push(node2);
93
+ } else if (node2 !== true && node2 !== false) {
94
+ if (arr.$keys === void 0) {
95
+ arr.$keys = null;
96
+ } else if (arr.$keys) {
97
+ throw new Error(`Children have mixed keys. Wrap strings in elem('span', {$key}, "My keyed string.")` );
98
+ }
99
+ arr.push({
100
+ is: VNODE_TEXT,
101
+ $tag: node2 + "",
102
+ $def: null,
103
+ attrs: null,
104
+ nodes: null,
105
+ up: null,
106
+ el: null
107
+ });
108
+ }
109
+ }
110
+ }
111
+ return arr;
112
+ };
113
+ const _lastRoot = (vNode) => {
114
+ if (vNode.is === VNODE_COMP && !vNode.attrs.to) {
115
+ for (let i = vNode.nodes.length - 1; i >= 0; i--) {
116
+ const root = _lastRoot(vNode.nodes[i]);
117
+ if (root) return root;
118
+ }
119
+ return null;
120
+ }
121
+ return vNode.el;
122
+ };
123
+ const _place = (vNode, parentEl, next) => {
124
+ if (vNode.is === VNODE_COMP && !vNode.attrs.to) {
125
+ for (let i = vNode.nodes.length - 1; i >= 0; i--) {
126
+ next = _place(vNode.nodes[i], parentEl, next);
127
+ }
128
+ } else if (vNode.el) {
129
+ if (vNode.el.nextSibling !== next) parentEl.insertBefore(vNode.el, next);
130
+ next = vNode.el;
131
+ }
132
+ return next;
133
+ };
134
+ const _updateNode = (parentNode, parentEl, newNode, oldNode, xmlns, skipMemo) => {
135
+ if (oldNode.el) {
136
+ const newNodeType = newNode.is;
137
+ if (newNodeType === oldNode.is) {
138
+ if (newNodeType === VNODE_ELEM) {
139
+ newNode.up = parentNode;
140
+ if (newNode.$tag === oldNode.$tag) {
141
+ newNode.el = oldNode.el;
142
+ newNode.$h = oldNode.$h;
143
+ const diff2 = newNode.attrs.$diff || DIFF_ALL;
144
+ if (diff2 & DIFF_SELF) {
145
+ _setElAttributes(newNode, oldNode.attrs);
146
+ }
147
+ if (diff2 & DIFF_NODES) {
148
+ _updateNodes(newNode, newNode.el, newNode.nodes, oldNode.nodes, newNode.attrs.xmlns || ns[newNode.$tag] || xmlns);
149
+ } else {
150
+ newNode.nodes = oldNode.nodes;
151
+ }
152
+ } else {
153
+ _create(parentNode, parentEl, newNode, xmlns);
154
+ parentEl.insertBefore(newNode.el, oldNode.el);
155
+ _remove(oldNode);
156
+ }
157
+ } else if (newNodeType === VNODE_TEXT) {
158
+ newNode.el = oldNode.el;
159
+ if (newNode.$tag !== oldNode.$tag) newNode.el.textContent = newNode.$tag;
160
+ } else if (newNodeType === VNODE_COMP) {
161
+ if (oldNode.$tag & FLAG_IS_REMOVING) {
162
+ oldNode.$tag &= ~FLAG_IS_REMOVING;
163
+ }
164
+ newNode.up = parentNode;
165
+ if (newNode.$def === oldNode.$def) {
166
+ newNode.el = oldNode.el;
167
+ newNode.$h = oldNode.$h;
168
+ newNode.nodes = oldNode.nodes;
169
+ if (skipMemo || oldNode.$tag & FLAG_IS_STALE || !newNode.$def.$memo || (newNode.$def.$memo === true ? newNode.attrs !== oldNode.attrs : !newNode.$def.$memo(newNode.attrs, oldNode.attrs))) {
170
+ newNode.$tag &= ~FLAG_IS_STALE;
171
+ _redrawComponent(newNode, parentEl, xmlns);
172
+ }
173
+ } else {
174
+ _create(parentNode, parentEl, newNode, xmlns);
175
+ _remove(oldNode);
176
+ }
177
+ } else if (newNodeType === VNODE_NODE) {
178
+ if (newNode.el !== oldNode.el) {
179
+ parentEl.insertBefore(newNode.el, null);
180
+ oldNode.el.remove();
181
+ }
182
+ }
183
+ } else {
184
+ _create(parentNode, parentEl, newNode, xmlns);
185
+ _remove(oldNode);
186
+ }
187
+ } else {
188
+ _create(parentNode, parentEl, newNode, xmlns);
189
+ }
190
+ };
191
+ const _updateNodes = (parentNode, parentEl, newNodes, oldNodes, xmlns, depth = 0) => {
192
+ const newNodesLength = newNodes.length;
193
+ const oldNodesLength = oldNodes.length;
194
+ if (newNodesLength) {
195
+ let oldNode;
196
+ let newNode;
197
+ let i = 0;
198
+ if (oldNodesLength) {
199
+ if (newNodes.$keys && oldNodes.$keys) {
200
+ while (i < newNodesLength && i < oldNodesLength && newNodes[i].attrs.$key === oldNodes[i].attrs.$key) {
201
+ _updateNode(parentNode, parentEl, newNodes[i], oldNodes[i], xmlns);
202
+ i++;
203
+ }
204
+ if (i < newNodesLength || i < oldNodesLength) {
205
+ const oldByKey = /* @__PURE__ */ new Map();
206
+ for (let k = i; k < oldNodesLength; k++) {
207
+ oldByKey.set(oldNodes[k].attrs.$key, oldNodes[k]);
208
+ }
209
+ const last = _lastRoot(oldNodes[oldNodesLength - 1]);
210
+ let next = last ? last.nextSibling : null;
211
+ for (let k = newNodesLength - 1; k >= i; k--) {
212
+ newNode = newNodes[k];
213
+ oldNode = oldByKey.get(newNode.attrs.$key);
214
+ if (oldNode) {
215
+ oldByKey.delete(newNode.attrs.$key);
216
+ if (newNode.is === VNODE_COMP && newNode.attrs.$remove) {
217
+ if (oldNode.$tag & FLAG_IS_REMOVING || !_remove(oldNode)) {
218
+ oldNode.up = parentNode;
219
+ newNodes[k] = oldNode;
220
+ } else {
221
+ newNodes.splice(k, 1);
222
+ continue;
223
+ }
224
+ } else {
225
+ _updateNode(parentNode, parentEl, newNode, oldNode, xmlns);
226
+ }
227
+ } else if (!newNode.attrs.$remove) {
228
+ _create(parentNode, parentEl, newNode, xmlns);
229
+ } else {
230
+ newNodes.splice(k, 1);
231
+ continue;
232
+ }
233
+ next = _place(newNodes[k], parentEl, next);
234
+ }
235
+ for (const oldNode2 of oldByKey.values()) _remove(oldNode2);
236
+ }
237
+ } else {
238
+ for (let i2 = newNodesLength; i2 < oldNodesLength; i2++) {
239
+ _remove(oldNodes[i2]);
240
+ }
241
+ for (let i2 = 0; i2 < newNodesLength; i2++) {
242
+ oldNode = oldNodes[i2];
243
+ newNode = newNodes[i2];
244
+ if (oldNode && oldNode.el) {
245
+ _updateNode(parentNode, parentEl, newNode, oldNode, xmlns);
246
+ } else {
247
+ _create(parentNode, parentEl, newNode, xmlns);
248
+ }
249
+ }
250
+ }
251
+ } else {
252
+ for (; i < newNodesLength; i++) {
253
+ _create(parentNode, parentEl, newNodes[i], xmlns);
254
+ }
255
+ }
256
+ } else {
257
+ if (parentNode.is === VNODE_ELEM) {
258
+ parentEl.textContent = "";
259
+ _unmount(oldNodes);
260
+ } else {
261
+ for (let i = 0; i < oldNodesLength; i++) _remove(oldNodes[i]);
262
+ }
263
+ }
264
+ parentNode.nodes = newNodes;
265
+ };
266
+ const _setElAttributes = (newNode, oldAttrs = ALWAYS_EMPTY_OBJECT) => {
267
+ let attr;
268
+ let valueType;
269
+ const el = newNode.el;
270
+ const newAttrs = newNode.attrs;
271
+ if (newNode.$tag === "input" && newAttrs.type) {
272
+ el.setAttribute("type", newAttrs.type);
273
+ }
274
+ for (attr in newAttrs) {
275
+ const value = newAttrs[attr];
276
+ if (attr[0] === "o" && attr[1] === "n") {
277
+ if (value !== oldAttrs[attr]) {
278
+ el[attr] = typeof value === "function" ? (e) => {
279
+ if (value.call(e.currentTarget, e) === false) {
280
+ e.preventDefault();
281
+ e.stopPropagation();
282
+ }
283
+ if (e.draw !== false) {
284
+ draw(newNode);
285
+ }
286
+ } : null;
287
+ }
288
+ } else if (attr[0] !== "$" && (attr !== "type" || newNode.$tag !== "input") && attr !== "is" && attr !== "xmlns") {
289
+ valueType = typeof value;
290
+ if (valueType === "string" || valueType === "number") {
291
+ if (attr === "value") {
292
+ if (value !== oldAttrs[attr]) el.value = value;
293
+ } else if (value !== oldAttrs[attr]) {
294
+ el.setAttribute(attr, value + "");
295
+ }
296
+ } else if (value === true) {
297
+ if (oldAttrs[attr] !== true) el.setAttribute(attr, attr);
298
+ } else if (!value) {
299
+ if (oldAttrs[attr]) el.removeAttribute(attr);
300
+ } else if (attr === "style") {
301
+ if (typeof oldAttrs.style === "string") {
302
+ el.removeAttribute("style");
303
+ } else {
304
+ for (const oldAttr in oldAttrs.style || ALWAYS_EMPTY_OBJECT) {
305
+ if (!(oldAttr in value)) {
306
+ el.style[oldAttr] = "";
307
+ }
308
+ }
309
+ }
310
+ Object.assign(el.style, value);
311
+ }
312
+ }
313
+ }
314
+ for (attr in oldAttrs) {
315
+ if (!(attr in newAttrs)) {
316
+ if (attr[0] === "o" && attr[1] === "n") {
317
+ el[attr] = null;
318
+ } else {
319
+ el.removeAttribute(attr);
320
+ }
321
+ }
322
+ }
323
+ };
324
+ const _create = (parentNode, parentEl, vNode, xmlns) => {
325
+ if (vNode.is === VNODE_ELEM) {
326
+ vNode.up = parentNode;
327
+ xmlns = vNode.attrs && vNode.attrs.xmlns || ns[vNode.$tag] || xmlns;
328
+ vNode.el = xmlns ? document.createElementNS(xmlns, vNode.$tag, vNode.attrs.is ? { is: vNode.attrs.is } : null) : document.createElement(vNode.$tag, vNode.attrs.is ? { is: vNode.attrs.is } : null);
329
+ _setElAttributes(vNode);
330
+ for (let i = 0; i < vNode.nodes.length; i++) {
331
+ _create(vNode, vNode.el, vNode.nodes[i], xmlns);
332
+ }
333
+ parentEl.insertBefore(vNode.el, null);
334
+ } else if (vNode.is === VNODE_TEXT) {
335
+ vNode = vNode;
336
+ vNode.el = document.createTextNode(vNode.$tag);
337
+ parentEl.insertBefore(vNode.el, null);
338
+ } else if (vNode.is === VNODE_COMP) {
339
+ vNode.up = parentNode;
340
+ if (vNode.$def.init) vNode.$def.init(vNode);
341
+ vNode.nodes = _flatten(vNode.$def.draw(vNode));
342
+ if (vNode.$tag & FLAG_HAS_LIFECYCLE) {
343
+ for (let current = vNode; current && !current.$h; current = current.up) {
344
+ current.$h = true;
345
+ }
346
+ }
347
+ if (vNode.attrs.to) {
348
+ if (!(vNode.attrs.to instanceof Element)) {
349
+ throw new Error('For components that act as portals, "to" attribute must be an Element');
350
+ }
351
+ vNode.el = document.createComment("");
352
+ parentEl.insertBefore(vNode.el, null);
353
+ }
354
+ for (let i = 0; i < vNode.nodes.length; i++) {
355
+ _create(vNode, vNode.attrs.to || parentEl, vNode.nodes[i], xmlns);
356
+ }
357
+ if (!vNode.el) vNode.el = vNode.nodes[0] && vNode.nodes[0].el;
358
+ if (vNode.$def.drawn) vNode.$def.drawn(vNode, true);
359
+ } else if (vNode.is === VNODE_NODE) {
360
+ parentEl.insertBefore(vNode.el, null);
361
+ }
362
+ };
363
+ const _redrawComponent = (vNode, parentEl, xmlns) => {
364
+ const oldChildren = vNode.nodes;
365
+ const newChildren = vNode.$def.draw(vNode, oldChildren);
366
+ vNode.$tag &= ~FLAG_IS_STALE;
367
+ if (newChildren !== oldChildren) {
368
+ _updateNodes(vNode, vNode.attrs.to || parentEl, _flatten(newChildren), oldChildren, xmlns);
369
+ if (!vNode.el) vNode.el = vNode.nodes[0] && vNode.nodes[0].el;
370
+ }
371
+ if (vNode.$def.drawn) vNode.$def.drawn(vNode);
372
+ };
373
+ const _unmountReusableArray = [];
374
+ const _unmount = (nodes) => {
375
+ if (!Array.isArray(nodes)) {
376
+ _unmountReusableArray[0] = nodes;
377
+ nodes = _unmountReusableArray;
378
+ }
379
+ for (let i = 0; i < nodes.length; i++) {
380
+ const node2 = nodes[i];
381
+ if (node2.is === VNODE_COMP) {
382
+ if (node2.$tag & FLAG_HAS_REMOVE || node2.$def.remove) {
383
+ if (!(node2.$tag & FLAG_REMOVE_CALLED)) {
384
+ node2.$def.remove(node2);
385
+ }
386
+ }
387
+ if (node2.$tag & FLAG_HAS_REMOVED || node2.$def.removed) {
388
+ node2.$def.removed(node2);
389
+ }
390
+ }
391
+ if (node2.$h && node2.nodes.length) {
392
+ _unmount(node2.nodes);
393
+ node2.nodes = null;
394
+ }
395
+ node2.attrs = node2.nodes = node2.$tag = node2.$def = node2.el = node2.up = null;
396
+ }
397
+ };
398
+ const _detach = (vNode) => {
399
+ if (vNode.is === VNODE_COMP) {
400
+ for (let i = 0; i < vNode.nodes.length; i++) {
401
+ _detach(vNode.nodes[i]);
402
+ }
403
+ if (vNode.attrs.to && vNode.el) vNode.el.remove();
404
+ } else if (vNode.el) {
405
+ vNode.el.remove();
406
+ }
407
+ };
408
+ const _destroy = (vNode) => {
409
+ _detach(vNode);
410
+ _unmount(vNode);
411
+ };
412
+ const _remove = (vNode) => {
413
+ if (vNode.is === VNODE_COMP) {
414
+ if (vNode.$tag & FLAG_HAS_REMOVE || vNode.$def.remove) {
415
+ if (vNode.$tag & FLAG_IS_REMOVING) {
416
+ return false;
417
+ }
418
+ vNode.$tag |= FLAG_REMOVE_CALLED | FLAG_IS_REMOVING;
419
+ const deferred = vNode.$def.remove(vNode);
420
+ if (deferred && deferred.then) {
421
+ if (!("$key" in vNode.attrs)) {
422
+ throw new Error(
423
+ "Component remove() returned a Promise but component has no $key attribute.\nDeferred removal requires a key to track the component during exit.\nAdd a $key and use $remove flag. Example:\ncomp(MyComponent, { $key: item.id, $remove: item.deleted })"
424
+ );
425
+ }
426
+ const deferredDestroy = () => {
427
+ if (vNode.$tag & FLAG_IS_REMOVING) {
428
+ const parent = vNode.up;
429
+ if (!parent) {
430
+ console.warn(
431
+ "Promise resolved but component was already removed.",
432
+ "This usually means the component was removed without using $remove attribute."
433
+ );
434
+ return;
435
+ }
436
+ if (parent) {
437
+ const i = parent.nodes.indexOf(vNode);
438
+ if (i !== -1) parent.nodes.splice(i, 1);
439
+ }
440
+ _destroy(vNode);
441
+ draw(parent);
442
+ }
443
+ };
444
+ deferred.then(deferredDestroy, deferredDestroy);
445
+ return false;
446
+ }
447
+ }
448
+ }
449
+ _destroy(vNode);
450
+ return true;
451
+ };
452
+ const elem = function(tag) {
453
+ const first = arguments[1];
454
+ const hasAttrs = first && typeof first === "object" && !Array.isArray(first) && !("$tag" in first);
455
+ return {
456
+ is: VNODE_ELEM,
457
+ $tag: tag,
458
+ // string: element name
459
+ $def: null,
460
+ // always null for elem
461
+ attrs: hasAttrs ? Object.freeze(first) : ALWAYS_EMPTY_OBJECT,
462
+ nodes: arguments.length > (hasAttrs ? 2 : 1) ? _flatten(arguments, hasAttrs ? 2 : 1) : ALWAYS_EMPTY_ARRAY,
463
+ up: null,
464
+ el: null
465
+ };
466
+ };
467
+ const compDef = (componentDefinition) => {
468
+ {
469
+ if (!componentDefinition.draw) {
470
+ throw new Error("Component definition must have a draw function");
471
+ }
472
+ if (typeof componentDefinition.draw !== "function") {
473
+ throw new Error("draw must be a function");
474
+ }
475
+ if (componentDefinition.init && typeof componentDefinition.init !== "function") {
476
+ throw new Error("init must be a function");
477
+ }
478
+ if (componentDefinition.drawn && typeof componentDefinition.drawn !== "function") {
479
+ throw new Error("drawn must be a function");
480
+ }
481
+ if (componentDefinition.remove && typeof componentDefinition.remove !== "function") {
482
+ throw new Error("remove must be a function");
483
+ }
484
+ if (componentDefinition.removed && typeof componentDefinition.removed !== "function") {
485
+ throw new Error("removed must be a function");
486
+ }
487
+ if (componentDefinition.$memo !== void 0 && typeof componentDefinition.$memo !== "boolean" && typeof componentDefinition.$memo !== "function") {
488
+ throw new Error("$memo must be a boolean or function");
489
+ }
490
+ }
491
+ return Object.freeze({
492
+ is: VNODE_COMPDEF,
493
+ $tag: FLAG_IS_DEFINED | (componentDefinition.remove ? FLAG_HAS_REMOVE : 0) | (componentDefinition.removed ? FLAG_HAS_REMOVED : 0) | (componentDefinition.remove || componentDefinition.removed ? FLAG_HAS_LIFECYCLE : 0),
494
+ ...componentDefinition
495
+ });
496
+ };
497
+ const comp = (componentDefinition, attrs = ALWAYS_EMPTY_OBJECT) => {
498
+ return {
499
+ is: VNODE_COMP,
500
+ $tag: componentDefinition.$tag || 0,
501
+ // number: flags
502
+ $def: componentDefinition,
503
+ // object: component definition
504
+ attrs: attrs === ALWAYS_EMPTY_OBJECT ? attrs : Object.freeze(attrs) ,
505
+ nodes: ALWAYS_EMPTY_ARRAY,
506
+ up: null,
507
+ el: null
508
+ };
509
+ };
510
+ const node = (el) => {
511
+ return {
512
+ is: VNODE_NODE,
513
+ $tag: el.nodeName.toLowerCase(),
514
+ // string: element name
515
+ $def: null,
516
+ // always null for node
517
+ attrs: null,
518
+ nodes: null,
519
+ up: null,
520
+ el
521
+ };
522
+ };
523
+ const RootWrapper = compDef({
524
+ draw: (vNode) => vNode.attrs.$nodes
525
+ });
526
+ const bind = (el, vNodeAnyOrArray) => {
527
+ if (el == null) throw new Error("mount");
528
+ const rootComp = boundNodes.get(el) || comp(RootWrapper);
529
+ rootComp.attrs = { $nodes: vNodeAnyOrArray };
530
+ boundNodes.set(rootComp.el = el, rootComp);
531
+ draw(rootComp);
532
+ sync();
533
+ return rootComp;
534
+ };
535
+
536
+ export { bind, comp, compDef, diff, draw, elem, node, ns, sync };
@@ -0,0 +1,2 @@
1
+ /*! Zenith v1.0.0-beta.13 | MIT License | © 2022-2025 Daniel Barber */
2
+ const e=new Map,t=new Set,ns={math:"http://www.w3.org/1998/Math/MathML",svg:"http://www.w3.org/2000/svg"},s=[],l={},n=new Map,sync=()=>{let s,l=t.size;if(l){const n=document.activeElement;for(const n of t)if(s=e.has(n.el)?n.el:n.attrs&&n.attrs.to||n.el&&n.el.parentNode||n.up&&n.up.el,t.delete(n),s&&g(n,s),! --l)break;t.size&&Promise.resolve().then(sync),n&&n!==document.activeElement&&"function"==typeof n.focus&&n.focus()}},draw=(e,s)=>{if(s)3===e.is&&(e.$tag|=2),t.add(e);else{let s;for(s=e;s.up;s=s.up);for(t.add(s),s=e;s.up;s=s.up)if(3===s.is){if(2&s.$tag)break;s.$tag|=2}}1===t.size&&Promise.resolve().then(sync)},r=[],o=(e,t=0,s=[])=>{let l;for(e&&"object"==typeof e&&null!=e.length||(r[0]=e,e=r);e.length>t;t++)if(l=e[t],Array.isArray(l))o(l,0,s);else if(null!=l)if(l.is){if(void 0===s.$keys)s.$keys=l.attrs&&"$key"in l.attrs?n:null;else if(!s.$keys!=!(l.attrs&&"$key"in l.attrs))throw Error("$keys");s.push(l)}else if(!0!==l&&!1!==l){if(void 0===s.$keys)s.$keys=null;else if(s.$keys)throw Error("$keys");s.push({is:2,$tag:l+"",$def:null,attrs:null,nodes:null,up:null,el:null})}return s},i=e=>{if(3===e.is&&!e.attrs.to){for(let t=e.nodes.length-1;t>=0;t--){const s=i(e.nodes[t]);if(s)return s}return null}return e.el},a=(e,t,s)=>{if(3!==e.is||e.attrs.to)e.el&&(e.el.nextSibling!==s&&t.insertBefore(e.el,s),s=e.el);else for(let l=e.nodes.length-1;l>=0;l--)s=a(e.nodes[l],t,s);return s},f=(e,t,s,l,n,r)=>{if(l.el){const o=s.is;if(o===l.is)if(1===o)if(s.up=e,s.$tag===l.$tag){s.el=l.el,s.$h=l.$h;const e=s.attrs.$diff||6;2&e&&$(s,l.attrs),4&e?d(s,s.el,s.nodes,l.nodes,s.attrs.xmlns||ns[s.$tag]||n):s.nodes=l.nodes}else u(e,t,s,n),t.insertBefore(s.el,l.el),h(l);else 2===o?(s.el=l.el,s.$tag!==l.$tag&&(s.el.textContent=s.$tag)):3===o?(4&l.$tag&&(l.$tag&=-5),s.up=e,s.$def===l.$def?(s.el=l.el,s.$h=l.$h,s.nodes=l.nodes,(r||2&l.$tag||!s.$def.$memo||(!0===s.$def.$memo?s.attrs!==l.attrs:!s.$def.$memo(s.attrs,l.attrs)))&&(s.$tag&=-3,g(s,t,n))):(u(e,t,s,n),h(l))):4===o&&s.el!==l.el&&(t.insertBefore(s.el,null),l.el.remove());else u(e,t,s,n),h(l)}else u(e,t,s,n)},d=(e,t,s,l,n,r=0)=>{const o=s.length,d=l.length;if(o){let r,$,g=0;if(d)if(s.$keys&&l.$keys){for(;o>g&&d>g&&s[g].attrs.$key===l[g].attrs.$key;)f(e,t,s[g],l[g],n),g++;if(o>g||d>g){const c=new Map;for(let e=g;d>e;e++)c.set(l[e].attrs.$key,l[e]);const m=i(l[d-1]);let p=m?m.nextSibling:null;for(let l=o-1;l>=g;l--){if($=s[l],r=c.get($.attrs.$key),r)if(c.delete($.attrs.$key),3===$.is&&$.attrs.$remove){if(!(4&r.$tag)&&h(r)){s.splice(l,1);continue}r.up=e,s[l]=r}else f(e,t,$,r,n);else{if($.attrs.$remove){s.splice(l,1);continue}u(e,t,$,n)}p=a(s[l],t,p)}for(const e of c.values())h(e)}}else{for(let e=o;d>e;e++)h(l[e]);for(let i=0;o>i;i++)r=l[i],$=s[i],r&&r.el?f(e,t,$,r,n):u(e,t,$,n)}else for(;o>g;g++)u(e,t,s[g],n)}else if(1===e.is)t.textContent="",m(l);else for(let e=0;d>e;e++)h(l[e]);e.nodes=s},$=(e,t=l)=>{let s,n;const r=e.el,o=e.attrs;for(s in"input"===e.$tag&&o.type&&r.setAttribute("type",o.type),o){const i=o[s];if("o"===s[0]&&"n"===s[1])i!==t[s]&&(r[s]="function"==typeof i?t=>{!1===i.call(t.currentTarget,t)&&(t.preventDefault(),t.stopPropagation()),!1!==t.draw&&draw(e)}:null);else if("$"!==s[0]&&("type"!==s||"input"!==e.$tag)&&"is"!==s&&"xmlns"!==s)if(n=typeof i,"string"===n||"number"===n)"value"===s?i!==t[s]&&(r.value=i):i!==t[s]&&r.setAttribute(s,i+"");else if(!0===i)!0!==t[s]&&r.setAttribute(s,s);else if(i){if("style"===s){if("string"==typeof t.style)r.removeAttribute("style");else for(const e in t.style||l)e in i||(r.style[e]="");Object.assign(r.style,i)}}else t[s]&&r.removeAttribute(s)}for(s in t)s in o||("o"===s[0]&&"n"===s[1]?r[s]=null:r.removeAttribute(s))},u=(e,t,s,l)=>{if(1===s.is){s.up=e,s.el=(l=s.attrs&&s.attrs.xmlns||ns[s.$tag]||l)?document.createElementNS(l,s.$tag,s.attrs.is?{is:s.attrs.is}:null):document.createElement(s.$tag,s.attrs.is?{is:s.attrs.is}:null),$(s);for(let e=0;s.nodes.length>e;e++)u(s,s.el,s.nodes[e],l);t.insertBefore(s.el,null)}else if(2===s.is)s.el=document.createTextNode(s.$tag),t.insertBefore(s.el,null);else if(3===s.is){if(s.up=e,s.$def.init&&s.$def.init(s),s.nodes=o(s.$def.draw(s)),8&s.$tag)for(let e=s;e&&!e.$h;e=e.up)e.$h=!0;s.attrs.to&&(s.el=document.createComment(""),t.insertBefore(s.el,null));for(let e=0;s.nodes.length>e;e++)u(s,s.attrs.to||t,s.nodes[e],l);s.el||(s.el=s.nodes[0]&&s.nodes[0].el),s.$def.drawn&&s.$def.drawn(s,!0)}else 4===s.is&&t.insertBefore(s.el,null)},g=(e,t,s)=>{const l=e.nodes,n=e.$def.draw(e,l);e.$tag&=-3,n!==l&&(d(e,e.attrs.to||t,o(n),l,s),e.el||(e.el=e.nodes[0]&&e.nodes[0].el)),e.$def.drawn&&e.$def.drawn(e)},c=[],m=e=>{Array.isArray(e)||(c[0]=e,e=c);for(let t=0;e.length>t;t++){const s=e[t];3===s.is&&((16&s.$tag||s.$def.remove)&&(64&s.$tag||s.$def.remove(s)),(32&s.$tag||s.$def.removed)&&s.$def.removed(s)),s.$h&&s.nodes.length&&(m(s.nodes),s.nodes=null),s.attrs=s.nodes=s.$tag=s.$def=s.el=s.up=null}},p=e=>{if(3===e.is){for(let t=0;e.nodes.length>t;t++)p(e.nodes[t]);e.attrs.to&&e.el&&e.el.remove()}else e.el&&e.el.remove()},y=e=>{p(e),m(e)},h=e=>{if(3===e.is&&(16&e.$tag||e.$def.remove)){if(4&e.$tag)return!1;e.$tag|=68;const t=e.$def.remove(e);if(t&&t.then){const s=()=>{if(4&e.$tag){const t=e.up;if(t){const s=t.nodes.indexOf(e);-1!==s&&t.nodes.splice(s,1)}y(e),draw(t)}};return t.then(s,s),!1}}return y(e),!0},compDef=e=>Object.freeze({is:5,$tag:1|(e.remove?16:0)|(e.removed?32:0)|(e.remove||e.removed?8:0),...e}),comp=(e,t=l)=>({is:3,$tag:e.$tag||0,$def:e,attrs:t,nodes:s,up:null,el:null}),v=compDef({draw:e=>e.attrs.$nodes});window.z={elem:function(e){const t=arguments[1],n=t&&"object"==typeof t&&!Array.isArray(t)&&!("$tag"in t);return{is:1,$tag:e,$def:null,attrs:n?t:l,nodes:arguments.length>(n?2:1)?o(arguments,n?2:1):s,up:null,el:null}},comp:comp,node:e=>({is:4,$tag:e.nodeName.toLowerCase(),$def:null,attrs:null,nodes:null,up:null,el:e}),compDef:compDef,bind:(t,s)=>{const l=e.get(t)||comp(v);return l.attrs={$nodes:s},e.set(l.el=t,l),draw(l),sync(),l},draw:draw,ns:ns,diff:{none:1,self:2,nodes:4,all:6}};
package/dist/zenith.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! Zenith v1.0.0-beta.13 | MIT License | © 2022-2025 Daniel Barber */
2
+ const e=new Map,t=new Set,ns={math:"http://www.w3.org/1998/Math/MathML",svg:"http://www.w3.org/2000/svg"},diff={none:1,self:2,nodes:4,all:6},s=[],l={},n=new Map,sync=()=>{let s,l=t.size;if(l){const n=document.activeElement;for(const n of t)if(s=e.has(n.el)?n.el:n.attrs&&n.attrs.to||n.el&&n.el.parentNode||n.up&&n.up.el,t.delete(n),s&&g(n,s),! --l)break;t.size&&Promise.resolve().then(sync),n&&n!==document.activeElement&&"function"==typeof n.focus&&n.focus()}},draw=(e,s)=>{if(s)3===e.is&&(e.$tag|=2),t.add(e);else{let s;for(s=e;s.up;s=s.up);for(t.add(s),s=e;s.up;s=s.up)if(3===s.is){if(2&s.$tag)break;s.$tag|=2}}1===t.size&&Promise.resolve().then(sync)},r=[],o=(e,t=0,s=[])=>{let l;for(e&&"object"==typeof e&&null!=e.length||(r[0]=e,e=r);e.length>t;t++)if(l=e[t],Array.isArray(l))o(l,0,s);else if(null!=l)if(l.is){if(void 0===s.$keys)s.$keys=l.attrs&&"$key"in l.attrs?n:null;else if(!s.$keys!=!(l.attrs&&"$key"in l.attrs))throw Error("$keys");s.push(l)}else if(!0!==l&&!1!==l){if(void 0===s.$keys)s.$keys=null;else if(s.$keys)throw Error("$keys");s.push({is:2,$tag:l+"",$def:null,attrs:null,nodes:null,up:null,el:null})}return s},i=e=>{if(3===e.is&&!e.attrs.to){for(let t=e.nodes.length-1;t>=0;t--){const s=i(e.nodes[t]);if(s)return s}return null}return e.el},a=(e,t,s)=>{if(3!==e.is||e.attrs.to)e.el&&(e.el.nextSibling!==s&&t.insertBefore(e.el,s),s=e.el);else for(let l=e.nodes.length-1;l>=0;l--)s=a(e.nodes[l],t,s);return s},f=(e,t,s,l,n,r)=>{if(l.el){const o=s.is;if(o===l.is)if(1===o)if(s.up=e,s.$tag===l.$tag){s.el=l.el,s.$h=l.$h;const e=s.attrs.$diff||6;2&e&&d(s,l.attrs),4&e?$(s,s.el,s.nodes,l.nodes,s.attrs.xmlns||ns[s.$tag]||n):s.nodes=l.nodes}else u(e,t,s,n),t.insertBefore(s.el,l.el),h(l);else 2===o?(s.el=l.el,s.$tag!==l.$tag&&(s.el.textContent=s.$tag)):3===o?(4&l.$tag&&(l.$tag&=-5),s.up=e,s.$def===l.$def?(s.el=l.el,s.$h=l.$h,s.nodes=l.nodes,(r||2&l.$tag||!s.$def.$memo||(!0===s.$def.$memo?s.attrs!==l.attrs:!s.$def.$memo(s.attrs,l.attrs)))&&(s.$tag&=-3,g(s,t,n))):(u(e,t,s,n),h(l))):4===o&&s.el!==l.el&&(t.insertBefore(s.el,null),l.el.remove());else u(e,t,s,n),h(l)}else u(e,t,s,n)},$=(e,t,s,l,n,r=0)=>{const o=s.length,$=l.length;if(o){let r,d,g=0;if($)if(s.$keys&&l.$keys){for(;o>g&&$>g&&s[g].attrs.$key===l[g].attrs.$key;)f(e,t,s[g],l[g],n),g++;if(o>g||$>g){const c=new Map;for(let e=g;$>e;e++)c.set(l[e].attrs.$key,l[e]);const p=i(l[$-1]);let m=p?p.nextSibling:null;for(let l=o-1;l>=g;l--){if(d=s[l],r=c.get(d.attrs.$key),r)if(c.delete(d.attrs.$key),3===d.is&&d.attrs.$remove){if(!(4&r.$tag)&&h(r)){s.splice(l,1);continue}r.up=e,s[l]=r}else f(e,t,d,r,n);else{if(d.attrs.$remove){s.splice(l,1);continue}u(e,t,d,n)}m=a(s[l],t,m)}for(const e of c.values())h(e)}}else{for(let e=o;$>e;e++)h(l[e]);for(let i=0;o>i;i++)r=l[i],d=s[i],r&&r.el?f(e,t,d,r,n):u(e,t,d,n)}else for(;o>g;g++)u(e,t,s[g],n)}else if(1===e.is)t.textContent="",p(l);else for(let e=0;$>e;e++)h(l[e]);e.nodes=s},d=(e,t=l)=>{let s,n;const r=e.el,o=e.attrs;for(s in"input"===e.$tag&&o.type&&r.setAttribute("type",o.type),o){const i=o[s];if("o"===s[0]&&"n"===s[1])i!==t[s]&&(r[s]="function"==typeof i?t=>{!1===i.call(t.currentTarget,t)&&(t.preventDefault(),t.stopPropagation()),!1!==t.draw&&draw(e)}:null);else if("$"!==s[0]&&("type"!==s||"input"!==e.$tag)&&"is"!==s&&"xmlns"!==s)if(n=typeof i,"string"===n||"number"===n)"value"===s?i!==t[s]&&(r.value=i):i!==t[s]&&r.setAttribute(s,i+"");else if(!0===i)!0!==t[s]&&r.setAttribute(s,s);else if(i){if("style"===s){if("string"==typeof t.style)r.removeAttribute("style");else for(const e in t.style||l)e in i||(r.style[e]="");Object.assign(r.style,i)}}else t[s]&&r.removeAttribute(s)}for(s in t)s in o||("o"===s[0]&&"n"===s[1]?r[s]=null:r.removeAttribute(s))},u=(e,t,s,l)=>{if(1===s.is){s.up=e,s.el=(l=s.attrs&&s.attrs.xmlns||ns[s.$tag]||l)?document.createElementNS(l,s.$tag,s.attrs.is?{is:s.attrs.is}:null):document.createElement(s.$tag,s.attrs.is?{is:s.attrs.is}:null),d(s);for(let e=0;s.nodes.length>e;e++)u(s,s.el,s.nodes[e],l);t.insertBefore(s.el,null)}else if(2===s.is)s.el=document.createTextNode(s.$tag),t.insertBefore(s.el,null);else if(3===s.is){if(s.up=e,s.$def.init&&s.$def.init(s),s.nodes=o(s.$def.draw(s)),8&s.$tag)for(let e=s;e&&!e.$h;e=e.up)e.$h=!0;s.attrs.to&&(s.el=document.createComment(""),t.insertBefore(s.el,null));for(let e=0;s.nodes.length>e;e++)u(s,s.attrs.to||t,s.nodes[e],l);s.el||(s.el=s.nodes[0]&&s.nodes[0].el),s.$def.drawn&&s.$def.drawn(s,!0)}else 4===s.is&&t.insertBefore(s.el,null)},g=(e,t,s)=>{const l=e.nodes,n=e.$def.draw(e,l);e.$tag&=-3,n!==l&&($(e,e.attrs.to||t,o(n),l,s),e.el||(e.el=e.nodes[0]&&e.nodes[0].el)),e.$def.drawn&&e.$def.drawn(e)},c=[],p=e=>{Array.isArray(e)||(c[0]=e,e=c);for(let t=0;e.length>t;t++){const s=e[t];3===s.is&&((16&s.$tag||s.$def.remove)&&(64&s.$tag||s.$def.remove(s)),(32&s.$tag||s.$def.removed)&&s.$def.removed(s)),s.$h&&s.nodes.length&&(p(s.nodes),s.nodes=null),s.attrs=s.nodes=s.$tag=s.$def=s.el=s.up=null}},m=e=>{if(3===e.is){for(let t=0;e.nodes.length>t;t++)m(e.nodes[t]);e.attrs.to&&e.el&&e.el.remove()}else e.el&&e.el.remove()},y=e=>{m(e),p(e)},h=e=>{if(3===e.is&&(16&e.$tag||e.$def.remove)){if(4&e.$tag)return!1;e.$tag|=68;const t=e.$def.remove(e);if(t&&t.then){const s=()=>{if(4&e.$tag){const t=e.up;if(t){const s=t.nodes.indexOf(e);-1!==s&&t.nodes.splice(s,1)}y(e),draw(t)}};return t.then(s,s),!1}}return y(e),!0},elem=function(e){const t=arguments[1],n=t&&"object"==typeof t&&!Array.isArray(t)&&!("$tag"in t);return{is:1,$tag:e,$def:null,attrs:n?t:l,nodes:arguments.length>(n?2:1)?o(arguments,n?2:1):s,up:null,el:null}},compDef=e=>Object.freeze({is:5,$tag:1|(e.remove?16:0)|(e.removed?32:0)|(e.remove||e.removed?8:0),...e}),comp=(e,t=l)=>({is:3,$tag:e.$tag||0,$def:e,attrs:t,nodes:s,up:null,el:null}),node=e=>({is:4,$tag:e.nodeName.toLowerCase(),$def:null,attrs:null,nodes:null,up:null,el:e}),v=compDef({draw:e=>e.attrs.$nodes}),bind=(t,s)=>{const l=e.get(t)||comp(v);return l.attrs={$nodes:s},e.set(l.el=t,l),draw(l),sync(),l};export{bind,comp,compDef,diff,draw,elem,node,ns,sync};
package/package.json CHANGED
@@ -1,11 +1,49 @@
1
1
  {
2
- "name": "zenith",
3
- "version": "0.0.1",
4
- "description": "client side initialization",
5
- "main": "index.js",
6
- "keywords": [
7
- "client side"
8
- ],
9
- "author": "Ryan Swanston <junkswanston@hotmail.com>",
10
- "license": "ISC"
2
+ "name": "zenith",
3
+ "version": "1.0.0-beta.13",
4
+ "description": "Another front-end framework.",
5
+ "type": "module",
6
+ "main": "dist/zenith.global.js",
7
+ "module": "dist/zenith.js",
8
+ "exports": {
9
+ ".": "./dist/zenith.js",
10
+ "./helpers": "./dist/zenith-helpers.js"
11
+ },
12
+ "files": [
13
+ "dist/"
14
+ ],
15
+ "sideEffects": false,
16
+ "scripts": {
17
+ "build": "rollup --config && node scripts/after-build.mjs",
18
+ "lint": "eslint . --ext .ts",
19
+ "test": "vitest --run --coverage --reporter verbose",
20
+ "test:ui": "vitest --ui",
21
+ "test:run": "vitest run"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/aleph1/zenith.git"
26
+ },
27
+ "author": "Daniel Barber / Aleph1",
28
+ "license": "MIT",
29
+ "bugs": {
30
+ "url": "https://github.com/aleph1/Zenith/issues"
31
+ },
32
+ "homepage": "https://github.com/aleph1/Zenith#readme",
33
+ "devDependencies": {
34
+ "@rollup/plugin-replace": "^4.0.0",
35
+ "@rollup/plugin-terser": "^1.0.0",
36
+ "@typescript-eslint/eslint-plugin": "^8.71.2",
37
+ "@typescript-eslint/parser": "^8.71.2",
38
+ "@vitest/coverage-v8": "^4.0.14",
39
+ "@vitest/ui": "^4.0.14",
40
+ "brotli": "^1.3.3",
41
+ "eslint": "^8.57.1",
42
+ "jsdom": "^27.2.0",
43
+ "rollup": "^2.74.1",
44
+ "rollup-plugin-brotli": "^3.1.0",
45
+ "rollup-plugin-esbuild": "^6.2.1",
46
+ "typescript": "^5.9.3",
47
+ "vitest": "^4.0.14"
48
+ }
11
49
  }
package/index.js DELETED
@@ -1,7 +0,0 @@
1
- // zenith is a WIP
2
-
3
- function zenith(params){
4
- return JSON.stringify(params, null, '\t')
5
- }
6
-
7
- module.exports = zenith
package/readme.md DELETED
@@ -1 +0,0 @@
1
- Zenith is a WIP client side initialization module