@ryupold/vode 1.0.2 → 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,6 +2,8 @@
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
@@ -133,6 +135,87 @@ A `vode` is a representation of a virtual DOM node, which is a tree structure of
133
135
 
134
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.
135
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
+
136
219
  ### Component
137
220
  ```ts
138
221
  type Component<S> = (s: S) => ChildVode<S>;
@@ -142,13 +225,26 @@ A `Component<State>` is a function that takes a state object and returns a `Vode
142
225
 
143
226
  ```ts
144
227
  // A full vode has a tag, properties, and children. props and children are optional.
145
- 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" },
146
231
 
147
232
  // a child vode can be a string, which results in a text node
148
233
  [H1, "Hello World"],
149
234
 
150
235
  // a vode can also be a self-closing tag
151
- [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],
152
248
 
153
249
  // style object maps directly to the HTML style attribute
154
250
  [P, { style: { color: "red", fontWeight: "bold" } }, "This is a paragraph."],
@@ -164,9 +260,9 @@ const CompFooBar = (s) => [DIV, { class: "container" },
164
260
  // and the HTML event object as second argument
165
261
  [BUTTON, {
166
262
  // all on* events accept `Patch<State>`
167
- onclick: (state, evt) => {
263
+ onclick: (s, evt) => {
168
264
  // objects returned by events are patched automatically
169
- return { counter: state.counter + 1 };
265
+ return { counter: s.counter + 1 };
170
266
  },
171
267
 
172
268
  // you can set the patch object directly for events
@@ -174,14 +270,14 @@ const CompFooBar = (s) => [DIV, { class: "container" },
174
270
  onmouseleave: { pointing: false },
175
271
 
176
272
  // a patch can be an async function
177
- onmouseup: async (state, evt) => {
178
- state.patch({ loading: true });
273
+ onmouseup: async (s, evt) => {
274
+ s.patch({ loading: true });
179
275
  const result = await apiCall();
180
276
  return { title: result.data.title, loading: false };
181
277
  },
182
278
 
183
279
  // you can also use a generator function that yields patches
184
- onmousedown: async function* (state, evt) {
280
+ onmousedown: async function* (s, evt) {
185
281
  yield { loading: true };
186
282
  const result = await apiCall();
187
283
  yield {
@@ -190,8 +286,18 @@ const CompFooBar = (s) => [DIV, { class: "container" },
190
286
  return { loading: false };
191
287
  },
192
288
 
289
+ // events can be attached condionally
290
+ ondblclick : s.counter > 20 && (s, evt) => {
291
+ return { counter: s.counter * 2 };
292
+ },
293
+
193
294
  class: { bar: s.pointing }
194
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),
195
301
  ];
196
302
  ```
197
303
 
