uraniyum 1.0.0 → 1.0.1
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/dist/helpers.d.ts +2 -1
- package/dist/index.esm.js +46 -31
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +46 -31
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/router.d.ts +4 -2
- package/package.json +2 -2
- package/src/helpers.ts +13 -17
- package/src/router.ts +43 -14
package/dist/helpers.d.ts
CHANGED
package/dist/index.esm.js
CHANGED
|
@@ -41,47 +41,62 @@ const tags = new Proxy({}, {
|
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
function router(routes) {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
const container = document.createElement("div");
|
|
45
|
+
const routePatterns = [];
|
|
46
|
+
for (const path in routes) {
|
|
47
|
+
const keys = [];
|
|
48
|
+
const pattern = path
|
|
49
|
+
.replace(/\/:[^\/]+/g, (match) => {
|
|
50
|
+
keys.push(match.slice(2));
|
|
51
|
+
return "/([^/]+)";
|
|
52
|
+
})
|
|
53
|
+
.replace(/\*/g, ".*");
|
|
54
|
+
const regex = new RegExp(`^${pattern}$`);
|
|
55
|
+
routePatterns.push({ regex, keys, handler: routes[path] });
|
|
56
|
+
}
|
|
47
57
|
const renderRoute = () => {
|
|
48
58
|
const path = window.location.pathname;
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
let matched = false;
|
|
60
|
+
for (const { regex, keys, handler } of routePatterns) {
|
|
61
|
+
const match = path.match(regex);
|
|
62
|
+
if (match) {
|
|
63
|
+
const params = {};
|
|
64
|
+
keys.forEach((key, i) => {
|
|
65
|
+
params[key] = match[i + 1];
|
|
66
|
+
});
|
|
67
|
+
container.innerHTML = "";
|
|
68
|
+
container.appendChild(handler(params));
|
|
69
|
+
matched = true;
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (!matched && routes["*"]) {
|
|
74
|
+
container.innerHTML = "";
|
|
75
|
+
container.appendChild(routes["*"]());
|
|
76
|
+
}
|
|
56
77
|
};
|
|
57
78
|
window.addEventListener("popstate", renderRoute);
|
|
79
|
+
renderRoute();
|
|
58
80
|
return {
|
|
59
81
|
render: renderRoute,
|
|
60
|
-
|
|
61
|
-
history.pushState(null, "", path);
|
|
62
|
-
renderRoute();
|
|
63
|
-
}
|
|
82
|
+
element: container
|
|
64
83
|
};
|
|
65
84
|
}
|
|
66
85
|
|
|
67
|
-
function add(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (typeof c === "function") {
|
|
73
|
-
const el = c();
|
|
74
|
-
if (!(el instanceof Node)) {
|
|
75
|
-
throw new Error("Component function must return an HTMLElement");
|
|
76
|
-
}
|
|
77
|
-
app.appendChild(el);
|
|
78
|
-
}
|
|
79
|
-
else if ("render" in c && typeof c.render === "function") {
|
|
80
|
-
c.render();
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
throw new Error("Invalid component passed to add()");
|
|
86
|
+
function add(component) {
|
|
87
|
+
if (typeof component === "function") {
|
|
88
|
+
const el = component();
|
|
89
|
+
if (!(el instanceof Node)) {
|
|
90
|
+
throw new Error("Component function must return an HTMLElement");
|
|
84
91
|
}
|
|
92
|
+
document.body.appendChild(el);
|
|
93
|
+
}
|
|
94
|
+
else if ("render" in component && typeof component.render === "function") {
|
|
95
|
+
document.body.appendChild(component.element || document.createElement("div"));
|
|
96
|
+
component.render();
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
throw new Error("Invalid component passed to add()");
|
|
85
100
|
}
|
|
86
101
|
}
|
|
87
102
|
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/state.ts","../src/tags.ts","../src/router.ts","../src/helpers.ts"],"sourcesContent":["export function state<T>(initial: T) {\r\n let value = initial\r\n const listeners: Function[] = []\r\n\r\n const set = (newValue: T) => {\r\n value = newValue\r\n listeners.forEach(fn => fn(value))\r\n }\r\n\r\n const get = () => value\r\n\r\n const subscribe = (fn: Function) => {\r\n listeners.push(fn)\r\n return () => {\r\n const index = listeners.indexOf(fn)\r\n if (index > -1) listeners.splice(index, 1)\r\n }\r\n }\r\n\r\n return { get, set, subscribe }\r\n}","export const tags = new Proxy({}, {\r\n get(_, tag: string) {\r\n return (attrsOrChild?: any, ...children: any[]) => {\r\n const el = document.createElement(tag)\r\n if (attrsOrChild && typeof attrsOrChild === 'object' && !Array.isArray(attrsOrChild) && !(attrsOrChild instanceof Node)) {\r\n for (const [k, v] of Object.entries(attrsOrChild)) {\r\n el.setAttribute(k, v as string)\r\n }\r\n } else if (attrsOrChild != null) {\r\n children.unshift(attrsOrChild)\r\n }\r\n\r\n for (const child of children.flat()) {\r\n if (child instanceof Node) el.appendChild(child)\r\n else el.appendChild(document.createTextNode(String(child)))\r\n }\r\n return el\r\n }\r\n }\r\n})","
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/state.ts","../src/tags.ts","../src/router.ts","../src/helpers.ts"],"sourcesContent":["export function state<T>(initial: T) {\r\n let value = initial\r\n const listeners: Function[] = []\r\n\r\n const set = (newValue: T) => {\r\n value = newValue\r\n listeners.forEach(fn => fn(value))\r\n }\r\n\r\n const get = () => value\r\n\r\n const subscribe = (fn: Function) => {\r\n listeners.push(fn)\r\n return () => {\r\n const index = listeners.indexOf(fn)\r\n if (index > -1) listeners.splice(index, 1)\r\n }\r\n }\r\n\r\n return { get, set, subscribe }\r\n}","export const tags = new Proxy({}, {\r\n get(_, tag: string) {\r\n return (attrsOrChild?: any, ...children: any[]) => {\r\n const el = document.createElement(tag)\r\n if (attrsOrChild && typeof attrsOrChild === 'object' && !Array.isArray(attrsOrChild) && !(attrsOrChild instanceof Node)) {\r\n for (const [k, v] of Object.entries(attrsOrChild)) {\r\n el.setAttribute(k, v as string)\r\n }\r\n } else if (attrsOrChild != null) {\r\n children.unshift(attrsOrChild)\r\n }\r\n\r\n for (const child of children.flat()) {\r\n if (child instanceof Node) el.appendChild(child)\r\n else el.appendChild(document.createTextNode(String(child)))\r\n }\r\n return el\r\n }\r\n }\r\n})","type RouteHandler = (params?: Record<string, string>) => HTMLElement\r\n\r\nexport function router(routes: Record<string, RouteHandler>) {\r\n const container = document.createElement(\"div\")\r\n const routePatterns: {\r\n regex: RegExp\r\n keys: string[]\r\n handler: RouteHandler\r\n }[] = []\r\n\r\n for (const path in routes) {\r\n const keys: string[] = []\r\n const pattern = path\r\n .replace(/\\/:[^\\/]+/g, (match) => {\r\n keys.push(match.slice(2))\r\n return \"/([^/]+)\"\r\n })\r\n .replace(/\\*/g, \".*\")\r\n const regex = new RegExp(`^${pattern}$`)\r\n routePatterns.push({ regex, keys, handler: routes[path] })\r\n }\r\n\r\n const renderRoute = () => {\r\n const path = window.location.pathname\r\n let matched = false\r\n\r\n for (const { regex, keys, handler } of routePatterns) {\r\n const match = path.match(regex)\r\n if (match) {\r\n const params: Record<string, string> = {}\r\n keys.forEach((key, i) => {\r\n params[key] = match[i + 1]\r\n })\r\n container.innerHTML = \"\"\r\n container.appendChild(handler(params))\r\n matched = true\r\n break\r\n }\r\n }\r\n\r\n if (!matched && routes[\"*\"]) {\r\n container.innerHTML = \"\"\r\n container.appendChild(routes[\"*\"]())\r\n }\r\n }\r\n\r\n window.addEventListener(\"popstate\", renderRoute)\r\n renderRoute()\r\n\r\n return {\r\n render: renderRoute,\r\n element: container\r\n }\r\n}\r\n","type Component = (() => HTMLElement) | { render: () => void; element?: HTMLElement }\r\n\r\nexport function add(component: Component) {\r\n if (typeof component === \"function\") {\r\n const el = component()\r\n if (!(el instanceof Node)) {\r\n throw new Error(\"Component function must return an HTMLElement\")\r\n }\r\n document.body.appendChild(el)\r\n } else if (\"render\" in component && typeof component.render === \"function\") {\r\n document.body.appendChild(component.element || document.createElement(\"div\"))\r\n component.render()\r\n } else {\r\n throw new Error(\"Invalid component passed to add()\")\r\n }\r\n}"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -45,47 +45,62 @@ const tags = new Proxy({}, {
|
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
function router(routes) {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
const container = document.createElement("div");
|
|
49
|
+
const routePatterns = [];
|
|
50
|
+
for (const path in routes) {
|
|
51
|
+
const keys = [];
|
|
52
|
+
const pattern = path
|
|
53
|
+
.replace(/\/:[^\/]+/g, (match) => {
|
|
54
|
+
keys.push(match.slice(2));
|
|
55
|
+
return "/([^/]+)";
|
|
56
|
+
})
|
|
57
|
+
.replace(/\*/g, ".*");
|
|
58
|
+
const regex = new RegExp(`^${pattern}$`);
|
|
59
|
+
routePatterns.push({ regex, keys, handler: routes[path] });
|
|
60
|
+
}
|
|
51
61
|
const renderRoute = () => {
|
|
52
62
|
const path = window.location.pathname;
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
let matched = false;
|
|
64
|
+
for (const { regex, keys, handler } of routePatterns) {
|
|
65
|
+
const match = path.match(regex);
|
|
66
|
+
if (match) {
|
|
67
|
+
const params = {};
|
|
68
|
+
keys.forEach((key, i) => {
|
|
69
|
+
params[key] = match[i + 1];
|
|
70
|
+
});
|
|
71
|
+
container.innerHTML = "";
|
|
72
|
+
container.appendChild(handler(params));
|
|
73
|
+
matched = true;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (!matched && routes["*"]) {
|
|
78
|
+
container.innerHTML = "";
|
|
79
|
+
container.appendChild(routes["*"]());
|
|
80
|
+
}
|
|
60
81
|
};
|
|
61
82
|
window.addEventListener("popstate", renderRoute);
|
|
83
|
+
renderRoute();
|
|
62
84
|
return {
|
|
63
85
|
render: renderRoute,
|
|
64
|
-
|
|
65
|
-
history.pushState(null, "", path);
|
|
66
|
-
renderRoute();
|
|
67
|
-
}
|
|
86
|
+
element: container
|
|
68
87
|
};
|
|
69
88
|
}
|
|
70
89
|
|
|
71
|
-
function add(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (typeof c === "function") {
|
|
77
|
-
const el = c();
|
|
78
|
-
if (!(el instanceof Node)) {
|
|
79
|
-
throw new Error("Component function must return an HTMLElement");
|
|
80
|
-
}
|
|
81
|
-
app.appendChild(el);
|
|
82
|
-
}
|
|
83
|
-
else if ("render" in c && typeof c.render === "function") {
|
|
84
|
-
c.render();
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
throw new Error("Invalid component passed to add()");
|
|
90
|
+
function add(component) {
|
|
91
|
+
if (typeof component === "function") {
|
|
92
|
+
const el = component();
|
|
93
|
+
if (!(el instanceof Node)) {
|
|
94
|
+
throw new Error("Component function must return an HTMLElement");
|
|
88
95
|
}
|
|
96
|
+
document.body.appendChild(el);
|
|
97
|
+
}
|
|
98
|
+
else if ("render" in component && typeof component.render === "function") {
|
|
99
|
+
document.body.appendChild(component.element || document.createElement("div"));
|
|
100
|
+
component.render();
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
throw new Error("Invalid component passed to add()");
|
|
89
104
|
}
|
|
90
105
|
}
|
|
91
106
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/state.ts","../src/tags.ts","../src/router.ts","../src/helpers.ts"],"sourcesContent":["export function state<T>(initial: T) {\r\n let value = initial\r\n const listeners: Function[] = []\r\n\r\n const set = (newValue: T) => {\r\n value = newValue\r\n listeners.forEach(fn => fn(value))\r\n }\r\n\r\n const get = () => value\r\n\r\n const subscribe = (fn: Function) => {\r\n listeners.push(fn)\r\n return () => {\r\n const index = listeners.indexOf(fn)\r\n if (index > -1) listeners.splice(index, 1)\r\n }\r\n }\r\n\r\n return { get, set, subscribe }\r\n}","export const tags = new Proxy({}, {\r\n get(_, tag: string) {\r\n return (attrsOrChild?: any, ...children: any[]) => {\r\n const el = document.createElement(tag)\r\n if (attrsOrChild && typeof attrsOrChild === 'object' && !Array.isArray(attrsOrChild) && !(attrsOrChild instanceof Node)) {\r\n for (const [k, v] of Object.entries(attrsOrChild)) {\r\n el.setAttribute(k, v as string)\r\n }\r\n } else if (attrsOrChild != null) {\r\n children.unshift(attrsOrChild)\r\n }\r\n\r\n for (const child of children.flat()) {\r\n if (child instanceof Node) el.appendChild(child)\r\n else el.appendChild(document.createTextNode(String(child)))\r\n }\r\n return el\r\n }\r\n }\r\n})","
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/state.ts","../src/tags.ts","../src/router.ts","../src/helpers.ts"],"sourcesContent":["export function state<T>(initial: T) {\r\n let value = initial\r\n const listeners: Function[] = []\r\n\r\n const set = (newValue: T) => {\r\n value = newValue\r\n listeners.forEach(fn => fn(value))\r\n }\r\n\r\n const get = () => value\r\n\r\n const subscribe = (fn: Function) => {\r\n listeners.push(fn)\r\n return () => {\r\n const index = listeners.indexOf(fn)\r\n if (index > -1) listeners.splice(index, 1)\r\n }\r\n }\r\n\r\n return { get, set, subscribe }\r\n}","export const tags = new Proxy({}, {\r\n get(_, tag: string) {\r\n return (attrsOrChild?: any, ...children: any[]) => {\r\n const el = document.createElement(tag)\r\n if (attrsOrChild && typeof attrsOrChild === 'object' && !Array.isArray(attrsOrChild) && !(attrsOrChild instanceof Node)) {\r\n for (const [k, v] of Object.entries(attrsOrChild)) {\r\n el.setAttribute(k, v as string)\r\n }\r\n } else if (attrsOrChild != null) {\r\n children.unshift(attrsOrChild)\r\n }\r\n\r\n for (const child of children.flat()) {\r\n if (child instanceof Node) el.appendChild(child)\r\n else el.appendChild(document.createTextNode(String(child)))\r\n }\r\n return el\r\n }\r\n }\r\n})","type RouteHandler = (params?: Record<string, string>) => HTMLElement\r\n\r\nexport function router(routes: Record<string, RouteHandler>) {\r\n const container = document.createElement(\"div\")\r\n const routePatterns: {\r\n regex: RegExp\r\n keys: string[]\r\n handler: RouteHandler\r\n }[] = []\r\n\r\n for (const path in routes) {\r\n const keys: string[] = []\r\n const pattern = path\r\n .replace(/\\/:[^\\/]+/g, (match) => {\r\n keys.push(match.slice(2))\r\n return \"/([^/]+)\"\r\n })\r\n .replace(/\\*/g, \".*\")\r\n const regex = new RegExp(`^${pattern}$`)\r\n routePatterns.push({ regex, keys, handler: routes[path] })\r\n }\r\n\r\n const renderRoute = () => {\r\n const path = window.location.pathname\r\n let matched = false\r\n\r\n for (const { regex, keys, handler } of routePatterns) {\r\n const match = path.match(regex)\r\n if (match) {\r\n const params: Record<string, string> = {}\r\n keys.forEach((key, i) => {\r\n params[key] = match[i + 1]\r\n })\r\n container.innerHTML = \"\"\r\n container.appendChild(handler(params))\r\n matched = true\r\n break\r\n }\r\n }\r\n\r\n if (!matched && routes[\"*\"]) {\r\n container.innerHTML = \"\"\r\n container.appendChild(routes[\"*\"]())\r\n }\r\n }\r\n\r\n window.addEventListener(\"popstate\", renderRoute)\r\n renderRoute()\r\n\r\n return {\r\n render: renderRoute,\r\n element: container\r\n }\r\n}\r\n","type Component = (() => HTMLElement) | { render: () => void; element?: HTMLElement }\r\n\r\nexport function add(component: Component) {\r\n if (typeof component === \"function\") {\r\n const el = component()\r\n if (!(el instanceof Node)) {\r\n throw new Error(\"Component function must return an HTMLElement\")\r\n }\r\n document.body.appendChild(el)\r\n } else if (\"render\" in component && typeof component.render === \"function\") {\r\n document.body.appendChild(component.element || document.createElement(\"div\"))\r\n component.render()\r\n } else {\r\n throw new Error(\"Invalid component passed to add()\")\r\n }\r\n}"],"names":[],"mappings":"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"}
|
package/dist/index.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).MiniUI={})}(this,function(e){"use strict";const n=new Proxy({},{get:(e,n)=>(e,...t)=>{const o=document.createElement(n);if(!e||"object"!=typeof e||Array.isArray(e)||e instanceof Node)null!=e&&t.unshift(e);else for(const[n,t]of Object.entries(e))o.setAttribute(n,t);for(const e of t.flat())e instanceof Node?o.appendChild(e):o.appendChild(document.createTextNode(String(e)));return o}});e.add=function(
|
|
1
|
+
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).MiniUI={})}(this,function(e){"use strict";const n=new Proxy({},{get:(e,n)=>(e,...t)=>{const o=document.createElement(n);if(!e||"object"!=typeof e||Array.isArray(e)||e instanceof Node)null!=e&&t.unshift(e);else for(const[n,t]of Object.entries(e))o.setAttribute(n,t);for(const e of t.flat())e instanceof Node?o.appendChild(e):o.appendChild(document.createTextNode(String(e)));return o}});e.add=function(e){if("function"==typeof e){const n=e();if(!(n instanceof Node))throw new Error("Component function must return an HTMLElement");document.body.appendChild(n)}else{if(!("render"in e)||"function"!=typeof e.render)throw new Error("Invalid component passed to add()");document.body.appendChild(e.element||document.createElement("div")),e.render()}},e.router=function(e){const n=document.createElement("div"),t=[];for(const n in e){const o=[],r=n.replace(/\/:[^\/]+/g,e=>(o.push(e.slice(2)),"/([^/]+)")).replace(/\*/g,".*"),i=new RegExp(`^${r}$`);t.push({regex:i,keys:o,handler:e[n]})}const o=()=>{const o=window.location.pathname;let r=!1;for(const{regex:e,keys:i,handler:d}of t){const t=o.match(e);if(t){const e={};i.forEach((n,o)=>{e[n]=t[o+1]}),n.innerHTML="",n.appendChild(d(e)),r=!0;break}}!r&&e["*"]&&(n.innerHTML="",n.appendChild(e["*"]()))};return window.addEventListener("popstate",o),o(),{render:o,element:n}},e.state=function(e){let n=e;const t=[];return{get:()=>n,set:e=>{n=e,t.forEach(e=>e(n))},subscribe:e=>(t.push(e),()=>{const n=t.indexOf(e);n>-1&&t.splice(n,1)})}},e.tags=n,Object.defineProperty(e,"__esModule",{value:!0})});
|
|
2
2
|
//# sourceMappingURL=index.min.js.map
|
package/dist/index.min.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.min.js","sources":["../src/tags.ts","../src/helpers.ts","../src/router.ts","../src/state.ts"],"sourcesContent":["export const tags = new Proxy({}, {\r\n get(_, tag: string) {\r\n return (attrsOrChild?: any, ...children: any[]) => {\r\n const el = document.createElement(tag)\r\n if (attrsOrChild && typeof attrsOrChild === 'object' && !Array.isArray(attrsOrChild) && !(attrsOrChild instanceof Node)) {\r\n for (const [k, v] of Object.entries(attrsOrChild)) {\r\n el.setAttribute(k, v as string)\r\n }\r\n } else if (attrsOrChild != null) {\r\n children.unshift(attrsOrChild)\r\n }\r\n\r\n for (const child of children.flat()) {\r\n if (child instanceof Node) el.appendChild(child)\r\n else el.appendChild(document.createTextNode(String(child)))\r\n }\r\n return el\r\n }\r\n }\r\n})","type Component = (() => HTMLElement) | { render: () => void }\r\n\r\nexport function add(
|
|
1
|
+
{"version":3,"file":"index.min.js","sources":["../src/tags.ts","../src/helpers.ts","../src/router.ts","../src/state.ts"],"sourcesContent":["export const tags = new Proxy({}, {\r\n get(_, tag: string) {\r\n return (attrsOrChild?: any, ...children: any[]) => {\r\n const el = document.createElement(tag)\r\n if (attrsOrChild && typeof attrsOrChild === 'object' && !Array.isArray(attrsOrChild) && !(attrsOrChild instanceof Node)) {\r\n for (const [k, v] of Object.entries(attrsOrChild)) {\r\n el.setAttribute(k, v as string)\r\n }\r\n } else if (attrsOrChild != null) {\r\n children.unshift(attrsOrChild)\r\n }\r\n\r\n for (const child of children.flat()) {\r\n if (child instanceof Node) el.appendChild(child)\r\n else el.appendChild(document.createTextNode(String(child)))\r\n }\r\n return el\r\n }\r\n }\r\n})","type Component = (() => HTMLElement) | { render: () => void; element?: HTMLElement }\r\n\r\nexport function add(component: Component) {\r\n if (typeof component === \"function\") {\r\n const el = component()\r\n if (!(el instanceof Node)) {\r\n throw new Error(\"Component function must return an HTMLElement\")\r\n }\r\n document.body.appendChild(el)\r\n } else if (\"render\" in component && typeof component.render === \"function\") {\r\n document.body.appendChild(component.element || document.createElement(\"div\"))\r\n component.render()\r\n } else {\r\n throw new Error(\"Invalid component passed to add()\")\r\n }\r\n}","type RouteHandler = (params?: Record<string, string>) => HTMLElement\r\n\r\nexport function router(routes: Record<string, RouteHandler>) {\r\n const container = document.createElement(\"div\")\r\n const routePatterns: {\r\n regex: RegExp\r\n keys: string[]\r\n handler: RouteHandler\r\n }[] = []\r\n\r\n for (const path in routes) {\r\n const keys: string[] = []\r\n const pattern = path\r\n .replace(/\\/:[^\\/]+/g, (match) => {\r\n keys.push(match.slice(2))\r\n return \"/([^/]+)\"\r\n })\r\n .replace(/\\*/g, \".*\")\r\n const regex = new RegExp(`^${pattern}$`)\r\n routePatterns.push({ regex, keys, handler: routes[path] })\r\n }\r\n\r\n const renderRoute = () => {\r\n const path = window.location.pathname\r\n let matched = false\r\n\r\n for (const { regex, keys, handler } of routePatterns) {\r\n const match = path.match(regex)\r\n if (match) {\r\n const params: Record<string, string> = {}\r\n keys.forEach((key, i) => {\r\n params[key] = match[i + 1]\r\n })\r\n container.innerHTML = \"\"\r\n container.appendChild(handler(params))\r\n matched = true\r\n break\r\n }\r\n }\r\n\r\n if (!matched && routes[\"*\"]) {\r\n container.innerHTML = \"\"\r\n container.appendChild(routes[\"*\"]())\r\n }\r\n }\r\n\r\n window.addEventListener(\"popstate\", renderRoute)\r\n renderRoute()\r\n\r\n return {\r\n render: renderRoute,\r\n element: container\r\n }\r\n}\r\n","export function state<T>(initial: T) {\r\n let value = initial\r\n const listeners: Function[] = []\r\n\r\n const set = (newValue: T) => {\r\n value = newValue\r\n listeners.forEach(fn => fn(value))\r\n }\r\n\r\n const get = () => value\r\n\r\n const subscribe = (fn: Function) => {\r\n listeners.push(fn)\r\n return () => {\r\n const index = listeners.indexOf(fn)\r\n if (index > -1) listeners.splice(index, 1)\r\n }\r\n }\r\n\r\n return { get, set, subscribe }\r\n}"],"names":["tags","Proxy","get","_","tag","attrsOrChild","children","el","document","createElement","Array","isArray","Node","unshift","k","v","Object","entries","setAttribute","child","flat","appendChild","createTextNode","String","component","Error","body","render","element","routes","container","routePatterns","path","keys","pattern","replace","match","push","slice","regex","RegExp","handler","renderRoute","window","location","pathname","matched","params","forEach","key","i","innerHTML","addEventListener","initial","value","listeners","set","newValue","fn","subscribe","index","indexOf","splice"],"mappings":"mPAAaA,EAAO,IAAIC,MAAM,GAAI,CAC9BC,IAAG,CAACC,EAAGC,IACI,CAACC,KAAuBC,KAC3B,MAAMC,EAAKC,SAASC,cAAcL,GAClC,IAAIC,GAAwC,iBAAjBA,GAA8BK,MAAMC,QAAQN,IAAmBA,aAAwBO,KAIvF,MAAhBP,GACPC,EAASO,QAAQR,QAJjB,IAAK,MAAOS,EAAGC,KAAMC,OAAOC,QAAQZ,GAChCE,EAAGW,aAAaJ,EAAGC,GAM3B,IAAK,MAAMI,KAASb,EAASc,OACrBD,aAAiBP,KAAML,EAAGc,YAAYF,GACrCZ,EAAGc,YAAYb,SAASc,eAAeC,OAAOJ,KAEvD,OAAOZ,WCdb,SAAciB,GAChB,GAAyB,mBAAdA,EAA0B,CACjC,MAAMjB,EAAKiB,IACX,KAAMjB,aAAcK,MAChB,MAAM,IAAIa,MAAM,iDAEpBjB,SAASkB,KAAKL,YAAYd,EAC7B,KAAM,MAAI,WAAYiB,IAAyC,mBAArBA,EAAUG,OAIjD,MAAM,IAAIF,MAAM,qCAHhBjB,SAASkB,KAAKL,YAAYG,EAAUI,SAAWpB,SAASC,cAAc,QACtEe,EAAUG,QAGb,CACL,WCbM,SAAiBE,GACnB,MAAMC,EAAYtB,SAASC,cAAc,OACnCsB,EAIA,GAEN,IAAK,MAAMC,KAAQH,EAAQ,CACvB,MAAMI,EAAiB,GACjBC,EAAUF,EACXG,QAAQ,aAAeC,IACpBH,EAAKI,KAAKD,EAAME,MAAM,IACf,aAEVH,QAAQ,MAAO,MACdI,EAAQ,IAAIC,OAAO,IAAIN,MAC7BH,EAAcM,KAAK,CAAEE,QAAON,OAAMQ,QAASZ,EAAOG,IACrD,CAED,MAAMU,EAAc,KAChB,MAAMV,EAAOW,OAAOC,SAASC,SAC7B,IAAIC,GAAU,EAEd,IAAK,MAAMP,MAAEA,EAAKN,KAAEA,EAAIQ,QAAEA,KAAaV,EAAe,CAClD,MAAMK,EAAQJ,EAAKI,MAAMG,GACzB,GAAIH,EAAO,CACP,MAAMW,EAAiC,CAAA,EACvCd,EAAKe,QAAQ,CAACC,EAAKC,KACfH,EAAOE,GAAOb,EAAMc,EAAI,KAE5BpB,EAAUqB,UAAY,GACtBrB,EAAUT,YAAYoB,EAAQM,IAC9BD,GAAU,EACV,KACH,CACJ,EAEIA,GAAWjB,EAAO,OACnBC,EAAUqB,UAAY,GACtBrB,EAAUT,YAAYQ,EAAO,UAOrC,OAHAc,OAAOS,iBAAiB,WAAYV,GACpCA,IAEO,CACHf,OAAQe,EACRd,QAASE,EAEjB,UCrDM,SAAmBuB,GACrB,IAAIC,EAAQD,EACZ,MAAME,EAAwB,GAiB9B,MAAO,CAAErD,IAVG,IAAMoD,EAUJE,IAfDC,IACTH,EAAQG,EACRF,EAAUP,QAAQU,GAAMA,EAAGJ,KAaZK,UARAD,IACfH,EAAUlB,KAAKqB,GACR,KACH,MAAME,EAAQL,EAAUM,QAAQH,GAC5BE,GAAS,GAAGL,EAAUO,OAAOF,EAAO,KAKpD"}
|
package/dist/router.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
type RouteHandler = (params?: Record<string, string>) => HTMLElement;
|
|
2
|
+
export declare function router(routes: Record<string, RouteHandler>): {
|
|
2
3
|
render: () => void;
|
|
3
|
-
|
|
4
|
+
element: HTMLDivElement;
|
|
4
5
|
};
|
|
6
|
+
export {};
|
package/package.json
CHANGED
package/src/helpers.ts
CHANGED
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
type Component = (() => HTMLElement) | { render: () => void }
|
|
1
|
+
type Component = (() => HTMLElement) | { render: () => void; element?: HTMLElement }
|
|
2
2
|
|
|
3
|
-
export function add(
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if (typeof c === "function") {
|
|
9
|
-
const el = c()
|
|
10
|
-
if (!(el instanceof Node)) {
|
|
11
|
-
throw new Error("Component function must return an HTMLElement")
|
|
12
|
-
}
|
|
13
|
-
app.appendChild(el)
|
|
14
|
-
} else if ("render" in c && typeof c.render === "function") {
|
|
15
|
-
c.render()
|
|
16
|
-
} else {
|
|
17
|
-
throw new Error("Invalid component passed to add()")
|
|
3
|
+
export function add(component: Component) {
|
|
4
|
+
if (typeof component === "function") {
|
|
5
|
+
const el = component()
|
|
6
|
+
if (!(el instanceof Node)) {
|
|
7
|
+
throw new Error("Component function must return an HTMLElement")
|
|
18
8
|
}
|
|
9
|
+
document.body.appendChild(el)
|
|
10
|
+
} else if ("render" in component && typeof component.render === "function") {
|
|
11
|
+
document.body.appendChild(component.element || document.createElement("div"))
|
|
12
|
+
component.render()
|
|
13
|
+
} else {
|
|
14
|
+
throw new Error("Invalid component passed to add()")
|
|
19
15
|
}
|
|
20
|
-
}
|
|
16
|
+
}
|
package/src/router.ts
CHANGED
|
@@ -1,25 +1,54 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
type RouteHandler = (params?: Record<string, string>) => HTMLElement
|
|
2
|
+
|
|
3
|
+
export function router(routes: Record<string, RouteHandler>) {
|
|
4
|
+
const container = document.createElement("div")
|
|
5
|
+
const routePatterns: {
|
|
6
|
+
regex: RegExp
|
|
7
|
+
keys: string[]
|
|
8
|
+
handler: RouteHandler
|
|
9
|
+
}[] = []
|
|
10
|
+
|
|
11
|
+
for (const path in routes) {
|
|
12
|
+
const keys: string[] = []
|
|
13
|
+
const pattern = path
|
|
14
|
+
.replace(/\/:[^\/]+/g, (match) => {
|
|
15
|
+
keys.push(match.slice(2))
|
|
16
|
+
return "/([^/]+)"
|
|
17
|
+
})
|
|
18
|
+
.replace(/\*/g, ".*")
|
|
19
|
+
const regex = new RegExp(`^${pattern}$`)
|
|
20
|
+
routePatterns.push({ regex, keys, handler: routes[path] })
|
|
4
21
|
}
|
|
5
22
|
|
|
6
23
|
const renderRoute = () => {
|
|
7
24
|
const path = window.location.pathname
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
25
|
+
let matched = false
|
|
26
|
+
|
|
27
|
+
for (const { regex, keys, handler } of routePatterns) {
|
|
28
|
+
const match = path.match(regex)
|
|
29
|
+
if (match) {
|
|
30
|
+
const params: Record<string, string> = {}
|
|
31
|
+
keys.forEach((key, i) => {
|
|
32
|
+
params[key] = match[i + 1]
|
|
33
|
+
})
|
|
34
|
+
container.innerHTML = ""
|
|
35
|
+
container.appendChild(handler(params))
|
|
36
|
+
matched = true
|
|
37
|
+
break
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (!matched && routes["*"]) {
|
|
42
|
+
container.innerHTML = ""
|
|
43
|
+
container.appendChild(routes["*"]())
|
|
44
|
+
}
|
|
14
45
|
}
|
|
15
46
|
|
|
16
47
|
window.addEventListener("popstate", renderRoute)
|
|
48
|
+
renderRoute()
|
|
17
49
|
|
|
18
50
|
return {
|
|
19
51
|
render: renderRoute,
|
|
20
|
-
|
|
21
|
-
history.pushState(null, "", path)
|
|
22
|
-
renderRoute()
|
|
23
|
-
}
|
|
52
|
+
element: container
|
|
24
53
|
}
|
|
25
|
-
}
|
|
54
|
+
}
|