@fynixorg/ui 1.0.11 → 1.0.12
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/dist/README.md +36 -0
- package/dist/context/context.d.ts +19 -0
- package/dist/context/context.d.ts.map +1 -0
- package/dist/context/context.js +3 -11
- package/dist/context/context.js.map +3 -3
- package/dist/custom/button.d.ts +2 -0
- package/dist/custom/button.d.ts.map +1 -0
- package/dist/custom/button.js +2 -9
- package/dist/custom/button.js.map +3 -3
- package/dist/custom/index.d.ts +3 -0
- package/dist/custom/index.d.ts.map +1 -0
- package/dist/custom/index.js +2 -7
- package/dist/custom/index.js.map +3 -3
- package/dist/custom/path.d.ts +14 -0
- package/dist/custom/path.d.ts.map +1 -0
- package/dist/custom/path.js +17 -34
- package/dist/custom/path.js.map +3 -3
- package/dist/error/errorOverlay.d.ts +3 -0
- package/dist/error/errorOverlay.d.ts.map +1 -0
- package/dist/error/errorOverlay.js +82 -91
- package/dist/error/errorOverlay.js.map +3 -3
- package/dist/fynix/index.d.ts +5 -0
- package/dist/fynix/index.d.ts.map +1 -0
- package/dist/fynix/index.js +2 -7
- package/dist/fynix/index.js.map +3 -3
- package/dist/hooks/nixAsync.d.ts +14 -0
- package/dist/hooks/nixAsync.d.ts.map +1 -0
- package/dist/hooks/nixAsync.js +38 -43
- package/dist/hooks/nixAsync.js.map +3 -3
- package/dist/hooks/nixAsyncCache.d.ts +14 -0
- package/dist/hooks/nixAsyncCache.d.ts.map +1 -0
- package/dist/hooks/nixAsyncCache.js +57 -59
- package/dist/hooks/nixAsyncCache.js.map +3 -3
- package/dist/hooks/nixAsyncDebounce.d.ts +22 -0
- package/dist/hooks/nixAsyncDebounce.d.ts.map +1 -0
- package/dist/hooks/nixAsyncDebounce.js +74 -85
- package/dist/hooks/nixAsyncDebounce.js.map +3 -3
- package/dist/hooks/nixAsyncQuery.d.ts +16 -0
- package/dist/hooks/nixAsyncQuery.d.ts.map +1 -0
- package/dist/hooks/nixAsyncQuery.js +85 -79
- package/dist/hooks/nixAsyncQuery.js.map +3 -3
- package/dist/hooks/nixCallback.d.ts +2 -0
- package/dist/hooks/nixCallback.d.ts.map +1 -0
- package/dist/hooks/nixCallback.js +30 -40
- package/dist/hooks/nixCallback.js.map +3 -3
- package/dist/hooks/nixComputed.d.ts +16 -0
- package/dist/hooks/nixComputed.d.ts.map +1 -0
- package/dist/hooks/nixComputed.js +166 -198
- package/dist/hooks/nixComputed.js.map +4 -4
- package/dist/hooks/nixDebounce.d.ts +11 -0
- package/dist/hooks/nixDebounce.d.ts.map +1 -0
- package/dist/hooks/nixDebounce.js +53 -58
- package/dist/hooks/nixDebounce.js.map +3 -3
- package/dist/hooks/nixEffect.d.ts +4 -0
- package/dist/hooks/nixEffect.d.ts.map +1 -0
- package/dist/hooks/nixEffect.js +65 -75
- package/dist/hooks/nixEffect.js.map +3 -3
- package/dist/hooks/nixForm.d.ts +33 -0
- package/dist/hooks/nixForm.d.ts.map +1 -0
- package/dist/hooks/nixForm.js +110 -120
- package/dist/hooks/nixForm.js.map +3 -3
- package/dist/hooks/nixFormAsync.d.ts +42 -0
- package/dist/hooks/nixFormAsync.d.ts.map +1 -0
- package/dist/hooks/nixFormAsync.js +158 -167
- package/dist/hooks/nixFormAsync.js.map +3 -3
- package/dist/hooks/nixInterval.d.ts +2 -0
- package/dist/hooks/nixInterval.d.ts.map +1 -0
- package/dist/hooks/nixInterval.js +21 -27
- package/dist/hooks/nixInterval.js.map +3 -3
- package/dist/hooks/nixLazy.d.ts +8 -0
- package/dist/hooks/nixLazy.d.ts.map +1 -0
- package/dist/hooks/nixLazy.js +53 -58
- package/dist/hooks/nixLazy.js.map +3 -3
- package/dist/hooks/nixLazyAsync.d.ts +10 -0
- package/dist/hooks/nixLazyAsync.d.ts.map +1 -0
- package/dist/hooks/nixLazyAsync.js +65 -71
- package/dist/hooks/nixLazyAsync.js.map +3 -3
- package/dist/hooks/nixLazyFormAsync.d.ts +50 -0
- package/dist/hooks/nixLazyFormAsync.d.ts.map +1 -0
- package/dist/hooks/nixLazyFormAsync.js +209 -213
- package/dist/hooks/nixLazyFormAsync.js.map +3 -3
- package/dist/hooks/nixLocalStorage.d.ts +5 -0
- package/dist/hooks/nixLocalStorage.d.ts.map +1 -0
- package/dist/hooks/nixLocalStorage.js +21 -25
- package/dist/hooks/nixLocalStorage.js.map +3 -3
- package/dist/hooks/nixMemo.d.ts +2 -0
- package/dist/hooks/nixMemo.d.ts.map +1 -0
- package/dist/hooks/nixMemo.js +27 -31
- package/dist/hooks/nixMemo.js.map +3 -3
- package/dist/hooks/nixPrevious.d.ts +2 -0
- package/dist/hooks/nixPrevious.d.ts.map +1 -0
- package/dist/hooks/nixPrevious.js +13 -19
- package/dist/hooks/nixPrevious.js.map +3 -3
- package/dist/hooks/nixRef.d.ts +4 -0
- package/dist/hooks/nixRef.d.ts.map +1 -0
- package/dist/hooks/nixRef.js +14 -20
- package/dist/hooks/nixRef.js.map +3 -3
- package/dist/hooks/nixState.d.ts +15 -0
- package/dist/hooks/nixState.d.ts.map +1 -0
- package/dist/hooks/nixState.js +120 -173
- package/dist/hooks/nixState.js.map +3 -3
- package/dist/hooks/nixStore.d.ts +7 -0
- package/dist/hooks/nixStore.d.ts.map +1 -0
- package/dist/hooks/nixStore.js +48 -54
- package/dist/hooks/nixStore.js.map +3 -3
- package/dist/package.json +213 -0
- package/dist/plugins/vite-plugin-res.d.ts +41 -0
- package/dist/plugins/vite-plugin-res.d.ts.map +1 -0
- package/dist/plugins/vite-plugin-res.js +620 -36
- package/dist/plugins/vite-plugin-res.js.map +4 -4
- package/dist/router/router.d.ts +35 -0
- package/dist/router/router.d.ts.map +1 -0
- package/dist/router/router.js +520 -486
- package/dist/router/router.js.map +3 -3
- package/dist/runtime.d.ts +62 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +833 -820
- package/dist/runtime.js.map +4 -4
- package/package.json +227 -44
- package/types/fnx.d.ts +72 -0
- package/types/fynix-ui.d.ts +323 -0
- package/types/global.d.ts +46 -6
- package/types/index.d.ts +37 -0
- package/types/vite-env.d.ts +553 -0
- package/runtime.d.ts +0 -83
- package/types/jsx.d.ts +0 -692
package/dist/router/router.js
CHANGED
|
@@ -1,530 +1,564 @@
|
|
|
1
|
-
|
|
2
|
-
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
-
function isExternal(url) {
|
|
4
|
-
return /^https?:\/\//.test(url);
|
|
5
|
-
}
|
|
6
|
-
__name(isExternal, "isExternal");
|
|
7
|
-
import { mount } from "../runtime.js";
|
|
1
|
+
import { mount } from "../runtime";
|
|
8
2
|
const MAX_CACHE_SIZE = 50;
|
|
9
3
|
const PROPS_NAMESPACE = "__fynixLinkProps__";
|
|
10
4
|
const MAX_LISTENERS = 100;
|
|
11
5
|
const ALLOWED_PROTOCOLS = ["http:", "https:", ""];
|
|
6
|
+
const RENDER_DEBOUNCE = 10;
|
|
12
7
|
let routerInstance = null;
|
|
13
8
|
let isRouterInitialized = false;
|
|
9
|
+
function isExternal(url) {
|
|
10
|
+
return /^https?:\/\//.test(url);
|
|
11
|
+
}
|
|
14
12
|
function escapeHTML(str) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
if (typeof str !== "string")
|
|
14
|
+
return "";
|
|
15
|
+
return str
|
|
16
|
+
.replace(/&/g, "&")
|
|
17
|
+
.replace(/</g, "<")
|
|
18
|
+
.replace(/>/g, ">")
|
|
19
|
+
.replace(/"/g, """)
|
|
20
|
+
.replace(/'/g, "'")
|
|
21
|
+
.replace(/`/g, "`")
|
|
22
|
+
.replace(/\//g, "/");
|
|
18
23
|
}
|
|
19
|
-
__name(escapeHTML, "escapeHTML");
|
|
20
24
|
function isValidURL(url) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
25
|
+
try {
|
|
26
|
+
const parsed = new URL(url, window.location.origin);
|
|
27
|
+
if (parsed.origin !== window.location.origin) {
|
|
28
|
+
console.warn("[Router] Security: Cross-origin navigation blocked");
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
if (!ALLOWED_PROTOCOLS.includes(parsed.protocol)) {
|
|
32
|
+
console.warn("[Router] Security: Dangerous protocol blocked:", parsed.protocol);
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
console.warn("[Router] Security: Invalid URL blocked");
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
39
41
|
}
|
|
40
|
-
__name(isValidURL, "isValidURL");
|
|
41
42
|
function sanitizePath(path) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
43
|
+
if (typeof path !== "string")
|
|
44
|
+
return "/";
|
|
45
|
+
try {
|
|
46
|
+
path = decodeURIComponent(path);
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
console.warn("[Router] Invalid URL encoding in path");
|
|
50
|
+
return "/";
|
|
51
|
+
}
|
|
52
|
+
path = path.replace(/\0/g, "");
|
|
53
|
+
path = path.replace(/\\/g, "/");
|
|
54
|
+
path = path.replace(/\/+/g, "/");
|
|
55
|
+
path = path
|
|
56
|
+
.split("/")
|
|
57
|
+
.filter((part) => part !== ".." && part !== ".")
|
|
58
|
+
.join("/");
|
|
59
|
+
if (!path.startsWith("/")) {
|
|
60
|
+
path = "/" + path;
|
|
61
|
+
}
|
|
62
|
+
if (path.length > 1 && path.endsWith("/")) {
|
|
63
|
+
path = path.slice(0, -1);
|
|
64
|
+
}
|
|
65
|
+
return path || "/";
|
|
61
66
|
}
|
|
62
|
-
__name(sanitizePath, "sanitizePath");
|
|
63
67
|
function tryGlobPaths() {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
try {
|
|
69
|
+
let modules = import.meta.glob(["./**/*.fnx", "./**/*.tsx", "./**/*.jsx", "./**/*.ts", "./**/*.js"], { eager: true });
|
|
70
|
+
console.log("[Router] Glob attempt 1 (./**):", Object.keys(modules));
|
|
71
|
+
if (Object.keys(modules).length === 0) {
|
|
72
|
+
modules = import.meta.glob(["../**/*.fnx", "../**/*.tsx", "../**/*.jsx"], { eager: true });
|
|
73
|
+
console.log("[Router] Glob attempt 2 (../**):", Object.keys(modules));
|
|
74
|
+
}
|
|
75
|
+
if (Object.keys(modules).length === 0) {
|
|
76
|
+
modules = import.meta.glob("/src/**/*.{fnx,tsx,jsx,ts,js}", {
|
|
77
|
+
eager: true,
|
|
78
|
+
});
|
|
79
|
+
console.log("[Router] Glob attempt 3 (/src/**):", Object.keys(modules));
|
|
80
|
+
}
|
|
81
|
+
console.log("[Router] Final modules loaded:", Object.keys(modules).length);
|
|
82
|
+
return modules || {};
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
console.error("[Router] Failed to load modules:", error);
|
|
86
|
+
return {};
|
|
87
|
+
}
|
|
73
88
|
}
|
|
74
|
-
__name(tryGlobPaths, "tryGlobPaths");
|
|
75
89
|
function filePathToRoute(filePath) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
90
|
+
let route = filePath
|
|
91
|
+
.replace(/^.*\/src/, "")
|
|
92
|
+
.replace(/\.(ts|tsx|js|jsx|fnx)$/, "")
|
|
93
|
+
.replace(/\/view$/, "")
|
|
94
|
+
.replace(/\/$/, "");
|
|
95
|
+
if (!route)
|
|
96
|
+
route = "/";
|
|
97
|
+
route = route.replace(/\[([^\]]+)\]/g, ":$1");
|
|
98
|
+
return route;
|
|
81
99
|
}
|
|
82
|
-
__name(filePathToRoute, "filePathToRoute");
|
|
83
100
|
function matchDynamicRoute(path, dynamicRoutes) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
101
|
+
for (const route of dynamicRoutes) {
|
|
102
|
+
const match = path.match(route.regex);
|
|
103
|
+
if (match) {
|
|
104
|
+
const params = {};
|
|
105
|
+
route.params.forEach((param, i) => {
|
|
106
|
+
const matchValue = match[i + 1];
|
|
107
|
+
params[param] = escapeHTML(matchValue || "");
|
|
108
|
+
});
|
|
109
|
+
return { component: route.component, params };
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
95
113
|
}
|
|
96
|
-
__name(matchDynamicRoute, "matchDynamicRoute");
|
|
97
114
|
function deserializeProps(props) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
115
|
+
if (!props || typeof props !== "object")
|
|
116
|
+
return {};
|
|
117
|
+
const deserialized = {};
|
|
118
|
+
for (const [key, value] of Object.entries(props)) {
|
|
119
|
+
if (typeof key !== "string" || key.startsWith("__")) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
deserialized[key] = value;
|
|
104
123
|
}
|
|
105
|
-
deserialized
|
|
106
|
-
}
|
|
107
|
-
return deserialized;
|
|
124
|
+
return deserialized;
|
|
108
125
|
}
|
|
109
|
-
__name(deserializeProps, "deserializeProps");
|
|
110
126
|
function normalizePath(path) {
|
|
111
|
-
|
|
127
|
+
return sanitizePath(path);
|
|
112
128
|
}
|
|
113
|
-
__name(normalizePath, "normalizePath");
|
|
114
129
|
function generateCacheKey() {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
130
|
+
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
131
|
+
return crypto.randomUUID();
|
|
132
|
+
}
|
|
133
|
+
return `${Date.now()}-${Math.random().toString(36).slice(2)}-${Math.random()
|
|
134
|
+
.toString(36)
|
|
135
|
+
.slice(2)}`;
|
|
119
136
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
let rootSelector = "#app-root";
|
|
136
|
-
let currentPath = null;
|
|
137
|
-
let isDestroyed = false;
|
|
138
|
-
let listenerCount = 0;
|
|
139
|
-
const listeners = [];
|
|
140
|
-
if (!window[PROPS_NAMESPACE]) {
|
|
141
|
-
window[PROPS_NAMESPACE] = {};
|
|
142
|
-
}
|
|
143
|
-
if (isDevMode && window.__fynixPropsCache) {
|
|
144
|
-
window.__fynixPropsCache.clear();
|
|
145
|
-
}
|
|
146
|
-
const __fynixPropsCache = window.__fynixPropsCache || /* @__PURE__ */ new Map();
|
|
147
|
-
window.__fynixPropsCache = __fynixPropsCache;
|
|
148
|
-
const modules = tryGlobPaths();
|
|
149
|
-
const routes = {};
|
|
150
|
-
const dynamicRoutes = [];
|
|
151
|
-
for (const [filePath, mod] of Object.entries(modules)) {
|
|
152
|
-
const routePath = filePathToRoute(filePath);
|
|
153
|
-
const component = mod.default || mod[Object.keys(mod)[0]] || Object.values(mod)[0];
|
|
154
|
-
if (!component)
|
|
155
|
-
continue;
|
|
156
|
-
const hasDynamic = /:[^/]+/.test(routePath);
|
|
157
|
-
if (hasDynamic) {
|
|
158
|
-
dynamicRoutes.push({
|
|
159
|
-
pattern: routePath,
|
|
160
|
-
regex: new RegExp("^" + routePath.replace(/:[^/]+/g, "([^/]+)") + "$"),
|
|
161
|
-
component,
|
|
162
|
-
params: [...routePath.matchAll(/:([^/]+)/g)].map((m) => m[1])
|
|
163
|
-
});
|
|
164
|
-
} else {
|
|
165
|
-
routes[routePath] = component;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
function addToCache(key, value) {
|
|
169
|
-
if (__fynixPropsCache.size >= MAX_CACHE_SIZE) {
|
|
170
|
-
const firstKey = __fynixPropsCache.keys().next().value;
|
|
171
|
-
const evicted = __fynixPropsCache.get(firstKey);
|
|
172
|
-
if (evicted && typeof evicted === "object") {
|
|
173
|
-
Object.values(evicted).forEach((val) => {
|
|
174
|
-
if (val && typeof val === "object" && val.cleanup) {
|
|
175
|
-
try {
|
|
176
|
-
val.cleanup();
|
|
177
|
-
} catch (e) {
|
|
137
|
+
function addToCache(cache, key, value) {
|
|
138
|
+
if (cache.size >= MAX_CACHE_SIZE) {
|
|
139
|
+
const firstKey = cache.keys().next().value;
|
|
140
|
+
if (typeof firstKey === "string") {
|
|
141
|
+
const evicted = cache.get(firstKey);
|
|
142
|
+
if (evicted && typeof evicted === "object") {
|
|
143
|
+
Object.values(evicted).forEach((val) => {
|
|
144
|
+
if (val && typeof val === "object" && "cleanup" in val) {
|
|
145
|
+
try {
|
|
146
|
+
val.cleanup();
|
|
147
|
+
}
|
|
148
|
+
catch (e) {
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
178
152
|
}
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
__fynixPropsCache.delete(firstKey);
|
|
153
|
+
cache.delete(firstKey);
|
|
154
|
+
}
|
|
183
155
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const MANAGED_META = [
|
|
156
|
+
cache.set(key, value);
|
|
157
|
+
}
|
|
158
|
+
const MANAGED_META = [
|
|
188
159
|
{ key: "description", name: "description" },
|
|
189
160
|
{ key: "keywords", name: "keywords" },
|
|
190
161
|
{ key: "twitterCard", name: "twitter:card" },
|
|
191
162
|
{ key: "ogTitle", property: "og:title" },
|
|
192
163
|
{ key: "ogDescription", property: "og:description" },
|
|
193
|
-
{ key: "ogImage", property: "og:image" }
|
|
194
|
-
|
|
195
|
-
|
|
164
|
+
{ key: "ogImage", property: "og:image" },
|
|
165
|
+
];
|
|
166
|
+
function updateMetaTags(meta = {}) {
|
|
196
167
|
if (!meta || typeof meta !== "object")
|
|
197
|
-
|
|
168
|
+
return;
|
|
198
169
|
if (meta.title && typeof meta.title === "string") {
|
|
199
|
-
|
|
170
|
+
document.title = escapeHTML(meta.title);
|
|
200
171
|
}
|
|
201
172
|
MANAGED_META.forEach((def) => {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
if (
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
173
|
+
const value = meta[def.key];
|
|
174
|
+
const selector = def.name
|
|
175
|
+
? `meta[name="${def.name}"]`
|
|
176
|
+
: `meta[property="${def.property}"]`;
|
|
177
|
+
let el = document.querySelector(selector);
|
|
178
|
+
if (value == null) {
|
|
179
|
+
if (el)
|
|
180
|
+
el.remove();
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
if (typeof value !== "string")
|
|
184
|
+
return;
|
|
185
|
+
if (!el) {
|
|
186
|
+
el = document.createElement("meta");
|
|
187
|
+
if (def.name)
|
|
188
|
+
el.setAttribute("name", def.name);
|
|
189
|
+
if (def.property)
|
|
190
|
+
el.setAttribute("property", def.property);
|
|
191
|
+
document.head.appendChild(el);
|
|
192
|
+
}
|
|
193
|
+
el.setAttribute("content", escapeHTML(value));
|
|
221
194
|
});
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
if (
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
195
|
+
}
|
|
196
|
+
function createFynix() {
|
|
197
|
+
const isDevMode = import.meta.hot !== undefined;
|
|
198
|
+
if (routerInstance && isRouterInitialized && !isDevMode) {
|
|
199
|
+
console.warn("[Router] Router already initialized, returning existing instance");
|
|
200
|
+
return routerInstance;
|
|
201
|
+
}
|
|
202
|
+
if (isDevMode && routerInstance) {
|
|
203
|
+
console.log("[Router] HMR: Cleaning up old router instance");
|
|
204
|
+
routerInstance.cleanup();
|
|
205
|
+
routerInstance = null;
|
|
206
|
+
isRouterInitialized = false;
|
|
207
|
+
}
|
|
208
|
+
let rootSelector = "#app-root";
|
|
209
|
+
let currentPath = null;
|
|
210
|
+
let isDestroyed = false;
|
|
211
|
+
let listenerCount = 0;
|
|
212
|
+
let renderTimeout = null;
|
|
213
|
+
const listeners = [];
|
|
214
|
+
if (!window[PROPS_NAMESPACE]) {
|
|
215
|
+
window[PROPS_NAMESPACE] = {};
|
|
216
|
+
}
|
|
217
|
+
if (isDevMode && window.__fynixPropsCache) {
|
|
218
|
+
window.__fynixPropsCache.clear();
|
|
219
|
+
}
|
|
220
|
+
const propsCache = window.__fynixPropsCache || new Map();
|
|
221
|
+
window.__fynixPropsCache = propsCache;
|
|
222
|
+
const modules = tryGlobPaths();
|
|
223
|
+
const routes = {};
|
|
224
|
+
const dynamicRoutes = [];
|
|
225
|
+
for (const [filePath, mod] of Object.entries(modules)) {
|
|
226
|
+
const routePath = filePathToRoute(filePath);
|
|
227
|
+
let component = undefined;
|
|
228
|
+
if (mod && typeof mod === "object") {
|
|
229
|
+
if ("default" in mod && mod.default) {
|
|
230
|
+
component = mod.default;
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
const keys = Object.keys(mod);
|
|
234
|
+
const firstKey = keys.length > 0 ? keys[0] : undefined;
|
|
235
|
+
if (firstKey !== undefined &&
|
|
236
|
+
typeof firstKey === "string" &&
|
|
237
|
+
typeof mod[firstKey] !== "undefined") {
|
|
238
|
+
component = mod[firstKey];
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
const values = Object.values(mod).filter(Boolean);
|
|
242
|
+
if (values.length > 0) {
|
|
243
|
+
component = values[0];
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
if (!component || typeof routePath !== "string")
|
|
249
|
+
continue;
|
|
250
|
+
const hasDynamic = /:[^/]+/.test(routePath);
|
|
251
|
+
if (hasDynamic) {
|
|
252
|
+
dynamicRoutes.push({
|
|
253
|
+
pattern: routePath,
|
|
254
|
+
regex: new RegExp("^" + routePath.replace(/:[^/]+/g, "([^/]+)") + "$"),
|
|
255
|
+
component,
|
|
256
|
+
params: [...routePath.matchAll(/:([^/]+)/g)]
|
|
257
|
+
.map((m) => m[1])
|
|
258
|
+
.filter((p) => typeof p === "string"),
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
routes[routePath] = component;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function renderRouteImmediate() {
|
|
266
|
+
if (isDestroyed)
|
|
267
|
+
return;
|
|
268
|
+
const path = normalizePath(window.location.pathname);
|
|
269
|
+
let Page = routes[path];
|
|
270
|
+
let params = {};
|
|
271
|
+
let routeProps = {};
|
|
272
|
+
if (!Page) {
|
|
273
|
+
const match = matchDynamicRoute(path, dynamicRoutes);
|
|
274
|
+
if (match) {
|
|
275
|
+
Page = match.component;
|
|
276
|
+
params = match.params;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
const root = document.querySelector(rootSelector);
|
|
280
|
+
if (!root) {
|
|
281
|
+
console.error("[Router] Root element not found:", rootSelector);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (!Page) {
|
|
285
|
+
root.innerHTML = `<h2>404 Not Found</h2><p>Path: ${escapeHTML(path)}</p>`;
|
|
286
|
+
updateMetaTags({ title: "404 - Page Not Found" });
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const state = (window.history.state || {});
|
|
290
|
+
let passedProps = {};
|
|
291
|
+
if (state.__fynixCacheKey && propsCache.has(state.__fynixCacheKey)) {
|
|
292
|
+
passedProps = propsCache.get(state.__fynixCacheKey);
|
|
293
|
+
}
|
|
294
|
+
else if (state.serializedProps) {
|
|
295
|
+
passedProps = deserializeProps(state.serializedProps);
|
|
296
|
+
}
|
|
297
|
+
if (Page.props) {
|
|
298
|
+
routeProps = typeof Page.props === "function" ? Page.props() : Page.props;
|
|
299
|
+
}
|
|
300
|
+
if (Page.meta) {
|
|
301
|
+
const meta = typeof Page.meta === "function" ? Page.meta(params) : Page.meta;
|
|
302
|
+
updateMetaTags(meta);
|
|
303
|
+
}
|
|
304
|
+
window.__lastRouteProps = {
|
|
305
|
+
...routeProps,
|
|
306
|
+
...passedProps,
|
|
307
|
+
params,
|
|
308
|
+
};
|
|
309
|
+
try {
|
|
310
|
+
mount(Page, rootSelector, window.__lastRouteProps);
|
|
311
|
+
}
|
|
312
|
+
catch (err) {
|
|
313
|
+
console.error("[Router] Mount failed:", err);
|
|
314
|
+
root.innerHTML = `<pre style="color:red;">Mount Error occurred</pre>`;
|
|
315
|
+
}
|
|
316
|
+
currentPath = path;
|
|
317
|
+
}
|
|
318
|
+
function renderRoute() {
|
|
319
|
+
if (isDestroyed)
|
|
320
|
+
return;
|
|
321
|
+
if (renderTimeout) {
|
|
322
|
+
clearTimeout(renderTimeout);
|
|
323
|
+
}
|
|
324
|
+
renderTimeout = setTimeout(async () => {
|
|
325
|
+
await renderRouteImmediate();
|
|
326
|
+
renderTimeout = null;
|
|
327
|
+
}, RENDER_DEBOUNCE);
|
|
328
|
+
}
|
|
329
|
+
function navigate(path, props = {}) {
|
|
330
|
+
if (isDestroyed)
|
|
331
|
+
return;
|
|
332
|
+
const normalizedPath = normalizePath(path);
|
|
333
|
+
if (!isValidURL(window.location.origin + normalizedPath)) {
|
|
334
|
+
console.error("[Router] Invalid navigation URL");
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
if (normalizedPath === currentPath)
|
|
338
|
+
return;
|
|
339
|
+
const cacheKey = generateCacheKey();
|
|
340
|
+
addToCache(propsCache, cacheKey, props);
|
|
341
|
+
try {
|
|
342
|
+
window.history.pushState({ __fynixCacheKey: cacheKey }, "", normalizedPath);
|
|
343
|
+
renderRoute();
|
|
344
|
+
}
|
|
345
|
+
catch (err) {
|
|
346
|
+
console.error("[Router] Navigation failed:", err);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
function replace(path, props = {}) {
|
|
350
|
+
if (isDestroyed)
|
|
351
|
+
return;
|
|
352
|
+
const normalizedPath = normalizePath(path);
|
|
353
|
+
if (!isValidURL(window.location.origin + normalizedPath)) {
|
|
354
|
+
console.error("[Router] Invalid replace URL");
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
const cacheKey = generateCacheKey();
|
|
358
|
+
addToCache(propsCache, cacheKey, props);
|
|
359
|
+
try {
|
|
360
|
+
window.history.replaceState({ __fynixCacheKey: cacheKey }, "", normalizedPath);
|
|
361
|
+
renderRoute();
|
|
362
|
+
}
|
|
363
|
+
catch (err) {
|
|
364
|
+
console.error("[Router] Replace failed:", err);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
function back() {
|
|
368
|
+
if (isDestroyed)
|
|
369
|
+
return;
|
|
370
|
+
try {
|
|
371
|
+
window.history.back();
|
|
372
|
+
}
|
|
373
|
+
catch (err) {
|
|
374
|
+
console.error("[Router] Back navigation failed:", err);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
const clickHandler = (e) => {
|
|
378
|
+
if (isDestroyed)
|
|
379
|
+
return;
|
|
380
|
+
const target = e.target;
|
|
381
|
+
const link = target.closest("a[data-fynix-link]");
|
|
382
|
+
if (!link)
|
|
383
|
+
return;
|
|
384
|
+
const href = link.getAttribute("href");
|
|
385
|
+
if (!href) {
|
|
386
|
+
console.warn("[Router] Missing href attribute");
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
if (isExternal(href)) {
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
const fullUrl = new URL(link.href, window.location.origin).href;
|
|
393
|
+
if (!isValidURL(fullUrl)) {
|
|
394
|
+
console.warn("[Router] Invalid link href");
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
e.preventDefault();
|
|
398
|
+
const path = normalizePath(new URL(link.href, window.location.origin).pathname);
|
|
399
|
+
if (path === currentPath)
|
|
400
|
+
return;
|
|
401
|
+
let props = {};
|
|
402
|
+
const propsKey = link.getAttribute("data-props-key");
|
|
403
|
+
if (propsKey &&
|
|
404
|
+
typeof propsKey === "string" &&
|
|
405
|
+
!propsKey.startsWith("__")) {
|
|
406
|
+
if (window[PROPS_NAMESPACE]?.[propsKey]) {
|
|
407
|
+
props = window[PROPS_NAMESPACE][propsKey];
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
const serializableProps = {};
|
|
411
|
+
for (const [k, v] of Object.entries(props)) {
|
|
412
|
+
if (typeof k !== "string" || k.startsWith("__"))
|
|
413
|
+
continue;
|
|
414
|
+
serializableProps[k] =
|
|
415
|
+
v && (v._isNixState || v._isRestState) ? v.value : v;
|
|
416
|
+
}
|
|
417
|
+
const cacheKey = generateCacheKey();
|
|
418
|
+
addToCache(propsCache, cacheKey, serializableProps);
|
|
419
|
+
try {
|
|
420
|
+
window.history.pushState({ __fynixCacheKey: cacheKey, serializedProps: serializableProps }, "", path);
|
|
421
|
+
renderRoute();
|
|
422
|
+
}
|
|
423
|
+
catch (err) {
|
|
424
|
+
console.error("[Router] Link navigation failed:", err);
|
|
425
|
+
}
|
|
280
426
|
};
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
}
|
|
318
|
-
const cacheKey = generateCacheKey();
|
|
319
|
-
addToCache(cacheKey, props);
|
|
320
|
-
try {
|
|
321
|
-
window.history.replaceState({ __fynixCacheKey: cacheKey }, "", path);
|
|
322
|
-
renderRoute();
|
|
323
|
-
} catch (err) {
|
|
324
|
-
console.error("[Router] Replace failed:", err);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
__name(replace, "replace");
|
|
328
|
-
function back() {
|
|
329
|
-
if (isDestroyed)
|
|
330
|
-
return;
|
|
331
|
-
try {
|
|
332
|
-
window.history.back();
|
|
333
|
-
} catch (err) {
|
|
334
|
-
console.error("[Router] Back navigation failed:", err);
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
__name(back, "back");
|
|
338
|
-
function mountRouter(selector = "#app-root") {
|
|
339
|
-
if (isDestroyed) {
|
|
340
|
-
console.error("[Router] Cannot mount destroyed router");
|
|
341
|
-
return;
|
|
342
|
-
}
|
|
343
|
-
if (typeof selector !== "string" || selector.length === 0) {
|
|
344
|
-
console.error("[Router] Invalid selector");
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
rootSelector = selector;
|
|
348
|
-
renderRoute();
|
|
349
|
-
isRouterInitialized = true;
|
|
350
|
-
}
|
|
351
|
-
__name(mountRouter, "mountRouter");
|
|
352
|
-
const clickHandler = /* @__PURE__ */ __name((e) => {
|
|
353
|
-
if (isDestroyed)
|
|
354
|
-
return;
|
|
355
|
-
const link = e.target.closest("a[data-fynix-link]");
|
|
356
|
-
if (!link)
|
|
357
|
-
return;
|
|
358
|
-
const href = link.getAttribute("href");
|
|
359
|
-
if (!href) {
|
|
360
|
-
console.warn("[Router] Missing href attribute");
|
|
361
|
-
return;
|
|
362
|
-
}
|
|
363
|
-
if (isExternal(href)) {
|
|
364
|
-
return;
|
|
365
|
-
}
|
|
366
|
-
const fullUrl = new URL(link.href, window.location.origin).href;
|
|
367
|
-
if (!isValidURL(fullUrl)) {
|
|
368
|
-
console.warn("[Router] Invalid link href");
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
e.preventDefault();
|
|
372
|
-
const path = normalizePath(
|
|
373
|
-
new URL(link.href, window.location.origin).pathname
|
|
374
|
-
);
|
|
375
|
-
if (path === currentPath)
|
|
376
|
-
return;
|
|
377
|
-
let props = {};
|
|
378
|
-
const propsKey = link.getAttribute("data-props-key");
|
|
379
|
-
if (propsKey && typeof propsKey === "string" && !propsKey.startsWith("__")) {
|
|
380
|
-
if (window[PROPS_NAMESPACE]?.[propsKey]) {
|
|
381
|
-
props = window[PROPS_NAMESPACE][propsKey];
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
const serializableProps = {};
|
|
385
|
-
for (const [k, v] of Object.entries(props)) {
|
|
386
|
-
if (typeof k !== "string" || k.startsWith("__"))
|
|
387
|
-
continue;
|
|
388
|
-
serializableProps[k] = v && (v._isNixState || v._isRestState) ? v.value : v;
|
|
389
|
-
}
|
|
390
|
-
const cacheKey = generateCacheKey();
|
|
391
|
-
addToCache(cacheKey, serializableProps);
|
|
392
|
-
try {
|
|
393
|
-
window.history.pushState(
|
|
394
|
-
{ __fynixCacheKey: cacheKey, serializedProps: serializableProps },
|
|
395
|
-
"",
|
|
396
|
-
path
|
|
397
|
-
);
|
|
398
|
-
renderRoute();
|
|
399
|
-
} catch (err) {
|
|
400
|
-
console.error("[Router] Link navigation failed:", err);
|
|
401
|
-
}
|
|
402
|
-
}, "clickHandler");
|
|
403
|
-
if (listenerCount < MAX_LISTENERS && !isRouterInitialized) {
|
|
404
|
-
document.addEventListener("click", clickHandler);
|
|
405
|
-
listeners.push({
|
|
406
|
-
element: document,
|
|
407
|
-
event: "click",
|
|
408
|
-
handler: clickHandler
|
|
409
|
-
});
|
|
410
|
-
listenerCount++;
|
|
411
|
-
window.addEventListener("popstate", renderRoute);
|
|
412
|
-
listeners.push({
|
|
413
|
-
element: window,
|
|
414
|
-
event: "popstate",
|
|
415
|
-
handler: renderRoute
|
|
416
|
-
});
|
|
417
|
-
listenerCount++;
|
|
418
|
-
}
|
|
419
|
-
function cleanup() {
|
|
420
|
-
if (renderTimeout) {
|
|
421
|
-
clearTimeout(renderTimeout);
|
|
422
|
-
renderTimeout = null;
|
|
423
|
-
}
|
|
424
|
-
isDestroyed = true;
|
|
425
|
-
listeners.forEach(({ element, event, handler }) => {
|
|
426
|
-
try {
|
|
427
|
-
element.removeEventListener(event, handler);
|
|
428
|
-
} catch (e) {
|
|
429
|
-
console.error("[Router] Cleanup error:", e);
|
|
430
|
-
}
|
|
431
|
-
});
|
|
432
|
-
listeners.length = 0;
|
|
433
|
-
listenerCount = 0;
|
|
434
|
-
__fynixPropsCache.forEach((props) => {
|
|
435
|
-
if (props && typeof props === "object") {
|
|
436
|
-
Object.values(props).forEach((val) => {
|
|
437
|
-
if (val && typeof val === "object" && val.cleanup) {
|
|
427
|
+
if (listenerCount < MAX_LISTENERS && !isRouterInitialized) {
|
|
428
|
+
document.addEventListener("click", clickHandler);
|
|
429
|
+
listeners.push({
|
|
430
|
+
element: document,
|
|
431
|
+
event: "click",
|
|
432
|
+
handler: clickHandler,
|
|
433
|
+
});
|
|
434
|
+
listenerCount++;
|
|
435
|
+
window.addEventListener("popstate", renderRoute);
|
|
436
|
+
listeners.push({
|
|
437
|
+
element: window,
|
|
438
|
+
event: "popstate",
|
|
439
|
+
handler: renderRoute,
|
|
440
|
+
});
|
|
441
|
+
listenerCount++;
|
|
442
|
+
}
|
|
443
|
+
function mountRouter(selector = "#app-root") {
|
|
444
|
+
if (isDestroyed) {
|
|
445
|
+
console.error("[Router] Cannot mount destroyed router");
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
if (typeof selector !== "string" || selector.length === 0) {
|
|
449
|
+
console.error("[Router] Invalid selector");
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
rootSelector = selector;
|
|
453
|
+
renderRoute();
|
|
454
|
+
isRouterInitialized = true;
|
|
455
|
+
}
|
|
456
|
+
function cleanup() {
|
|
457
|
+
if (renderTimeout) {
|
|
458
|
+
clearTimeout(renderTimeout);
|
|
459
|
+
renderTimeout = null;
|
|
460
|
+
}
|
|
461
|
+
isDestroyed = true;
|
|
462
|
+
listeners.forEach(({ element, event, handler }) => {
|
|
438
463
|
try {
|
|
439
|
-
|
|
440
|
-
}
|
|
464
|
+
element.removeEventListener(event, handler);
|
|
465
|
+
}
|
|
466
|
+
catch (e) {
|
|
467
|
+
console.error("[Router] Cleanup error:", e);
|
|
441
468
|
}
|
|
442
|
-
}
|
|
443
469
|
});
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
470
|
+
listeners.length = 0;
|
|
471
|
+
listenerCount = 0;
|
|
472
|
+
propsCache.forEach((props) => {
|
|
473
|
+
if (props && typeof props === "object") {
|
|
474
|
+
Object.values(props).forEach((val) => {
|
|
475
|
+
if (val && typeof val === "object" && "cleanup" in val) {
|
|
476
|
+
try {
|
|
477
|
+
val.cleanup();
|
|
478
|
+
}
|
|
479
|
+
catch (e) {
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
propsCache.clear();
|
|
486
|
+
if (window[PROPS_NAMESPACE]) {
|
|
487
|
+
const ns = window[PROPS_NAMESPACE];
|
|
488
|
+
if (ns && typeof ns === "object") {
|
|
489
|
+
Object.keys(ns).forEach((key) => {
|
|
490
|
+
delete ns[key];
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
delete window[PROPS_NAMESPACE];
|
|
494
|
+
}
|
|
495
|
+
if (window.__lastRouteProps) {
|
|
496
|
+
delete window.__lastRouteProps;
|
|
497
|
+
}
|
|
498
|
+
isRouterInitialized = false;
|
|
499
|
+
routerInstance = null;
|
|
500
|
+
console.log("[Router] Cleanup complete");
|
|
501
|
+
}
|
|
502
|
+
if (import.meta.hot) {
|
|
503
|
+
import.meta.hot.accept(() => {
|
|
504
|
+
console.log("[Router] HMR detected, re-rendering route...");
|
|
505
|
+
renderRoute();
|
|
506
|
+
});
|
|
507
|
+
import.meta.hot.dispose(() => {
|
|
508
|
+
console.log("[Router] HMR dispose, cleaning up...");
|
|
509
|
+
cleanup();
|
|
510
|
+
routerInstance = null;
|
|
511
|
+
isRouterInitialized = false;
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
const router = {
|
|
515
|
+
mountRouter,
|
|
516
|
+
navigate,
|
|
517
|
+
replace,
|
|
518
|
+
back,
|
|
519
|
+
cleanup,
|
|
520
|
+
routes,
|
|
521
|
+
dynamicRoutes,
|
|
522
|
+
};
|
|
523
|
+
routerInstance = router;
|
|
524
|
+
return router;
|
|
484
525
|
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
window[PROPS_NAMESPACE]
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
526
|
+
export { createFynix };
|
|
527
|
+
export default createFynix;
|
|
528
|
+
export function setLinkProps(key, props) {
|
|
529
|
+
if (typeof key !== "string" || key.startsWith("__")) {
|
|
530
|
+
console.error("[Router] Invalid props key");
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
if (!props || typeof props !== "object") {
|
|
534
|
+
console.error("[Router] Invalid props object");
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
if (!window[PROPS_NAMESPACE]) {
|
|
538
|
+
window[PROPS_NAMESPACE] = {};
|
|
539
|
+
}
|
|
540
|
+
if (Object.keys(window[PROPS_NAMESPACE]).length >= MAX_CACHE_SIZE) {
|
|
541
|
+
console.warn("[Router] Props storage limit reached");
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
window[PROPS_NAMESPACE][key] = props;
|
|
503
545
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
546
|
+
export function clearLinkProps(key) {
|
|
547
|
+
if (typeof key !== "string")
|
|
548
|
+
return;
|
|
549
|
+
if (window[PROPS_NAMESPACE]?.[key]) {
|
|
550
|
+
const props = window[PROPS_NAMESPACE][key];
|
|
551
|
+
if (props && typeof props === "object") {
|
|
552
|
+
Object.values(props).forEach((val) => {
|
|
553
|
+
if (val && typeof val === "object" && "cleanup" in val) {
|
|
554
|
+
try {
|
|
555
|
+
val.cleanup();
|
|
556
|
+
}
|
|
557
|
+
catch (e) {
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
delete window[PROPS_NAMESPACE][key];
|
|
563
|
+
}
|
|
522
564
|
}
|
|
523
|
-
__name(clearLinkProps, "clearLinkProps");
|
|
524
|
-
export {
|
|
525
|
-
clearLinkProps,
|
|
526
|
-
createFynix,
|
|
527
|
-
createFynix as default,
|
|
528
|
-
setLinkProps
|
|
529
|
-
};
|
|
530
|
-
//# sourceMappingURL=router.js.map
|