lithent 0.36.1 → 0.37.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
@@ -1,6 +1,6 @@
1
1
  # lithent
2
2
 
3
- > A lightweight Virtual DOM UI library
3
+ > An extensible virtual DOM library for lightweight use in a variety of environments.
4
4
 
5
5
  Lithent were developed to make it easy to insert Virtual DOM component
6
6
  fragments into pages already drawn with SSR, and are intended to be
@@ -9,16 +9,21 @@ used lightly in a variety of situations.
9
9
  - https://superlucky84.github.io/lithent
10
10
  - (This guide page is written in lithent.)
11
11
 
12
- `(9.54 KiB / gzip: 3.54 KiB)`
12
+ `(9.60 KiB / gzip: 3.54 KiB)`
13
+
13
14
 
14
15
  ## 🚩 Table of Contents
15
16
 
16
17
  - [Why Use Lithent](#why-use-lithent)
17
18
  - [Basic Guide](#basic-guide)
18
19
  - [How To Install](#how-to-install)
20
+ - [Use NPM](#use-npm)
21
+ - [Use CDN](#or-use-cdn)
19
22
  - [With HTM](#with-htm)
20
23
  - [With JSX](#with-jsx)
21
24
  - [Examples](#examples)
25
+ - [With ESM](#with-esm)
26
+ - [With UMD](#with-umd)
22
27
  - [Develop Guide](#develop-guide)
23
28
 
24
29
  ## Why use Lithent?
@@ -47,10 +52,20 @@ JavaScript users are used to using closures and love to develop with them.
47
52
 
48
53
  ## How To Install
49
54
 
55
+ #### Use NPM
56
+
50
57
  ```bash
51
58
  pnpm add lithent
52
59
  ```
53
60
 
61
+ #### Or Use CDN
62
+
63
+ * UMD : https://cdn.jsdelivr.net/npm/lithent@0.36.2/dist/lithent.umd.js
64
+ * UMD-HELPER: https://cdn.jsdelivr.net/npm/lithent@0.36.2/helper/dist/lithentHelper.umd.js
65
+ * ESM : https://cdn.jsdelivr.net/npm/lithent@0.36.2/dist/lithent.mjs
66
+ * ESM-HELPER: https://cdn.jsdelivr.net/npm/lithent@0.36.2/helper/dist/lithentHelper.mjs
67
+
68
+
54
69
  It's easier to use lithent with JSX or HTM.
55
70
 
56
71
  #### With HTM
@@ -75,6 +90,7 @@ const html = htm.bind(h);
75
90
 
76
91
  - [More Examples](https://superlucky84.github.io/lithent/#examples)
77
92
 
93
+ #### With ESM
78
94
  ```js
79
95
  import { h, render, mount, Fragment } from 'lithent';
80
96
  import { state } from 'lithent/helper';
@@ -102,6 +118,41 @@ const Component = mount((r, _props) => {
102
118
  render(html`<${Component} />`, document.getElementById('root'));
103
119
  ```
104
120
 
121
+ #### With UMD
122
+
123
+ ```html
124
+ <script src="https://cdn.jsdelivr.net/npm/lithent@0.36.2/dist/lithent.umd.js"></script>
125
+ <!--script src="https://cdn.jsdelivr.net/npm/lithent@0.36.2/helper/dist/lithentHelper.umd.js"></script-->
126
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/htm/3.1.1/htm.js"></script>
127
+
128
+ <div id="root"></div>
129
+
130
+ <script>
131
+ const { h, Fragment, render, mount } = lithent;
132
+ // const { state } = lithentHelper;
133
+ const html = htm.bind(h);
134
+
135
+ const Component = mount(renew => {
136
+ count = 0;
137
+
138
+ const change = () => {
139
+ count += 1;
140
+ renew();
141
+ };
142
+
143
+ // Updater
144
+ return () => html`
145
+ <${Fragment}>
146
+ <li>count: ${count}</li>
147
+ <button onClick=${change}>increase</button>
148
+ <//>
149
+ `;
150
+ });
151
+
152
+ render(html`<${Component} />`, document.getElementById('root'));
153
+ </script>
154
+ ```
155
+
105
156
  ## Develop Guide
106
157
 
107
158
  It's open source, so you can develop and contribute together.
package/dist/lithent.mjs CHANGED
@@ -1,8 +1,5 @@
1
- const checkCustemComponentFunction = (target) => typeof target === "function" && !checkFragmentFunction(target) || typeof target === "object" && "resolve" in target;
2
- const checkFragmentFunction = (target) => typeof target === "function" && target === Fragment;
3
1
  const checkPlainWDomType = (wDom) => typeof wDom === "object" && !("resolve" in wDom);
4
2
  const checkPlainType = (wDom, typeName) => checkPlainWDomType(wDom) && wDom.type === typeName;
5
- const checkEmptyElement = (wDom) => checkPlainWDomType(wDom) && !wDom.type;
6
3
  const checkSameCustomComponent = (newWDom, originalWDom) => newWDom.constructor === (originalWDom == null ? void 0 : originalWDom.constructor);
7
4
  const checkSameFragment = (newWDom, originalWDom) => {
8
5
  var _a, _b;
@@ -16,24 +13,18 @@ const checkNormalTypeElement = (newWDom, originalWDom) => {
16
13
  var _a, _b;
17
14
  return checkPlainWDomType(newWDom) && (originalWDom == null ? void 0 : originalWDom.type) === newWDom.type && (((_a = originalWDom == null ? void 0 : originalWDom.children) == null ? void 0 : _a.length) === ((_b = newWDom == null ? void 0 : newWDom.children) == null ? void 0 : _b.length) || newWDom.type === "loop");
18
15
  };
16
+ const checkCustemComponentFunction = (target) => typeof target === "function" && !checkFragmentFunction(target) || typeof target === "object" && "resolve" in target;
17
+ const checkFragmentFunction = (target) => typeof target === "function" && target === Fragment;
18
+ const checkEmptyElement = (wDom) => checkPlainWDomType(wDom) && !wDom.type;
19
19
  const checkExisty = (value) => value !== null && value !== void 0;
20
20
  const checkStyleData = (dataKey, dataValue) => dataKey === "style" && typeof dataValue === "object";
21
21
  const checkRefData = (dataKey, dataValue) => dataKey === "ref" && typeof dataValue === "object";
22
- const checkOptionElement = (element) => {
23
- return element.nodeType === 1 && element.tagName === "OPTION";
24
- };
25
- const checkTextareaElement = (element) => {
26
- return element.nodeType === 1 && element.tagName === "TEXTAREA";
27
- };
28
- const checkCheckboxElement = (element) => {
29
- return element.nodeType === 1 && element.type === "checkbox";
30
- };
31
- const checkRadioElement = (element) => {
32
- return element.nodeType === 1 && element.type === "radio";
33
- };
22
+ const checkOptionElement = (element) => element.nodeType === 1 && element.tagName === "OPTION";
23
+ const checkTextareaElement = (element) => element.nodeType === 1 && element.tagName === "TEXTAREA";
24
+ const checkCheckableElement = (element) => element.nodeType === 1 && ["radio", "checkbox"].includes(element.type);
34
25
  const checkNormalAttribute = (dataValue) => typeof dataValue === "number" || typeof dataValue === "string";
35
26
  const getWDomType = (wDom) => {
36
- let result;
27
+ let result = "et";
37
28
  if (checkCustemComponentFunction(wDom)) {
38
29
  result = "c";
39
30
  } else if (checkPlainType(wDom, "fragment")) {
@@ -59,9 +50,6 @@ const checkSameWDomWithOriginal = {
59
50
  };
60
51
  const getParent = (vDom) => {
61
52
  const parentVDom = vDom.getParent && vDom.getParent();
62
- if (!parentVDom) {
63
- throw Error("Not found parent vDom");
64
- }
65
53
  return parentVDom;
66
54
  };
67
55
  const reRender = (vDom, infoVdom) => {
@@ -74,12 +62,10 @@ const reRender = (vDom, infoVdom) => {
74
62
  updateChildren(children, infoChidren);
75
63
  }
76
64
  const newVDom = vDom.reRender && vDom.reRender();
77
- if (!newVDom) {
78
- throw Error("Unable reRender");
79
- }
80
65
  return newVDom;
81
66
  };
82
67
  const getEventName = (eventKey) => eventKey.replace(/^on(.*)/, (_match, p1) => p1.toLowerCase());
68
+ const getAttrKey = (keyName) => keyName === "className" ? "class" : keyName;
83
69
  const updateProps$1 = (props, infoProps) => {
84
70
  if (props && infoProps !== props) {
85
71
  Object.keys(props).forEach((key) => delete props[key]);
@@ -96,6 +82,7 @@ const updateChildren = (children, infoChidren) => {
96
82
  }
97
83
  }
98
84
  };
85
+ const xmlnsRef = { value: "" };
99
86
  const componentKeyRef = { value: {} };
100
87
  const needDiffRef = { value: false };
101
88
  const componentRef = /* @__PURE__ */ new WeakMap();
@@ -261,12 +248,10 @@ const runUpdatedQueueFromWDom = (newWDom) => {
261
248
  };
262
249
  const checkNeedPushQueue = (originalDefs, newDefs) => !originalDefs.length && !originalDefs.length ? true : originalDefs.some((def, index) => def !== newDefs[index]);
263
250
  const render = (wDom, wrapElement, afterElement) => {
264
- if (!wrapElement) {
265
- throw Error("WrapELement is null");
266
- }
251
+ wrapElement != null ? wrapElement : wrapElement = document.body;
267
252
  wDom.isRoot = true;
268
253
  wDom.wrapElement = wrapElement;
269
- const Dom = wDomToDom(wDom, true);
254
+ const Dom = wDomToDom(wDom);
270
255
  if (afterElement) {
271
256
  wDom.afterElement = afterElement;
272
257
  wrapElement.insertBefore(Dom, afterElement);
@@ -275,28 +260,25 @@ const render = (wDom, wrapElement, afterElement) => {
275
260
  }
276
261
  return () => {
277
262
  var _a;
278
- if (wDom.componentProps) {
279
- const component = (_a = componentRef.get(wDom.componentProps)) == null ? void 0 : _a.vd.value;
280
- if (component) {
281
- runUnmountQueueFromWDom(component);
282
- recursiveRemoveEvent(component);
283
- rootDelete(component);
284
- }
263
+ const component = (_a = componentRef.get(wDom.componentProps || {})) == null ? void 0 : _a.vd.value;
264
+ if (component) {
265
+ runUnmountQueueFromWDom(component);
266
+ recursiveRemoveEvent(component);
267
+ rootDelete(component);
285
268
  }
286
269
  };
287
270
  };
288
271
  const wDomUpdate = (newWDomTree) => {
289
272
  const { needRerender } = newWDomTree;
290
273
  if (needRerender && needRerender !== "N") {
291
- const exec = {
274
+ ({
292
275
  A: typeAdd,
293
276
  D: typeDelete,
294
277
  R: typeReplace,
295
278
  U: typeUpdate,
296
279
  SR: typeSortedReplace,
297
280
  SU: typeSortedUpdate
298
- }[needRerender];
299
- exec(newWDomTree);
281
+ })[needRerender](newWDomTree);
300
282
  }
301
283
  };
302
284
  const recursiveRemoveEvent = (originalWDom) => {
@@ -308,16 +290,16 @@ const recursiveRemoveEvent = (originalWDom) => {
308
290
  });
309
291
  };
310
292
  const rootDelete = (newWDom) => {
311
- const parent = newWDom.wrapElement;
312
- deleteRealDom(newWDom, parent);
293
+ deleteRealDom(newWDom, newWDom.wrapElement);
313
294
  };
314
295
  const typeDelete = (newWDom) => {
315
- const parentWDom = getParent(newWDom);
316
- const parent = findRealParentElement(parentWDom);
317
296
  if (newWDom.oldProps && newWDom.el) {
318
297
  removeEvent(newWDom.oldProps, newWDom.el);
319
298
  }
320
- deleteRealDom(newWDom, parent);
299
+ deleteRealDom(
300
+ newWDom,
301
+ findRealParentElement(getParent(newWDom))
302
+ );
321
303
  };
322
304
  const deleteRealDom = (newWDom, parent) => {
323
305
  var _a, _b;
@@ -350,18 +332,13 @@ const typeSortedUpdate = (newWDom) => {
350
332
  };
351
333
  const typeAdd = (newWDom, newElement) => {
352
334
  if (!newElement) {
353
- newElement = wDomToDom(newWDom, true);
335
+ newElement = wDomToDom(newWDom);
354
336
  }
355
337
  const parentWDom = getParent(newWDom);
356
338
  if (parentWDom.type) {
357
339
  const parentEl = findRealParentElement(parentWDom);
358
340
  const isLoop = parentWDom.type === "loop";
359
- let nextEl;
360
- if (isLoop) {
361
- nextEl = startFindNextBrotherElement(parentWDom, getParent(parentWDom));
362
- } else {
363
- nextEl = startFindNextBrotherElement(newWDom, parentWDom);
364
- }
341
+ const nextEl = isLoop ? startFindNextBrotherElement(parentWDom, getParent(parentWDom)) : startFindNextBrotherElement(newWDom, parentWDom);
365
342
  if (newElement && parentEl) {
366
343
  if (nextEl) {
367
344
  parentEl.insertBefore(newElement, nextEl);
@@ -413,7 +390,7 @@ const typeReplace = (newWDom) => {
413
390
  typeSortedReplace(newWDom);
414
391
  } else {
415
392
  const parentElement = findRealParentElement(parentWDom);
416
- const newElement = wDomToDom(newWDom, true);
393
+ const newElement = wDomToDom(newWDom);
417
394
  if (parentElement) {
418
395
  parentElement.replaceChild(newElement, orignalElement);
419
396
  }
@@ -463,7 +440,7 @@ const updateProps = (props, element, oldProps) => {
463
440
  ([dataKey, dataValue]) => {
464
441
  if (dataKey === "key")
465
442
  ;
466
- else if (dataKey === "innerHTML" && element && typeof dataValue === "string") {
443
+ else if (dataKey === "innerHTML" && typeof dataValue === "string") {
467
444
  element.innerHTML = dataValue;
468
445
  } else if (checkStyleData(dataKey, dataValue)) {
469
446
  updateStyle(
@@ -480,16 +457,25 @@ const updateProps = (props, element, oldProps) => {
480
457
  dataValue,
481
458
  originalProps[dataKey]
482
459
  );
483
- } else if (checkRadioElement(element) && dataKey === "checked") {
484
- element.checked = !!dataValue;
485
- } else if (checkCheckboxElement(element) && dataKey === "checked") {
460
+ } else if (checkCheckableElement(element) && dataKey === "checked") {
486
461
  element.checked = !!dataValue;
487
462
  } else if (checkTextareaElement(element) && dataKey === "value") {
488
463
  element.value = dataValue;
489
464
  } else if (checkOptionElement(element) && dataKey === "selected") {
490
465
  element.selected = !!dataValue;
491
466
  } else if (checkNormalAttribute(dataValue)) {
492
- element.setAttribute(dataKey, String(dataValue));
467
+ if (xmlnsRef.value && dataKey !== "xmlns") {
468
+ element.setAttributeNS(
469
+ null,
470
+ getAttrKey(dataKey),
471
+ String(dataValue)
472
+ );
473
+ } else {
474
+ element.setAttribute(
475
+ getAttrKey(dataKey),
476
+ String(dataValue)
477
+ );
478
+ }
493
479
  }
494
480
  delete originalProps[dataKey];
495
481
  }
@@ -498,37 +484,43 @@ const updateProps = (props, element, oldProps) => {
498
484
  (dataKey) => element.removeAttribute(dataKey)
499
485
  );
500
486
  };
501
- const wDomToDom = (wDom, init) => {
487
+ const wDomToDom = (wDom) => {
502
488
  let element;
503
489
  const { type, tag, text, props, children = [] } = wDom;
504
490
  const isVirtualType = type === "fragment" || type === "loop";
491
+ if (tag === "svg") {
492
+ xmlnsRef.value = String(props == null ? void 0 : props.xmlns);
493
+ }
505
494
  if (isVirtualType) {
506
495
  element = new DocumentFragment();
507
496
  } else if (type === "element" && tag) {
508
- element = document.createElement(tag);
497
+ element = xmlnsRef.value ? document.createElementNS(xmlnsRef.value, tag) : document.createElement(tag);
509
498
  } else if (type === "text" && checkExisty(text)) {
510
499
  element = document.createTextNode(String(text));
500
+ } else {
501
+ element = document.createElement("e");
511
502
  }
512
- wDomChildrenToDom(children, element, init);
503
+ wDomChildrenToDom(children, element);
513
504
  updateProps(props, element);
514
505
  wDom.el = element;
515
506
  runMountedQueueFromWDom(wDom);
516
- return element || document.createElement("div");
517
- };
518
- const wDomChildrenToDom = (children, parentElement, init) => {
519
- if (init) {
520
- const elementChildren = children.reduce(
521
- (acc, childItem) => {
522
- if (childItem.type) {
523
- acc.appendChild(wDomToDom(childItem, init));
524
- }
525
- return acc;
526
- },
527
- new DocumentFragment()
528
- );
529
- if (parentElement && elementChildren.hasChildNodes()) {
530
- parentElement.appendChild(elementChildren);
531
- }
507
+ if (tag === "svg") {
508
+ xmlnsRef.value = "";
509
+ }
510
+ return element;
511
+ };
512
+ const wDomChildrenToDom = (children, parentElement) => {
513
+ const elementChildren = children.reduce(
514
+ (acc, childItem) => {
515
+ if (childItem.type) {
516
+ acc.appendChild(wDomToDom(childItem));
517
+ }
518
+ return acc;
519
+ },
520
+ new DocumentFragment()
521
+ );
522
+ if (parentElement && elementChildren.hasChildNodes()) {
523
+ parentElement.appendChild(elementChildren);
532
524
  }
533
525
  };
534
526
  const updateEvent = (element, eventKey, newEventHandler, oldEventHandler) => {
@@ -565,15 +557,11 @@ const findRealParentElement = (vDom) => {
565
557
  }
566
558
  return findRealParentElement(getParent(vDom));
567
559
  };
568
- const makeNewWDomTree = (newWDom, originalWDom) => {
569
- const type = getWDomType(newWDom);
570
- if (!type) {
571
- throw new Error("Unknown type wdom");
572
- }
573
- const isSameType = checkSameWDomWithOriginal[type](newWDom, originalWDom);
574
- const result = remakeNewWDom(newWDom, isSameType, originalWDom);
575
- return result;
576
- };
560
+ const makeNewWDomTree = (newWDom, originalWDom) => remakeNewWDom(
561
+ newWDom,
562
+ checkSameWDomWithOriginal[getWDomType(newWDom)](newWDom, originalWDom),
563
+ originalWDom
564
+ );
577
565
  const remakeNewWDom = (newWDom, isSameType, originalWDom) => {
578
566
  const remakeWDom = generalize(newWDom, isSameType, originalWDom);
579
567
  remakeWDom.children = remakeChildrenForDiff(
@@ -646,7 +634,7 @@ const remakeChildrenForUpdate = (newWDom, originalWDom) => {
646
634
  });
647
635
  };
648
636
  const remakeChildrenForLoopUpdate = (newWDom, originalWDom) => {
649
- const { remakedChildren, unUsedChildren } = diffLoopChildren(
637
+ const [remakedChildren, unUsedChildren] = diffLoopChildren(
650
638
  newWDom,
651
639
  originalWDom
652
640
  );
@@ -670,17 +658,11 @@ const diffLoopChildren = (newWDom, originalWDom) => {
670
658
  childItem.getParent = () => newWDom;
671
659
  return childItem;
672
660
  });
673
- return {
674
- remakedChildren,
675
- unUsedChildren: originalChildren
676
- };
677
- };
678
- const findSameKeyOriginalItem = (item, originalChildren) => {
679
- const key = getKey(item);
680
- return originalChildren.find(
681
- (orignalChildItem) => getKey(orignalChildItem) === key
682
- );
661
+ return [remakedChildren, originalChildren];
683
662
  };
663
+ const findSameKeyOriginalItem = (item, originalChildren) => originalChildren.find(
664
+ (orignalChildItem) => getKey(orignalChildItem) === getKey(item)
665
+ );
684
666
  const getKey = (target) => {
685
667
  var _a, _b, _c;
686
668
  return (_c = (_a = target == null ? void 0 : target.componentProps) == null ? void 0 : _a.key) != null ? _c : (_b = target == null ? void 0 : target.props) == null ? void 0 : _b.key;
@@ -763,14 +745,14 @@ const makeWDomResolver = (tag, props, children) => {
763
745
  };
764
746
  const makeCustomNode = (componentMaker, componentKey, tag, props, children) => {
765
747
  const customNode = componentMaker(props);
766
- const reRender2 = makeReRender(
767
- componentMaker,
748
+ addComponentProps(
749
+ customNode,
768
750
  componentKey,
769
751
  tag,
770
752
  props,
771
- children
753
+ children,
754
+ makeReRender(componentMaker, componentKey, tag, props, children)
772
755
  );
773
- addComponentProps(customNode, componentKey, tag, props, children, reRender2);
774
756
  return customNode;
775
757
  };
776
758
  const makeReRender = (componentMaker, componentKey, tag, props, children) => {