@esmx/router 3.0.0-rc.12 → 3.0.0-rc.122

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.
Files changed (106) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +158 -0
  3. package/README.zh-CN.md +158 -0
  4. package/dist/error.d.ts +23 -0
  5. package/dist/error.mjs +64 -0
  6. package/dist/increment-id.d.ts +7 -0
  7. package/dist/increment-id.mjs +16 -0
  8. package/dist/index.d.ts +14 -3
  9. package/dist/index.mjs +13 -3
  10. package/dist/location.d.ts +22 -0
  11. package/dist/location.mjs +64 -0
  12. package/dist/matcher.d.ts +4 -0
  13. package/dist/matcher.mjs +49 -0
  14. package/dist/micro-app.d.ts +20 -0
  15. package/dist/micro-app.mjs +132 -0
  16. package/dist/navigation.d.ts +45 -0
  17. package/dist/navigation.mjs +153 -0
  18. package/dist/options.d.ts +4 -0
  19. package/dist/options.mjs +95 -0
  20. package/dist/route-task.d.ts +40 -0
  21. package/dist/route-task.mjs +77 -0
  22. package/dist/route-transition.d.ts +54 -0
  23. package/dist/route-transition.mjs +362 -0
  24. package/dist/route.d.ts +77 -0
  25. package/dist/route.mjs +223 -0
  26. package/dist/router-link.d.ts +10 -0
  27. package/dist/router-link.mjs +142 -0
  28. package/dist/router.d.ts +113 -102
  29. package/dist/router.mjs +321 -354
  30. package/dist/scroll.d.ts +33 -0
  31. package/dist/scroll.mjs +50 -0
  32. package/dist/types.d.ts +312 -0
  33. package/dist/types.mjs +18 -0
  34. package/dist/util.d.ts +32 -0
  35. package/dist/util.mjs +100 -0
  36. package/package.json +89 -62
  37. package/src/error.ts +84 -0
  38. package/src/increment-id.ts +12 -0
  39. package/src/index.ts +67 -3
  40. package/src/location.ts +124 -0
  41. package/src/matcher.ts +71 -0
  42. package/src/micro-app.ts +153 -0
  43. package/src/navigation.ts +202 -0
  44. package/src/options.ts +136 -0
  45. package/src/route-task.ts +102 -0
  46. package/src/route-transition.ts +480 -0
  47. package/src/route.ts +335 -0
  48. package/src/router-link.ts +241 -0
  49. package/src/router.ts +351 -467
  50. package/src/scroll.ts +106 -0
  51. package/src/types.ts +415 -0
  52. package/src/util.ts +184 -0
  53. package/dist/history/abstract.d.ts +0 -29
  54. package/dist/history/abstract.mjs +0 -107
  55. package/dist/history/base.d.ts +0 -79
  56. package/dist/history/base.mjs +0 -275
  57. package/dist/history/html.d.ts +0 -22
  58. package/dist/history/html.mjs +0 -181
  59. package/dist/history/index.d.ts +0 -7
  60. package/dist/history/index.mjs +0 -16
  61. package/dist/matcher/create-matcher.d.ts +0 -5
  62. package/dist/matcher/create-matcher.mjs +0 -218
  63. package/dist/matcher/create-matcher.spec.d.ts +0 -1
  64. package/dist/matcher/create-matcher.spec.mjs +0 -0
  65. package/dist/matcher/index.d.ts +0 -1
  66. package/dist/matcher/index.mjs +0 -1
  67. package/dist/task-pipe/index.d.ts +0 -1
  68. package/dist/task-pipe/index.mjs +0 -1
  69. package/dist/task-pipe/task.d.ts +0 -30
  70. package/dist/task-pipe/task.mjs +0 -66
  71. package/dist/utils/bom.d.ts +0 -5
  72. package/dist/utils/bom.mjs +0 -10
  73. package/dist/utils/encoding.d.ts +0 -48
  74. package/dist/utils/encoding.mjs +0 -44
  75. package/dist/utils/guards.d.ts +0 -9
  76. package/dist/utils/guards.mjs +0 -12
  77. package/dist/utils/index.d.ts +0 -7
  78. package/dist/utils/index.mjs +0 -27
  79. package/dist/utils/path.d.ts +0 -60
  80. package/dist/utils/path.mjs +0 -264
  81. package/dist/utils/path.spec.d.ts +0 -1
  82. package/dist/utils/path.spec.mjs +0 -30
  83. package/dist/utils/scroll.d.ts +0 -25
  84. package/dist/utils/scroll.mjs +0 -59
  85. package/dist/utils/utils.d.ts +0 -16
  86. package/dist/utils/utils.mjs +0 -11
  87. package/dist/utils/warn.d.ts +0 -2
  88. package/dist/utils/warn.mjs +0 -12
  89. package/src/history/abstract.ts +0 -149
  90. package/src/history/base.ts +0 -408
  91. package/src/history/html.ts +0 -231
  92. package/src/history/index.ts +0 -20
  93. package/src/matcher/create-matcher.spec.ts +0 -3
  94. package/src/matcher/create-matcher.ts +0 -293
  95. package/src/matcher/index.ts +0 -1
  96. package/src/task-pipe/index.ts +0 -1
  97. package/src/task-pipe/task.ts +0 -97
  98. package/src/utils/bom.ts +0 -14
  99. package/src/utils/encoding.ts +0 -153
  100. package/src/utils/guards.ts +0 -25
  101. package/src/utils/index.ts +0 -27
  102. package/src/utils/path.spec.ts +0 -44
  103. package/src/utils/path.ts +0 -397
  104. package/src/utils/scroll.ts +0 -120
  105. package/src/utils/utils.ts +0 -30
  106. package/src/utils/warn.ts +0 -13
