lithent 0.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/LICENSE +21 -0
- package/README.md +202 -0
- package/dist/diff.d.ts +14 -0
- package/dist/hook/mountCallback.d.ts +3 -0
- package/dist/hook/ref.d.ts +3 -0
- package/dist/hook/unmount.d.ts +3 -0
- package/dist/hook/updateCallback.d.ts +2 -0
- package/dist/hook/useUpdate.d.ts +3 -0
- package/dist/index.d.ts +29 -0
- package/dist/lithent.mjs +867 -0
- package/dist/lithent.mjs.map +1 -0
- package/dist/lithent.umd.js +2 -0
- package/dist/lithent.umd.js.map +1 -0
- package/dist/render.d.ts +15 -0
- package/dist/types/index.d.ts +65 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/predicator.d.ts +36 -0
- package/dist/utils/universalRef.d.ts +59 -0
- package/dist/wDom.d.ts +17 -0
- package/examples/dist/assets/index.e76a0ef8.js +2 -0
- package/examples/dist/assets/index.e76a0ef8.js.map +1 -0
- package/examples/dist/index.html +13 -0
- package/examples/package.json +33 -0
- package/examples/src/index.tsx +109 -0
- package/helper/dist/hook/computed.d.ts +4 -0
- package/helper/dist/hook/effect.d.ts +1 -0
- package/helper/dist/hook/state.d.ts +4 -0
- package/helper/dist/hook/store.d.ts +8 -0
- package/helper/dist/index.d.ts +4 -0
- package/helper/dist/lithentHelper.mjs +56 -0
- package/helper/dist/lithentHelper.mjs.map +1 -0
- package/helper/dist/lithentHelper.umd.js +2 -0
- package/helper/dist/lithentHelper.umd.js.map +1 -0
- package/helper/package.json +32 -0
- package/helper/src/hook/computed.ts +23 -0
- package/helper/src/hook/effect.ts +20 -0
- package/helper/src/hook/state.ts +26 -0
- package/helper/src/hook/store.ts +25 -0
- package/helper/src/index.ts +4 -0
- package/package.json +90 -0
- package/router/dist/Router.d.ts +4 -0
- package/router/dist/Router.mjs +56 -0
- package/router/dist/Router.mjs.map +1 -0
- package/router/dist/Router.umd.js +2 -0
- package/router/dist/Router.umd.js.map +1 -0
- package/router/dist/hook/params.d.ts +2 -0
- package/router/package.json +37 -0
- package/router/src/Router.tsx +63 -0
- package/router/src/components/Main.tsx +14 -0
- package/router/src/components/Sub.tsx +7 -0
- package/router/src/components/Sub2.tsx +17 -0
- package/router/src/example.tsx +19 -0
- package/router/src/hook/params.ts +9 -0
- package/src/diff.ts +235 -0
- package/src/examples/callback.tsx +81 -0
- package/src/examples/insert.tsx +36 -0
- package/src/examples/loop.tsx +33 -0
- package/src/examples/nested.tsx +44 -0
- package/src/examples/renew.tsx +29 -0
- package/src/examples/selectbox.tsx +42 -0
- package/src/examples/textarea.tsx +24 -0
- package/src/hook/mountCallback.ts +41 -0
- package/src/hook/ref.ts +1 -0
- package/src/hook/unmount.ts +26 -0
- package/src/hook/updateCallback.ts +29 -0
- package/src/hook/useUpdate.ts +51 -0
- package/src/index.ts +50 -0
- package/src/render.ts +409 -0
- package/src/types/index.ts +107 -0
- package/src/utils/index.ts +52 -0
- package/src/utils/predicator.ts +119 -0
- package/src/utils/universalRef.ts +137 -0
- package/src/wDom.ts +284 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { mount as h, mountCallback as i, h as v, Fragment as m } from "lithent";
|
|
2
|
+
const w = (a, s) => {
|
|
3
|
+
let t = a;
|
|
4
|
+
return {
|
|
5
|
+
get value() {
|
|
6
|
+
return t;
|
|
7
|
+
},
|
|
8
|
+
get v() {
|
|
9
|
+
return t;
|
|
10
|
+
},
|
|
11
|
+
set value(r) {
|
|
12
|
+
t = r, s();
|
|
13
|
+
},
|
|
14
|
+
set v(r) {
|
|
15
|
+
t = r, s();
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}, f = { value: {} };
|
|
19
|
+
function C() {
|
|
20
|
+
return f.value;
|
|
21
|
+
}
|
|
22
|
+
function S(a, s) {
|
|
23
|
+
f.value[a] = s;
|
|
24
|
+
}
|
|
25
|
+
const L = h((a, s, t) => {
|
|
26
|
+
const r = w("", a), g = (o) => t.find((n) => {
|
|
27
|
+
var e;
|
|
28
|
+
return ((e = n.componentProps) == null ? void 0 : e.path) === o;
|
|
29
|
+
}), P = () => t.find((o) => {
|
|
30
|
+
var n;
|
|
31
|
+
return /^:/.test(String(((n = o == null ? void 0 : o.componentProps) == null ? void 0 : n.path) || ""));
|
|
32
|
+
}), u = () => {
|
|
33
|
+
var e, c, p, l;
|
|
34
|
+
const o = window.location.hash.replace(/^[#\/]*/, "") || String(((c = (e = t[0]) == null ? void 0 : e.componentProps) == null ? void 0 : c.path) || "");
|
|
35
|
+
let n = g(o);
|
|
36
|
+
n || (n = P(), n && S(
|
|
37
|
+
String(((p = n == null ? void 0 : n.componentProps) == null ? void 0 : p.path) || "").replace(/^:/, ""),
|
|
38
|
+
o
|
|
39
|
+
)), n && (r.v = String(((l = n == null ? void 0 : n.componentProps) == null ? void 0 : l.path) || ""));
|
|
40
|
+
}, d = () => {
|
|
41
|
+
console.log("unmount"), window.removeEventListener("hashchange", u);
|
|
42
|
+
};
|
|
43
|
+
return window.addEventListener("hashchange", u), i(() => (u(), d)), () => /* @__PURE__ */ v(m, null, t.map((o) => {
|
|
44
|
+
var c, p;
|
|
45
|
+
const n = String(((c = o == null ? void 0 : o.componentProps) == null ? void 0 : c.path) || ""), e = (p = o == null ? void 0 : o.componentProps) == null ? void 0 : p.element;
|
|
46
|
+
return r.v === n ? e : null;
|
|
47
|
+
}));
|
|
48
|
+
}), R = h(function() {
|
|
49
|
+
return () => /* @__PURE__ */ v("div", null);
|
|
50
|
+
});
|
|
51
|
+
export {
|
|
52
|
+
L as Router,
|
|
53
|
+
R as RouterItem,
|
|
54
|
+
C as useParams
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=Router.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Router.mjs","sources":["../../helper/dist/lithentHelper.mjs","../src/hook/params.ts","../src/Router.tsx"],"sourcesContent":["import { mountCallback as o, updateCallback as a } from \"lithent\";\nconst s = (r, e) => {\n let t = r;\n return {\n get value() {\n return t;\n },\n get v() {\n return t;\n },\n set value(u) {\n t = u, e();\n },\n set v(u) {\n t = u, e();\n }\n };\n}, v = (r) => {\n let e = r;\n return {\n get value() {\n return e();\n },\n get v() {\n return e();\n },\n set value(t) {\n throw new Error(\"You can't change 'computed'\");\n },\n set v(t) {\n throw new Error(\"You can't change 'computed'\");\n }\n };\n}, g = (r, e, t = () => []) => {\n o(() => (r(), e)), a(() => (e(), r), t);\n}, p = (r, e) => c({\n initValue: r,\n renew: e\n}), c = ({\n initValue: r,\n renew: e\n}) => new Proxy(r, {\n get(t, u) {\n return t[u];\n },\n set(t, u, n) {\n return t[u] = n, e(), !0;\n }\n});\nexport {\n v as computed,\n g as effect,\n s as state,\n p as store\n};\n//# sourceMappingURL=lithentHelper.mjs.map\n","const routerParams = { value: {} } as { value: Record<string, string> };\n\nexport function useParams() {\n return routerParams.value;\n}\n\nexport function addParams(key: string, value: string) {\n routerParams.value[key] = value;\n}\n","import { h, Fragment, TagFunction, mountCallback, mount } from 'lithent';\nimport { state } from 'lithent/helper';\nimport { addParams } from '@/hook/params';\nexport { useParams } from '@/hook/params';\n\nexport const Router: TagFunction = mount((renew, _props, children) => {\n const targetPathString = state<string>('', renew);\n const findPath = (injectPath: string) =>\n children.find(item => item.componentProps?.path === injectPath);\n\n const findDynamicPath = () =>\n children.find(item => /^:/.test(String(item?.componentProps?.path || '')));\n\n const handleHashChange = () => {\n const injectPath =\n window.location.hash.replace(/^[#\\/]*/, '') ||\n String(children[0]?.componentProps?.path || '');\n let targetPath = findPath(injectPath);\n\n if (!targetPath) {\n targetPath = findDynamicPath();\n\n if (targetPath) {\n addParams(\n String(targetPath?.componentProps?.path || '').replace(/^:/, ''),\n injectPath\n );\n }\n }\n\n if (targetPath) {\n targetPathString.v = String(targetPath?.componentProps?.path || '');\n }\n };\n\n const removeEvent = () => {\n console.log('unmount');\n window.removeEventListener('hashchange', handleHashChange);\n };\n\n window.addEventListener('hashchange', handleHashChange);\n\n mountCallback(() => {\n handleHashChange();\n\n return removeEvent;\n });\n\n return () => (\n <Fragment>\n {children.map(item => {\n const path = String(item?.componentProps?.path || '');\n const element = item?.componentProps?.element;\n\n return targetPathString.v === path ? element : null;\n })}\n </Fragment>\n );\n});\n\nexport const RouterItem: TagFunction = mount(function () {\n return () => <div />;\n});\n"],"names":["s","r","e","u","routerParams","useParams","addParams","key","value","Router","mount","renew","_props","children","targetPathString","state","findPath","injectPath","item","_a","findDynamicPath","handleHashChange","_b","targetPath","_c","_d","removeEvent","mountCallback","h","Fragment","path","element","RouterItem"],"mappings":";AACK,MAACA,IAAI,CAACC,GAAGC,MAAM;AAClB,MAAI,IAAID;AACR,SAAO;AAAA,IACL,IAAI,QAAQ;AACV,aAAO;AAAA,IACR;AAAA,IACD,IAAI,IAAI;AACN,aAAO;AAAA,IACR;AAAA,IACD,IAAI,MAAME,GAAG;AACX,UAAIA,GAAGD;IACR;AAAA,IACD,IAAI,EAAEC,GAAG;AACP,UAAIA,GAAGD;IACR;AAAA,EACL;AACA,GCjBME,IAAe,EAAE,OAAO,CAAA;AAEvB,SAASC,IAAY;AAC1B,SAAOD,EAAa;AACtB;AAEgB,SAAAE,EAAUC,GAAaC,GAAe;AACpD,EAAAJ,EAAa,MAAMG,KAAOC;AAC5B;ACHO,MAAMC,IAAsBC,EAAM,CAACC,GAAOC,GAAQC,MAAa;AAC9D,QAAAC,IAAmBC,EAAc,IAAIJ,CAAK,GAC1CK,IAAW,CAACC,MAChBJ,EAAS,KAAK,CAAQK,MAAA;;AAAA,aAAAC,IAAAD,EAAK,mBAAL,gBAAAC,EAAqB,UAASF;AAAA,GAAU,GAE1DG,IAAkB,MACtBP,EAAS,KAAK,CAAQK,MAAA;;AAAA,gBAAK,KAAK,SAAOC,IAAAD,KAAA,gBAAAA,EAAM,mBAAN,gBAAAC,EAAsB,SAAQ,EAAE,CAAC;AAAA,GAAC,GAErEE,IAAmB,MAAM;;AAC7B,UAAMJ,IACJ,OAAO,SAAS,KAAK,QAAQ,WAAW,EAAE,KAC1C,SAAOK,KAAAH,IAAAN,EAAS,OAAT,gBAAAM,EAAa,mBAAb,gBAAAG,EAA6B,SAAQ,EAAE;AAC5C,QAAAC,IAAaP,EAASC,CAAU;AAEpC,IAAKM,MACHA,IAAaH,EAAgB,GAEzBG,KACFjB;AAAA,MACE,SAAOkB,IAAAD,KAAA,gBAAAA,EAAY,mBAAZ,gBAAAC,EAA4B,SAAQ,EAAE,EAAE,QAAQ,MAAM,EAAE;AAAA,MAC/DP;AAAA,IAAA,IAKFM,MACFT,EAAiB,IAAI,SAAOW,IAAAF,KAAA,gBAAAA,EAAY,mBAAZ,gBAAAE,EAA4B,SAAQ,EAAE;AAAA,EACpE,GAGIC,IAAc,MAAM;AACxB,YAAQ,IAAI,SAAS,GACd,OAAA,oBAAoB,cAAcL,CAAgB;AAAA,EAAA;AAGpD,gBAAA,iBAAiB,cAAcA,CAAgB,GAEtDM,EAAc,OACKN,KAEVK,EACR,GAEM,MACL,gBAAAE,EAACC,GACE,MAAAhB,EAAS,IAAI,CAAQK,MAAA;;AACpB,UAAMY,IAAO,SAAOX,IAAAD,KAAA,gBAAAA,EAAM,mBAAN,gBAAAC,EAAsB,SAAQ,EAAE,GAC9CY,KAAUT,IAAAJ,KAAA,gBAAAA,EAAM,mBAAN,gBAAAI,EAAsB;AAE/B,WAAAR,EAAiB,MAAMgB,IAAOC,IAAU;AAAA,EAChD,CAAA,CACH;AAEJ,CAAC,GAEYC,IAA0BtB,EAAM,WAAY;AAChD,SAAA,wBAAO,OAAI,IAAA;AACpB,CAAC;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(function(t,o){typeof exports=="object"&&typeof module<"u"?o(exports,require("lithent")):typeof define=="function"&&define.amd?define(["exports","lithent"],o):(t=typeof globalThis<"u"?globalThis:t||self,o(t.Router={},t.lithent))})(this,function(t,o){"use strict";const h=(a,c)=>{let r=a;return{get value(){return r},get v(){return r},set value(u){r=u,c()},set v(u){r=u,c()}}},d={value:{}};function v(){return d.value}function m(a,c){d.value[a]=c}const P=o.mount((a,c,r)=>{const u=h("",a),S=e=>r.find(n=>{var s;return((s=n.componentProps)==null?void 0:s.path)===e}),w=()=>r.find(e=>{var n;return/^:/.test(String(((n=e==null?void 0:e.componentProps)==null?void 0:n.path)||""))}),l=()=>{var s,p,i,f;const e=window.location.hash.replace(/^[#\/]*/,"")||String(((p=(s=r[0])==null?void 0:s.componentProps)==null?void 0:p.path)||"");let n=S(e);n||(n=w(),n&&m(String(((i=n==null?void 0:n.componentProps)==null?void 0:i.path)||"").replace(/^:/,""),e)),n&&(u.v=String(((f=n==null?void 0:n.componentProps)==null?void 0:f.path)||""))},R=()=>{console.log("unmount"),window.removeEventListener("hashchange",l)};return window.addEventListener("hashchange",l),o.mountCallback(()=>(l(),R)),()=>o.h(o.Fragment,null,r.map(e=>{var p,i;const n=String(((p=e==null?void 0:e.componentProps)==null?void 0:p.path)||""),s=(i=e==null?void 0:e.componentProps)==null?void 0:i.element;return u.v===n?s:null}))}),g=o.mount(function(){return()=>o.h("div",null)});t.Router=P,t.RouterItem=g,t.useParams=v,Object.defineProperties(t,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
|
2
|
+
//# sourceMappingURL=Router.umd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Router.umd.js","sources":["../../helper/dist/lithentHelper.mjs","../src/hook/params.ts","../src/Router.tsx"],"sourcesContent":["import { mountCallback as o, updateCallback as a } from \"lithent\";\nconst s = (r, e) => {\n let t = r;\n return {\n get value() {\n return t;\n },\n get v() {\n return t;\n },\n set value(u) {\n t = u, e();\n },\n set v(u) {\n t = u, e();\n }\n };\n}, v = (r) => {\n let e = r;\n return {\n get value() {\n return e();\n },\n get v() {\n return e();\n },\n set value(t) {\n throw new Error(\"You can't change 'computed'\");\n },\n set v(t) {\n throw new Error(\"You can't change 'computed'\");\n }\n };\n}, g = (r, e, t = () => []) => {\n o(() => (r(), e)), a(() => (e(), r), t);\n}, p = (r, e) => c({\n initValue: r,\n renew: e\n}), c = ({\n initValue: r,\n renew: e\n}) => new Proxy(r, {\n get(t, u) {\n return t[u];\n },\n set(t, u, n) {\n return t[u] = n, e(), !0;\n }\n});\nexport {\n v as computed,\n g as effect,\n s as state,\n p as store\n};\n//# sourceMappingURL=lithentHelper.mjs.map\n","const routerParams = { value: {} } as { value: Record<string, string> };\n\nexport function useParams() {\n return routerParams.value;\n}\n\nexport function addParams(key: string, value: string) {\n routerParams.value[key] = value;\n}\n","import { h, Fragment, TagFunction, mountCallback, mount } from 'lithent';\nimport { state } from 'lithent/helper';\nimport { addParams } from '@/hook/params';\nexport { useParams } from '@/hook/params';\n\nexport const Router: TagFunction = mount((renew, _props, children) => {\n const targetPathString = state<string>('', renew);\n const findPath = (injectPath: string) =>\n children.find(item => item.componentProps?.path === injectPath);\n\n const findDynamicPath = () =>\n children.find(item => /^:/.test(String(item?.componentProps?.path || '')));\n\n const handleHashChange = () => {\n const injectPath =\n window.location.hash.replace(/^[#\\/]*/, '') ||\n String(children[0]?.componentProps?.path || '');\n let targetPath = findPath(injectPath);\n\n if (!targetPath) {\n targetPath = findDynamicPath();\n\n if (targetPath) {\n addParams(\n String(targetPath?.componentProps?.path || '').replace(/^:/, ''),\n injectPath\n );\n }\n }\n\n if (targetPath) {\n targetPathString.v = String(targetPath?.componentProps?.path || '');\n }\n };\n\n const removeEvent = () => {\n console.log('unmount');\n window.removeEventListener('hashchange', handleHashChange);\n };\n\n window.addEventListener('hashchange', handleHashChange);\n\n mountCallback(() => {\n handleHashChange();\n\n return removeEvent;\n });\n\n return () => (\n <Fragment>\n {children.map(item => {\n const path = String(item?.componentProps?.path || '');\n const element = item?.componentProps?.element;\n\n return targetPathString.v === path ? element : null;\n })}\n </Fragment>\n );\n});\n\nexport const RouterItem: TagFunction = mount(function () {\n return () => <div />;\n});\n"],"names":["s","r","e","t","routerParams","useParams","addParams","key","value","Router","mount","renew","_props","children","targetPathString","state","findPath","injectPath","item","_a","findDynamicPath","handleHashChange","_b","targetPath","_c","_d","removeEvent","mountCallback","h","Fragment","path","element","RouterItem"],"mappings":"uQACK,MAACA,EAAI,CAACC,EAAGC,IAAM,CAClB,IAAIC,EAAIF,EACR,MAAO,CACL,IAAI,OAAQ,CACV,OAAOE,CACR,EACD,IAAI,GAAI,CACN,OAAOA,CACR,EACD,IAAI,MAAM,EAAG,CACXA,EAAI,EAAGD,GACR,EACD,IAAI,EAAE,EAAG,CACPC,EAAI,EAAGD,GACR,CACL,CACA,ECjBME,EAAe,CAAE,MAAO,CAAA,GAEvB,SAASC,GAAY,CAC1B,OAAOD,EAAa,KACtB,CAEgB,SAAAE,EAAUC,EAAaC,EAAe,CACpDJ,EAAa,MAAMG,GAAOC,CAC5B,CCHa,MAAAC,EAAsBC,EAAAA,MAAM,CAACC,EAAOC,EAAQC,IAAa,CAC9D,MAAAC,EAAmBC,EAAc,GAAIJ,CAAK,EAC1CK,EAAYC,GAChBJ,EAAS,KAAaK,GAAA,OAAA,QAAAC,EAAAD,EAAK,iBAAL,YAAAC,EAAqB,QAASF,EAAU,EAE1DG,EAAkB,IACtBP,EAAS,KAAaK,GAAA,OAAA,WAAK,KAAK,SAAOC,EAAAD,GAAA,YAAAA,EAAM,iBAAN,YAAAC,EAAsB,OAAQ,EAAE,CAAC,EAAC,EAErEE,EAAmB,IAAM,aAC7B,MAAMJ,EACJ,OAAO,SAAS,KAAK,QAAQ,UAAW,EAAE,GAC1C,SAAOK,GAAAH,EAAAN,EAAS,KAAT,YAAAM,EAAa,iBAAb,YAAAG,EAA6B,OAAQ,EAAE,EAC5C,IAAAC,EAAaP,EAASC,CAAU,EAE/BM,IACHA,EAAaH,EAAgB,EAEzBG,GACFjB,EACE,SAAOkB,EAAAD,GAAA,YAAAA,EAAY,iBAAZ,YAAAC,EAA4B,OAAQ,EAAE,EAAE,QAAQ,KAAM,EAAE,EAC/DP,CAAA,GAKFM,IACFT,EAAiB,EAAI,SAAOW,EAAAF,GAAA,YAAAA,EAAY,iBAAZ,YAAAE,EAA4B,OAAQ,EAAE,EACpE,EAGIC,EAAc,IAAM,CACxB,QAAQ,IAAI,SAAS,EACd,OAAA,oBAAoB,aAAcL,CAAgB,CAAA,EAGpD,cAAA,iBAAiB,aAAcA,CAAgB,EAEtDM,EAAAA,cAAc,KACKN,IAEVK,EACR,EAEM,IACLE,EAAA,EAACC,WACE,KAAAhB,EAAS,IAAYK,GAAA,SACpB,MAAMY,EAAO,SAAOX,EAAAD,GAAA,YAAAA,EAAM,iBAAN,YAAAC,EAAsB,OAAQ,EAAE,EAC9CY,GAAUT,EAAAJ,GAAA,YAAAA,EAAM,iBAAN,YAAAI,EAAsB,QAE/B,OAAAR,EAAiB,IAAMgB,EAAOC,EAAU,IAChD,CAAA,CACH,CAEJ,CAAC,EAEYC,EAA0BtB,QAAM,UAAY,CAChD,MAAA,QAAO,MAAI,IAAA,CACpB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lithent-router",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.6.0",
|
|
5
|
+
"description": "lithent-router",
|
|
6
|
+
"main": "./dist/Router.umd.js",
|
|
7
|
+
"module": "./dist/Router.mjs",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/Router.mjs",
|
|
11
|
+
"require": "./dist/Router.umd.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"types": "./dist/Router.d.ts",
|
|
15
|
+
"scripts": {
|
|
16
|
+
"dev": "vite",
|
|
17
|
+
"build": "vite build"
|
|
18
|
+
},
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"lithent": "workspace:*",
|
|
21
|
+
"lithent-helper": "workspace:*"
|
|
22
|
+
},
|
|
23
|
+
"author": "superlucky84",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https@github.com:superlucky84/lithent.git",
|
|
28
|
+
"directory": "router"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/superlucky84/lithent/tree/master/router",
|
|
31
|
+
"keywords": [
|
|
32
|
+
"lithent"
|
|
33
|
+
],
|
|
34
|
+
"volta": {
|
|
35
|
+
"node": "20.3.0"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { h, Fragment, TagFunction, mountCallback, mount } from 'lithent';
|
|
2
|
+
import { state } from 'lithent/helper';
|
|
3
|
+
import { addParams } from '@/hook/params';
|
|
4
|
+
export { useParams } from '@/hook/params';
|
|
5
|
+
|
|
6
|
+
export const Router: TagFunction = mount((renew, _props, children) => {
|
|
7
|
+
const targetPathString = state<string>('', renew);
|
|
8
|
+
const findPath = (injectPath: string) =>
|
|
9
|
+
children.find(item => item.componentProps?.path === injectPath);
|
|
10
|
+
|
|
11
|
+
const findDynamicPath = () =>
|
|
12
|
+
children.find(item => /^:/.test(String(item?.componentProps?.path || '')));
|
|
13
|
+
|
|
14
|
+
const handleHashChange = () => {
|
|
15
|
+
const injectPath =
|
|
16
|
+
window.location.hash.replace(/^[#\/]*/, '') ||
|
|
17
|
+
String(children[0]?.componentProps?.path || '');
|
|
18
|
+
let targetPath = findPath(injectPath);
|
|
19
|
+
|
|
20
|
+
if (!targetPath) {
|
|
21
|
+
targetPath = findDynamicPath();
|
|
22
|
+
|
|
23
|
+
if (targetPath) {
|
|
24
|
+
addParams(
|
|
25
|
+
String(targetPath?.componentProps?.path || '').replace(/^:/, ''),
|
|
26
|
+
injectPath
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (targetPath) {
|
|
32
|
+
targetPathString.v = String(targetPath?.componentProps?.path || '');
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const removeEvent = () => {
|
|
37
|
+
console.log('unmount');
|
|
38
|
+
window.removeEventListener('hashchange', handleHashChange);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
window.addEventListener('hashchange', handleHashChange);
|
|
42
|
+
|
|
43
|
+
mountCallback(() => {
|
|
44
|
+
handleHashChange();
|
|
45
|
+
|
|
46
|
+
return removeEvent;
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return () => (
|
|
50
|
+
<Fragment>
|
|
51
|
+
{children.map(item => {
|
|
52
|
+
const path = String(item?.componentProps?.path || '');
|
|
53
|
+
const element = item?.componentProps?.element;
|
|
54
|
+
|
|
55
|
+
return targetPathString.v === path ? element : null;
|
|
56
|
+
})}
|
|
57
|
+
</Fragment>
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
export const RouterItem: TagFunction = mount(function () {
|
|
62
|
+
return () => <div />;
|
|
63
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { h, mount, TagFunction } from 'lithent';
|
|
2
|
+
import { useParams } from '@/hook/params';
|
|
3
|
+
|
|
4
|
+
const Sub2: TagFunction = mount(function () {
|
|
5
|
+
const params = useParams();
|
|
6
|
+
const handle = () => {
|
|
7
|
+
console.log('red', params);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
return () => (
|
|
11
|
+
<div style={{ color: 'red' }} onClick={handle}>
|
|
12
|
+
Sub222
|
|
13
|
+
</div>
|
|
14
|
+
);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export default Sub2;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { h, Fragment, render, mount } from 'lithent';
|
|
2
|
+
import { Router, RouterItem } from '@/Router';
|
|
3
|
+
import Main from '@/components/Main';
|
|
4
|
+
import Sub from '@/components/Sub';
|
|
5
|
+
import Sub2 from '@/components/Sub2';
|
|
6
|
+
|
|
7
|
+
const Root = mount(function () {
|
|
8
|
+
return () => (
|
|
9
|
+
<Fragment>
|
|
10
|
+
<Router>
|
|
11
|
+
<RouterItem path="main" element={<Main />} />
|
|
12
|
+
<RouterItem path="sub" element={<Sub />} />
|
|
13
|
+
<RouterItem path=":sub" element={<Sub2 />} />
|
|
14
|
+
</Router>
|
|
15
|
+
</Fragment>
|
|
16
|
+
);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
render(<Root />, document.getElementById('root'));
|
package/src/diff.ts
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 변경점의 컴포넌트로 부터 기존트리와 상태를 비교하며 새로 가상돔 트리를 새로 만든다.
|
|
3
|
+
* (오리지널 가상돔으로 부터 유의미한 상태를 유지해야 하는 경우를 판별하여 새로운 트리를 만듬)
|
|
4
|
+
*
|
|
5
|
+
* 1. 동일한 트리의 위치해 있고 오리지널과 컴포넌트의 타입이 같은경우 기존 상태를 계승한다.
|
|
6
|
+
* 2. 동일한 컴포넌트가 아니라고 판단되는 경우에는 기존 상태를 무시하는 새로운 트리를 생성한다.
|
|
7
|
+
* 3. fragment타입의 경우에는 children의 갯수까지 같아야지 같은 타입이라고 판단한다.
|
|
8
|
+
* 4. loop타입의 자식들은 같은 키값을 가졌는지로 동일한지 판단하며 키값이 없을경우 fragment타입처럼 취급한다.
|
|
9
|
+
*/
|
|
10
|
+
import { WDom, TagFunctionResolver, RenderType } from '@/types';
|
|
11
|
+
import { checkCustemComponentFunction } from '@/utils/predicator';
|
|
12
|
+
import { getParent, reRender } from '@/utils';
|
|
13
|
+
import { recursiveRemoveEvent } from '@/render';
|
|
14
|
+
import {
|
|
15
|
+
checkEmptyElement,
|
|
16
|
+
checkSameWDomWithOriginal,
|
|
17
|
+
getWDomType,
|
|
18
|
+
checkExisty,
|
|
19
|
+
} from '@/utils/predicator';
|
|
20
|
+
|
|
21
|
+
import { runUnmountQueueFromWDom } from '@/hook/unmount';
|
|
22
|
+
import { removeNodeChildKey } from '@/utils/universalRef';
|
|
23
|
+
|
|
24
|
+
type DiffPrimaryParam = {
|
|
25
|
+
originalWDom?: WDom;
|
|
26
|
+
newWDom: WDom | TagFunctionResolver;
|
|
27
|
+
isSameType: boolean;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
type DiffSecondeParam = {
|
|
31
|
+
originalWDom?: WDom;
|
|
32
|
+
newWDom: WDom;
|
|
33
|
+
isSameType: boolean;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const makeNewWDomTree = ({
|
|
37
|
+
originalWDom,
|
|
38
|
+
newWDom,
|
|
39
|
+
}: {
|
|
40
|
+
originalWDom?: WDom;
|
|
41
|
+
newWDom: WDom | TagFunctionResolver;
|
|
42
|
+
}) => {
|
|
43
|
+
const type = getWDomType(newWDom);
|
|
44
|
+
|
|
45
|
+
if (!type) {
|
|
46
|
+
throw new Error('Unknown type wdom');
|
|
47
|
+
}
|
|
48
|
+
const isSameType = checkSameWDomWithOriginal[type]({ originalWDom, newWDom });
|
|
49
|
+
|
|
50
|
+
const result = remakeNewWDom({ originalWDom, newWDom, isSameType });
|
|
51
|
+
|
|
52
|
+
if (result?.nodeChildKey) {
|
|
53
|
+
removeNodeChildKey(result.nodeChildKey);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return result;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const remakeNewWDom = ({
|
|
60
|
+
newWDom,
|
|
61
|
+
originalWDom,
|
|
62
|
+
isSameType,
|
|
63
|
+
}: DiffPrimaryParam) => {
|
|
64
|
+
const remakeWDom = generalize({ newWDom, originalWDom, isSameType });
|
|
65
|
+
|
|
66
|
+
remakeWDom.children = remakeChildrenForDiff({
|
|
67
|
+
isSameType,
|
|
68
|
+
newWDom: remakeWDom,
|
|
69
|
+
originalWDom,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const needRerender = addReRenderTypeProperty({
|
|
73
|
+
originalWDom,
|
|
74
|
+
newWDom: remakeWDom,
|
|
75
|
+
isSameType,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
remakeWDom.needRerender = needRerender;
|
|
79
|
+
|
|
80
|
+
if (needRerender !== 'A' && originalWDom) {
|
|
81
|
+
remakeWDom.el = originalWDom.el;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (
|
|
85
|
+
needRerender &&
|
|
86
|
+
['D', 'R', 'SR'].includes(needRerender) &&
|
|
87
|
+
originalWDom?.componentKey
|
|
88
|
+
) {
|
|
89
|
+
runUnmountQueueFromWDom(originalWDom);
|
|
90
|
+
recursiveRemoveEvent(originalWDom);
|
|
91
|
+
remakeWDom.children = originalWDom.children;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
remakeWDom.oldProps = originalWDom?.props;
|
|
95
|
+
|
|
96
|
+
return remakeWDom;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const addReRenderTypeProperty = ({
|
|
100
|
+
originalWDom,
|
|
101
|
+
newWDom,
|
|
102
|
+
isSameType,
|
|
103
|
+
}: DiffSecondeParam): RenderType | undefined => {
|
|
104
|
+
const existOriginalWDom = originalWDom && originalWDom.type;
|
|
105
|
+
const isEmptyElement = checkEmptyElement(newWDom);
|
|
106
|
+
const isRoot = !newWDom.getParent;
|
|
107
|
+
const parentType = !isRoot && getParent(newWDom).type;
|
|
108
|
+
const key = getKey(newWDom);
|
|
109
|
+
const isKeyCheckedWDom = parentType === 'loop' && checkExisty(key);
|
|
110
|
+
const isSameText =
|
|
111
|
+
newWDom.type === 'text' &&
|
|
112
|
+
isSameType &&
|
|
113
|
+
newWDom.text === originalWDom?.text;
|
|
114
|
+
|
|
115
|
+
let result: RenderType | undefined;
|
|
116
|
+
if (isEmptyElement) {
|
|
117
|
+
result = 'D';
|
|
118
|
+
} else if (isSameText) {
|
|
119
|
+
result = 'N';
|
|
120
|
+
} else if (!existOriginalWDom) {
|
|
121
|
+
result = 'A';
|
|
122
|
+
} else if (isSameType) {
|
|
123
|
+
result = isKeyCheckedWDom ? 'SU' : 'U';
|
|
124
|
+
} else {
|
|
125
|
+
result = isKeyCheckedWDom ? 'SR' : 'R';
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return result;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const generalize = ({
|
|
132
|
+
newWDom,
|
|
133
|
+
originalWDom,
|
|
134
|
+
isSameType,
|
|
135
|
+
}: DiffPrimaryParam): WDom => {
|
|
136
|
+
if (checkCustemComponentFunction(newWDom)) {
|
|
137
|
+
return isSameType && originalWDom
|
|
138
|
+
? reRender(originalWDom, newWDom)
|
|
139
|
+
: newWDom.resolve();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return newWDom;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const remakeChildrenForDiff = ({
|
|
146
|
+
isSameType,
|
|
147
|
+
newWDom,
|
|
148
|
+
originalWDom,
|
|
149
|
+
}: DiffSecondeParam) =>
|
|
150
|
+
isSameType && originalWDom
|
|
151
|
+
? remakeChildrenForUpdate(newWDom, originalWDom)
|
|
152
|
+
: remakeChildrenForAdd(newWDom);
|
|
153
|
+
|
|
154
|
+
const remakeChildrenForAdd = (newWDom: WDom) =>
|
|
155
|
+
(newWDom.children || []).map((item: WDom) => {
|
|
156
|
+
const childItem = makeNewWDomTree({ newWDom: item });
|
|
157
|
+
|
|
158
|
+
childItem.getParent = () => newWDom;
|
|
159
|
+
|
|
160
|
+
return childItem;
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
const remakeChildrenForUpdate = (newWDom: WDom, originalWDom: WDom) => {
|
|
164
|
+
if (
|
|
165
|
+
newWDom.type === 'loop' &&
|
|
166
|
+
checkExisty(getKey((newWDom.children || [])[0]))
|
|
167
|
+
) {
|
|
168
|
+
return remakeChildrenForLoopUpdate(newWDom, originalWDom);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return (newWDom.children || []).map((item: WDom, index: number) => {
|
|
172
|
+
const childItem = makeNewWDomTree({
|
|
173
|
+
newWDom: item,
|
|
174
|
+
originalWDom: (originalWDom.children || [])[index],
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
childItem.getParent = () => newWDom;
|
|
178
|
+
|
|
179
|
+
return childItem;
|
|
180
|
+
});
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const remakeChildrenForLoopUpdate = (newWDom: WDom, originalWDom: WDom) => {
|
|
184
|
+
const { remakedChildren, unUsedChildren } = diffLoopChildren(
|
|
185
|
+
newWDom,
|
|
186
|
+
originalWDom
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
unUsedChildren.map(unusedItem => {
|
|
190
|
+
const el = unusedItem.el;
|
|
191
|
+
|
|
192
|
+
if (el && el.parentNode) {
|
|
193
|
+
el.parentNode.removeChild(el);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
return remakedChildren;
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const diffLoopChildren = (newWDom: WDom, originalWDom: WDom) => {
|
|
201
|
+
const newChildren = [...(newWDom.children || [])];
|
|
202
|
+
const originalChildren = [...(originalWDom.children || [])];
|
|
203
|
+
|
|
204
|
+
const remakedChildren = newChildren.map(item => {
|
|
205
|
+
const originalItem = findSameKeyOriginalItem(item, originalChildren);
|
|
206
|
+
const childItem = makeNewWDomTree({
|
|
207
|
+
newWDom: item,
|
|
208
|
+
originalWDom: originalItem,
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
if (originalItem) {
|
|
212
|
+
originalChildren.splice(originalChildren.indexOf(originalItem), 1);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
childItem.getParent = () => newWDom;
|
|
216
|
+
|
|
217
|
+
return childItem;
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
return {
|
|
221
|
+
remakedChildren,
|
|
222
|
+
unUsedChildren: originalChildren,
|
|
223
|
+
};
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const findSameKeyOriginalItem = (item: WDom, originalChildren: WDom[]) => {
|
|
227
|
+
const key = getKey(item);
|
|
228
|
+
|
|
229
|
+
return originalChildren.find(
|
|
230
|
+
orignalChildItem => getKey(orignalChildItem) === key
|
|
231
|
+
);
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const getKey = (target: WDom) =>
|
|
235
|
+
target?.componentProps?.key ?? target?.props?.key;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// example.jsx
|
|
2
|
+
import { h, Fragment, render, mount, mountCallback } from '@/index';
|
|
3
|
+
|
|
4
|
+
const Depth4 = mount(() => {
|
|
5
|
+
mountCallback(() => {
|
|
6
|
+
console.log('MOUNT - Depth4');
|
|
7
|
+
return () => console.log('UNMOUNT - Depth4');
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
return () => (
|
|
11
|
+
<Fragment>
|
|
12
|
+
<div>depth4</div>
|
|
13
|
+
</Fragment>
|
|
14
|
+
);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const Depth3 = mount(() => {
|
|
18
|
+
mountCallback(() => {
|
|
19
|
+
console.log('MOUNT - Depth3');
|
|
20
|
+
return () => console.log('UNMOUNT - Depth3');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return () => (
|
|
24
|
+
<Fragment>
|
|
25
|
+
<div>depth3</div>
|
|
26
|
+
<Depth4 />
|
|
27
|
+
</Fragment>
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const Depth2 = mount(() => {
|
|
32
|
+
mountCallback(() => {
|
|
33
|
+
console.log('MOUNT - Depth2');
|
|
34
|
+
return () => console.log('UNMOUNT - Depth2');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
return () => (
|
|
38
|
+
<Fragment>
|
|
39
|
+
<div>depth2</div>
|
|
40
|
+
<Depth3 />
|
|
41
|
+
</Fragment>
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const Depth1 = mount(() => {
|
|
46
|
+
mountCallback(() => {
|
|
47
|
+
console.log('MOUNT - Depth1');
|
|
48
|
+
return () => console.log('UNMOUNT - Depth1');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return () => (
|
|
52
|
+
<Fragment>
|
|
53
|
+
<div>depth1</div>
|
|
54
|
+
<Depth2 />
|
|
55
|
+
</Fragment>
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const CallbackRoot = mount(renew => {
|
|
60
|
+
let isShow = true;
|
|
61
|
+
|
|
62
|
+
const toggle = () => {
|
|
63
|
+
isShow = !isShow;
|
|
64
|
+
console.log(isShow);
|
|
65
|
+
renew();
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return () => (
|
|
69
|
+
<Fragment>
|
|
70
|
+
<button onClick={toggle}>TOGGLE</button>
|
|
71
|
+
{isShow ? <Depth1 /> : null}
|
|
72
|
+
</Fragment>
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const Root = <CallbackRoot />;
|
|
77
|
+
|
|
78
|
+
//@ts-ignore
|
|
79
|
+
window.root = Root;
|
|
80
|
+
|
|
81
|
+
render(Root, document.getElementById('root'));
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// example.jsx
|
|
2
|
+
import { h, Fragment, render, mount } from '@/index';
|
|
3
|
+
|
|
4
|
+
const Root = mount(function (renew) {
|
|
5
|
+
let showFive = false;
|
|
6
|
+
let showSix = false;
|
|
7
|
+
|
|
8
|
+
const toggleFive = () => {
|
|
9
|
+
showFive = !showFive;
|
|
10
|
+
renew();
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const toggleSix = () => {
|
|
14
|
+
showSix = !showSix;
|
|
15
|
+
renew();
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
return () => (
|
|
19
|
+
<Fragment>
|
|
20
|
+
<li>
|
|
21
|
+
4 <button onClick={toggleFive}>ShowFive</button>
|
|
22
|
+
<button onClick={toggleSix}>ShowSix</button>
|
|
23
|
+
</li>
|
|
24
|
+
{showFive ? <li>5</li> : null}
|
|
25
|
+
{showSix ? <li>6</li> : null}
|
|
26
|
+
<li>7</li>
|
|
27
|
+
</Fragment>
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const R = <Root />;
|
|
32
|
+
|
|
33
|
+
//@ts-ignore
|
|
34
|
+
window.root = R;
|
|
35
|
+
|
|
36
|
+
render(R, document.getElementById('list-root'), document.getElementById('8'));
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { mount, render, Fragment, h } from '@/index';
|
|
2
|
+
|
|
3
|
+
const Loop = mount(function (renew) {
|
|
4
|
+
let list: { key: number; value: string }[] = [
|
|
5
|
+
{ key: 1, value: '일' },
|
|
6
|
+
{ key: 2, value: '이' },
|
|
7
|
+
{ key: 3, value: '삼' },
|
|
8
|
+
{ key: 4, value: '사' },
|
|
9
|
+
];
|
|
10
|
+
const handle = () => {
|
|
11
|
+
list = [
|
|
12
|
+
{ key: 3, value: '삼삼' },
|
|
13
|
+
{ key: 2, value: '이이' },
|
|
14
|
+
];
|
|
15
|
+
renew();
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
return () => (
|
|
19
|
+
<Fragment>
|
|
20
|
+
<button onClick={handle}>handle</button>
|
|
21
|
+
{list.map(item => (
|
|
22
|
+
<div key={item.key}>{item.value}</div>
|
|
23
|
+
))}
|
|
24
|
+
</Fragment>
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const Root = <Loop />;
|
|
29
|
+
|
|
30
|
+
//@ts-ignore
|
|
31
|
+
window.root = Root;
|
|
32
|
+
|
|
33
|
+
render(Root, document.getElementById('root'));
|