@@ -199,7 +305,7 @@ const CompFooBar = (s) => [DIV, { class: "container" },
199
305
 
200
306
  `app` is a function that takes a HTML node, a state object, and a render function (`Component<State>`).
201
307
  ```ts
202
- const appNode = document.getElementById('APP-ID');
308
+ const containerNode = document.getElementById('APP-ID');
203
309
  const state = {
204
310
  counter: 0,
205
311
  pointing: false,
@@ -207,12 +313,38 @@ const state = {
207
313
  title: '',
208
314
  body: '',
209
315
  };
210
- const patch = app(appNode, state, (s) => CompFooBar(s));
316
+ const patch = app(containerNode, state, (s) => CompFooBar(s));
211
317
  ```
212
- It will render the 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.
213
319
 
320
+ #### they multiply
214
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.
215
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.
347
+
216
348
  ### state & patch
217
349
  The state object you pass to [`app`](#app) can be updated directly or via `patch`.
218
350
  During the call to `app`, the state object is bound to the vode app instance and becomes a singleton from its perspective.
package/dist/vode.js CHANGED
@@ -236,12 +236,6 @@ 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;
@@ -249,7 +243,7 @@ var V = (() => {
249
243
  else return [tag2, ...children2];
250
244
  }
251
245
  function app(container, state, dom, ...initialPatches) {
252
- if (!container) throw new Error("container must be a valid HTMLElement");
246
+ if (!container?.parentElement) throw new Error("container must be a valid HTMLElement inside the <html></html> document");
253
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 = {};
@@ -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++;
@@ -331,9 +329,14 @@ var V = (() => {
331
329
  _vode.q = null;
332
330
  const root = container;
333
331
  root._vode = _vode;
334
- const initialVode = dom(state);
335
- _vode.vode = initialVode;
336
- _vode.vode = render(state, _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:()=>it,BODY:()=>pt,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:()=>io,FECOMPONENTTRANSFER:()=>po,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:()=>ie,NOSCRIPT:()=>pe,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("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 c=>{if(!(!c||typeof c!="function"&&typeof c!="object"))if(e.stats.patchCount++,c?.next){let l=c;e.stats.liveEffectCount++;try{let i=await l.next();for(;i.done===!1;){e.stats.liveEffectCount++;try{e.patch(i.value),i=await l.next()}finally{e.stats.liveEffectCount--}}e.patch(i.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,i=l?e:e?.node;if(c){i?.onUnmount&&o(i.onUnmount(i)),i?.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 i.nodeValue!==r&&(i.nodeValue=r),e;if(E&&(!i||!l)){let T=document.createTextNode(r);return i?(i.onUnmount&&o(i.onUnmount(i)),i.replaceWith(T)):n.childNodes[s]?n.insertBefore(T,n.childNodes[s]):n.appendChild(T),T}if(m&&(!i||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),i?(i.onUnmount&&o(i.onUnmount(i)),i.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 p=S[f],x=P(t,o,T,f,void 0,p,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=i;let T=r,y=e,g=!1;if(T[1]?.__memo){let p=T[1];if(T[1]=O(t,T[1],y[1]),p!==T[1]){let x=d(r);R(o,i,d(e),x,a),g=!!x}}else{let p=d(r);R(o,i,d(e),p,a),g=!!p}let S=A(r),f=A(e);if(S){for(let p=0;p<S.length;p++){let x=S[p],F=f&&f[p],b=P(t,o,i,p,F,x,a);b&&(r[g?p+2:p+1]=b)}for(let p=S.length;f&&p<f.length;p++)f[p]?.node?f[p].node.remove():f[p]?.nodeType===Node.TEXT_NODE&&f[p].remove()}for(let p=S?.length||0;p<f?.length;p++)f[p]?.node?f[p].node.remove():f[p]?.nodeType===Node.TEXT_NODE&&f[p].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=i=>t([l,i])}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",it="blockquote",pt="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",ie="nav",pe="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",io="feColorMatrix",po="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("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(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 i(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=m(f);if(L>0)return f.slice(L);return null}function p(f){return f.length-m(f)}function V(f,L){return f[L+m(f)]}function m(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],x=H(f,L,F,G,_,Z,z);if(x)X[Y?G+2:G+1]=x}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=N(L,f);if(typeof X==="object")X.__memo=L?.__memo;return X}function N(f,L){if(typeof f==="function")return N(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=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 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 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",s="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",Sf="footer",mf="form",xf="h1",Nf="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",rf="ins",sf="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",SE="strong",mE="style",xE="sub",NE="summary",yE="sup",_E="table",bE="tbody",kE="td",PE="template",hE="textarea",gE="tfoot",uE="th",cE="thead",vE="time",iE="title",pE="tr",VE="track",wE="u",rE="ul",sE="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",SL="filter",mL="foreignObject",xL="g",NL="image",yL="line",_L="linearGradient",bL="marker",kL="mask",PL="metadata",hL="mpath",gL="path",uL="pattern",cL="polygon",vL="polyline",iL="radialGradient",pL="rect",VL="set",wL="stop",rL="svg",sL="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",SX="munderover",mX="semantics";function NX(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,i as mergeClass,c as memo,NX as htmlToVode,P as createState,h as createPatch,m as childrenStart,D as children,p as childCount,V as child,u as app,lE as WBR,oL as VIEW,sE as VIDEO,dL as USE,rE as UL,wE as U,aL as TSPAN,VE as TRACK,pE as TR,iE 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,sL as SWITCH,rL as SVG,yE as SUP,NE as SUMMARY,xE as SUB,mE as STYLE,SE as STRONG,wL as STOP,KE as SPAN,IE as SOURCE,DE as SMALL,ME as SLOT,VL as SET,mX 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,pL as RECT,iL 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,SX 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,sf as KBD,rf as INS,wf as INPUT,Vf as IMG,NL 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,Nf as H2,xf as H1,xL as G,mf as FORM,mL as FOREIGNOBJECT,Sf as FOOTER,SL 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,s as ABBR,r 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");
@@ -16,8 +10,8 @@ function vode(tag, props, ...children) {
16
10
  return [tag, ...children];
17
11
  }
18
12
  function app(container, state, dom, ...initialPatches) {
19
- if (!container)
20
- throw new Error("container must be a valid HTMLElement");
13
+ if (!container?.parentElement)
14
+ throw new Error("container must be a valid HTMLElement inside the <html></html> document");
21
15
  if (!state || typeof state !== "object")
22
16
  throw new Error("given state must be an object");
23
17
  if (typeof dom !== "function")
@@ -89,7 +83,11 @@ function app(container, state, 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++;
@@ -105,9 +103,7 @@ function app(container, state, dom, ...initialPatches) {
105
103
  _vode.q = null;
106
104
  const root = container;
107
105
  root._vode = _vode;
108
- const initialVode = dom(state);
109
- _vode.vode = initialVode;
110
- _vode.vode = render(state, _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.2",
3
+ "version": "1.1.0",
4
4
  "description": "Small web framework for minimal websites",
5
5
  "author": "Michael Scherbakow (ryupold)",
6
6
  "license": "MIT",
package/src/vode.ts CHANGED
@@ -5,7 +5,7 @@ export type JustTagVode = [tag: Tag];
5
5
  export type ChildVode<S> = Vode<S> | TextVode | NoVode | Component<S>;
6
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 };
8
+ export type AttachedVode<S> = Vode<S> & { node: ChildNode } | Text & { node?: never };
9
9
  export type Tag = keyof (HTMLElementTagNameMap & SVGElementTagNameMap & MathMLElementTagNameMap) | (string & {});
10
10
  export type Component<S> = (s: S) => ChildVode<S>;
11
11
 
@@ -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 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>`
@@ -115,12 +109,12 @@ export function vode<S extends object | unknown>(tag: Tag | Vode<S>, props?: Pro
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
111
  * @param state the state object that is used as singleton state bound to the vode app and is updated with `patch()`
118
- * @param dom creates the initial dom from the state and is called on every render
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, state: Omit<S, "patch">, dom: Component<S>, ...initialPatches: Patch<S>[]) {
123
- if (!container) throw new Error("container must be a valid HTMLElement");
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");
124
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
 
@@ -186,7 +180,11 @@ export function app<S extends object | unknown>(container: HTMLElement, state: O
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++;
@@ -205,9 +203,14 @@ export function app<S extends object | unknown>(container: HTMLElement, state: O
205
203
  const root = container as ContainerNode<S>;
206
204
  root._vode = _vode;
207
205
 
208
- const initialVode = dom(<S>state);
209
- _vode.vode = <AttachedVode<S>>initialVode;
210
- _vode.vode = render(<S>state, _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
  }