@@ -0,0 +1,142 @@
1
+ const CSS_CLASSES = {
2
+ BASE: "router-link",
3
+ ACTIVE: "router-link-active",
4
+ EXACT_ACTIVE: "router-link-exact-active"
5
+ };
6
+ function normalizeNavigationType(props) {
7
+ if (props.replace) {
8
+ console.warn(
9
+ '[RouterLink] The `replace` property is deprecated and will be removed in a future version.\nPlease use `type="replace"` instead.\nBefore: <RouterLink replace={true} />\nAfter: <RouterLink type="replace" />'
10
+ );
11
+ return "replace";
12
+ }
13
+ return props.type || "push";
14
+ }
15
+ function getEventTypeList(eventType) {
16
+ const events = Array.isArray(eventType) ? eventType : [eventType];
17
+ const validEvents = events.filter((type) => typeof type === "string").map((type) => type.trim()).filter(Boolean);
18
+ return validEvents.length ? validEvents : ["click"];
19
+ }
20
+ function shouldHandleNavigation(e) {
21
+ var _a;
22
+ if (e.defaultPrevented) return false;
23
+ if (e instanceof MouseEvent) {
24
+ if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return false;
25
+ if (e.button !== void 0 && e.button !== 0) return false;
26
+ }
27
+ (_a = e.preventDefault) == null ? void 0 : _a.call(e);
28
+ return true;
29
+ }
30
+ async function executeNavigation(router, props, linkType) {
31
+ const { to, layerOptions } = props;
32
+ switch (linkType) {
33
+ case "push":
34
+ await router.push(to);
35
+ break;
36
+ case "replace":
37
+ await router.replace(to);
38
+ break;
39
+ case "pushWindow":
40
+ await router.pushWindow(to);
41
+ break;
42
+ case "replaceWindow":
43
+ await router.replaceWindow(to);
44
+ break;
45
+ case "pushLayer":
46
+ await router.pushLayer(
47
+ layerOptions ? typeof to === "string" ? { path: to, layer: layerOptions } : { ...to, layer: layerOptions } : to
48
+ );
49
+ break;
50
+ default:
51
+ await router.push(to);
52
+ }
53
+ }
54
+ function createNavigateFunction(router, props, navigationType) {
55
+ return async (e) => {
56
+ if (shouldHandleNavigation(e)) {
57
+ await executeNavigation(router, props, navigationType);
58
+ }
59
+ };
60
+ }
61
+ function computeAttributes(href, navigationType, isExternal, isActive, isExactActive, activeClass) {
62
+ const isNewWindow = navigationType === "pushWindow";
63
+ const classes = [CSS_CLASSES.BASE];
64
+ if (isActive) {
65
+ classes.push(activeClass || CSS_CLASSES.ACTIVE);
66
+ }
67
+ if (isExactActive) {
68
+ classes.push(CSS_CLASSES.EXACT_ACTIVE);
69
+ }
70
+ const attributes = {
71
+ href,
72
+ class: classes.join(" ")
73
+ };
74
+ if (isNewWindow) {
75
+ attributes.target = "_blank";
76
+ }
77
+ const relParts = [];
78
+ if (isNewWindow) {
79
+ relParts.push("noopener", "noreferrer");
80
+ }
81
+ if (isExternal) {
82
+ relParts.push("external", "nofollow");
83
+ }
84
+ if (relParts.length > 0) {
85
+ attributes.rel = relParts.join(" ");
86
+ }
87
+ return attributes;
88
+ }
89
+ function createEventHandlersGenerator(router, props, navigationType, eventTypes) {
90
+ return (format) => {
91
+ const handlers = {};
92
+ const navigate = createNavigateFunction(router, props, navigationType);
93
+ eventTypes.forEach((eventType) => {
94
+ var _a;
95
+ const eventName = (_a = format == null ? void 0 : format(eventType)) != null ? _a : eventType.toLowerCase();
96
+ handlers[eventName] = (event) => {
97
+ var _a2;
98
+ (_a2 = props.beforeNavigate) == null ? void 0 : _a2.call(props, event, eventType);
99
+ return navigate(event);
100
+ };
101
+ });
102
+ return handlers;
103
+ };
104
+ }
105
+ export function createLinkResolver(router, props) {
106
+ const route = router.resolve(props.to);
107
+ const type = normalizeNavigationType(props);
108
+ const href = route.url.href;
109
+ const isActive = router.isRouteMatched(route, props.exact);
110
+ const isExactActive = router.isRouteMatched(route, "exact");
111
+ const isExternal = route.url.origin !== router.route.url.origin;
112
+ const attributes = computeAttributes(
113
+ href,
114
+ type,
115
+ isExternal,
116
+ isActive,
117
+ isExactActive,
118
+ props.activeClass
119
+ );
120
+ const eventTypes = getEventTypeList(props.event || "click");
121
+ const createEventHandlers = createEventHandlersGenerator(
122
+ router,
123
+ props,
124
+ type,
125
+ eventTypes
126
+ );
127
+ const navigate = createNavigateFunction(router, props, type);
128
+ return router.parsedOptions.resolveLink(
129
+ {
130
+ route,
131
+ type,
132
+ isActive,
133
+ isExactActive,
134
+ isExternal,
135
+ tag: props.tag || "a",
136
+ attributes,
137
+ navigate,
138
+ createEventHandlers
139
+ },
140
+ props
141
+ );
142
+ }
package/dist/router.d.ts CHANGED
@@ -1,111 +1,122 @@
1
- import { type HistoryState, type NavigationGuard, type NavigationGuardAfter, type RegisteredConfig, type RegisteredConfigMap, type Route, type RouteRecord, type RouterBase, type RouterHistory, type RouterInitOptions, type RouterInstance, type RouterMatcher, RouterMode, type RouterOptions, type RouterRawLocation, type RouterScrollBehavior } from './types';
2
- /**
3
- * 路由类
4
- */
5
- export declare class Router implements RouterInstance {
6
- /**
7
- * 当前路由对象的上级路由对象
8
- */
9
- parent: RouterInstance | null;
10
- options: RouterOptions;
11
- /**
12
- * 路由固定前置路径
13
- * 需要注意的是如果使用函数返回 base,需要尽量保证相同的路径返回相同base
14
- */
15
- base: RouterBase;
16
- mode: RouterMode;
17
- matcher: RouterMatcher;
18
- history: RouterHistory;
19
- scrollBehavior: RouterScrollBehavior;
20
- route: Route;
1
+ import { MicroApp } from './micro-app';
2
+ import { Navigation } from './navigation';
3
+ import { Route } from './route';
4
+ import { RouteTransition } from './route-transition';
5
+ import type { RouteConfirmHook, RouteLayerResult, RouteLocationInput, RouteMatchType, RouteNotifyHook, RouterLinkProps, RouterLinkResolved, RouterOptions, RouterParsedOptions } from './types';
6
+ import { RouterMode, RouteType } from './types';
7
+ export declare class Router {
8
+ readonly options: RouterOptions;
9
+ readonly parsedOptions: RouterParsedOptions;
10
+ readonly isLayer: boolean;
11
+ readonly navigation: Navigation;
12
+ readonly microApp: MicroApp;
13
+ readonly transition: RouteTransition;
14
+ get route(): Route;
15
+ get context(): Record<string | symbol, unknown>;
16
+ get data(): Record<string | symbol, unknown>;
17
+ get appId(): string;
18
+ get mode(): RouterMode;
19
+ get base(): URL;
20
+ get req(): import("http").IncomingMessage | null;
21
+ get res(): import("http").ServerResponse<import("http").IncomingMessage> | null;
21
22
  constructor(options: RouterOptions);
22
- updateRoute(route: RouteRecord): void;
23
- protected applyRoute(route: RouteRecord): void;
24
- resolve(location: RouterRawLocation): RouteRecord;
23
+ push(toInput: RouteLocationInput): Promise<Route>;
24
+ replace(toInput: RouteLocationInput): Promise<Route>;
25
+ pushWindow(toInput: RouteLocationInput): Promise<Route>;
26
+ replaceWindow(toInput: RouteLocationInput): Promise<Route>;
27
+ restartApp(toInput?: RouteLocationInput): Promise<Route>;
28
+ back(): Promise<Route | null>;
29
+ go(index: number): Promise<Route | null>;
30
+ forward(): Promise<Route | null>;
25
31
  /**
26
- * 新增单个路由匹配规则
32
+ * Parse route location without performing actual navigation
33
+ *
34
+ * This method is used to parse route configuration and return the corresponding route object,
35
+ * but does not trigger actual page navigation. It is mainly used for the following scenarios:
36
+ * - Generate link URLs without jumping
37
+ * - Pre-check route matching
38
+ * - Get route parameters, meta information, etc.
39
+ * - Test the validity of route configuration
40
+ *
41
+ * @param toInput Target route location, can be a string path or route configuration object
42
+ * @returns Parsed route object containing complete route information
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * // Parse string path
47
+ * const route = router.resolve('/user/123');
48
+ * const url = route.url.href; // Get complete URL
49
+ *
50
+ * // Parse named route
51
+ * const userRoute = router.resolve({
52
+ * name: 'user',
53
+ * params: { id: '123' }
54
+ * });
55
+ * console.log(userRoute.params.id); // '123'
56
+ *
57
+ * // Check route validity
58
+ * const testRoute = router.resolve('/some/path');
59
+ * if (testRoute.matched.length > 0) {
60
+ * // Route matched successfully
61
+ * }
62
+ * ```
27
63
  */
64
+ resolve(toInput: RouteLocationInput, toType?: RouteType): Route;
28
65
  /**
29
- * 新增多个路由匹配规则
66
+ * Check if the route matches the current route
67
+ *
68
+ * @param toRoute Target route object to compare
69
+ * @param matchType Match type
70
+ * - 'route': Route-level matching, compare if route configurations are the same
71
+ * - 'exact': Exact matching, compare if paths are completely the same
72
+ * - 'include': Include matching, check if current path contains target path
73
+ * @returns Whether it matches
30
74
  */
31
- init(options?: RouterInitOptions): Promise<void>;
75
+ isRouteMatched(toRoute: Route, matchType?: RouteMatchType): boolean;
32
76
  /**
33
- * 卸载方法
77
+ * Resolve router link configuration and return complete link data
78
+ *
79
+ * This method analyzes router link properties and returns a comprehensive
80
+ * link resolution result including route information, navigation functions,
81
+ * HTML attributes, and event handlers. It's primarily used for:
82
+ * - Framework-agnostic link component implementation
83
+ * - Generating link attributes and navigation handlers
84
+ * - Computing active states and CSS classes
85
+ * - Creating event handlers for different frameworks
86
+ *
87
+ * @param props Router link configuration properties
88
+ * @returns Complete link resolution result with all necessary data
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * // Basic link resolution
93
+ * const linkData = router.resolveLink({
94
+ * to: '/user/123',
95
+ * type: 'push'
96
+ * });
97
+ *
98
+ * // Access resolved data
99
+ * console.log(linkData.route.path); // '/user/123'
100
+ * console.log(linkData.attributes.href); // Full href URL
101
+ * console.log(linkData.isActive); // Active state
102
+ *
103
+ * // Use navigation function
104
+ * linkData.navigate(); // Programmatic navigation
105
+ *
106
+ * // Get event handlers for React
107
+ * const handlers = linkData.createEventHandlers(name => `on${name.charAt(0).toUpperCase() + name.slice(1)}`);
108
+ * // handlers.onClick for React
109
+ * ```
34
110
  */
35
- destroy(): Promise<void>;
36
- registeredConfigMap: RegisteredConfigMap;
37
- register(name: string, config: (router: RouterInstance) => RegisteredConfig): void;
38
- readonly guards: {
39
- beforeEach: NavigationGuard[];
40
- afterEach: NavigationGuardAfter[];
41
- };
42
- beforeEach(guard: NavigationGuard): void;
43
- unBindBeforeEach(guard: NavigationGuard): void;
44
- afterEach(guard: NavigationGuardAfter): void;
45
- unBindAfterEach(guard: NavigationGuardAfter): void;
46
- push(location: RouterRawLocation): Promise<void>;
47
- replace(location: RouterRawLocation): Promise<void>;
48
- /**
49
- * 当前路由弹层id,用于区分不同的路由弹层
50
- */
51
- layerId: number;
52
- /**
53
- * 路由弹层配置
54
- * key为路由弹层id
55
- */
56
- layerConfigList: Array<{
57
- /**
58
- * 路由弹层id
59
- */
60
- id: number;
61
- /**
62
- * 路由弹层深度
63
- */
64
- depth: number;
65
- }>;
66
- /**
67
- * 路由弹层id与路由实例的map
68
- */
69
- layerMap: Record<number, {
70
- router: RouterInstance;
71
- config: RegisteredConfig;
72
- destroyed: boolean;
111
+ resolveLink(props: RouterLinkProps): RouterLinkResolved;
112
+ createLayer(toInput: RouteLocationInput): Promise<{
113
+ promise: Promise<RouteLayerResult>;
114
+ router: Router;
73
115
  }>;
74
- /**
75
- * 路由是否冻结
76
- */
77
- isFrozen: boolean;
78
- /**
79
- * 路由冻结方法
80
- */
81
- freeze(): void;
82
- /**
83
- * 路由解冻方法
84
- */
85
- unfreeze(): void;
86
- /**
87
- * 打开路由弹层方法,会创建新的路由实例并调用注册的 register 方法
88
- * 服务端会使用 push 作为替代
89
- */
90
- pushLayer(location: RouterRawLocation): Promise<void>;
91
- /**
92
- * 更新路由弹层方法
93
- * @param state 参数为history.state
94
- * @description 没有传入 state 时使用当前配置更新 history.state,传入了 state 时使用传入的 state 更新当前配置
95
- */
96
- checkLayerState(state: HistoryState): boolean;
97
- updateLayerState(route: RouteRecord): void;
98
- /**
99
- * 新开浏览器窗口的方法,在服务端会调用 push 作为替代
100
- */
101
- pushWindow(location: RouterRawLocation): void;
102
- /**
103
- * 替换当前浏览器窗口的方法,在服务端会调用 replace 作为替代
104
- */
105
- replaceWindow(location: RouterRawLocation): void;
106
- go(delta?: number): void;
107
- forward(): void;
108
- back(): void;
109
- getRoutes(): any;
116
+ pushLayer(toInput: RouteLocationInput): Promise<RouteLayerResult>;
117
+ closeLayer(data?: any): void;
118
+ renderToString(throwError?: boolean): Promise<string | null>;
119
+ beforeEach(guard: RouteConfirmHook): () => void;
120
+ afterEach(guard: RouteNotifyHook): () => void;
121
+ destroy(): void;
110
122
  }
111
- export declare function createRouter(options: RouterOptions): RouterInstance;