@ryupold/vode 1.0.1 → 1.1.0

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/README.md CHANGED
@@ -2,9 +2,12 @@
2
2
 
3
3
  A small web framework for a minimalistic development flow. Zero dependencies, no build step except for typescript compilation, and a simple virtual DOM implementation that is easy to understand and use. Autocompletion out of the box due to binding to `lib.dom.d.ts`.
4
4
 
5
+ It can be used to create single page applications or isolated components with complex state. The usage of arrays gives flexibility in composition and makes refactoring easy.
6
+
5
7
  ## Usage
6
8
 
7
9
  ### ESM
10
+
8
11
  ```html
9
12
  <!DOCTYPE html>
10
13
  <html>
@@ -54,15 +57,15 @@ Binds the library to the global `V` variable.
54
57
  var state = { counter: 0 };
55
58
 
56
59
  V.app(appNode, state,
57
- (s) => ["DIV",
58
- ["INPUT", {
60
+ (s) => ["div",
61
+ ["input", {
59
62
  type: 'button',
60
63
  onclick: { counter: s.counter + 1 },
61
64
  value: 'Click me',
62
65
  }
63
66
  ],
64
- ["BR"],
65
- ["SPAN", { style: { color: 'red' } }, `${s.counter}`],
67
+ ["br"],
68
+ ["span", { style: { color: 'red' } }, `${s.counter}`],
66
69
  ]);
67
70
  </script>
68
71
  </body>
@@ -71,6 +74,8 @@ Binds the library to the global `V` variable.
71
74
 
72
75
  ### NPM
73
76
 
77
+ [![NPM](https://badge.fury.io/js/%40ryupold%2Fvode.svg)](https://www.npmjs.com/package/@ryupold/vode)
78
+
74
79
  ```bash
75
80
  # npm
76
81
  npm install @ryupold/vode --save
@@ -130,6 +135,87 @@ A `vode` is a representation of a virtual DOM node, which is a tree structure of
130
135
 
131
136
  As you can see, it is a simple array with the first element being the tag name, the second element being an optional properties object, and the rest being child-vodes.
132
137
 
138
+ They are lightweight structures to describe what the DOM should look like.
139
+
140
+ Imagine this HTML:
141
+
142
+ ```html
143
+ <div class="card">
144
+ <div class="card-image">
145
+ <figure class="image is-4by3">
146
+ <img
147
+ src="https://bulma.io/assets/images/placeholders/1280x960.png"
148
+ alt="Placeholder image"
149
+ />
150
+ </figure>
151
+ </div>
152
+ <div class="card-content">
153
+ <div class="media">
154
+ <div class="media-left">
155
+ <figure class="image is-48x48">
156
+ <img
157
+ src="https://bulma.io/assets/images/placeholders/96x96.png"
158
+ alt="Placeholder image"
159
+ />
160
+ </figure>
161
+ </div>
162
+ <div class="media-content">
163
+ <p class="title is-4">John Smith</p>
164
+ <p class="subtitle is-6">@johnsmith</p>
165
+ </div>
166
+ </div>
167
+
168
+ <div class="content">
169
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus nec
170
+ iaculis mauris. <a>@bulmaio</a>. <a href="#">#css</a>
171
+ <a href="#">#responsive</a>
172
+ <br />
173
+ <time datetime="2025-09-24">10:09 PM - 24 Sep 2025</time>
174
+ </div>
175
+ </div>
176
+ </div>
177
+ ```
178
+
179
+ expressed as **"vode"** it would look like this:
180
+
181
+ ```ts
182
+ [DIV, { class: "card" },
183
+ [DIV, { class: "card-image" },
184
+ [FIGURE, { class: "image is-4by3" },
185
+ [IMG, {
186
+ src: "https://bulma.io/assets/images/placeholders/1280x960.png",
187
+ alt: "Placeholder image"
188
+ }]
189
+ ]
190
+ ],
191
+ [DIV, { class: "card-content" },
192
+ [DIV, { class: "media" },
193
+ [DIV, { class: "media-left" },
194
+ [FIGURE, { class: "image is-48x48" },
195
+ [IMG, {
196
+ src: "https://bulma.io/assets/images/placeholders/96x96.png",
197
+ alt: "Placeholder image"
198
+ }]
199
+ ]
200
+ ],
201
+ [DIV, { class: "media-content" },
202
+ [P, { class: "title is-4" }, "John Smith"],
203
+ [P, { class: "subtitle is-6" }, "@johnsmith"]
204
+ ]
205
+ ],
206
+ [DIV, { class: "content" },
207
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus nec iaculis mauris. ",
208
+ [A, "@bulmaio"], ". ", [A, { href: "#" }, "#css"],
209
+ [A, { href: "#" }, "#responsive"],
210
+ [BR],
211
+ [TIME, { datetime: "2025-09-24" }, "10:09 PM - 24 Sep 2025"]
212
+ ]
213
+ ]
214
+ ]
215
+ ```
216
+
217
+ Viewed alone it does not provide an obvious benefit (apart from looking better imho), but as the result of a function of state, it can become very useful to express conditional UI this way.
218
+
133
219
  ### Component
134
220
  ```ts
135
221
  type Component<S> = (s: S) => ChildVode<S>;
@@ -139,13 +225,26 @@ A `Component<State>` is a function that takes a state object and returns a `Vode
139
225
 
140
226
  ```ts
141
227
  // A full vode has a tag, properties, and children. props and children are optional.
142
- const CompFooBar = (s) => [DIV, { class: "container" },
228
+ const CompFoo = (s) => [SPAN, { class: "foo" }, s.isAuthenticated ? "foo" : "bar"];
229
+
230
+ const CompBar = (s) => [DIV, { class: "container" },
143
231
 
144
232
  // a child vode can be a string, which results in a text node
145
233
  [H1, "Hello World"],
146
234
 
147
235
  // a vode can also be a self-closing tag
148
- [BR],
236
+ [HR],
237
+
238
+ // conditional rendering
239
+ s.isAuthenticated
240
+ ? [STRONG, `and also hello ${s.user}`]
241
+ : [FORM,
242
+ [INPUT, { type: "email", name: "email" }],
243
+ [INPUT, { type: "password", name: "pw" }],
244
+ [INPUT, { type: "submit" }],
245
+ ],
246
+ // a child-vode of false, undefined or null is not rendered
247
+ !s.isAuthenticated && [HR],
149
248
 
150
249
  // style object maps directly to the HTML style attribute
151
250
  [P, { style: { color: "red", fontWeight: "bold" } }, "This is a paragraph."],
@@ -161,9 +260,9 @@ const CompFooBar = (s) => [DIV, { class: "container" },
161
260
  // and the HTML event object as second argument
162
261
  [BUTTON, {
163
262
  // all on* events accept `Patch<State>`
164
- onclick: (state, evt) => {
263
+ onclick: (s, evt) => {
165
264
  // objects returned by events are patched automatically
166
- return { counter: state.counter + 1 };
265
+ return { counter: s.counter + 1 };
167
266
  },
168
267
 
169
268
  // you can set the patch object directly for events
@@ -171,14 +270,14 @@ const CompFooBar = (s) => [DIV, { class: "container" },
171
270
  onmouseleave: { pointing: false },
172
271
 
173
272
  // a patch can be an async function
174
- onmouseup: async (state, evt) => {
175
- state.patch({ loading: true });
273
+ onmouseup: async (s, evt) => {
274
+ s.patch({ loading: true });
176
275
  const result = await apiCall();
177
276
  return { title: result.data.title, loading: false };
178
277
  },
179
278
 
180
279
  // you can also use a generator function that yields patches
181
- onmousedown: async function* (state, evt) {
280
+ onmousedown: async function* (s, evt) {
182
281
  yield { loading: true };
183
282
  const result = await apiCall();
184
283
  yield {
@@ -187,16 +286,26 @@ const CompFooBar = (s) => [DIV, { class: "container" },
187
286
  return { loading: false };
188
287
  },
189
288
 
289
+ // events can be attached condionally
290
+ ondblclick : s.counter > 20 && (s, evt) => {
291
+ return { counter: s.counter * 2 };
292
+ },
293
+
190
294
  class: { bar: s.pointing }
191
295
  }, "Click me!"],
296
+
297
+ // components can be used as child-vodes, they are called lazy on render
298
+ CompFoo,
299
+ // or this way
300
+ CompFoo(s),
192
301
  ];
193
302
  ```
194
303
 
195
304
  ### app
196
305
 
197
- `app` is a function that takes a HTML node, an initial state object, and a render function (`Component<State>`).
306
+ `app` is a function that takes a HTML node, a state object, and a render function (`Component<State>`).
198
307
  ```ts
199
- const appNode = document.getElementById('APP-ID');
308
+ const containerNode = document.getElementById('APP-ID');
200
309
  const state = {
201
310
  counter: 0,
202
311
  pointing: false,
@@ -204,17 +313,45 @@ const state = {
204
313
  title: '',
205
314
  body: '',
206
315
  };
207
- const patch = app<State>(appNode, state, (s) => CompFooBar(s));
316
+ const patch = app(containerNode, state, (s) => CompFooBar(s));
208
317
  ```
209
- It will render the initial state and update the DOM when patches are applied to the patch function or via events. All elements returned by the render function are placed under `appNode`.
318
+ It will analyse the current structure of the given `containerNode` and adjust its structure in the first render. When render-patches are applied to the `patch` function or via yield/return of events, the `containerNode` is updated to match the vode structure 1:1.
210
319
 
211
- You can have multiple isolated `app` instances on a page, each with its own state and render function. The returned patch function from `app` can be used to synchronize the state between them.
320
+ #### they multiply
321
+ You can have multiple isolated vode app instances on a page, each with its own state and render function. The returned patch function from `app` can be used to synchronize the state between them.
322
+
323
+ #### nesting
324
+ It is possible to nest vode-apps inside vode-apps, but the library is not opionated on how you do that. One can imagine this type of component:
325
+
326
+ ```ts
327
+ export function IsolatedVodeApp<OuterState, InnerState>(
328
+ tag: Tag,
329
+ props: Props<OuterState>,
330
+ state: InnerState,
331
+ View: (ins:InnerState) => Vode<InnerState>,
332
+ ...initialPatches: Patch<InnerState>[]
333
+ ): ChildVode<OuterState> {
334
+ return memo<OuterState>([],
335
+ () => [tag,
336
+ {
337
+ ...props,
338
+ onMount: (_: OuterState, container: HTMLElement) => {
339
+ app<InnerState>(container, state, View, ...initialPatches);
340
+ }
341
+ }
342
+ ]
343
+ );
344
+ }
345
+ ```
346
+ The `empty memo` prevents further render calls from the outer app so rendering of the subtree inside is controlled by the inner app.
212
347
 
