vite-plugin-vanjs 0.1.22 → 0.1.24

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/meta/Head.mjs CHANGED
@@ -6,6 +6,7 @@ import { getTagKey } from "./helpers.mjs";
6
6
  /** @typedef {typeof import("./types.d.ts").resetHeadTags} ResetTags */
7
7
  /** @typedef {typeof import("./types.d.ts").initializeHeadTags} InitializeTags */
8
8
  /** @typedef {typeof import("./types.d.ts").addMeta} AddMeta */
9
+ /** @typedef {typeof import("./types.d.ts").removeMeta} RemoveMeta */
9
10
  /** @typedef {typeof import("./types.d.ts").Head} HeadComp */
10
11
 
11
12
  /**
@@ -69,6 +70,25 @@ export const addMeta = (tag) => {
69
70
  tags.set(key, tag);
70
71
  };
71
72
 
73
+ /**
74
+ * Remove a new meta tag `van.tags.script({ id })`
75
+ * or TAGNAME.id key.
76
+ * Only client side.
77
+ * @type {RemoveMeta}
78
+ */
79
+ export const removeMeta = (tagOrId) => {
80
+ if (!tagOrId || isServer) return;
81
+ const tags = getHeadTags();
82
+ const tagIsString = typeof tagOrId === "string";
83
+ const key = tagIsString ? tagOrId : getTagKey(tagOrId);
84
+ const id = tagIsString ? tagOrId.split(".")[1] : tagOrId.id;
85
+ // istanbul ignore else
86
+ if (id) {
87
+ document.getElementById(id)?.remove();
88
+ tags.delete(key);
89
+ }
90
+ };
91
+
72
92
  /**
73
93
  * Get the head tags
74
94
  * @type {HeadComp}
package/meta/global.d.ts CHANGED
@@ -29,7 +29,8 @@ declare module "@vanjs/meta" {
29
29
 
30
30
  export type HeadTags = SupportedTags[] | TagFunc[];
31
31
 
32
- export const addMeta: (tag?: TagProps) => void;
32
+ export const addMeta: (tag?: Partial<SupportedTags>) => void;
33
+ export const removeMeta = (_tag: string | Partial<SupportedTags>) => null;
33
34
 
34
35
  export const Head: () => HeadTags;
35
36
 
package/meta/helpers.mjs CHANGED
@@ -19,6 +19,7 @@ export const parseAttributes = (attributeString) => {
19
19
  /** @type {typeof import('./types.d.ts').getTagAttribute} */
