@esmx/router 3.0.0-rc.25 → 3.0.0-rc.26
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/navigation.d.ts +3 -1
- package/dist/navigation.mjs +8 -2
- package/dist/router-link.mjs +12 -7
- package/dist/router.mjs +14 -2
- package/dist/types.d.ts +4 -2
- package/package.json +3 -3
- package/src/navigation.ts +9 -2
- package/src/router-link.ts +20 -17
- package/src/router.ts +14 -2
- package/src/types.ts +7 -2
package/dist/navigation.d.ts
CHANGED
|
@@ -18,7 +18,9 @@ export declare class Navigation {
|
|
|
18
18
|
replace(data: any, url?: string | URL | null): RouteState;
|
|
19
19
|
pushHistoryState(data: any, url?: string | URL | null): void;
|
|
20
20
|
replaceHistoryState(data: any, url?: string | URL | null): void;
|
|
21
|
-
|
|
21
|
+
backHistoryState(): Promise<NavigationGoResult>;
|
|
22
|
+
private _go;
|
|
23
|
+
go(delta?: number): Promise<NavigationGoResult>;
|
|
22
24
|
forward(): Promise<NavigationGoResult>;
|
|
23
25
|
back(): Promise<NavigationGoResult>;
|
|
24
26
|
destroy(): void;
|
package/dist/navigation.mjs
CHANGED
|
@@ -53,7 +53,10 @@ export class Navigation {
|
|
|
53
53
|
replaceHistoryState(data, url) {
|
|
54
54
|
this._replace(history, data, url);
|
|
55
55
|
}
|
|
56
|
-
|
|
56
|
+
backHistoryState() {
|
|
57
|
+
return this._go(history, -1);
|
|
58
|
+
}
|
|
59
|
+
_go(history2, index) {
|
|
57
60
|
if (this._promiseResolve) {
|
|
58
61
|
return Promise.resolve(null);
|
|
59
62
|
}
|
|
@@ -64,9 +67,12 @@ export class Navigation {
|
|
|
64
67
|
resolve({ type: "success", url, state: state || {} });
|
|
65
68
|
};
|
|
66
69
|
setTimeout(this._promiseResolve, 80);
|
|
67
|
-
|
|
70
|
+
history2.go(index);
|
|
68
71
|
});
|
|
69
72
|
}
|
|
73
|
+
go(delta) {
|
|
74
|
+
return this._go(this._history, delta || 0);
|
|
75
|
+
}
|
|
70
76
|
forward() {
|
|
71
77
|
return this.go(1);
|
|
72
78
|
}
|
package/dist/router-link.mjs
CHANGED
|
@@ -18,9 +18,13 @@ function getEventTypeList(eventType) {
|
|
|
18
18
|
return validEvents.length ? validEvents : ["click"];
|
|
19
19
|
}
|
|
20
20
|
function guardEvent(e) {
|
|
21
|
-
|
|
22
|
-
if (e
|
|
23
|
-
if (e.
|
|
21
|
+
var _a, _b, _c;
|
|
22
|
+
if (!e) return;
|
|
23
|
+
if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return;
|
|
24
|
+
if (e.defaultPrevented) return;
|
|
25
|
+
if (e.button !== void 0 && e.button !== 0) return;
|
|
26
|
+
const target = (_c = (_b = (_a = e.currentTarget) == null ? void 0 : _a.getAttribute) == null ? void 0 : _b.call(_a, "target")) != null ? _c : "";
|
|
27
|
+
if (/\b_blank\b/i.test(target)) return;
|
|
24
28
|
if (e.preventDefault) e.preventDefault();
|
|
25
29
|
return true;
|
|
26
30
|
}
|
|
@@ -50,9 +54,9 @@ async function executeNavigation(router, props, linkType) {
|
|
|
50
54
|
}
|
|
51
55
|
function createNavigateFunction(router, props, navigationType) {
|
|
52
56
|
return async (e) => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
var _a;
|
|
58
|
+
const eventHandler = (_a = props.eventHandler) != null ? _a : guardEvent;
|
|
59
|
+
if (!eventHandler(e)) return;
|
|
56
60
|
await executeNavigation(router, props, navigationType);
|
|
57
61
|
};
|
|
58
62
|
}
|
|
@@ -88,7 +92,8 @@ function createEventHandlersGenerator(navigate, eventTypes) {
|
|
|
88
92
|
return (nameTransform) => {
|
|
89
93
|
const handlers = {};
|
|
90
94
|
eventTypes.forEach((eventType) => {
|
|
91
|
-
|
|
95
|
+
var _a;
|
|
96
|
+
const eventName = (_a = nameTransform == null ? void 0 : nameTransform(eventType)) != null ? _a : eventType.toLowerCase();
|
|
92
97
|
handlers[eventName] = navigate;
|
|
93
98
|
});
|
|
94
99
|
return handlers;
|
package/dist/router.mjs
CHANGED
|
@@ -200,10 +200,10 @@ export class Router {
|
|
|
200
200
|
}
|
|
201
201
|
async createLayer(toInput) {
|
|
202
202
|
var _a;
|
|
203
|
-
const layerOptions =
|
|
203
|
+
const layerOptions = isPlainObject(toInput) && toInput.layer || {};
|
|
204
204
|
const zIndex = (_a = layerOptions.zIndex) != null ? _a : this.parsedOptions.zIndex + LAYER_ID.next();
|
|
205
205
|
let promiseResolve;
|
|
206
|
-
|
|
206
|
+
let promise = new Promise((resolve) => {
|
|
207
207
|
promiseResolve = resolve;
|
|
208
208
|
});
|
|
209
209
|
const router = new Router({
|
|
@@ -265,6 +265,18 @@ export class Router {
|
|
|
265
265
|
router.route.state,
|
|
266
266
|
router.route.url
|
|
267
267
|
);
|
|
268
|
+
promise = promise.then(async (result) => {
|
|
269
|
+
await this.navigation.backHistoryState();
|
|
270
|
+
return result;
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
if (layerOptions.autoPush) {
|
|
274
|
+
promise = promise.then(async (result) => {
|
|
275
|
+
if (result.type === "push") {
|
|
276
|
+
await this.push(result.route.url.href);
|
|
277
|
+
}
|
|
278
|
+
return result;
|
|
279
|
+
});
|
|
268
280
|
}
|
|
269
281
|
return {
|
|
270
282
|
promise,
|
package/dist/types.d.ts
CHANGED
|
@@ -214,6 +214,7 @@ export interface RouterLinkAttributes {
|
|
|
214
214
|
target?: '_blank';
|
|
215
215
|
rel?: string;
|
|
216
216
|
}
|
|
217
|
+
export type RouterLinkEventHandler = <E extends Event = MouseEvent>(event: E) => boolean | void;
|
|
217
218
|
/**
|
|
218
219
|
* Framework-agnostic link configuration interface
|
|
219
220
|
*/
|
|
@@ -229,6 +230,7 @@ export interface RouterLinkProps {
|
|
|
229
230
|
event?: string | string[];
|
|
230
231
|
tag?: string;
|
|
231
232
|
layerOptions?: RouteLayerOptions;
|
|
233
|
+
eventHandler?: RouterLinkEventHandler;
|
|
232
234
|
}
|
|
233
235
|
/**
|
|
234
236
|
* Framework-agnostic link resolution result
|
|
@@ -241,6 +243,6 @@ export interface RouterLinkResolved {
|
|
|
241
243
|
isExternal: boolean;
|
|
242
244
|
tag: string;
|
|
243
245
|
attributes: RouterLinkAttributes;
|
|
244
|
-
navigate: (e?:
|
|
245
|
-
getEventHandlers: (nameTransform?: (eventType: string) => string) => Record<string, (e:
|
|
246
|
+
navigate: (e?: Event) => Promise<void>;
|
|
247
|
+
getEventHandlers: (nameTransform?: (eventType: string) => string) => Record<string, (e: Event) => Promise<void> | undefined>;
|
|
246
248
|
}
|
package/package.json
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@biomejs/biome": "1.9.4",
|
|
35
|
-
"@esmx/lint": "3.0.0-rc.
|
|
35
|
+
"@esmx/lint": "3.0.0-rc.26",
|
|
36
36
|
"@types/node": "^24.0.10",
|
|
37
37
|
"@vitest/coverage-v8": "3.2.4",
|
|
38
38
|
"happy-dom": "^18.0.1",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"unbuild": "3.5.0",
|
|
42
42
|
"vitest": "3.2.4"
|
|
43
43
|
},
|
|
44
|
-
"version": "3.0.0-rc.
|
|
44
|
+
"version": "3.0.0-rc.26",
|
|
45
45
|
"type": "module",
|
|
46
46
|
"private": false,
|
|
47
47
|
"exports": {
|
|
@@ -60,5 +60,5 @@
|
|
|
60
60
|
"template",
|
|
61
61
|
"public"
|
|
62
62
|
],
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "2f52f94c8ac27aca32ef3148afd109d0f0470d52"
|
|
64
64
|
}
|
package/src/navigation.ts
CHANGED
|
@@ -86,7 +86,11 @@ export class Navigation {
|
|
|
86
86
|
this._replace(history, data, url);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
public
|
|
89
|
+
public backHistoryState() {
|
|
90
|
+
return this._go(history, -1);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private _go(history: History, index: number): Promise<NavigationGoResult> {
|
|
90
94
|
if (this._promiseResolve) {
|
|
91
95
|
return Promise.resolve(null);
|
|
92
96
|
}
|
|
@@ -97,9 +101,12 @@ export class Navigation {
|
|
|
97
101
|
resolve({ type: 'success', url, state: state || {} });
|
|
98
102
|
};
|
|
99
103
|
setTimeout(this._promiseResolve, 80);
|
|
100
|
-
|
|
104
|
+
history.go(index);
|
|
101
105
|
});
|
|
102
106
|
}
|
|
107
|
+
public go(delta?: number): Promise<NavigationGoResult> {
|
|
108
|
+
return this._go(this._history, delta || 0);
|
|
109
|
+
}
|
|
103
110
|
public forward(): Promise<NavigationGoResult> {
|
|
104
111
|
return this.go(1);
|
|
105
112
|
}
|
package/src/router-link.ts
CHANGED
|
@@ -43,19 +43,24 @@ function getEventTypeList(eventType: unknown | unknown[]): string[] {
|
|
|
43
43
|
/**
|
|
44
44
|
* Event guard check - determines if the router should handle the navigation
|
|
45
45
|
*
|
|
46
|
-
* Returns
|
|
47
|
-
* Returns
|
|
46
|
+
* Returns !0: Let browser handle default behavior (normal link navigation)
|
|
47
|
+
* Returns 0: Router takes over navigation, prevents default browser behavior
|
|
48
48
|
*
|
|
49
49
|
* This function intelligently decides when to let the browser handle clicks
|
|
50
50
|
* (like Ctrl+click for new tabs) vs when to use SPA routing
|
|
51
51
|
*/
|
|
52
|
-
function guardEvent(e
|
|
52
|
+
function guardEvent(e?: Event & Partial<MouseEvent>): true | undefined {
|
|
53
|
+
if (!e) return;
|
|
53
54
|
// don't redirect with control keys
|
|
54
|
-
if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return
|
|
55
|
+
if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return;
|
|
55
56
|
// don't redirect when preventDefault called
|
|
56
|
-
if (e.defaultPrevented) return
|
|
57
|
+
if (e.defaultPrevented) return;
|
|
57
58
|
// don't redirect on right click
|
|
58
|
-
if (e.button !== undefined && e.button !== 0) return
|
|
59
|
+
if (e.button !== undefined && e.button !== 0) return;
|
|
60
|
+
// don't redirect if `target="_blank"`
|
|
61
|
+
// @ts-expect-error getAttribute exists
|
|
62
|
+
const target = e.currentTarget?.getAttribute?.('target') ?? '';
|
|
63
|
+
if (/\b_blank\b/i.test(target)) return;
|
|
59
64
|
// Prevent default browser navigation to enable SPA routing
|
|
60
65
|
// Note: this may be a Weex event which doesn't have this method
|
|
61
66
|
if (e.preventDefault) e.preventDefault();
|
|
@@ -107,11 +112,10 @@ function createNavigateFunction(
|
|
|
107
112
|
router: Router,
|
|
108
113
|
props: RouterLinkProps,
|
|
109
114
|
navigationType: RouterLinkType
|
|
110
|
-
): (e?:
|
|
111
|
-
return async (e?:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
+
): (e?: Event) => Promise<void> {
|
|
116
|
+
return async (e?: Event): Promise<void> => {
|
|
117
|
+
const eventHandler = props.eventHandler ?? guardEvent;
|
|
118
|
+
if (!eventHandler(e!)) return;
|
|
115
119
|
|
|
116
120
|
await executeNavigation(router, props, navigationType);
|
|
117
121
|
};
|
|
@@ -169,18 +173,17 @@ function computeAttributes(
|
|
|
169
173
|
* Create event handlers generator function
|
|
170
174
|
*/
|
|
171
175
|
function createEventHandlersGenerator(
|
|
172
|
-
navigate: (e
|
|
176
|
+
navigate: (e: Event) => Promise<void>,
|
|
173
177
|
eventTypes: string[]
|
|
174
178
|
): (
|
|
175
179
|
nameTransform?: (eventType: string) => string
|
|
176
|
-
) => Record<string, (e:
|
|
180
|
+
) => Record<string, (e: Event) => Promise<void>> {
|
|
177
181
|
return (nameTransform?: (eventType: string) => string) => {
|
|
178
|
-
const handlers: Record<string, (e:
|
|
182
|
+
const handlers: Record<string, (e: Event) => Promise<void>> = {};
|
|
179
183
|
|
|
180
184
|
eventTypes.forEach((eventType) => {
|
|
181
|
-
const eventName =
|
|
182
|
-
|
|
183
|
-
: eventType.toLowerCase();
|
|
185
|
+
const eventName =
|
|
186
|
+
nameTransform?.(eventType) ?? eventType.toLowerCase();
|
|
184
187
|
handlers[eventName] = navigate;
|
|
185
188
|
});
|
|
186
189
|
|
package/src/router.ts
CHANGED
|
@@ -227,13 +227,13 @@ export class Router {
|
|
|
227
227
|
toInput: RouteLocationInput
|
|
228
228
|
): Promise<{ promise: Promise<RouteLayerResult>; router: Router }> {
|
|
229
229
|
const layerOptions: RouteLayerOptions =
|
|
230
|
-
(isPlainObject(toInput)
|
|
230
|
+
(isPlainObject(toInput) && toInput.layer) || {};
|
|
231
231
|
|
|
232
232
|
const zIndex =
|
|
233
233
|
layerOptions.zIndex ?? this.parsedOptions.zIndex + LAYER_ID.next();
|
|
234
234
|
|
|
235
235
|
let promiseResolve: (result: RouteLayerResult) => void;
|
|
236
|
-
|
|
236
|
+
let promise = new Promise<RouteLayerResult>((resolve) => {
|
|
237
237
|
promiseResolve = resolve;
|
|
238
238
|
});
|
|
239
239
|
|
|
@@ -297,6 +297,18 @@ export class Router {
|
|
|
297
297
|
router.route.state,
|
|
298
298
|
router.route.url
|
|
299
299
|
);
|
|
300
|
+
promise = promise.then(async (result) => {
|
|
301
|
+
await this.navigation.backHistoryState();
|
|
302
|
+
return result;
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
if (layerOptions.autoPush) {
|
|
306
|
+
promise = promise.then(async (result) => {
|
|
307
|
+
if (result.type === 'push') {
|
|
308
|
+
await this.push(result.route.url.href);
|
|
309
|
+
}
|
|
310
|
+
return result;
|
|
311
|
+
});
|
|
300
312
|
}
|
|
301
313
|
return {
|
|
302
314
|
promise,
|
package/src/types.ts
CHANGED
|
@@ -299,6 +299,10 @@ export interface RouterLinkAttributes {
|
|
|
299
299
|
rel?: string;
|
|
300
300
|
}
|
|
301
301
|
|
|
302
|
+
export type RouterLinkEventHandler = <E extends Event = MouseEvent>(
|
|
303
|
+
event: E
|
|
304
|
+
) => boolean | void;
|
|
305
|
+
|
|
302
306
|
/**
|
|
303
307
|
* Framework-agnostic link configuration interface
|
|
304
308
|
*/
|
|
@@ -314,6 +318,7 @@ export interface RouterLinkProps {
|
|
|
314
318
|
event?: string | string[];
|
|
315
319
|
tag?: string;
|
|
316
320
|
layerOptions?: RouteLayerOptions;
|
|
321
|
+
eventHandler?: RouterLinkEventHandler;
|
|
317
322
|
}
|
|
318
323
|
|
|
319
324
|
/**
|
|
@@ -332,10 +337,10 @@ export interface RouterLinkResolved {
|
|
|
332
337
|
attributes: RouterLinkAttributes;
|
|
333
338
|
|
|
334
339
|
// Navigation function
|
|
335
|
-
navigate: (e?:
|
|
340
|
+
navigate: (e?: Event) => Promise<void>;
|
|
336
341
|
|
|
337
342
|
// Event handling
|
|
338
343
|
getEventHandlers: (
|
|
339
344
|
nameTransform?: (eventType: string) => string
|
|
340
|
-
) => Record<string, (e:
|
|
345
|
+
) => Record<string, (e: Event) => Promise<void> | undefined>;
|
|
341
346
|
}
|