213
- ### state
214
- The state is a singleton object that can be updated. A re-render happens when a patch object is supplied to the patch function or via event.
348
+ ### state & patch
349
+ The state object you pass to [`app`](#app) can be updated directly or via `patch`.
350
+ During the call to `app`, the state object is bound to the vode app instance and becomes a singleton from its perspective.
351
+ Also a `patch` function is added to the state object; it is the same function that is also returned by `app`.
352
+ A re-render happens when a patch object is supplied to the `patch` function or via event.
215
353
 
216
354
  ```js
217
- // type safe way to create the state object
218
355
  const s = {
219
356
  counter: 0,
220
357
  pointing: false,
@@ -300,4 +437,4 @@ Not planning to add more features, just keeping it simple and easy.
300
437
  But if you find bugs or have suggestions, feel free to open an [issue](https://github.com/ryupold/vode/issues) or a pull request.
301
438
 
302
439
  ## License
303
- [MIT](./LICENSE)
440
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](./LICENSE)
package/dist/vode.js CHANGED
@@ -236,25 +236,19 @@ var V = (() => {
236
236
  });
237
237
 
238
238
  // src/vode.ts
239
- function createState(state) {
240
- return state;
241
- }
242
- function createPatch(p) {
243
- return p;
244
- }
245
239
  function vode(tag2, props2, ...children2) {
246
240
  if (!tag2) throw new Error("tag must be a string or vode");
247
241
  if (Array.isArray(tag2)) return tag2;
248
242
  else if (props2) return [tag2, props2, ...children2];
249
243
  else return [tag2, ...children2];
250
244
  }
251
- function app(container, initialState, dom, ...initialPatches) {
252
- if (!container) throw new Error("container must be a valid HTMLElement");
253
- if (!initialState || typeof initialState !== "object") throw new Error("initialState must be an object");
245
+ function app(container, state, dom, ...initialPatches) {
246
+ if (!container?.parentElement) throw new Error("container must be a valid HTMLElement inside the <html></html> document");
247
+ if (!state || typeof state !== "object") throw new Error("given state must be an object");
254
248
  if (typeof dom !== "function") throw new Error("dom must be a function that returns a vode");
255
249
  const _vode = {};
256
250
  _vode.stats = { lastRenderTime: 0, renderCount: 0, liveEffectCount: 0, patchCount: 0, renderPatchCount: 0 };
257
- Object.defineProperty(initialState, "patch", {
251
+ Object.defineProperty(state, "patch", {
258
252
  enumerable: false,
259
253
  configurable: true,
260
254
  writable: false,
@@ -315,7 +309,11 @@ var V = (() => {
315
309
  try {
316
310
  _vode.state = mergeState(_vode.state, _vode.q, true);
317
311
  _vode.q = null;
318
- _vode.vode = render(_vode.state, _vode.patch, container, 0, _vode.vode, dom(_vode.state));
312
+ const vom = dom(_vode.state);
313
+ _vode.vode = render(_vode.state, _vode.patch, container.parentElement, 0, _vode.vode, vom);
314
+ if (container.tagName !== vom[0].toUpperCase()) {
315
+ container = _vode.vode.node;
316
+ }
319
317
  } finally {
320
318
  _vode.isRendering = false;
321
319
  _vode.stats.renderCount++;
@@ -326,14 +324,19 @@ var V = (() => {
326
324
  }
327
325
  })
328
326
  });
329
- _vode.patch = initialState.patch;
330
- _vode.state = initialState;
327
+ _vode.patch = state.patch;
328
+ _vode.state = state;
331
329
  _vode.q = null;
332
330
  const root = container;
333
331
  root._vode = _vode;
334
- const initialVode = dom(initialState);
335
- _vode.vode = initialVode;
336
- _vode.vode = render(initialState, _vode.patch, container, 0, void 0, initialVode);
332
+ _vode.vode = render(
333
+ state,
334
+ _vode.patch,
335
+ container.parentElement,
336
+ Array.from(container.parentElement.children).indexOf(container),
337
+ hydrate(container),
338
+ dom(state)
339
+ );
337
340
  for (const effect of initialPatches) {
338
341
  _vode.patch(effect);
339
342
  }
@@ -343,6 +346,12 @@ var V = (() => {
343
346
  componentOrProps.__memo = compare;
344
347
  return componentOrProps;
345
348
  }
349
+ function createState(state) {
350
+ return state;
351
+ }
352
+ function createPatch(p) {
353
+ return p;
354
+ }
346
355
  function tag(v) {
347
356
  return !!v ? Array.isArray(v) ? v[0] : typeof v === "string" || v.nodeType === Node.TEXT_NODE ? "#text" : void 0 : void 0;
348
357
  }
@@ -442,6 +451,34 @@ var V = (() => {
442
451
  }
443
452
  return target;
444
453
  }
454
+ function hydrate(element) {
455
+ if (element?.nodeType === Node.TEXT_NODE) {
456
+ if (element.nodeValue?.trim() !== "")
457
+ return element;
458
+ return void 0;
459
+ } else if (element.nodeType === Node.COMMENT_NODE) {
460
+ return void 0;
461
+ } else {
462
+ const tag2 = element.tagName.toLowerCase();
463
+ const root = [tag2];
464
+ root.node = element;
465
+ if (element?.hasAttributes()) {
466
+ const props2 = {};
467
+ const attr = element.attributes;
468
+ for (let a of attr) {
469
+ props2[a.name] = a.value;
470
+ }
471
+ root.push(props2);
472
+ }
473
+ if (element.hasChildNodes()) {
474
+ for (let child2 of element.childNodes) {
475
+ const wet = child2 && hydrate(child2);
476
+ if (wet) root.push(wet);
477
+ }
478
+ }
479
+ return root;
480
+ }
481
+ }
445
482
  function render(state, patch, parent, childIndex, oldVode, newVode, svg) {
446
483
  newVode = remember(state, newVode, oldVode);
447
484
  const isNoVode = !newVode || typeof newVode === "number" || typeof newVode === "boolean";
@@ -477,8 +514,8 @@ var V = (() => {
477
514
  oldNode.onUnmount && patch(oldNode.onUnmount(oldNode));
478
515
  oldNode.replaceWith(text);
479
516
  } else {
480
- if (parent.childNodes[childIndex]) {
481
- parent.insertBefore(text, parent.childNodes[childIndex]);
517
+ if (parent.childNodes[childIndex + 1]) {
518
+ parent.insertBefore(text, parent.childNodes[childIndex + 1]);
482
519
  } else {
483
520
  parent.appendChild(text);
484
521
  }
@@ -499,8 +536,8 @@ var V = (() => {
499
536
  oldNode.onUnmount && patch(oldNode.onUnmount(oldNode));
500
537
  oldNode.replaceWith(newNode);
501
538
  } else {
502
- if (parent.childNodes[childIndex]) {
503
- parent.insertBefore(newNode, parent.childNodes[childIndex]);
539
+ if (parent.childNodes[childIndex + 1]) {
540
+ parent.insertBefore(newNode, parent.childNodes[childIndex + 1]);
504
541
  } else {
505
542
  parent.appendChild(newNode);
506
543
  }
package/dist/vode.min.js CHANGED
@@ -1 +1 @@
1
- "use strict";var V=(()=>{var N=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var V=Object.prototype.hasOwnProperty;var k=(t,o)=>{for(var n in o)N(t,n,{get:o[n],enumerable:!0})},H=(t,o,n,s)=>{if(o&&typeof o=="object"||typeof o=="function")for(let e of G(o))!V.call(t,e)&&e!==n&&N(t,e,{get:()=>o[e],enumerable:!(s=v(o,e))||s.enumerable});return t};var U=t=>H(N({},"__esModule",{value:!0}),t);var kn={};k(kn,{A:()=>z,ABBR:()=>Z,ADDRESS:()=>w,ANIMATE:()=>we,ANIMATEMOTION:()=>to,ANIMATETRANSFORM:()=>eo,ANNOTATION:()=>sn,ANNOTATION_XML:()=>an,AREA:()=>tt,ARTICLE:()=>et,ASIDE:()=>ot,AUDIO:()=>nt,B:()=>rt,BASE:()=>st,BDI:()=>at,BDO:()=>ct,BLOCKQUOTE:()=>pt,BODY:()=>it,BR:()=>Tt,BUTTON:()=>ft,CANVAS:()=>lt,CAPTION:()=>St,CIRCLE:()=>oo,CITE:()=>dt,CLIPPATH:()=>no,CODE:()=>gt,COL:()=>xt,COLGROUP:()=>ut,DATA:()=>yt,DATALIST:()=>Et,DD:()=>mt,DEFS:()=>ro,DEL:()=>ht,DESC:()=>so,DETAILS:()=>At,DFN:()=>Pt,DIALOG:()=>Ct,DIV:()=>Mt,DL:()=>Nt,DT:()=>Ot,ELLIPSE:()=>ao,EM:()=>Rt,EMBED:()=>Lt,FEBLEND:()=>co,FECOLORMATRIX:()=>po,FECOMPONENTTRANSFER:()=>io,FECOMPOSITE:()=>To,FECONVOLVEMATRIX:()=>fo,FEDIFFUSELIGHTING:()=>lo,FEDISPLACEMENTMAP:()=>So,FEDISTANTLIGHT:()=>go,FEDROPSHADOW:()=>xo,FEFLOOD:()=>uo,FEFUNCA:()=>yo,FEFUNCB:()=>Eo,FEFUNCG:()=>mo,FEFUNCR:()=>ho,FEGAUSSIANBLUR:()=>Ao,FEIMAGE:()=>Po,FEMERGE:()=>Co,FEMERGENODE:()=>Mo,FEMORPHOLOGY:()=>No,FEOFFSET:()=>Oo,FEPOINTLIGHT:()=>Ro,FESPECULARLIGHTING:()=>Lo,FESPOTLIGHT:()=>bo,FETILE:()=>Io,FETURBULENCE:()=>Do,FIELDSET:()=>bt,FIGCAPTION:()=>It,FIGURE:()=>Dt,FILTER:()=>Fo,FOOTER:()=>Ft,FOREIGNOBJECT:()=>vo,FORM:()=>vt,G:()=>Go,H1:()=>Gt,H2:()=>Vt,H3:()=>kt,H4:()=>Ht,H5:()=>Ut,H6:()=>jt,HEAD:()=>Bt,HEADER:()=>_t,HGROUP:()=>Kt,HR:()=>Xt,HTML:()=>qt,I:()=>Yt,IFRAME:()=>Wt,IMAGE:()=>Vo,IMG:()=>$t,INPUT:()=>Jt,INS:()=>Qt,KBD:()=>zt,LABEL:()=>Zt,LEGEND:()=>wt,LI:()=>te,LINE:()=>ko,LINEARGRADIENT:()=>Ho,LINK:()=>ee,MACTION:()=>cn,MAIN:()=>oe,MAP:()=>ne,MARK:()=>re,MARKER:()=>Uo,MASK:()=>jo,MATH:()=>pn,MENU:()=>se,MERROR:()=>Tn,META:()=>ae,METADATA:()=>Bo,METER:()=>ce,MFRAC:()=>fn,MI:()=>ln,MMULTISCRIPTS:()=>Sn,MN:()=>dn,MO:()=>gn,MOVER:()=>xn,MPADDED:()=>un,MPATH:()=>_o,MPHANTOM:()=>yn,MPRESCRIPTS:()=>En,MROOT:()=>mn,MROW:()=>hn,MS:()=>An,MSPACE:()=>Pn,MSQRT:()=>Cn,MSTYLE:()=>Mn,MSUB:()=>Nn,MSUBSUP:()=>On,MSUP:()=>Rn,MTABLE:()=>Ln,MTD:()=>bn,MTEXT:()=>In,MTR:()=>Dn,MUNDER:()=>Fn,MUNDEROVER:()=>vn,NAV:()=>pe,NOSCRIPT:()=>ie,OBJECT:()=>Te,OL:()=>fe,OPTGROUP:()=>le,OPTION:()=>Se,OUTPUT:()=>de,P:()=>ge,PATH:()=>Ko,PATTERN:()=>Xo,PICTURE:()=>xe,POLYGON:()=>qo,POLYLINE:()=>Yo,PRE:()=>ue,PROGRESS:()=>ye,Q:()=>Ee,RADIALGRADIENT:()=>Wo,RECT:()=>$o,RP:()=>me,RT:()=>he,RUBY:()=>Ae,S:()=>Pe,SAMP:()=>Ce,SCRIPT:()=>Me,SECTION:()=>Ne,SELECT:()=>Oe,SEMANTICS:()=>Gn,SET:()=>Jo,SLOT:()=>Re,SMALL:()=>Le,SOURCE:()=>be,SPAN:()=>Ie,STOP:()=>Qo,STRONG:()=>De,STYLE:()=>Fe,SUB:()=>ve,SUMMARY:()=>Ge,SUP:()=>Ve,SVG:()=>zo,SWITCH:()=>Zo,SYMBOL:()=>wo,TABLE:()=>ke,TBODY:()=>He,TD:()=>Ue,TEMPLATE:()=>je,TEXT:()=>tn,TEXTAREA:()=>Be,TEXTPATH:()=>en,TFOOT:()=>_e,TH:()=>Ke,THEAD:()=>Xe,TIME:()=>qe,TITLE:()=>Ye,TR:()=>We,TRACK:()=>$e,TSPAN:()=>on,U:()=>Je,UL:()=>Qe,USE:()=>nn,VIDEO:()=>ze,VIEW:()=>rn,WBR:()=>Ze,app:()=>K,child:()=>$,childCount:()=>W,children:()=>A,childrenStart:()=>C,createPatch:()=>B,createState:()=>j,htmlToVode:()=>Vn,memo:()=>X,mergeClass:()=>Y,props:()=>d,tag:()=>q,vode:()=>_});function j(t){return t}function B(t){return t}function _(t,o,...n){if(!t)throw new Error("tag must be a string or vode");return Array.isArray(t)?t:o?[t,o,...n]:[t,...n]}function K(t,o,n,...s){if(!t)throw new Error("container must be a valid HTMLElement");if(!o||typeof o!="object")throw new Error("initialState must be an object");if(typeof n!="function")throw new Error("dom must be a function that returns a vode");let e={};e.stats={lastRenderTime:0,renderCount:0,liveEffectCount:0,patchCount:0,renderPatchCount:0},Object.defineProperty(o,"patch",{enumerable:!1,configurable:!0,writable:!1,value:async c=>{if(!(!c||typeof c!="function"&&typeof c!="object"))if(e.stats.patchCount++,c?.next){let l=c;e.stats.liveEffectCount++;try{let p=await l.next();for(;p.done===!1;){e.stats.liveEffectCount++;try{e.patch(p.value),p=await l.next()}finally{e.stats.liveEffectCount--}}e.patch(p.value)}finally{e.stats.liveEffectCount--}}else if(c.then){e.stats.liveEffectCount++;try{let l=await c;e.patch(l)}finally{e.stats.liveEffectCount--}}else Array.isArray(c)?typeof c[0]=="function"?c.length>1?e.patch(c[0](e.state,...c.slice(1))):e.patch(c[0](e.state)):e.stats.patchCount--:typeof c=="function"?e.patch(c(e.state)):(e.stats.renderPatchCount++,e.q=u(e.q||{},c,!1),e.isRendering||e.render())}}),Object.defineProperty(e,"render",{enumerable:!1,configurable:!0,writable:!1,value:()=>requestAnimationFrame(()=>{if(e.isRendering||!e.q)return;e.isRendering=!0;let c=Date.now();try{e.state=u(e.state,e.q,!0),e.q=null,e.vode=P(e.state,e.patch,t,0,e.vode,n(e.state))}finally{e.isRendering=!1,e.stats.renderCount++,e.stats.lastRenderTime=Date.now()-c,e.q&&e.render()}})}),e.patch=o.patch,e.state=o,e.q=null;let r=t;r._vode=e;let a=n(o);e.vode=a,e.vode=P(o,e.patch,t,0,void 0,a);for(let c of s)e.patch(c);return e.patch}function X(t,o){return o.__memo=t,o}function q(t){return t?Array.isArray(t)?t[0]:typeof t=="string"||t.nodeType===Node.TEXT_NODE?"#text":void 0:void 0}function d(t){if(Array.isArray(t)&&t.length>1&&t[1]&&!Array.isArray(t[1])&&typeof t[1]=="object"&&t[1].nodeType!==Node.TEXT_NODE)return t[1]}function Y(t,o){if(!t)return o;if(!o)return t;if(typeof t=="string"&&typeof o=="string"){let n=t.split(" "),s=o.split(" "),e=new Set([...n,...s]);return Array.from(e).join(" ").trim()}else if(typeof t=="string"&&Array.isArray(o)){let n=new Set([...o,...t.split(" ")]);return Array.from(n).join(" ").trim()}else if(Array.isArray(t)&&typeof o=="string"){let n=new Set([...t,...o.split(" ")]);return Array.from(n).join(" ").trim()}else if(Array.isArray(t)&&Array.isArray(o)){let n=new Set([...t,...o]);return Array.from(n).join(" ").trim()}else{if(typeof t=="string"&&typeof o=="object")return{[t]:!0,...o};if(typeof t=="object"&&typeof o=="string")return{...t,[o]:!0};if(typeof t=="object"&&typeof o=="object")return{...t,...o};if(typeof t=="object"&&Array.isArray(o)){let n={...t};for(let s of o)n[s]=!0;return n}else if(Array.isArray(t)&&typeof o=="object"){let n={};for(let s of t)n[s]=!0;for(let s of Object.keys(o))n[s]=o[s];return n}}throw new Error(`cannot merge classes of ${t} (${typeof t}) and ${o} (${typeof o})`)}function A(t){let o=C(t);return o>0?t.slice(o):null}function W(t){return t.length-C(t)}function $(t,o){return t[o+C(t)]}function C(t){return d(t)?2:1}function u(t,o,n){if(!o)return t;for(let s in o){let e=o[s];if(e&&typeof e=="object"){let r=t[s];r?Array.isArray(e)?t[s]=[...e]:e instanceof Date&&r!==e?t[s]=new Date(e):Array.isArray(r)?t[s]=u({},e,n):typeof r=="object"?u(t[s],e,n):t[s]=u({},e,n):Array.isArray(e)?t[s]=[...e]:e instanceof Date?t[s]=new Date(e):t[s]=u({},e,n)}else e===void 0&&n?delete t[s]:t[s]=e}return t}function P(t,o,n,s,e,r,a){r=O(t,r,e);let c=!r||typeof r=="number"||typeof r=="boolean";if(r===e||!e&&c)return e;let l=e?.nodeType===Node.TEXT_NODE,p=l?e:e?.node;if(c){p?.onUnmount&&o(p.onUnmount(p)),p?.remove();return}let E=!c&&Q(r),m=!c&&J(r),M=!!r&&typeof r!="string"&&!!(r?.node||r?.nodeType===Node.TEXT_NODE);if(!E&&!m&&!M&&!e)throw new Error("Invalid vode: "+typeof r+" "+JSON.stringify(r));if(M&&E?r=r.wholeText:M&&m&&(r=[...r]),l&&E)return p.nodeValue!==r&&(p.nodeValue=r),e;if(E&&(!p||!l)){let T=document.createTextNode(r);return p?(p.onUnmount&&o(p.onUnmount(p)),p.replaceWith(T)):n.childNodes[s]?n.insertBefore(T,n.childNodes[s]):n.appendChild(T),T}if(m&&(!p||l||e[0]!==r[0])){a=a||r[0]==="svg";let T=a?document.createElementNS("http://www.w3.org/2000/svg",r[0]):document.createElement(r[0]);r.node=T;let y=r;1 in y&&(y[1]=O(t,y[1],void 0));let g=d(r);R(o,T,void 0,g,a),p?(p.onUnmount&&o(p.onUnmount(p)),p.replaceWith(T)):n.childNodes[s]?n.insertBefore(T,n.childNodes[s]):n.appendChild(T);let S=A(r);if(S)for(let f=0;f<S.length;f++){let i=S[f],x=P(t,o,T,f,void 0,i,a);r[g?f+2:f+1]=x}return T.onMount&&o(T.onMount(T)),r}if(!l&&m&&e[0]===r[0]){a=a||r[0]==="svg",r.node=p;let T=r,y=e,g=!1;if(T[1]?.__memo){let i=T[1];if(T[1]=O(t,T[1],y[1]),i!==T[1]){let x=d(r);R(o,p,d(e),x,a),g=!!x}}else{let i=d(r);R(o,p,d(e),i,a),g=!!i}let S=A(r),f=A(e);if(S){for(let i=0;i<S.length;i++){let x=S[i],F=f&&f[i],b=P(t,o,p,i,F,x,a);b&&(r[g?i+2:i+1]=b)}for(let i=S.length;f&&i<f.length;i++)f[i]?.node?f[i].node.remove():f[i]?.nodeType===Node.TEXT_NODE&&f[i].remove()}for(let i=S?.length||0;i<f?.length;i++)f[i]?.node?f[i].node.remove():f[i]?.nodeType===Node.TEXT_NODE&&f[i].remove();return r}}function J(t){return Array.isArray(t)&&t.length>0&&typeof t[0]=="string"}function Q(t){return typeof t=="string"||t?.nodeType===Node.TEXT_NODE}function O(t,o,n){if(typeof o!="function")return o;let s=o?.__memo,e=n?.__memo;if(Array.isArray(s)&&Array.isArray(e)&&s.length===e.length){let a=!0;for(let c=0;c<s.length;c++)if(s[c]!==e[c]){a=!1;break}if(a)return n}let r=I(o,t);return typeof r=="object"&&(r.__memo=o?.__memo),r}function I(t,o){return typeof t=="function"?I(t(o),o):t}function R(t,o,n,s,e){if(!(!s&&!n)){if(n)for(let r in n){let a=n[r],c=s?.[r];a!==c&&(s?s[r]=h(t,o,r,a,c,e):h(t,o,r,a,void 0,e))}if(s&&n){for(let r in s)if(!(r in n)){let a=s[r];s[r]=h(t,o,r,void 0,a,e)}}else if(s)for(let r in s){let a=s[r];s[r]=h(t,o,r,void 0,a,e)}}}function h(t,o,n,s,e,r){if(n==="style")if(!e)o.style.cssText="";else if(s)for(let a in{...s,...e})!s||e[a]!==s[a]?o.style[a]=e[a]:s[a]&&!e[a]&&(o.style[a]=void 0);else for(let a in e)o.style[a]=e[a];else if(n==="class")if(r)if(e){let a=L(e);o.classList.value=a}else o.classList.value="";else if(e){let a=L(e);o.className=a}else o.className="";else if(n[0]==="o"&&n[1]==="n")if(e){let a=null;if(typeof e=="function"){let c=e;a=l=>t([c,l])}else if(Array.isArray(e)){let c=e,l=e[0];c.length>1?a=()=>t([l,...c.slice(1)]):a=p=>t([l,p])}else typeof e=="object"&&(a=()=>t(e));o[n]=a}else o[n]=null;else e!=null&&e!==!1?o.setAttribute(n,e):o.removeAttribute(n);return e}function L(t){return typeof t=="string"?t:Array.isArray(t)?t.map(L).join(" "):typeof t=="object"?Object.keys(t).filter(o=>t[o]).join(" "):""}var z="a",Z="abbr",w="address",tt="area",et="article",ot="aside",nt="audio",rt="b",st="base",at="bdi",ct="bdo",pt="blockquote",it="body",Tt="br",ft="button",lt="canvas",St="caption",dt="cite",gt="code",xt="col",ut="colgroup",yt="data",Et="datalist",mt="dd",ht="del",At="details",Pt="dfn",Ct="dialog",Mt="div",Nt="dl",Ot="dt",Rt="em",Lt="embed",bt="fieldset",It="figcaption",Dt="figure",Ft="footer",vt="form",Gt="h1",Vt="h2",kt="h3",Ht="h4",Ut="h5",jt="h6",Bt="head",_t="header",Kt="hgroup",Xt="hr",qt="html",Yt="i",Wt="iframe",$t="img",Jt="input",Qt="ins",zt="kbd",Zt="label",wt="legend",te="li",ee="link",oe="main",ne="map",re="mark",se="menu",ae="meta",ce="meter",pe="nav",ie="noscript",Te="object",fe="ol",le="optgroup",Se="option",de="output",ge="p",xe="picture",ue="pre",ye="progress",Ee="q",me="rp",he="rt",Ae="ruby",Pe="s",Ce="samp",Me="script",Ne="section",Oe="select",Re="slot",Le="small",be="source",Ie="span",De="strong",Fe="style",ve="sub",Ge="summary",Ve="sup",ke="table",He="tbody",Ue="td",je="template",Be="textarea",_e="tfoot",Ke="th",Xe="thead",qe="time",Ye="title",We="tr",$e="track",Je="u",Qe="ul",ze="video",Ze="wbr",we="animate",to="animateMotion",eo="animateTransform",oo="circle",no="clipPath",ro="defs",so="desc",ao="ellipse",co="feBlend",po="feColorMatrix",io="feComponentTransfer",To="feComposite",fo="feConvolveMatrix",lo="feDiffuseLighting",So="feDisplacementMap",go="feDistantLight",xo="feDropShadow",uo="feFlood",yo="feFuncA",Eo="feFuncB",mo="feFuncG",ho="feFuncR",Ao="feGaussianBlur",Po="feImage",Co="feMerge",Mo="feMergeNode",No="feMorphology",Oo="feOffset",Ro="fePointLight",Lo="feSpecularLighting",bo="feSpotLight",Io="feTile",Do="feTurbulence",Fo="filter",vo="foreignObject",Go="g",Vo="image",ko="line",Ho="linearGradient",Uo="marker",jo="mask",Bo="metadata",_o="mpath",Ko="path",Xo="pattern",qo="polygon",Yo="polyline",Wo="radialGradient",$o="rect",Jo="set",Qo="stop",zo="svg",Zo="switch",wo="symbol",tn="text",en="textPath",on="tspan",nn="use",rn="view",sn="annotation",an="annotation-xml",cn="maction",pn="math",Tn="merror",fn="mfrac",ln="mi",Sn="mmultiscripts",dn="mn",gn="mo",xn="mover",un="mpadded",yn="mphantom",En="mprescripts",mn="mroot",hn="mrow",An="ms",Pn="mspace",Cn="msqrt",Mn="mstyle",Nn="msub",On="msubsup",Rn="msup",Ln="mtable",bn="mtd",In="mtext",Dn="mtr",Fn="munder",vn="munderover",Gn="semantics";function Vn(t){let o=document.createElement("div");o.innerHTML=t.trim();let n=[];for(let s of o.childNodes){let e=D(s);e!=null&&n.push(e)}return n}function D(t){if(t.nodeType===Node.TEXT_NODE)return t.textContent;if(t.nodeType!==Node.ELEMENT_NODE)return;let o=[t.tagName.toLowerCase()];if(t.hasAttributes()){let n={};for(let s of t.attributes)n[s.name]=s.value;o.push(n)}for(let n of t.childNodes){let s=D(n);s&&(typeof s!="string"||s.length>0)&&o.push(s)}return o}return U(kn);})();
1
+ "use strict";var V=(()=>{var M=Object.defineProperty;var V=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var k=Object.prototype.hasOwnProperty;var H=(t,o)=>{for(var n in o)M(t,n,{get:o[n],enumerable:!0})},U=(t,o,n,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let e of G(o))!k.call(t,e)&&e!==n&&M(t,e,{get:()=>o[e],enumerable:!(r=V(o,e))||r.enumerable});return t};var j=t=>U(M({},"__esModule",{value:!0}),t);var Hn={};H(Hn,{A:()=>Z,ABBR:()=>w,ADDRESS:()=>tt,ANIMATE:()=>to,ANIMATEMOTION:()=>eo,ANIMATETRANSFORM:()=>oo,ANNOTATION:()=>an,ANNOTATION_XML:()=>cn,AREA:()=>et,ARTICLE:()=>ot,ASIDE:()=>nt,AUDIO:()=>rt,B:()=>st,BASE:()=>at,BDI:()=>ct,BDO:()=>it,BLOCKQUOTE:()=>pt,BODY:()=>Tt,BR:()=>ft,BUTTON:()=>lt,CANVAS:()=>St,CAPTION:()=>dt,CIRCLE:()=>no,CITE:()=>gt,CLIPPATH:()=>ro,CODE:()=>ut,COL:()=>xt,COLGROUP:()=>yt,DATA:()=>Et,DATALIST:()=>mt,DD:()=>ht,DEFS:()=>so,DEL:()=>At,DESC:()=>ao,DETAILS:()=>Pt,DFN:()=>Ct,DIALOG:()=>Nt,DIV:()=>Mt,DL:()=>Ot,DT:()=>Rt,ELLIPSE:()=>co,EM:()=>Lt,EMBED:()=>bt,FEBLEND:()=>io,FECOLORMATRIX:()=>po,FECOMPONENTTRANSFER:()=>To,FECOMPOSITE:()=>fo,FECONVOLVEMATRIX:()=>lo,FEDIFFUSELIGHTING:()=>So,FEDISPLACEMENTMAP:()=>go,FEDISTANTLIGHT:()=>uo,FEDROPSHADOW:()=>xo,FEFLOOD:()=>yo,FEFUNCA:()=>Eo,FEFUNCB:()=>mo,FEFUNCG:()=>ho,FEFUNCR:()=>Ao,FEGAUSSIANBLUR:()=>Po,FEIMAGE:()=>Co,FEMERGE:()=>No,FEMERGENODE:()=>Mo,FEMORPHOLOGY:()=>Oo,FEOFFSET:()=>Ro,FEPOINTLIGHT:()=>Lo,FESPECULARLIGHTING:()=>bo,FESPOTLIGHT:()=>Do,FETILE:()=>Io,FETURBULENCE:()=>Fo,FIELDSET:()=>Dt,FIGCAPTION:()=>It,FIGURE:()=>Ft,FILTER:()=>vo,FOOTER:()=>vt,FOREIGNOBJECT:()=>Vo,FORM:()=>Vt,G:()=>Go,H1:()=>Gt,H2:()=>kt,H3:()=>Ht,H4:()=>Ut,H5:()=>jt,H6:()=>Bt,HEAD:()=>_t,HEADER:()=>Kt,HGROUP:()=>Xt,HR:()=>qt,HTML:()=>Yt,I:()=>Wt,IFRAME:()=>$t,IMAGE:()=>ko,IMG:()=>Jt,INPUT:()=>Qt,INS:()=>zt,KBD:()=>Zt,LABEL:()=>wt,LEGEND:()=>te,LI:()=>ee,LINE:()=>Ho,LINEARGRADIENT:()=>Uo,LINK:()=>oe,MACTION:()=>pn,MAIN:()=>ne,MAP:()=>re,MARK:()=>se,MARKER:()=>jo,MASK:()=>Bo,MATH:()=>Tn,MENU:()=>ae,MERROR:()=>fn,META:()=>ce,METADATA:()=>_o,METER:()=>ie,MFRAC:()=>ln,MI:()=>Sn,MMULTISCRIPTS:()=>dn,MN:()=>gn,MO:()=>un,MOVER:()=>xn,MPADDED:()=>yn,MPATH:()=>Ko,MPHANTOM:()=>En,MPRESCRIPTS:()=>mn,MROOT:()=>hn,MROW:()=>An,MS:()=>Pn,MSPACE:()=>Cn,MSQRT:()=>Nn,MSTYLE:()=>Mn,MSUB:()=>On,MSUBSUP:()=>Rn,MSUP:()=>Ln,MTABLE:()=>bn,MTD:()=>Dn,MTEXT:()=>In,MTR:()=>Fn,MUNDER:()=>vn,MUNDEROVER:()=>Vn,NAV:()=>pe,NOSCRIPT:()=>Te,OBJECT:()=>fe,OL:()=>le,OPTGROUP:()=>Se,OPTION:()=>de,OUTPUT:()=>ge,P:()=>ue,PATH:()=>Xo,PATTERN:()=>qo,PICTURE:()=>xe,POLYGON:()=>Yo,POLYLINE:()=>Wo,PRE:()=>ye,PROGRESS:()=>Ee,Q:()=>me,RADIALGRADIENT:()=>$o,RECT:()=>Jo,RP:()=>he,RT:()=>Ae,RUBY:()=>Pe,S:()=>Ce,SAMP:()=>Ne,SCRIPT:()=>Me,SECTION:()=>Oe,SELECT:()=>Re,SEMANTICS:()=>Gn,SET:()=>Qo,SLOT:()=>Le,SMALL:()=>be,SOURCE:()=>De,SPAN:()=>Ie,STOP:()=>zo,STRONG:()=>Fe,STYLE:()=>ve,SUB:()=>Ve,SUMMARY:()=>Ge,SUP:()=>ke,SVG:()=>Zo,SWITCH:()=>wo,SYMBOL:()=>tn,TABLE:()=>He,TBODY:()=>Ue,TD:()=>je,TEMPLATE:()=>Be,TEXT:()=>en,TEXTAREA:()=>_e,TEXTPATH:()=>on,TFOOT:()=>Ke,TH:()=>Xe,THEAD:()=>qe,TIME:()=>Ye,TITLE:()=>We,TR:()=>$e,TRACK:()=>Je,TSPAN:()=>nn,U:()=>Qe,UL:()=>ze,USE:()=>rn,VIDEO:()=>Ze,VIEW:()=>sn,WBR:()=>we,app:()=>_,child:()=>J,childCount:()=>$,children:()=>A,childrenStart:()=>C,createPatch:()=>q,createState:()=>X,htmlToVode:()=>kn,memo:()=>K,mergeClass:()=>W,props:()=>d,tag:()=>Y,vode:()=>B});function B(t,o,...n){if(!t)throw new Error("tag must be a string or vode");return Array.isArray(t)?t:o?[t,o,...n]:[t,...n]}function _(t,o,n,...r){if(!t?.parentElement)throw new Error("container must be a valid HTMLElement inside the <html></html> document");if(!o||typeof o!="object")throw new Error("given state must be an object");if(typeof n!="function")throw new Error("dom must be a function that returns a vode");let e={};e.stats={lastRenderTime:0,renderCount:0,liveEffectCount:0,patchCount:0,renderPatchCount:0},Object.defineProperty(o,"patch",{enumerable:!1,configurable:!0,writable:!1,value:async a=>{if(!(!a||typeof a!="function"&&typeof a!="object"))if(e.stats.patchCount++,a?.next){let i=a;e.stats.liveEffectCount++;try{let l=await i.next();for(;l.done===!1;){e.stats.liveEffectCount++;try{e.patch(l.value),l=await i.next()}finally{e.stats.liveEffectCount--}}e.patch(l.value)}finally{e.stats.liveEffectCount--}}else if(a.then){e.stats.liveEffectCount++;try{let i=await a;e.patch(i)}finally{e.stats.liveEffectCount--}}else Array.isArray(a)?typeof a[0]=="function"?a.length>1?e.patch(a[0](e.state,...a.slice(1))):e.patch(a[0](e.state)):e.stats.patchCount--:typeof a=="function"?e.patch(a(e.state)):(e.stats.renderPatchCount++,e.q=x(e.q||{},a,!1),e.isRendering||e.render())}}),Object.defineProperty(e,"render",{enumerable:!1,configurable:!0,writable:!1,value:()=>requestAnimationFrame(()=>{if(e.isRendering||!e.q)return;e.isRendering=!0;let a=Date.now();try{e.state=x(e.state,e.q,!0),e.q=null;let i=n(e.state);e.vode=P(e.state,e.patch,t.parentElement,0,e.vode,i),t.tagName!==i[0].toUpperCase()&&(t=e.vode.node)}finally{e.isRendering=!1,e.stats.renderCount++,e.stats.lastRenderTime=Date.now()-a,e.q&&e.render()}})}),e.patch=o.patch,e.state=o,e.q=null;let s=t;s._vode=e,e.vode=P(o,e.patch,t.parentElement,Array.from(t.parentElement.children).indexOf(t),D(t),n(o));for(let a of r)e.patch(a);return e.patch}function K(t,o){return o.__memo=t,o}function X(t){return t}function q(t){return t}function Y(t){return t?Array.isArray(t)?t[0]:typeof t=="string"||t.nodeType===Node.TEXT_NODE?"#text":void 0:void 0}function d(t){if(Array.isArray(t)&&t.length>1&&t[1]&&!Array.isArray(t[1])&&typeof t[1]=="object"&&t[1].nodeType!==Node.TEXT_NODE)return t[1]}function W(t,o){if(!t)return o;if(!o)return t;if(typeof t=="string"&&typeof o=="string"){let n=t.split(" "),r=o.split(" "),e=new Set([...n,...r]);return Array.from(e).join(" ").trim()}else if(typeof t=="string"&&Array.isArray(o)){let n=new Set([...o,...t.split(" ")]);return Array.from(n).join(" ").trim()}else if(Array.isArray(t)&&typeof o=="string"){let n=new Set([...t,...o.split(" ")]);return Array.from(n).join(" ").trim()}else if(Array.isArray(t)&&Array.isArray(o)){let n=new Set([...t,...o]);return Array.from(n).join(" ").trim()}else{if(typeof t=="string"&&typeof o=="object")return{[t]:!0,...o};if(typeof t=="object"&&typeof o=="string")return{...t,[o]:!0};if(typeof t=="object"&&typeof o=="object")return{...t,...o};if(typeof t=="object"&&Array.isArray(o)){let n={...t};for(let r of o)n[r]=!0;return n}else if(Array.isArray(t)&&typeof o=="object"){let n={};for(let r of t)n[r]=!0;for(let r of Object.keys(o))n[r]=o[r];return n}}throw new Error(`cannot merge classes of ${t} (${typeof t}) and ${o} (${typeof o})`)}function A(t){let o=C(t);return o>0?t.slice(o):null}function $(t){return t.length-C(t)}function J(t,o){return t[o+C(t)]}function C(t){return d(t)?2:1}function x(t,o,n){if(!o)return t;for(let r in o){let e=o[r];if(e&&typeof e=="object"){let s=t[r];s?Array.isArray(e)?t[r]=[...e]:e instanceof Date&&s!==e?t[r]=new Date(e):Array.isArray(s)?t[r]=x({},e,n):typeof s=="object"?x(t[r],e,n):t[r]=x({},e,n):Array.isArray(e)?t[r]=[...e]:e instanceof Date?t[r]=new Date(e):t[r]=x({},e,n)}else e===void 0&&n?delete t[r]:t[r]=e}return t}function D(t){if(t?.nodeType===Node.TEXT_NODE)return t.nodeValue?.trim()!==""?t:void 0;if(t.nodeType===Node.COMMENT_NODE)return;{let n=[t.tagName.toLowerCase()];if(n.node=t,t?.hasAttributes()){let r={},e=t.attributes;for(let s of e)r[s.name]=s.value;n.push(r)}if(t.hasChildNodes())for(let r of t.childNodes){let e=r&&D(r);e&&n.push(e)}return n}}function P(t,o,n,r,e,s,a){s=O(t,s,e);let i=!s||typeof s=="number"||typeof s=="boolean";if(s===e||!e&&i)return e;let l=e?.nodeType===Node.TEXT_NODE,p=l?e:e?.node;if(i){p?.onUnmount&&o(p.onUnmount(p)),p?.remove();return}let E=!i&&z(s),m=!i&&Q(s),N=!!s&&typeof s!="string"&&!!(s?.node||s?.nodeType===Node.TEXT_NODE);if(!E&&!m&&!N&&!e)throw new Error("Invalid vode: "+typeof s+" "+JSON.stringify(s));if(N&&E?s=s.wholeText:N&&m&&(s=[...s]),l&&E)return p.nodeValue!==s&&(p.nodeValue=s),e;if(E&&(!p||!l)){let T=document.createTextNode(s);return p?(p.onUnmount&&o(p.onUnmount(p)),p.replaceWith(T)):n.childNodes[r+1]?n.insertBefore(T,n.childNodes[r+1]):n.appendChild(T),T}if(m&&(!p||l||e[0]!==s[0])){a=a||s[0]==="svg";let T=a?document.createElementNS("http://www.w3.org/2000/svg",s[0]):document.createElement(s[0]);s.node=T;let y=s;1 in y&&(y[1]=O(t,y[1],void 0));let g=d(s);R(o,T,void 0,g,a),p?(p.onUnmount&&o(p.onUnmount(p)),p.replaceWith(T)):n.childNodes[r+1]?n.insertBefore(T,n.childNodes[r+1]):n.appendChild(T);let S=A(s);if(S)for(let f=0;f<S.length;f++){let c=S[f],u=P(t,o,T,f,void 0,c,a);s[g?f+2:f+1]=u}return T.onMount&&o(T.onMount(T)),s}if(!l&&m&&e[0]===s[0]){a=a||s[0]==="svg",s.node=p;let T=s,y=e,g=!1;if(T[1]?.__memo){let c=T[1];if(T[1]=O(t,T[1],y[1]),c!==T[1]){let u=d(s);R(o,p,d(e),u,a),g=!!u}}else{let c=d(s);R(o,p,d(e),c,a),g=!!c}let S=A(s),f=A(e);if(S){for(let c=0;c<S.length;c++){let u=S[c],v=f&&f[c],b=P(t,o,p,c,v,u,a);b&&(s[g?c+2:c+1]=b)}for(let c=S.length;f&&c<f.length;c++)f[c]?.node?f[c].node.remove():f[c]?.nodeType===Node.TEXT_NODE&&f[c].remove()}for(let c=S?.length||0;c<f?.length;c++)f[c]?.node?f[c].node.remove():f[c]?.nodeType===Node.TEXT_NODE&&f[c].remove();return s}}function Q(t){return Array.isArray(t)&&t.length>0&&typeof t[0]=="string"}function z(t){return typeof t=="string"||t?.nodeType===Node.TEXT_NODE}function O(t,o,n){if(typeof o!="function")return o;let r=o?.__memo,e=n?.__memo;if(Array.isArray(r)&&Array.isArray(e)&&r.length===e.length){let a=!0;for(let i=0;i<r.length;i++)if(r[i]!==e[i]){a=!1;break}if(a)return n}let s=I(o,t);return typeof s=="object"&&(s.__memo=o?.__memo),s}function I(t,o){return typeof t=="function"?I(t(o),o):t}function R(t,o,n,r,e){if(!(!r&&!n)){if(n)for(let s in n){let a=n[s],i=r?.[s];a!==i&&(r?r[s]=h(t,o,s,a,i,e):h(t,o,s,a,void 0,e))}if(r&&n){for(let s in r)if(!(s in n)){let a=r[s];r[s]=h(t,o,s,void 0,a,e)}}else if(r)for(let s in r){let a=r[s];r[s]=h(t,o,s,void 0,a,e)}}}function h(t,o,n,r,e,s){if(n==="style")if(!e)o.style.cssText="";else if(r)for(let a in{...r,...e})!r||e[a]!==r[a]?o.style[a]=e[a]:r[a]&&!e[a]&&(o.style[a]=void 0);else for(let a in e)o.style[a]=e[a];else if(n==="class")if(s)if(e){let a=L(e);o.classList.value=a}else o.classList.value="";else if(e){let a=L(e);o.className=a}else o.className="";else if(n[0]==="o"&&n[1]==="n")if(e){let a=null;if(typeof e=="function"){let i=e;a=l=>t([i,l])}else if(Array.isArray(e)){let i=e,l=e[0];i.length>1?a=()=>t([l,...i.slice(1)]):a=p=>t([l,p])}else typeof e=="object"&&(a=()=>t(e));o[n]=a}else o[n]=null;else e!=null&&e!==!1?o.setAttribute(n,e):o.removeAttribute(n);return e}function L(t){return typeof t=="string"?t:Array.isArray(t)?t.map(L).join(" "):typeof t=="object"?Object.keys(t).filter(o=>t[o]).join(" "):""}var Z="a",w="abbr",tt="address",et="area",ot="article",nt="aside",rt="audio",st="b",at="base",ct="bdi",it="bdo",pt="blockquote",Tt="body",ft="br",lt="button",St="canvas",dt="caption",gt="cite",ut="code",xt="col",yt="colgroup",Et="data",mt="datalist",ht="dd",At="del",Pt="details",Ct="dfn",Nt="dialog",Mt="div",Ot="dl",Rt="dt",Lt="em",bt="embed",Dt="fieldset",It="figcaption",Ft="figure",vt="footer",Vt="form",Gt="h1",kt="h2",Ht="h3",Ut="h4",jt="h5",Bt="h6",_t="head",Kt="header",Xt="hgroup",qt="hr",Yt="html",Wt="i",$t="iframe",Jt="img",Qt="input",zt="ins",Zt="kbd",wt="label",te="legend",ee="li",oe="link",ne="main",re="map",se="mark",ae="menu",ce="meta",ie="meter",pe="nav",Te="noscript",fe="object",le="ol",Se="optgroup",de="option",ge="output",ue="p",xe="picture",ye="pre",Ee="progress",me="q",he="rp",Ae="rt",Pe="ruby",Ce="s",Ne="samp",Me="script",Oe="section",Re="select",Le="slot",be="small",De="source",Ie="span",Fe="strong",ve="style",Ve="sub",Ge="summary",ke="sup",He="table",Ue="tbody",je="td",Be="template",_e="textarea",Ke="tfoot",Xe="th",qe="thead",Ye="time",We="title",$e="tr",Je="track",Qe="u",ze="ul",Ze="video",we="wbr",to="animate",eo="animateMotion",oo="animateTransform",no="circle",ro="clipPath",so="defs",ao="desc",co="ellipse",io="feBlend",po="feColorMatrix",To="feComponentTransfer",fo="feComposite",lo="feConvolveMatrix",So="feDiffuseLighting",go="feDisplacementMap",uo="feDistantLight",xo="feDropShadow",yo="feFlood",Eo="feFuncA",mo="feFuncB",ho="feFuncG",Ao="feFuncR",Po="feGaussianBlur",Co="feImage",No="feMerge",Mo="feMergeNode",Oo="feMorphology",Ro="feOffset",Lo="fePointLight",bo="feSpecularLighting",Do="feSpotLight",Io="feTile",Fo="feTurbulence",vo="filter",Vo="foreignObject",Go="g",ko="image",Ho="line",Uo="linearGradient",jo="marker",Bo="mask",_o="metadata",Ko="mpath",Xo="path",qo="pattern",Yo="polygon",Wo="polyline",$o="radialGradient",Jo="rect",Qo="set",zo="stop",Zo="svg",wo="switch",tn="symbol",en="text",on="textPath",nn="tspan",rn="use",sn="view",an="annotation",cn="annotation-xml",pn="maction",Tn="math",fn="merror",ln="mfrac",Sn="mi",dn="mmultiscripts",gn="mn",un="mo",xn="mover",yn="mpadded",En="mphantom",mn="mprescripts",hn="mroot",An="mrow",Pn="ms",Cn="mspace",Nn="msqrt",Mn="mstyle",On="msub",Rn="msubsup",Ln="msup",bn="mtable",Dn="mtd",In="mtext",Fn="mtr",vn="munder",Vn="munderover",Gn="semantics";function kn(t){let o=document.createElement("div");o.innerHTML=t.trim();let n=[];for(let r of o.childNodes){let e=F(r);e!=null&&n.push(e)}return n}function F(t){if(t.nodeType===Node.TEXT_NODE)return t.textContent;if(t.nodeType!==Node.ELEMENT_NODE)return;let o=[t.tagName.toLowerCase()];if(t.hasAttributes()){let n={};for(let r of t.attributes)n[r.name]=r.value;o.push(n)}for(let n of t.childNodes){let r=F(n);r&&(typeof r!="string"||r.length>0)&&o.push(r)}return o}return j(Hn);})();
package/dist/vode.min.mjs CHANGED
@@ -1 +1 @@
1
- function P(f){return f}function h(f){return f}function g(f,L,...j){if(!f)throw new Error("tag must be a string or vode");if(Array.isArray(f))return f;else if(L)return[f,L,...j];else return[f,...j]}function u(f,L,j,...q){if(!f)throw new Error("container must be a valid HTMLElement");if(!L||typeof L!=="object")throw new Error("initialState must be an object");if(typeof j!=="function")throw new Error("dom must be a function that returns a vode");let E={};E.stats={lastRenderTime:0,renderCount:0,liveEffectCount:0,patchCount:0,renderPatchCount:0},Object.defineProperty(L,"patch",{enumerable:!1,configurable:!0,writable:!1,value:async(B)=>{if(!B||typeof B!=="function"&&typeof B!=="object")return;if(E.stats.patchCount++,B?.next){let U=B;E.stats.liveEffectCount++;try{let F=await U.next();while(F.done===!1){E.stats.liveEffectCount++;try{E.patch(F.value),F=await U.next()}finally{E.stats.liveEffectCount--}}E.patch(F.value)}finally{E.stats.liveEffectCount--}}else if(B.then){E.stats.liveEffectCount++;try{let U=await B;E.patch(U)}finally{E.stats.liveEffectCount--}}else if(Array.isArray(B))if(typeof B[0]==="function")if(B.length>1)E.patch(B[0](E.state,...B.slice(1)));else E.patch(B[0](E.state));else E.stats.patchCount--;else if(typeof B==="function")E.patch(B(E.state));else if(E.stats.renderPatchCount++,E.q=A(E.q||{},B,!1),!E.isRendering)E.render()}}),Object.defineProperty(E,"render",{enumerable:!1,configurable:!0,writable:!1,value:()=>requestAnimationFrame(()=>{if(E.isRendering||!E.q)return;E.isRendering=!0;let B=Date.now();try{E.state=A(E.state,E.q,!0),E.q=null,E.vode=H(E.state,E.patch,f,0,E.vode,j(E.state))}finally{if(E.isRendering=!1,E.stats.renderCount++,E.stats.lastRenderTime=Date.now()-B,E.q)E.render()}})}),E.patch=L.patch,E.state=L,E.q=null;let X=f;X._vode=E;let z=j(L);E.vode=z,E.vode=H(L,E.patch,f,0,void 0,z);for(let B of q)E.patch(B);return E.patch}function c(f,L){return L.__memo=f,L}function v(f){return f?Array.isArray(f)?f[0]:typeof f==="string"||f.nodeType===Node.TEXT_NODE?"#text":void 0:void 0}function $(f){if(Array.isArray(f)&&f.length>1&&f[1]&&!Array.isArray(f[1])){if(typeof f[1]==="object"&&f[1].nodeType!==Node.TEXT_NODE)return f[1]}return}function p(f,L){if(!f)return L;if(!L)return f;if(typeof f==="string"&&typeof L==="string"){let j=f.split(" "),q=L.split(" "),E=new Set([...j,...q]);return Array.from(E).join(" ").trim()}else if(typeof f==="string"&&Array.isArray(L)){let j=new Set([...L,...f.split(" ")]);return Array.from(j).join(" ").trim()}else if(Array.isArray(f)&&typeof L==="string"){let j=new Set([...f,...L.split(" ")]);return Array.from(j).join(" ").trim()}else if(Array.isArray(f)&&Array.isArray(L)){let j=new Set([...f,...L]);return Array.from(j).join(" ").trim()}else if(typeof f==="string"&&typeof L==="object")return{[f]:!0,...L};else if(typeof f==="object"&&typeof L==="string")return{...f,[L]:!0};else if(typeof f==="object"&&typeof L==="object")return{...f,...L};else if(typeof f==="object"&&Array.isArray(L)){let j={...f};for(let q of L)j[q]=!0;return j}else if(Array.isArray(f)&&typeof L==="object"){let j={};for(let q of f)j[q]=!0;for(let q of Object.keys(L))j[q]=L[q];return j}throw new Error(`cannot merge classes of ${f} (${typeof f}) and ${L} (${typeof L})`)}function D(f){let L=x(f);if(L>0)return f.slice(L);return null}function V(f){return f.length-x(f)}function i(f,L){return f[L+x(f)]}function x(f){return $(f)?2:1}function A(f,L,j){if(!L)return f;for(let q in L){let E=L[q];if(E&&typeof E==="object"){let X=f[q];if(X)if(Array.isArray(E))f[q]=[...E];else if(E instanceof Date&&X!==E)f[q]=new Date(E);else if(Array.isArray(X))f[q]=A({},E,j);else if(typeof X==="object")A(f[q],E,j);else f[q]=A({},E,j);else if(Array.isArray(E))f[q]=[...E];else if(E instanceof Date)f[q]=new Date(E);else f[q]=A({},E,j)}else if(E===void 0&&j)delete f[q];else f[q]=E}return f}function H(f,L,j,q,E,X,z){X=I(f,X,E);let B=!X||typeof X==="number"||typeof X==="boolean";if(X===E||!E&&B)return E;let U=E?.nodeType===Node.TEXT_NODE,F=U?E:E?.node;if(B){F?.onUnmount&&L(F.onUnmount(F)),F?.remove();return}let T=!B&&k(X),R=!B&&b(X),M=!!X&&typeof X!=="string"&&!!(X?.node||X?.nodeType===Node.TEXT_NODE);if(!T&&!R&&!M&&!E)throw new Error("Invalid vode: "+typeof X+" "+JSON.stringify(X));else if(M&&T)X=X.wholeText;else if(M&&R)X=[...X];if(U&&T){if(F.nodeValue!==X)F.nodeValue=X;return E}if(T&&(!F||!U)){let J=document.createTextNode(X);if(F)F.onUnmount&&L(F.onUnmount(F)),F.replaceWith(J);else if(j.childNodes[q])j.insertBefore(J,j.childNodes[q]);else j.appendChild(J);return J}if(R&&(!F||U||E[0]!==X[0])){z=z||X[0]==="svg";let J=z?document.createElementNS("http://www.w3.org/2000/svg",X[0]):document.createElement(X[0]);X.node=J;let O=X;if(1 in O)O[1]=I(f,O[1],void 0);let Y=$(X);if(K(L,J,void 0,Y,z),F)F.onUnmount&&L(F.onUnmount(F)),F.replaceWith(J);else if(j.childNodes[q])j.insertBefore(J,j.childNodes[q]);else j.appendChild(J);let W=D(X);if(W)for(let Q=0;Q<W.length;Q++){let G=W[Q],Z=H(f,L,J,Q,void 0,G,z);X[Y?Q+2:Q+1]=Z}return J.onMount&&L(J.onMount(J)),X}if(!U&&R&&E[0]===X[0]){z=z||X[0]==="svg",X.node=F;let J=X,O=E,Y=!1;if(J[1]?.__memo){let G=J[1];if(J[1]=I(f,J[1],O[1]),G!==J[1]){let Z=$(X);K(L,F,$(E),Z,z),Y=!!Z}}else{let G=$(X);K(L,F,$(E),G,z),Y=!!G}let W=D(X),Q=D(E);if(W){for(let G=0;G<W.length;G++){let Z=W[G],_=Q&&Q[G],N=H(f,L,F,G,_,Z,z);if(N)X[Y?G+2:G+1]=N}for(let G=W.length;Q&&G<Q.length;G++)if(Q[G]?.node)Q[G].node.remove();else if(Q[G]?.nodeType===Node.TEXT_NODE)Q[G].remove()}for(let G=W?.length||0;G<Q?.length;G++)if(Q[G]?.node)Q[G].node.remove();else if(Q[G]?.nodeType===Node.TEXT_NODE)Q[G].remove();return X}return}function b(f){return Array.isArray(f)&&f.length>0&&typeof f[0]==="string"}function k(f){return typeof f==="string"||f?.nodeType===Node.TEXT_NODE}function I(f,L,j){if(typeof L!=="function")return L;let q=L?.__memo,E=j?.__memo;if(Array.isArray(q)&&Array.isArray(E)&&q.length===E.length){let z=!0;for(let B=0;B<q.length;B++)if(q[B]!==E[B]){z=!1;break}if(z)return j}let X=S(L,f);if(typeof X==="object")X.__memo=L?.__memo;return X}function S(f,L){if(typeof f==="function")return S(f(L),L);else return f}function K(f,L,j,q,E){if(!q&&!j)return;if(j)for(let X in j){let z=j[X],B=q?.[X];if(z!==B)if(q)q[X]=C(f,L,X,z,B,E);else C(f,L,X,z,void 0,E)}if(q&&j){for(let X in q)if(!(X in j)){let z=q[X];q[X]=C(f,L,X,void 0,z,E)}}else if(q)for(let X in q){let z=q[X];q[X]=C(f,L,X,void 0,z,E)}}function C(f,L,j,q,E,X){if(j==="style")if(!E)L.style.cssText="";else if(q){for(let z in{...q,...E})if(!q||E[z]!==q[z])L.style[z]=E[z];else if(q[z]&&!E[z])L.style[z]=void 0}else for(let z in E)L.style[z]=E[z];else if(j==="class")if(X)if(E){let z=m(E);L.classList.value=z}else L.classList.value="";else if(E){let z=m(E);L.className=z}else L.className="";else if(j[0]==="o"&&j[1]==="n")if(E){let z=null;if(typeof E==="function"){let B=E;z=(U)=>f([B,U])}else if(Array.isArray(E)){let B=E,U=E[0];if(B.length>1)z=()=>f([U,...B.slice(1)]);else z=(F)=>f([U,F])}else if(typeof E==="object")z=()=>f(E);L[j]=z}else L[j]=null;else if(E!==null&&E!==void 0&&E!==!1)L.setAttribute(j,E);else L.removeAttribute(j);return E}function m(f){if(typeof f==="string")return f;else if(Array.isArray(f))return f.map(m).join(" ");else if(typeof f==="object")return Object.keys(f).filter((L)=>f[L]).join(" ");else return""}var s="a",r="abbr",l="address",t="area",n="article",a="aside",d="audio",o="b",e="base",ff="bdi",Ef="bdo",Lf="blockquote",Xf="body",jf="br",qf="button",zf="canvas",Bf="caption",Ff="cite",Gf="code",Jf="col",Qf="colgroup",Uf="data",Wf="datalist",Yf="dd",Zf="del",$f="details",Af="dfn",Of="dialog",Tf="div",Rf="dl",Cf="dt",Hf="em",Mf="embed",Df="fieldset",If="figcaption",Kf="figure",mf="footer",xf="form",Nf="h1",Sf="h2",yf="h3",_f="h4",bf="h5",kf="h6",Pf="head",hf="header",gf="hgroup",uf="hr",cf="html",vf="i",pf="iframe",Vf="img",wf="input",sf="ins",rf="kbd",lf="label",tf="legend",nf="li",af="link",df="main",of="map",ef="mark",fE="menu",EE="meta",LE="meter",XE="nav",jE="noscript",qE="object",zE="ol",BE="optgroup",FE="option",GE="output",JE="p",QE="picture",UE="pre",WE="progress",YE="q",ZE="rp",$E="rt",AE="ruby",OE="s",TE="samp",RE="script",CE="section",HE="select",ME="slot",DE="small",IE="source",KE="span",mE="strong",xE="style",NE="sub",SE="summary",yE="sup",_E="table",bE="tbody",kE="td",PE="template",hE="textarea",gE="tfoot",uE="th",cE="thead",vE="time",pE="title",VE="tr",iE="track",wE="u",sE="ul",rE="video",lE="wbr",tE="animate",nE="animateMotion",aE="animateTransform",dE="circle",oE="clipPath",eE="defs",fL="desc",EL="ellipse",LL="feBlend",XL="feColorMatrix",jL="feComponentTransfer",qL="feComposite",zL="feConvolveMatrix",BL="feDiffuseLighting",FL="feDisplacementMap",GL="feDistantLight",JL="feDropShadow",QL="feFlood",UL="feFuncA",WL="feFuncB",YL="feFuncG",ZL="feFuncR",$L="feGaussianBlur",AL="feImage",OL="feMerge",TL="feMergeNode",RL="feMorphology",CL="feOffset",HL="fePointLight",ML="feSpecularLighting",DL="feSpotLight",IL="feTile",KL="feTurbulence",mL="filter",xL="foreignObject",NL="g",SL="image",yL="line",_L="linearGradient",bL="marker",kL="mask",PL="metadata",hL="mpath",gL="path",uL="pattern",cL="polygon",vL="polyline",pL="radialGradient",VL="rect",iL="set",wL="stop",sL="svg",rL="switch",lL="symbol",tL="text",nL="textPath",aL="tspan",dL="use",oL="view",eL="annotation",fX="annotation-xml",EX="maction",LX="math",XX="merror",jX="mfrac",qX="mi",zX="mmultiscripts",BX="mn",FX="mo",GX="mover",JX="mpadded",QX="mphantom",UX="mprescripts",WX="mroot",YX="mrow",ZX="ms",$X="mspace",AX="msqrt",OX="mstyle",TX="msub",RX="msubsup",CX="msup",HX="mtable",MX="mtd",DX="mtext",IX="mtr",KX="munder",mX="munderover",xX="semantics";function SX(f){let L=document.createElement("div");L.innerHTML=f.trim();let j=[];for(let q of L.childNodes){let E=y(q);if(E!=null)j.push(E)}return j}function y(f){if(f.nodeType===Node.TEXT_NODE)return f.textContent;if(f.nodeType!==Node.ELEMENT_NODE)return;let L=[f.tagName.toLowerCase()];if(f.hasAttributes()){let j={};for(let q of f.attributes)j[q.name]=q.value;L.push(j)}for(let j of f.childNodes){let q=y(j);if(q&&(typeof q!=="string"||q.length>0))L.push(q)}return L}export{g as vode,v as tag,$ as props,p as mergeClass,c as memo,SX as htmlToVode,P as createState,h as createPatch,x as childrenStart,D as children,V as childCount,i as child,u as app,lE as WBR,oL as VIEW,rE as VIDEO,dL as USE,sE as UL,wE as U,aL as TSPAN,iE as TRACK,VE as TR,pE as TITLE,vE as TIME,cE as THEAD,uE as TH,gE as TFOOT,nL as TEXTPATH,hE as TEXTAREA,tL as TEXT,PE as TEMPLATE,kE as TD,bE as TBODY,_E as TABLE,lL as SYMBOL,rL as SWITCH,sL as SVG,yE as SUP,SE as SUMMARY,NE as SUB,xE as STYLE,mE as STRONG,wL as STOP,KE as SPAN,IE as SOURCE,DE as SMALL,ME as SLOT,iL as SET,xX as SEMANTICS,HE as SELECT,CE as SECTION,RE as SCRIPT,TE as SAMP,OE as S,AE as RUBY,$E as RT,ZE as RP,VL as RECT,pL as RADIALGRADIENT,YE as Q,WE as PROGRESS,UE as PRE,vL as POLYLINE,cL as POLYGON,QE as PICTURE,uL as PATTERN,gL as PATH,JE as P,GE as OUTPUT,FE as OPTION,BE as OPTGROUP,zE as OL,qE as OBJECT,jE as NOSCRIPT,XE as NAV,mX as MUNDEROVER,KX as MUNDER,IX as MTR,DX as MTEXT,MX as MTD,HX as MTABLE,CX as MSUP,RX as MSUBSUP,TX as MSUB,OX as MSTYLE,AX as MSQRT,$X as MSPACE,ZX as MS,YX as MROW,WX as MROOT,UX as MPRESCRIPTS,QX as MPHANTOM,hL as MPATH,JX as MPADDED,GX as MOVER,FX as MO,BX as MN,zX as MMULTISCRIPTS,qX as MI,jX as MFRAC,LE as METER,PL as METADATA,EE as META,XX as MERROR,fE as MENU,LX as MATH,kL as MASK,bL as MARKER,ef as MARK,of as MAP,df as MAIN,EX as MACTION,af as LINK,_L as LINEARGRADIENT,yL as LINE,nf as LI,tf as LEGEND,lf as LABEL,rf as KBD,sf as INS,wf as INPUT,Vf as IMG,SL as IMAGE,pf as IFRAME,vf as I,cf as HTML,uf as HR,gf as HGROUP,hf as HEADER,Pf as HEAD,kf as H6,bf as H5,_f as H4,yf as H3,Sf as H2,Nf as H1,NL as G,xf as FORM,xL as FOREIGNOBJECT,mf as FOOTER,mL as FILTER,Kf as FIGURE,If as FIGCAPTION,Df as FIELDSET,KL as FETURBULENCE,IL as FETILE,DL as FESPOTLIGHT,ML as FESPECULARLIGHTING,HL as FEPOINTLIGHT,CL as FEOFFSET,RL as FEMORPHOLOGY,TL as FEMERGENODE,OL as FEMERGE,AL as FEIMAGE,$L as FEGAUSSIANBLUR,ZL as FEFUNCR,YL as FEFUNCG,WL as FEFUNCB,UL as FEFUNCA,QL as FEFLOOD,JL as FEDROPSHADOW,GL as FEDISTANTLIGHT,FL as FEDISPLACEMENTMAP,BL as FEDIFFUSELIGHTING,zL as FECONVOLVEMATRIX,qL as FECOMPOSITE,jL as FECOMPONENTTRANSFER,XL as FECOLORMATRIX,LL as FEBLEND,Mf as EMBED,Hf as EM,EL as ELLIPSE,Cf as DT,Rf as DL,Tf as DIV,Of as DIALOG,Af as DFN,$f as DETAILS,fL as DESC,Zf as DEL,eE as DEFS,Yf as DD,Wf as DATALIST,Uf as DATA,Qf as COLGROUP,Jf as COL,Gf as CODE,oE as CLIPPATH,Ff as CITE,dE as CIRCLE,Bf as CAPTION,zf as CANVAS,qf as BUTTON,jf as BR,Xf as BODY,Lf as BLOCKQUOTE,Ef as BDO,ff as BDI,e as BASE,o as B,d as AUDIO,a as ASIDE,n as ARTICLE,t as AREA,fX as ANNOTATION_XML,eL as ANNOTATION,aE as ANIMATETRANSFORM,nE as ANIMATEMOTION,tE as ANIMATE,l as ADDRESS,r as ABBR,s as A};
1
+ function h(f,L,...j){if(!f)throw new Error("tag must be a string or vode");if(Array.isArray(f))return f;else if(L)return[f,L,...j];else return[f,...j]}function g(f,L,j,...q){if(!f?.parentElement)throw new Error("container must be a valid HTMLElement inside the <html></html> document");if(!L||typeof L!=="object")throw new Error("given state must be an object");if(typeof j!=="function")throw new Error("dom must be a function that returns a vode");let E={};E.stats={lastRenderTime:0,renderCount:0,liveEffectCount:0,patchCount:0,renderPatchCount:0},Object.defineProperty(L,"patch",{enumerable:!1,configurable:!0,writable:!1,value:async(z)=>{if(!z||typeof z!=="function"&&typeof z!=="object")return;if(E.stats.patchCount++,z?.next){let F=z;E.stats.liveEffectCount++;try{let U=await F.next();while(U.done===!1){E.stats.liveEffectCount++;try{E.patch(U.value),U=await F.next()}finally{E.stats.liveEffectCount--}}E.patch(U.value)}finally{E.stats.liveEffectCount--}}else if(z.then){E.stats.liveEffectCount++;try{let F=await z;E.patch(F)}finally{E.stats.liveEffectCount--}}else if(Array.isArray(z))if(typeof z[0]==="function")if(z.length>1)E.patch(z[0](E.state,...z.slice(1)));else E.patch(z[0](E.state));else E.stats.patchCount--;else if(typeof z==="function")E.patch(z(E.state));else if(E.stats.renderPatchCount++,E.q=A(E.q||{},z,!1),!E.isRendering)E.render()}}),Object.defineProperty(E,"render",{enumerable:!1,configurable:!0,writable:!1,value:()=>requestAnimationFrame(()=>{if(E.isRendering||!E.q)return;E.isRendering=!0;let z=Date.now();try{E.state=A(E.state,E.q,!0),E.q=null;let F=j(E.state);if(E.vode=H(E.state,E.patch,f.parentElement,0,E.vode,F),f.tagName!==F[0].toUpperCase())f=E.vode.node}finally{if(E.isRendering=!1,E.stats.renderCount++,E.stats.lastRenderTime=Date.now()-z,E.q)E.render()}})}),E.patch=L.patch,E.state=L,E.q=null;let X=f;X._vode=E,E.vode=H(L,E.patch,f.parentElement,Array.from(f.parentElement.children).indexOf(f),y(f),j(L));for(let z of q)E.patch(z);return E.patch}function u(f,L){return L.__memo=f,L}function c(f){return f}function v(f){return f}function i(f){return f?Array.isArray(f)?f[0]:typeof f==="string"||f.nodeType===Node.TEXT_NODE?"#text":void 0:void 0}function $(f){if(Array.isArray(f)&&f.length>1&&f[1]&&!Array.isArray(f[1])){if(typeof f[1]==="object"&&f[1].nodeType!==Node.TEXT_NODE)return f[1]}return}function V(f,L){if(!f)return L;if(!L)return f;if(typeof f==="string"&&typeof L==="string"){let j=f.split(" "),q=L.split(" "),E=new Set([...j,...q]);return Array.from(E).join(" ").trim()}else if(typeof f==="string"&&Array.isArray(L)){let j=new Set([...L,...f.split(" ")]);return Array.from(j).join(" ").trim()}else if(Array.isArray(f)&&typeof L==="string"){let j=new Set([...f,...L.split(" ")]);return Array.from(j).join(" ").trim()}else if(Array.isArray(f)&&Array.isArray(L)){let j=new Set([...f,...L]);return Array.from(j).join(" ").trim()}else if(typeof f==="string"&&typeof L==="object")return{[f]:!0,...L};else if(typeof f==="object"&&typeof L==="string")return{...f,[L]:!0};else if(typeof f==="object"&&typeof L==="object")return{...f,...L};else if(typeof f==="object"&&Array.isArray(L)){let j={...f};for(let q of L)j[q]=!0;return j}else if(Array.isArray(f)&&typeof L==="object"){let j={};for(let q of f)j[q]=!0;for(let q of Object.keys(L))j[q]=L[q];return j}throw new Error(`cannot merge classes of ${f} (${typeof f}) and ${L} (${typeof L})`)}function D(f){let L=x(f);if(L>0)return f.slice(L);return null}function p(f){return f.length-x(f)}function w(f,L){return f[L+x(f)]}function x(f){return $(f)?2:1}function A(f,L,j){if(!L)return f;for(let q in L){let E=L[q];if(E&&typeof E==="object"){let X=f[q];if(X)if(Array.isArray(E))f[q]=[...E];else if(E instanceof Date&&X!==E)f[q]=new Date(E);else if(Array.isArray(X))f[q]=A({},E,j);else if(typeof X==="object")A(f[q],E,j);else f[q]=A({},E,j);else if(Array.isArray(E))f[q]=[...E];else if(E instanceof Date)f[q]=new Date(E);else f[q]=A({},E,j)}else if(E===void 0&&j)delete f[q];else f[q]=E}return f}function y(f){if(f?.nodeType===Node.TEXT_NODE){if(f.nodeValue?.trim()!=="")return f;return}else if(f.nodeType===Node.COMMENT_NODE)return;else{let j=[f.tagName.toLowerCase()];if(j.node=f,f?.hasAttributes()){let q={},E=f.attributes;for(let X of E)q[X.name]=X.value;j.push(q)}if(f.hasChildNodes())for(let q of f.childNodes){let E=q&&y(q);if(E)j.push(E)}return j}}function H(f,L,j,q,E,X,z){X=I(f,X,E);let F=!X||typeof X==="number"||typeof X==="boolean";if(X===E||!E&&F)return E;let U=E?.nodeType===Node.TEXT_NODE,G=U?E:E?.node;if(F){G?.onUnmount&&L(G.onUnmount(G)),G?.remove();return}let T=!F&&P(X),R=!F&&k(X),M=!!X&&typeof X!=="string"&&!!(X?.node||X?.nodeType===Node.TEXT_NODE);if(!T&&!R&&!M&&!E)throw new Error("Invalid vode: "+typeof X+" "+JSON.stringify(X));else if(M&&T)X=X.wholeText;else if(M&&R)X=[...X];if(U&&T){if(G.nodeValue!==X)G.nodeValue=X;return E}if(T&&(!G||!U)){let J=document.createTextNode(X);if(G)G.onUnmount&&L(G.onUnmount(G)),G.replaceWith(J);else if(j.childNodes[q+1])j.insertBefore(J,j.childNodes[q+1]);else j.appendChild(J);return J}if(R&&(!G||U||E[0]!==X[0])){z=z||X[0]==="svg";let J=z?document.createElementNS("http://www.w3.org/2000/svg",X[0]):document.createElement(X[0]);X.node=J;let O=X;if(1 in O)O[1]=I(f,O[1],void 0);let Y=$(X);if(K(L,J,void 0,Y,z),G)G.onUnmount&&L(G.onUnmount(G)),G.replaceWith(J);else if(j.childNodes[q+1])j.insertBefore(J,j.childNodes[q+1]);else j.appendChild(J);let W=D(X);if(W)for(let Q=0;Q<W.length;Q++){let B=W[Q],Z=H(f,L,J,Q,void 0,B,z);X[Y?Q+2:Q+1]=Z}return J.onMount&&L(J.onMount(J)),X}if(!U&&R&&E[0]===X[0]){z=z||X[0]==="svg",X.node=G;let J=X,O=E,Y=!1;if(J[1]?.__memo){let B=J[1];if(J[1]=I(f,J[1],O[1]),B!==J[1]){let Z=$(X);K(L,G,$(E),Z,z),Y=!!Z}}else{let B=$(X);K(L,G,$(E),B,z),Y=!!B}let W=D(X),Q=D(E);if(W){for(let B=0;B<W.length;B++){let Z=W[B],b=Q&&Q[B],N=H(f,L,G,B,b,Z,z);if(N)X[Y?B+2:B+1]=N}for(let B=W.length;Q&&B<Q.length;B++)if(Q[B]?.node)Q[B].node.remove();else if(Q[B]?.nodeType===Node.TEXT_NODE)Q[B].remove()}for(let B=W?.length||0;B<Q?.length;B++)if(Q[B]?.node)Q[B].node.remove();else if(Q[B]?.nodeType===Node.TEXT_NODE)Q[B].remove();return X}return}function k(f){return Array.isArray(f)&&f.length>0&&typeof f[0]==="string"}function P(f){return typeof f==="string"||f?.nodeType===Node.TEXT_NODE}function I(f,L,j){if(typeof L!=="function")return L;let q=L?.__memo,E=j?.__memo;if(Array.isArray(q)&&Array.isArray(E)&&q.length===E.length){let z=!0;for(let F=0;F<q.length;F++)if(q[F]!==E[F]){z=!1;break}if(z)return j}let X=m(L,f);if(typeof X==="object")X.__memo=L?.__memo;return X}function m(f,L){if(typeof f==="function")return m(f(L),L);else return f}function K(f,L,j,q,E){if(!q&&!j)return;if(j)for(let X in j){let z=j[X],F=q?.[X];if(z!==F)if(q)q[X]=C(f,L,X,z,F,E);else C(f,L,X,z,void 0,E)}if(q&&j){for(let X in q)if(!(X in j)){let z=q[X];q[X]=C(f,L,X,void 0,z,E)}}else if(q)for(let X in q){let z=q[X];q[X]=C(f,L,X,void 0,z,E)}}function C(f,L,j,q,E,X){if(j==="style")if(!E)L.style.cssText="";else if(q){for(let z in{...q,...E})if(!q||E[z]!==q[z])L.style[z]=E[z];else if(q[z]&&!E[z])L.style[z]=void 0}else for(let z in E)L.style[z]=E[z];else if(j==="class")if(X)if(E){let z=S(E);L.classList.value=z}else L.classList.value="";else if(E){let z=S(E);L.className=z}else L.className="";else if(j[0]==="o"&&j[1]==="n")if(E){let z=null;if(typeof E==="function"){let F=E;z=(U)=>f([F,U])}else if(Array.isArray(E)){let F=E,U=E[0];if(F.length>1)z=()=>f([U,...F.slice(1)]);else z=(G)=>f([U,G])}else if(typeof E==="object")z=()=>f(E);L[j]=z}else L[j]=null;else if(E!==null&&E!==void 0&&E!==!1)L.setAttribute(j,E);else L.removeAttribute(j);return E}function S(f){if(typeof f==="string")return f;else if(Array.isArray(f))return f.map(S).join(" ");else if(typeof f==="object")return Object.keys(f).filter((L)=>f[L]).join(" ");else return""}var r="a",l="abbr",t="address",n="area",a="article",d="aside",o="audio",e="b",ff="base",Ef="bdi",Lf="bdo",Xf="blockquote",jf="body",qf="br",zf="button",Bf="canvas",Ff="caption",Gf="cite",Jf="code",Qf="col",Uf="colgroup",Wf="data",Yf="datalist",Zf="dd",$f="del",Af="details",Of="dfn",Tf="dialog",Rf="div",Cf="dl",Hf="dt",Mf="em",Df="embed",If="fieldset",Kf="figcaption",Sf="figure",xf="footer",Nf="form",yf="h1",mf="h2",_f="h3",bf="h4",kf="h5",Pf="h6",hf="head",gf="header",uf="hgroup",cf="hr",vf="html",Vf="i",pf="iframe",wf="img",sf="input",rf="ins",lf="kbd",tf="label",nf="legend",af="li",df="link",of="main",ef="map",fE="mark",EE="menu",LE="meta",XE="meter",jE="nav",qE="noscript",zE="object",BE="ol",FE="optgroup",GE="option",JE="output",QE="p",UE="picture",WE="pre",YE="progress",ZE="q",$E="rp",AE="rt",OE="ruby",TE="s",RE="samp",CE="script",HE="section",ME="select",DE="slot",IE="small",KE="source",SE="span",xE="strong",NE="style",yE="sub",mE="summary",_E="sup",bE="table",kE="tbody",PE="td",hE="template",gE="textarea",uE="tfoot",cE="th",vE="thead",iE="time",VE="title",pE="tr",wE="track",sE="u",rE="ul",lE="video",tE="wbr",nE="animate",aE="animateMotion",dE="animateTransform",oE="circle",eE="clipPath",fL="defs",EL="desc",LL="ellipse",XL="feBlend",jL="feColorMatrix",qL="feComponentTransfer",zL="feComposite",BL="feConvolveMatrix",FL="feDiffuseLighting",GL="feDisplacementMap",JL="feDistantLight",QL="feDropShadow",UL="feFlood",WL="feFuncA",YL="feFuncB",ZL="feFuncG",$L="feFuncR",AL="feGaussianBlur",OL="feImage",TL="feMerge",RL="feMergeNode",CL="feMorphology",HL="feOffset",ML="fePointLight",DL="feSpecularLighting",IL="feSpotLight",KL="feTile",SL="feTurbulence",xL="filter",NL="foreignObject",yL="g",mL="image",_L="line",bL="linearGradient",kL="marker",PL="mask",hL="metadata",gL="mpath",uL="path",cL="pattern",vL="polygon",iL="polyline",VL="radialGradient",pL="rect",wL="set",sL="stop",rL="svg",lL="switch",tL="symbol",nL="text",aL="textPath",dL="tspan",oL="use",eL="view",fX="annotation",EX="annotation-xml",LX="maction",XX="math",jX="merror",qX="mfrac",zX="mi",BX="mmultiscripts",FX="mn",GX="mo",JX="mover",QX="mpadded",UX="mphantom",WX="mprescripts",YX="mroot",ZX="mrow",$X="ms",AX="mspace",OX="msqrt",TX="mstyle",RX="msub",CX="msubsup",HX="msup",MX="mtable",DX="mtd",IX="mtext",KX="mtr",SX="munder",xX="munderover",NX="semantics";function mX(f){let L=document.createElement("div");L.innerHTML=f.trim();let j=[];for(let q of L.childNodes){let E=_(q);if(E!=null)j.push(E)}return j}function _(f){if(f.nodeType===Node.TEXT_NODE)return f.textContent;if(f.nodeType!==Node.ELEMENT_NODE)return;let L=[f.tagName.toLowerCase()];if(f.hasAttributes()){let j={};for(let q of f.attributes)j[q.name]=q.value;L.push(j)}for(let j of f.childNodes){let q=_(j);if(q&&(typeof q!=="string"||q.length>0))L.push(q)}return L}export{h as vode,i as tag,$ as props,V as mergeClass,u as memo,mX as htmlToVode,c as createState,v as createPatch,x as childrenStart,D as children,p as childCount,w as child,g as app,tE as WBR,eL as VIEW,lE as VIDEO,oL as USE,rE as UL,sE as U,dL as TSPAN,wE as TRACK,pE as TR,VE as TITLE,iE as TIME,vE as THEAD,cE as TH,uE as TFOOT,aL as TEXTPATH,gE as TEXTAREA,nL as TEXT,hE as TEMPLATE,PE as TD,kE as TBODY,bE as TABLE,tL as SYMBOL,lL as SWITCH,rL as SVG,_E as SUP,mE as SUMMARY,yE as SUB,NE as STYLE,xE as STRONG,sL as STOP,SE as SPAN,KE as SOURCE,IE as SMALL,DE as SLOT,wL as SET,NX as SEMANTICS,ME as SELECT,HE as SECTION,CE as SCRIPT,RE as SAMP,TE as S,OE as RUBY,AE as RT,$E as RP,pL as RECT,VL as RADIALGRADIENT,ZE as Q,YE as PROGRESS,WE as PRE,iL as POLYLINE,vL as POLYGON,UE as PICTURE,cL as PATTERN,uL as PATH,QE as P,JE as OUTPUT,GE as OPTION,FE as OPTGROUP,BE as OL,zE as OBJECT,qE as NOSCRIPT,jE as NAV,xX as MUNDEROVER,SX as MUNDER,KX as MTR,IX as MTEXT,DX as MTD,MX as MTABLE,HX as MSUP,CX as MSUBSUP,RX as MSUB,TX as MSTYLE,OX as MSQRT,AX as MSPACE,$X as MS,ZX as MROW,YX as MROOT,WX as MPRESCRIPTS,UX as MPHANTOM,gL as MPATH,QX as MPADDED,JX as MOVER,GX as MO,FX as MN,BX as MMULTISCRIPTS,zX as MI,qX as MFRAC,XE as METER,hL as METADATA,LE as META,jX as MERROR,EE as MENU,XX as MATH,PL as MASK,kL as MARKER,fE as MARK,ef as MAP,of as MAIN,LX as MACTION,df as LINK,bL as LINEARGRADIENT,_L as LINE,af as LI,nf as LEGEND,tf as LABEL,lf as KBD,rf as INS,sf as INPUT,wf as IMG,mL as IMAGE,pf as IFRAME,Vf as I,vf as HTML,cf as HR,uf as HGROUP,gf as HEADER,hf as HEAD,Pf as H6,kf as H5,bf as H4,_f as H3,mf as H2,yf as H1,yL as G,Nf as FORM,NL as FOREIGNOBJECT,xf as FOOTER,xL as FILTER,Sf as FIGURE,Kf as FIGCAPTION,If as FIELDSET,SL as FETURBULENCE,KL as FETILE,IL as FESPOTLIGHT,DL as FESPECULARLIGHTING,ML as FEPOINTLIGHT,HL as FEOFFSET,CL as FEMORPHOLOGY,RL as FEMERGENODE,TL as FEMERGE,OL as FEIMAGE,AL as FEGAUSSIANBLUR,$L as FEFUNCR,ZL as FEFUNCG,YL as FEFUNCB,WL as FEFUNCA,UL as FEFLOOD,QL as FEDROPSHADOW,JL as FEDISTANTLIGHT,GL as FEDISPLACEMENTMAP,FL as FEDIFFUSELIGHTING,BL as FECONVOLVEMATRIX,zL as FECOMPOSITE,qL as FECOMPONENTTRANSFER,jL as FECOLORMATRIX,XL as FEBLEND,Df as EMBED,Mf as EM,LL as ELLIPSE,Hf as DT,Cf as DL,Rf as DIV,Tf as DIALOG,Of as DFN,Af as DETAILS,EL as DESC,$f as DEL,fL as DEFS,Zf as DD,Yf as DATALIST,Wf as DATA,Uf as COLGROUP,Qf as COL,Jf as CODE,eE as CLIPPATH,Gf as CITE,oE as CIRCLE,Ff as CAPTION,Bf as CANVAS,zf as BUTTON,qf as BR,jf as BODY,Xf as BLOCKQUOTE,Lf as BDO,Ef as BDI,ff as BASE,e as B,o as AUDIO,d as ASIDE,a as ARTICLE,n as AREA,EX as ANNOTATION_XML,fX as ANNOTATION,dE as ANIMATETRANSFORM,aE as ANIMATEMOTION,nE as ANIMATE,t as ADDRESS,l as ABBR,r as A};
package/dist/vode.mjs CHANGED
@@ -1,10 +1,4 @@
1
1
  // src/vode.ts
2
- function createState(state) {
3
- return state;
4
- }
5
- function createPatch(p) {
6
- return p;
7
- }
8
2
  function vode(tag, props, ...children) {
9
3
  if (!tag)
10
4
  throw new Error("tag must be a string or vode");
@@ -15,16 +9,16 @@ function vode(tag, props, ...children) {
15
9
  else
16
10
  return [tag, ...children];
17
11
  }
18
- function app(container, initialState, dom, ...initialPatches) {
19
- if (!container)
20
- throw new Error("container must be a valid HTMLElement");
21
- if (!initialState || typeof initialState !== "object")
22
- throw new Error("initialState must be an object");
12
+ function app(container, state, dom, ...initialPatches) {
13
+ if (!container?.parentElement)
14
+ throw new Error("container must be a valid HTMLElement inside the <html></html> document");
15
+ if (!state || typeof state !== "object")
16
+ throw new Error("given state must be an object");
23
17
  if (typeof dom !== "function")
24
18
  throw new Error("dom must be a function that returns a vode");
25
19
  const _vode = {};
26
20
  _vode.stats = { lastRenderTime: 0, renderCount: 0, liveEffectCount: 0, patchCount: 0, renderPatchCount: 0 };
27
- Object.defineProperty(initialState, "patch", {
21
+ Object.defineProperty(state, "patch", {
28
22
  enumerable: false,
29
23
  configurable: true,
30
24
  writable: false,
@@ -89,7 +83,11 @@ function app(container, initialState, dom, ...initialPatches) {
89
83
  try {
90
84
  _vode.state = mergeState(_vode.state, _vode.q, true);
91
85
  _vode.q = null;
92
- _vode.vode = render(_vode.state, _vode.patch, container, 0, _vode.vode, dom(_vode.state));
86
+ const vom = dom(_vode.state);
87
+ _vode.vode = render(_vode.state, _vode.patch, container.parentElement, 0, _vode.vode, vom);
88
+ if (container.tagName !== vom[0].toUpperCase()) {
89
+ container = _vode.vode.node;
90
+ }
93
91
  } finally {
94
92
  _vode.isRendering = false;
95
93
  _vode.stats.renderCount++;
@@ -100,14 +98,12 @@ function app(container, initialState, dom, ...initialPatches) {
100
98
  }
101
99
  })
102
100
  });
103
- _vode.patch = initialState.patch;
104
- _vode.state = initialState;
101
+ _vode.patch = state.patch;
102
+ _vode.state = state;
105
103
  _vode.q = null;
106
104
  const root = container;
107
105
  root._vode = _vode;
108
- const initialVode = dom(initialState);
109
- _vode.vode = initialVode;
110
- _vode.vode = render(initialState, _vode.patch, container, 0, undefined, initialVode);
106
+ _vode.vode = render(state, _vode.patch, container.parentElement, Array.from(container.parentElement.children).indexOf(container), hydrate(container), dom(state));
111
107
  for (const effect of initialPatches) {
112
108
  _vode.patch(effect);
113
109
  }
@@ -117,6 +113,12 @@ function memo(compare, componentOrProps) {
117
113
  componentOrProps.__memo = compare;
118
114
  return componentOrProps;
119
115
  }
116
+ function createState(state) {
117
+ return state;
118
+ }
119
+ function createPatch(p) {
120
+ return p;
121
+ }
120
122
  function tag(v) {
121
123
  return v ? Array.isArray(v) ? v[0] : typeof v === "string" || v.nodeType === Node.TEXT_NODE ? "#text" : undefined : undefined;
122
124
  }
@@ -222,6 +224,35 @@ function mergeState(target, source, allowDeletion) {
222
224
  }
223
225
  return target;
224
226
  }
227
+ function hydrate(element) {
228
+ if (element?.nodeType === Node.TEXT_NODE) {
229
+ if (element.nodeValue?.trim() !== "")
230
+ return element;
231
+ return;
232
+ } else if (element.nodeType === Node.COMMENT_NODE) {
233
+ return;
234
+ } else {
235
+ const tag2 = element.tagName.toLowerCase();
236
+ const root = [tag2];
237
+ root.node = element;
238
+ if (element?.hasAttributes()) {
239
+ const props2 = {};
240
+ const attr = element.attributes;
241
+ for (let a of attr) {
242
+ props2[a.name] = a.value;
243
+ }
244
+ root.push(props2);
245
+ }
246
+ if (element.hasChildNodes()) {
247
+ for (let child2 of element.childNodes) {
248
+ const wet = child2 && hydrate(child2);
249
+ if (wet)
250
+ root.push(wet);
251
+ }
252
+ }
253
+ return root;
254
+ }
255
+ }
225
256
  function render(state, patch, parent, childIndex, oldVode, newVode, svg) {
226
257
  newVode = remember(state, newVode, oldVode);
227
258
  const isNoVode = !newVode || typeof newVode === "number" || typeof newVode === "boolean";
@@ -257,8 +288,8 @@ function render(state, patch, parent, childIndex, oldVode, newVode, svg) {
257
288
  oldNode.onUnmount && patch(oldNode.onUnmount(oldNode));
258
289
  oldNode.replaceWith(text);
259
290
  } else {
260
- if (parent.childNodes[childIndex]) {
261
- parent.insertBefore(text, parent.childNodes[childIndex]);
291
+ if (parent.childNodes[childIndex + 1]) {
292
+ parent.insertBefore(text, parent.childNodes[childIndex + 1]);
262
293
  } else {
263
294
  parent.appendChild(text);
264
295
  }
@@ -279,8 +310,8 @@ function render(state, patch, parent, childIndex, oldVode, newVode, svg) {
279
310
  oldNode.onUnmount && patch(oldNode.onUnmount(oldNode));
280
311
  oldNode.replaceWith(newNode);
281
312
  } else {
282
- if (parent.childNodes[childIndex]) {
283
- parent.insertBefore(newNode, parent.childNodes[childIndex]);
313
+ if (parent.childNodes[childIndex + 1]) {
314
+ parent.insertBefore(newNode, parent.childNodes[childIndex + 1]);
284
315
  } else {
285
316
  parent.appendChild(newNode);
286
317
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryupold/vode",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "Small web framework for minimal websites",
5
5
  "author": "Michael Scherbakow (ryupold)",
6
6
  "license": "MIT",
@@ -32,8 +32,8 @@
32
32
  "watch": "tsc -b -w"
33
33
  },
34
34
  "devDependencies": {
35
- "bun": "^1.2.18",
36
- "esbuild": "^0.25.8",
37
- "typescript": "^5.8.3"
35
+ "bun": "^1.2.21",
36
+ "esbuild": "^0.25.9",
37
+ "typescript": "^5.9.2"
38
38
  }
39
39
  }
package/src/vode.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  export type Vode<S> = FullVode<S> | JustTagVode | NoPropsVode<S>;
2
2
  export type FullVode<S> = [tag: Tag, props: Props<S>, ...children: ChildVode<S>[]];
3
- export type NoPropsVode<S> = [tag: Tag, ...children: ChildVode<S>[]] | string[];
3
+ export type NoPropsVode<S> = [tag: Tag, ...children: ChildVode<S>[]] | (TextVode[]);
4
4
  export type JustTagVode = [tag: Tag];
5
5
  export type ChildVode<S> = Vode<S> | TextVode | NoVode | Component<S>;
6
- export type TextVode = string;
6
+ export type TextVode = string & {};
7
7
  export type NoVode = undefined | null | number | boolean | bigint | void;
8
- export type AttachedVode<S> = Vode<S> & { node: ChildNode, id?: string } | Text & { node?: never, id?: never };
9
- export type Tag = keyof (HTMLElementTagNameMap & SVGElementTagNameMap & MathMLElementTagNameMap);
8
+ export type AttachedVode<S> = Vode<S> & { node: ChildNode } | Text & { node?: never };
9
+ export type Tag = keyof (HTMLElementTagNameMap & SVGElementTagNameMap & MathMLElementTagNameMap) | (string & {});
10
10
  export type Component<S> = (s: S) => ChildVode<S>;
11
11
 
12
12
  export type Patch<S> =
@@ -68,7 +68,7 @@ export type PropertyValue<S> =
68
68
  | Patch<S>;
69
69
 
70
70
  export type Dispatch<S> = (action: Patch<S>) => void;
71
- export type PatchableState<S> = S & { patch: Dispatch<Patch<S>> };
71
+ export type PatchableState<S> = S & { patch: Dispatch<S> };
72
72
 
73
73
  export type ContainerNode<S> = HTMLElement & {
74
74
  /** the `_vode` property is added to the container in `app()`.
@@ -92,12 +92,6 @@ export type ContainerNode<S> = HTMLElement & {
92
92
  }
93
93
  };
94
94
 
95
- /** create a state object used as initial state for `app()`. it is updated with `PatchableState.patch()` using `merge()` */
96
- export function createState<S extends object | unknown>(state: S): PatchableState<S> { return state as PatchableState<S>; }
97
-
98
- /** type safe way to create a patch. useful for type inference and autocompletion. */
99
- export function createPatch<S extends object | unknown>(p: DeepPartial<S> | Effect<S> | IgnoredPatch): typeof p { return p; }
100
-
101
95
  /** type-safe way to create a vode. useful for type inference and autocompletion.
102
96
  *
103
97
  * - just a tag: `vode("div")` => `["div"]` --*rendered*-> `<div></div>`
@@ -114,20 +108,20 @@ export function vode<S extends object | unknown>(tag: Tag | Vode<S>, props?: Pro
114
108
 
115
109
  /** create a vode app inside a container element
116
110
  * @param container will use this container as root and places the result of the dom function and further renderings in it
117
- * @param initialState
118
- * @param dom creates the initial dom from the state and is called on every render
111
+ * @param state the state object that is used as singleton state bound to the vode app and is updated with `patch()`
112
+ * @param dom function is alled every render and returnes the vode-dom that is updated incrementally to the DOM based on the state.
119
113
  * @param initialPatches variadic list of patches that are applied after the first render
120
114
  * @returns a patch function that can be used to update the state
121
115
  */
122
- export function app<S extends object | unknown>(container: HTMLElement, initialState: Omit<S, "patch">, dom: Component<S>, ...initialPatches: Patch<S>[]) {
123
- if (!container) throw new Error("container must be a valid HTMLElement");
124
- if (!initialState || typeof initialState !== "object") throw new Error("initialState must be an object");
116
+ export function app<S extends object | unknown>(container: Element, state: Omit<S, "patch">, dom: (s: S) => Vode<S>, ...initialPatches: Patch<S>[]) {
117
+ if (!container?.parentElement) throw new Error("container must be a valid HTMLElement inside the <html></html> document");
118
+ if (!state || typeof state !== "object") throw new Error("given state must be an object");
125
119
  if (typeof dom !== "function") throw new Error("dom must be a function that returns a vode");
126
120
 
127
121
  const _vode = {} as ContainerNode<S>["_vode"];
128
122
  _vode.stats = { lastRenderTime: 0, renderCount: 0, liveEffectCount: 0, patchCount: 0, renderPatchCount: 0 };
129
123
 
130
- Object.defineProperty(initialState, "patch", {
124
+ Object.defineProperty(state, "patch", {
131
125
  enumerable: false, configurable: true,
132
126
  writable: false, value: async (action: Patch<S>) => {
133
127
  if (!action || (typeof action !== "function" && typeof action !== "object")) return;
@@ -186,7 +180,11 @@ export function app<S extends object | unknown>(container: HTMLElement, initialS
186
180
  try {
187
181
  _vode.state = mergeState(_vode.state, _vode.q, true);
188
182
  _vode.q = null;
189
- _vode.vode = render(_vode.state, _vode.patch, container, 0, _vode.vode, dom(_vode.state))!;
183
+ const vom = dom(_vode.state);
184
+ _vode.vode = render(_vode.state, _vode.patch, container.parentElement as Element, 0, _vode.vode, vom)!;
185
+ if ((<ContainerNode<S>>container).tagName !== (vom[0] as Tag).toUpperCase()) { //the tag name was changed during render -> update reference to vode-app-root
186
+ container = _vode.vode.node as Element;
187
+ }
190
188
  } finally {
191
189
  _vode.isRendering = false;
192
190
  _vode.stats.renderCount++;
@@ -198,16 +196,21 @@ export function app<S extends object | unknown>(container: HTMLElement, initialS
198
196
  })
199
197
  });
200
198
 
201
- _vode.patch = (<PatchableState<S>>initialState).patch;
202
- _vode.state = <PatchableState<S>>initialState;
199
+ _vode.patch = (<PatchableState<S>>state).patch;
200
+ _vode.state = <PatchableState<S>>state;
203
201
  _vode.q = null;
204
202
 
205
203
  const root = container as ContainerNode<S>;
206
204
  root._vode = _vode;
207
205
 
208
- const initialVode = dom(<S>initialState);
209
- _vode.vode = <AttachedVode<S>>initialVode;
210
- _vode.vode = render(<S>initialState, _vode.patch!, container, 0, undefined, initialVode)!;
206
+ _vode.vode = render(
207
+ <S>state,
208
+ _vode.patch!,
209
+ container.parentElement,
210
+ Array.from(container.parentElement.children).indexOf(container),
211
+ hydrate<S>(container),
212
+ dom(<S>state)
213
+ )!;
211
214
 
212
215
  for (const effect of initialPatches) {
213
216
  _vode.patch!(effect);
@@ -223,6 +226,12 @@ export function memo<S>(compare: any[], componentOrProps: Component<S> | ((s: S)
223
226
  return componentOrProps as typeof componentOrProps extends ((s: S) => Props<S>) ? ((s: S) => Props<S>) : Component<S>;
224
227
  }
225
228
 
229
+ /** create a state object used as state for `app()`. it is updated with `PatchableState.patch()` using `merge()` */
230
+ export function createState<S extends object | unknown>(state: S): PatchableState<S> { return state as PatchableState<S>; }
231
+
232
+ /** type safe way to create a patch. useful for type inference and autocompletion. */
233
+ export function createPatch<S extends object | unknown>(p: DeepPartial<S> | Effect<S> | IgnoredPatch): typeof p { return p; }
234
+
226
235
  /** html tag of the vode or `#text` if it is a text node */
227
236
  export function tag<S>(v: Vode<S> | TextVode | NoVode | AttachedVode<S>): Tag | "#text" | undefined {
228
237
  return !!v ? (Array.isArray(v)
@@ -356,7 +365,39 @@ function mergeState(target: any, source: any, allowDeletion: boolean) {
356
365
  return target;
357
366
  };
358
367
 
359
- function render<S>(state: S, patch: Dispatch<S>, parent: ChildNode, childIndex: number, oldVode: AttachedVode<S> | undefined, newVode: ChildVode<S>, svg?: boolean): AttachedVode<S> | undefined {
368
+ function hydrate<S = unknown>(element: Element | Text): AttachedVode<S> | undefined {
369
+ if ((element as Text)?.nodeType === Node.TEXT_NODE) {
370
+ if ((element as Text).nodeValue?.trim() !== "")
371
+ return element as Text;
372
+ return undefined; //ignore (mostly html whitespace)
373
+ }
374
+ else if (element.nodeType === Node.COMMENT_NODE) {
375
+ return undefined; //ignore (not interesting)
376
+ }
377
+ else {
378
+ const tag: Tag = (<Element>element).tagName.toLowerCase();
379
+ const root: Vode<S> = [tag];
380
+
381
+ (<AttachedVode<S>>root).node = element;
382
+ if ((element as HTMLElement)?.hasAttributes()) {
383
+ const props: Props<S> = {};
384
+ const attr = (<HTMLElement>element).attributes;
385
+ for (let a of attr) {
386
+ props[a.name] = a.value;
387
+ }
388
+ (<Vode<S>>root).push(props as any);
389
+ }
390
+ if (element.hasChildNodes()) {
391
+ for (let child of element.childNodes) {
392
+ const wet = child && hydrate<S>(child as Element | Text)! as ChildVode<S>;
393
+ if (wet) root.push(wet as any);
394
+ }
395
+ }
396
+ return <AttachedVode<S>>root;
397
+ }
398
+ }
399
+
400
+ function render<S>(state: S, patch: Dispatch<S>, parent: Element, childIndex: number, oldVode: AttachedVode<S> | undefined, newVode: ChildVode<S>, svg?: boolean): AttachedVode<S> | undefined {
360
401
  // unwrap component if it is memoized
361
402
  newVode = remember(state, newVode, oldVode) as ChildVode<S>;
362
403
 
@@ -403,13 +444,12 @@ function render<S>(state: S, patch: Dispatch<S>, parent: ChildNode, childIndex:
403
444
  (<any>oldNode).onUnmount && patch((<any>oldNode).onUnmount(oldNode));
404
445
  oldNode.replaceWith(text);
405
446
  } else {
406
- if (parent.childNodes[childIndex]) {
407
- parent.insertBefore(text, parent.childNodes[childIndex]);
447
+ if (parent.childNodes[childIndex + 1]) {
448
+ parent.insertBefore(text, parent.childNodes[childIndex + 1]);
408
449
  } else {
409
450
  parent.appendChild(text);
410
451
  }
411
452
  }
412
-
413
453
  return text as Text;
414
454
  }
415
455
 
@@ -435,8 +475,8 @@ function render<S>(state: S, patch: Dispatch<S>, parent: ChildNode, childIndex:
435
475
  (<any>oldNode).onUnmount && patch((<any>oldNode).onUnmount(oldNode));
436
476
  oldNode.replaceWith(newNode);
437
477
  } else {
438
- if (parent.childNodes[childIndex]) {
439
- parent.insertBefore(newNode, parent.childNodes[childIndex]);
478
+ if (parent.childNodes[childIndex + 1]) {
479
+ parent.insertBefore(newNode, parent.childNodes[childIndex + 1]);
440
480
  } else {
441
481
  parent.appendChild(newNode);
442
482
  }
@@ -446,7 +486,7 @@ function render<S>(state: S, patch: Dispatch<S>, parent: ChildNode, childIndex:
446
486
  if (newChildren) {
447
487
  for (let i = 0; i < newChildren.length; i++) {
448
488
  const child = newChildren[i];
449
- const attached = render(state, patch, newNode, i, undefined, child, svg);
489
+ const attached = render(state, patch, newNode as Element, i, undefined, child, svg);
450
490
  (<Vode<S>>newVode!)[properties ? i + 2 : i + 1] = <Vode<S>>attached;
451
491
  }
452
492
  }
@@ -486,7 +526,7 @@ function render<S>(state: S, patch: Dispatch<S>, parent: ChildNode, childIndex:
486
526
  const child = newKids[i];
487
527
  const oldChild = oldKids && oldKids[i];
488
528
 
489
- const attached = render(state, patch, oldNode!, i, oldChild, child, svg);
529
+ const attached = render(state, patch, oldNode as Element, i, oldChild, child, svg);
490
530
  if (attached) {
491
531
  (<Vode<S>>newVode)[hasProps ? i + 2 : i + 1] = <Vode<S>>attached;
492
532
  }