20
20
  const getTagAttribute = (tag) => {
21
21
  const attributes = [
22
+ "id",
22
23
  "name",
23
24
  "property",
24
25
  "charset",
@@ -28,7 +29,6 @@ const getTagAttribute = (tag) => {
28
29
  "rel",
29
30
  "src",
30
31
  "href",
31
- "id",
32
32
  ];
33
33
 
34
34
  for (const attr of attributes) {
package/meta/types.d.ts CHANGED
@@ -29,7 +29,8 @@ export type TagProps = SupportedTags | PropsWithKnownKeys<SupportedTags>;
29
29
 
30
30
  export type HeadTags = AllHeadTags[] | TagFunc[];
31
31
 
32
- export const addMeta = (_tag: string | TagProps) => null;
32
+ export const addMeta = (_tag: string | Partial<SupportedTags>) => null;
33
+ export const removeMeta = (_tag: string | Partial<SupportedTags>) => null;
33
34
 
34
35
  export const Head: () => HeadTags;
35
36
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-vanjs",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
4
4
  "author": "thednp",
5
5
  "license": "MIT",
6
6
  "description": "An async first mini meta-framework for VanJS powered by Vite",
@@ -88,13 +88,13 @@
88
88
  "vanjs-ext": "^0.6.3"
89
89
  },
90
90
  "devDependencies": {
91
- "@types/node": "^25.6.0",
91
+ "@types/node": "^25.6.2",
92
92
  "@vitest/browser": "^4.1.5",
93
93
  "@vitest/coverage-istanbul": "^4.1.5",
94
94
  "@vitest/ui": "^4.1.5",
95
95
  "happy-dom": "^20.9.0",
96
96
  "typescript": "6.0.3",
97
- "vite": "^8.0.10",
97
+ "vite": "^8.0.12",
98
98
  "vitest": "^4.1.5"
99
99
  },
100
100
  "engines": {
@@ -0,0 +1,8 @@
1
+ const ENV = import.meta.env;
2
+ const SSR = ENV.SSR;
3
+ const DEV = ENV.DEV;
4
+ const PROD = ENV.PROD;
5
+ const MODE = ENV.MODE;
6
+ const BASE_URL = ENV.BASE_URL;
7
+
8
+ export { BASE_URL, DEV, MODE, PROD, SSR };
@@ -218,28 +218,28 @@ export const generateRouteProloaders = (route) => {
218
218
  const layoutName = "Module";
219
219
 
220
220
  return `{
221
- preload: async (params) => {
222
- ${
221
+ preload: async (params) => {
222
+ ${
223
223
  route.layouts.map((layout) =>
224
224
  `if (${layout.id + layoutName}?.route?.preload) await ${
225
225
  layout.id + layoutName
226
226
  }?.route?.preload(params);`
227
- ).join("\n ")
227
+ ).join("\n ")
228
228
  }
229
- if (${moduleName}?.route?.preload) await ${moduleName}?.route?.preload(params);
230
- },
231
- load: async (params) => {
232
- let _data;
233
- ${
229
+ if (${moduleName}?.route?.preload) await ${moduleName}?.route?.preload(params);
230
+ },
231
+ load: async (params) => {
232
+ let _data;
233
+ ${
234
234
  route.layouts.map((layout) =>
235
235
  `if (${layout.id + layoutName}?.route?.load) await ${
236
236
  layout.id + layoutName
237
237
  }?.route?.load(params);`
238
- ).join("\n ")
239
- }
240
- if (${moduleName}?.route?.load) _data = await ${moduleName}?.route?.load(params);
241
- return _data;
238
+ ).join("\n ")
242
239
  }
240
+ if (${moduleName}?.route?.load) _data = await ${moduleName}?.route?.load(params);
241
+ return _data;
242
+ }
243
243
  }`;
244
244
  };
245
245
 
package/plugin/types.d.ts CHANGED
@@ -14,8 +14,8 @@ export type VanJSPluginOptions = {
14
14
  excludeRoutesProd?: string[]; // NEW — excluded in production only
15
15
  };
16
16
 
17
- export declare const VitePluginVanJS: (
17
+ const VitePluginVanJS: (
18
18
  config?: VanJSPluginOptions,
19
- ) => Plugin;
19
+ ) => Plugin<VanJSPluginOptions>;
20
20
 
21
21
  export default VitePluginVanJS;
package/router/a.mjs CHANGED
@@ -29,8 +29,8 @@ export const A = (
29
29
  href,
30
30
  ...props,
31
31
  onclick: async (e) => {
32
- const HREF = getValue(href);
33
32
  e.preventDefault();
33
+ const HREF = getValue(href);
34
34
  /* istanbul ignore next */
35
35
  if (isCurrentPage(HREF)) return;
36
36
 
@@ -60,7 +60,7 @@ export const A = (
60
60
  newProps["aria-current"] = van.derive(() => {
61
61
  const isPage = isCurrentPage(href);
62
62
  const isLocation = isCurrentLocation(href);
63
- return isPage ? "page" : isLocation ? "location" : null;
63
+ return isPage ? "page" : isLocation ? "location" : "";
64
64
  });
65
65
 
66
66
  return van.tags.a(newProps, children || otherChildren);
@@ -139,12 +139,8 @@ declare module "@vanjs/router" {
139
139
  path: string;
140
140
  component: () => Promise<ComponentModule>;
141
141
  params?: Record<string, string>;
142
- preload?: (
143
- params?: Record<string, string>,
144
- ) => boolean | void | Promise<boolean | void>;
145
- load?: (
146
- params?: Record<string, string>,
147
- ) => boolean | void | Promise<boolean | void>;
142
+ preload?: (params?: Record<string, string>) => unknown;
143
+ load?: (params?: Record<string, string>) => Promise<unknown>;
148
144
  };
149
145
 
150
146
  export type ImportFn = () => LazyComponent;
@@ -157,12 +153,8 @@ declare module "@vanjs/router" {
157
153
  | VanComponent
158
154
  | ComponentFn
159
155
  | (() => Promise<ComponentModule>);
160
- preload?: (
161
- params?: Record<string, string>,
162
- ) => boolean | void | Promise<boolean | void>;
163
- load?: (
164
- params?: Record<string, string>,
165
- ) => boolean | void | Promise<boolean | void>;
156
+ preload?: (params?: Record<string, string>) => unknown;
157
+ load?: (params?: Record<string, string>) => Promise<unknown>;
166
158
  };
167
159
 
168
160
  export type RouteConfig = {
@@ -191,9 +183,9 @@ declare module "@vanjs/router" {
191
183
  // state.mjs
192
184
  export type RouterState = {
193
185
  pathname: string;
194
- searchParams: URLSearchParams;
186
+ searchParams: string;
195
187
  params: Record<string, string>;
196
- status: "idle" | "pending" | "success" | "error";
188
+ loading: boolean;
197
189
  };
198
190
 
199
191
  /**
@@ -204,7 +196,7 @@ declare module "@vanjs/router" {
204
196
  pathname: RouterState["pathname"];
205
197
  searchParams: RouterState["searchParams"];
206
198
  params?: RouterState["params"];
207
- status: RouterState["status"];
199
+ loading: RouterState["loading"];
208
200
  };
209
201
 
210
202
  /**
@@ -294,9 +286,8 @@ declare module "@vanjs/router" {
294
286
  export const executeLifecycle: (
295
287
  route: RouteEntry | {
296
288
  preload?: (params?: Record<string, string>) => unknown;
297
- load?: (params?: Record<string, string>) => unknown;
289
+ load?: (params?: Record<string, string>) => Promise<unknown>;
298
290
  } | null,
299
- params: Record<string, string> | undefined,
300
291
  ) => Promise<boolean>;
301
292
 
302
293
  /**
@@ -304,8 +295,7 @@ declare module "@vanjs/router" {
304
295
  */
305
296
  export const matchRoute: (path: string) => RouteEntry | null;
306
297
 
307
- /**
308
- * Convenience hook to get the current route's cached data.
298
+ /** * Convenience hook to get the current route's cached data.
309
299
  */
310
300
  export const useRouteData: <T>() => T | undefined;
311
301
 
@@ -1,15 +1,46 @@
1
+ import van from "vanjs-core";
1
2
  import isServer from "../setup/isServer.mjs";
2
3
  import { routerState, setRouterState } from "./state.mjs";
3
4
  import { matchRoute } from "./matchRoute.mjs";
5
+ import { unwrap } from "./unwrap.mjs";
6
+ import { hydrate } from "../client/index.mjs";
7
+ import { Head } from "../meta/index.mjs";
8
+
4
9
  import * as dataCache from "./dataCache.mjs";
5
10
 
6
11
  /** @typedef {typeof import("./types.d.ts").navigate} Navigate */
12
+ /** @typedef {import("./types.d.ts").SearchParamDef} SearchParamDef */
7
13
  /** @typedef {import("./types.d.ts").Route} Route */
8
14
  /** @typedef {import("./types.d.ts").VanNode} VanNode */
9
15
  /** @typedef {import("./types.d.ts").ComponentModule} ComponentModule */
10
16
  /** @typedef {import("./types.d.ts").ComponentFn} ComponentFn */
11
17
  /** @typedef {import("./types.d.ts").LazyComponent} LazyComponent */
12
18
 
19
+ /**
20
+ * Update head tags
21
+ */
22
+ const updateHead = () => {
23
+ // istanbul ignore else
24
+ if (document.head) {
25
+ hydrate(document.head, Head());
26
+ }
27
+ };
28
+
29
+ /**
30
+ * Resolve component children from a module
31
+ * @param {ComponentModule | Element | Element[] | any} module
32
+ * @returns {VanNode[]}
33
+ */
34
+ export const resolveChildren = (module) => {
35
+ const isElement = typeof Element !== "undefined" && module instanceof Element;
36
+ const cp = (Array.isArray(module) || isElement)
37
+ ? module
38
+ : typeof module.component === "function"
39
+ ? module.component()
40
+ : module.component;
41
+ return cp ? Array.from(unwrap(cp).children) : /* istanbul ignore next */ [];
42
+ };
43
+
13
44
  /**
14
45
  * Returns the HREF string value
15
46
  * @param {unknown} v
@@ -19,13 +50,25 @@ export const getValue = (v) => {
19
50
  return typeof v === "function" ? v() : v.rawVal ? v.val : v;
20
51
  };
21
52
 
53
+ export const getCacheKey = () => {
54
+ const params = routerState.params;
55
+ const search = routerState.searchParams;
56
+ return Object.keys(params).length === 0
57
+ ? search || ""
58
+ : JSON.stringify(params) + (search ? `&${search}` : "");
59
+ };
60
+
22
61
  /**
23
62
  * Check if selected page is the current page;
24
63
  * @param {string} pageName
25
64
  * @returns {boolean}
26
65
  */
27
66
  export const isCurrentPage = (pageName) => {
28
- return routerState.pathname === getValue(pageName);
67
+ const href = getValue(pageName);
68
+ const url = new URL(href, "http://localhost:5173");
69
+ // console.log({ href }, routerState.searchParams, url.searchParams.toString())
70
+ return routerState.pathname === url.pathname &&
71
+ routerState.searchParams === url.searchParams.toString();
29
72
  };
30
73
 
31
74
  /**
@@ -34,8 +77,12 @@ export const isCurrentPage = (pageName) => {
34
77
  * @returns {boolean}
35
78
  */
36
79
  export const isCurrentLocation = (pageName) => {
37
- const pathName = routerState.pathname;
38
- return pathName !== "/" && pathName.includes(getValue(pageName));
80
+ const href = getValue(pageName);
81
+ const searchParams = new URLSearchParams(routerState.searchParams);
82
+ const pathname = routerState.pathname;
83
+ const url = new URL(href, "http://localhost:5173");
84
+ return url.pathname !== "/" && pathname.includes(url.pathname) ||
85
+ pathname === url.pathname && searchParams.size > 0;
39
86
  };
40
87
 
41
88
  /**
@@ -53,10 +100,9 @@ export const isLazyComponent = (component) => {
53
100
  /**
54
101
  * Execute lifecycle methods preload and / or load
55
102
  * @param {import("./types.d.ts").RouteEntry} route
56
- * @param {Record<string, string> | undefined} params
57
103
  * @returns {Promise<boolean>}
58
104
  */
59
- export const executeLifecycle = async (route, params) => {
105
+ export const executeLifecycle = async (route) => {
60
106
  // istanbul ignore next
61
107
  try {
62
108
  if (!route) return true;
@@ -66,13 +112,11 @@ export const executeLifecycle = async (route, params) => {
66
112
  const load = route.load;
67
113
 
68
114
  const pathname = routerState.pathname;
69
- const cacheKey = Object.keys(params || {}).length === 0
70
- ? ""
71
- : JSON.stringify(params);
115
+ const cacheKey = getCacheKey();
72
116
 
73
- if (preload) await preload(params);
117
+ if (preload) await preload(route.params);
74
118
  if (!data && load && !dataCache.has(pathname, cacheKey)) {
75
- data = await load(params);
119
+ data = await load(route.params);
76
120
  } else if (load && dataCache.has(pathname, cacheKey)) {
77
121
  dataCache.touch(pathname);
78
122
  }
@@ -97,13 +141,37 @@ export const executeLifecycle = async (route, params) => {
97
141
  }
98
142
  };
99
143
 
144
+ /**
145
+ * @param {RouteEntry} route
146
+ * @param {HTMLElement} wrapper
147
+ * @param {boolean} ssr
148
+ * @returns
149
+ */
150
+ export const executeModule = async (route, wrapper, ssr) => {
151
+ if (routerState.loading === true) return;
152
+ // 0. Set Loading State
153
+ routerState.loading = true;
154
+ // 1. Resolve the module first (to get route lifecycle hooks)
155
+ const module = await route.component();
156
+ // 2. Execute lifecycle (a complete route includes all props)
157
+ await executeLifecycle(Object.assign(route, module.route));
158
+ // 3. Resolve children
159
+ const children = resolveChildren(module);
160
+ // 4. Update <head> in the client
161
+ if (!isServer) updateHead();
162
+ // 5. Set Loading State
163
+ routerState.loading = false;
164
+ // 6. Update / replace children in wrapper
165
+ if (ssr) return van.add(wrapper, ...children);
166
+ else wrapper.replaceChildren(...children);
167
+ };
168
+
100
169
  /**
101
170
  * Convenience hook to get the current route's cached data.
102
171
  * @returns {any | undefined}
103
172
  */
104
173
  export const useRouteData = () => {
105
- const params = routerState.params;
106
- const key = Object.keys(params).length === 0 ? "" : JSON.stringify(params);
174
+ const key = getCacheKey();
107
175
  return dataCache.get(routerState.pathname, key)?.data;
108
176
  };
109
177
 
package/router/router.mjs CHANGED
@@ -1,43 +1,19 @@
1
1
  import van from "vanjs-core";
2
2
  import isServer from "../setup/isServer.mjs";
3
+ import { MODE } from "../plugin/const.mjs";
3
4
  import { routerState, setRouterState } from "./state.mjs";
4
5
  import { matchRoute } from "./matchRoute.mjs";
5
- import { executeLifecycle } from "./helpers.mjs";
6
- import { unwrap } from "./unwrap.mjs";
7
- import { hydrate } from "../client/index.mjs";
8
- import { Head, initializeHeadTags } from "../meta/index.mjs";
6
+ import { executeModule } from "./helpers.mjs";
7
+ import { initializeHeadTags } from "../meta/index.mjs";
9
8
  import * as dataCache from "./dataCache.mjs";
10
9
  import "virtual:@vanjs/routes";
11
10
 
11
+ const isDev = MODE === "development";
12
+
12
13
  /** @typedef {import("./types.d.ts").ComponentModule} ComponentModule */
13
14
  /** @typedef {import("./types.d.ts").RouteEntry} RouteEntry */
14
15
  /** @typedef {import("./types.d.ts").VanNode} VanNode */
15
16
 
16
- /**
17
- * Resolve component children from a module
18
- * @param {ComponentModule | Element | Element[] | any} module
19
- * @returns {VanNode[]}
20
- */
21
- const resolveChildren = (module) => {
22
- const isElement = typeof Element !== "undefined" && module instanceof Element;
23
- const cp = (Array.isArray(module) || isElement)
24
- ? module
25
- : typeof module.component === "function"
26
- ? module.component()
27
- : module.component;
28
- return cp ? Array.from(unwrap(cp).children) : /* istanbul ignore next */ [];
29
- };
30
-
31
- /**
32
- * Update head tags
33
- */
34
- const updateHead = () => {
35
- // istanbul ignore else
36
- if (document.head) {
37
- hydrate(document.head, Head());
38
- }
39
- };
40
-
41
17
  /**
42
18
  * Initialize client-side router (Head + popstate listener)
43
19
  */
@@ -53,8 +29,10 @@ const initClient = () => {
53
29
  (e) => {
54
30
  const location = e.target.location;
55
31
  const oldPath = routerState.pathname;
32
+ const oldSearch = routerState.searchParams;
33
+ const newSearch = new URLSearchParams(location.search).toString();
56
34
  // istanbul ignore next - cannot test
57
- if (location.pathname !== oldPath) {
35
+ if (location.pathname !== oldPath || newSearch !== oldSearch) {
58
36
  setRouterState(location.pathname, location.search);
59
37
  }
60
38
  },
@@ -69,25 +47,18 @@ export const Router = (initialProps = /* istanbul ignore next */ {}) => {
69
47
  );
70
48
  const wrapper = main({ ...props, "data-root": "" });
71
49
  const route = matchRoute(routerState.pathname);
50
+ let _searchParams = routerState.searchParams;
72
51
 
73
52
  /* istanbul ignore else */
74
53
  if (!route) return van.add(wrapper, div("No Route Found"));
75
-
76
- Object.assign(routerState.params, route.params || {});
54
+ // It's important to READ the params
55
+ Object.assign(routerState.params, route.params);
77
56
 
78
57
  // Server-side rendering
79
58
  if (isServer) {
80
59
  return async () => {
81
60
  try {
82
- // 1. Resolve the module first (to get route lifecycle hooks)
83
- const module = await route.component();
84
-
85
- // 2. Execute lifecycle
86
- await executeLifecycle(module.route, route.params);
87
- const children = resolveChildren(module);
88
-
89
- // 3. Render the component (data is now in dataCache)
90
- return van.add(wrapper, ...children);
61
+ return await executeModule(route, wrapper, true);
91
62
  } catch (error) {
92
63
  /* istanbul ignore next */
93
64
  console.error("Router error:", error);
@@ -98,11 +69,13 @@ export const Router = (initialProps = /* istanbul ignore next */ {}) => {
98
69
  }
99
70
 
100
71
  // Init client here
101
- if (!isServer) initClient();
72
+ initClient();
73
+ let initialized = false;
102
74
 
103
75
  // Client-side: hydrate data cache from SSR output
104
76
  // This must happen BEFORE any component renders so useRouteData() works
105
- if (globalThis.__DATA_CACHE) {
77
+ // Skip in dev mode: we manually clear dataCache on mutations for instant updates
78
+ if (globalThis.__DATA_CACHE && !isDev) {
106
79
  dataCache.hydrateFromJSON(globalThis.__DATA_CACHE);
107
80
  }
108
81
 
@@ -110,13 +83,22 @@ export const Router = (initialProps = /* istanbul ignore next */ {}) => {
110
83
  const root = document.querySelector("[data-root]");
111
84
 
112
85
  if (root) {
86
+ van.derive(() => {
87
+ if (!initialized) return;
88
+ const matchedRoute = matchRoute(routerState.pathname);
89
+ if (!matchedRoute) {
90
+ wrapper.replaceChildren(div("No Route Found"));
91
+ return;
92
+ }
93
+ (async () => {
94
+ _searchParams = routerState.searchParams;
95
+ await executeModule(matchedRoute, wrapper);
96
+ })();
97
+ });
113
98
  return async () => {
114
- const module = await route.component();
115
-
116
- await executeLifecycle(module.route, route.params);
117
- const children = resolveChildren(module);
118
- updateHead();
119
- return van.add(wrapper, ...children);
99
+ const result = await executeModule(route, wrapper, true);
100
+ initialized = true;
101
+ return result;
120
102
  };
121
103
  }
122
104
 
@@ -129,11 +111,8 @@ export const Router = (initialProps = /* istanbul ignore next */ {}) => {
129
111
  }
130
112
 
131
113
  (async () => {
132
- const module = await matchedRoute.component();
133
- await executeLifecycle(module.route, matchedRoute.params);
134
- const children = resolveChildren(module);
135
- wrapper.replaceChildren(...children);
136
- updateHead();
114
+ _searchParams = routerState.searchParams;
115
+ await executeModule(matchedRoute, wrapper);
137
116
  })();
138
117
  });
139
118
 
package/router/state.mjs CHANGED
@@ -18,6 +18,16 @@ export const fixRouteUrl = (url) => {
18
18
  const initialPath = !isServer ? globalThis.location.pathname : "/";
19
19
  const initialSearch = !isServer ? globalThis.location.search : "";
20
20
 
21
+ /**
22
+ * Normalize a search string to a plain string (strip leading "?")
23
+ * @param {string} search
24
+ * @returns {string}
25
+ */
26
+ const normalizeSearch = (search) => {
27
+ if (!search) return "";
28
+ return search.startsWith("?") ? search.slice(1) : search;
29
+ };
30
+
21
31
  const STATE_PROXY = "_proxy";
22
32
  const proxyProps = {
23
33
  value: 1,
@@ -72,7 +82,7 @@ export function microStore(init) {
72
82
  target[prop] = defineProxy(sp, sv, {});
73
83
  }
74
84
  } else if (isPlainObject) {
75
- target[prop] = value;
85
+ defineProxy(prop, value, target);
76
86
  } else if (!Array.isArray(value) && value != null) {
77
87
  defineProxy(prop, value, target);
78
88
  } else {
@@ -82,29 +92,20 @@ export function microStore(init) {
82
92
  return target;
83
93
  }
84
94
 
85
- /**
86
- * @type {typeof import("./types.d.ts").routerState}
87
- */
88
- const initialStatus = isServer
89
- ? "success"
90
- : (globalThis.__DATA_CACHE ? "success" : "idle");
91
-
92
95
  export const routerState = microStore({
93
96
  pathname: initialPath,
94
- searchParams: new URLSearchParams(initialSearch),
97
+ searchParams: normalizeSearch(initialSearch),
95
98
  params: {},
96
- status: initialStatus,
99
+ loading: false,
97
100
  });
98
101
 
99
102
  /**
100
103
  * @type {typeof import("./types.d.ts").setRouterState}
101
104
  */
102
105
  export const setRouterState = (path, search = undefined, params = {}) => {
103
- const [pathname, searchParams] = fixRouteUrl(path).split("?");
106
+ const [pathname, searchPart] = fixRouteUrl(path).split("?");
104
107
  routerState.pathname = pathname;
105
- routerState.searchParams = new URLSearchParams(
106
- search || searchParams || "",
107
- );
108
+ routerState.searchParams = normalizeSearch(search || searchPart || "");
108
109
  Object.keys(routerState.params).forEach((key) =>
109
110
  delete routerState.params[key]
110
111
  );
package/router/types.d.ts CHANGED
@@ -83,10 +83,9 @@ export const isLazyComponent: (component: unknown) => boolean;
83
83
 
84
84
  export const executeLifecycle: (
85
85
  route: RouteEntry | {
86
- preload?: (params?: Record<string, string>) => unknown;
87
- load?: (params?: Record<string, string>) => unknown;
86
+ preload?: (params?: Record<string, unknown>) => unknown;
87
+ load?: (params?: Record<string, string>) => Promise<unknown>;
88
88
  } | null,
89
- params: Record<string, string> | undefined,
90
89
  ) => Promise<boolean>;
91
90
 
92
91
  export const useRouteData: <T>() => T | undefined;
@@ -104,12 +103,8 @@ export type RouteEntry = {
104
103
  path: string;
105
104
  component: () => Promise<ComponentModule>;
106
105
  params?: Record<string, string>;
107
- preload?: (
108
- params?: Record<string, string>,
109
- ) => boolean | void | Promise<boolean | void>;
110
- load?: (
111
- params?: Record<string, string>,
112
- ) => boolean | void | Promise<boolean | void>;
106
+ preload?: (params?: Record<string, string>) => unknown;
107
+ load?: (params?: Record<string, string>) => Promise<unknown>;
113
108
  };
114
109
 
115
110
  export type ImportFn = () => LazyComponent;
@@ -124,12 +119,8 @@ export type RouteProps = {
124
119
  | VanComponent
125
120
  | ComponentFn
126
121
  | (() => Promise<ComponentModule>);
127
- preload?: (
128
- params?: Record<string, string>,
129
- ) => boolean | void | Promise<boolean | void>;
130
- load?: (
131
- params?: Record<string, string>,
132
- ) => boolean | void | Promise<boolean | void>;
122
+ preload?: (params?: Record<string, string>) => unknown;
123
+ load?: (params?: Record<string, string>) => Promise<unknown>;
133
124
  };
134
125
 
135
126
  export type RouteConfig = {
@@ -145,16 +136,16 @@ export const Route: (route: RouteProps) => void;
145
136
  // state.mjs
146
137
  export type RouterState = {
147
138
  pathname: string;
148
- searchParams: URLSearchParams;
139
+ searchParams: string;
149
140
  params: Record<string, string>;
150
- status: "idle" | "pending" | "success" | "error";
141
+ loading: boolean;
151
142
  };
152
143
 
153
144
  export const routerState: {
154
145
  pathname: RouterState["pathname"];
155
146
  searchParams: RouterState["searchParams"];
156
147
  params?: RouterState["params"];
157
- status: RouterState["status"];
148
+ loading: RouterState["loading"];
158
149
  };
159
150
 
160
151
  export const setRouterState: (