@xfe-repo/web-router 1.2.3 → 1.2.6

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/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { History } from 'history';
2
1
  import { LoadableComponent, loadableReady } from '@loadable/component';
2
+ import { History } from 'history';
3
3
  import { ParsedQuery } from '@xfe-repo/web-utils/tools';
4
4
  import React, { ReactElement, PropsWithChildren, ComponentType } from 'react';
5
5
  import { RegisterComponentStatic } from '@xfe-repo/web-register';
@@ -22,6 +22,12 @@ declare const routerIndexRegx: RegExp;
22
22
  declare const routerDynamicRegx: RegExp;
23
23
  declare const getRoutes: (config: GetRoutesConfig) => RouteConfig[];
24
24
 
25
+ type LinkProps = Omit<LinkProps$1, 'to'> & {
26
+ to: string;
27
+ preload?: boolean;
28
+ };
29
+ declare const Link: React.MemoExoticComponent<(props: LinkProps) => react_jsx_runtime.JSX.Element>;
30
+
25
31
  type RouterProps = PropsWithChildren<{
26
32
  navigator: NavigatorType;
27
33
  routes: RouteConfig[];
@@ -30,11 +36,60 @@ type RouterProps = PropsWithChildren<{
30
36
  }>;
31
37
  declare const Router: React.MemoExoticComponent<(props: RouterProps) => react_jsx_runtime.JSX.Element>;
32
38
 
33
- type LinkProps = Omit<LinkProps$1, 'to'> & {
34
- to: string;
35
- preload?: boolean;
36
- };
37
- declare const Link: React.MemoExoticComponent<(props: LinkProps) => react_jsx_runtime.JSX.Element>;
39
+ /**
40
+ * History API 拦截器
41
+ *
42
+ * 劫持 history.pushState 和 history.replaceState 方法,
43
+ * 在调用原始方法后触发标准化的 historychange 事件。
44
+ *
45
+ * @example
46
+ * // 监听 URL 变化
47
+ * window.addEventListener('historychange', (event) => {
48
+ * console.log('URL changed:', event.detail.url)
49
+ * })
50
+ */
51
+ /** 自定义事件名称 */
52
+ declare const HISTORY_CHANGE_EVENT = "historychange";
53
+ /** History 变化事件详情 */
54
+ interface HistoryChangeEventDetail {
55
+ /** 变化类型 */
56
+ type: 'pushState' | 'replaceState' | 'popstate';
57
+ /** 完整 URL */
58
+ url: string;
59
+ /** 路径部分 */
60
+ pathname: string;
61
+ /** 查询参数部分 */
62
+ search: string;
63
+ /** hash 部分 */
64
+ hash: string;
65
+ /** history state */
66
+ state: any;
67
+ /** 时间戳 */
68
+ timestamp: number;
69
+ }
70
+ /** History 变化事件类型 */
71
+ interface HistoryChangeEvent extends CustomEvent<HistoryChangeEventDetail> {
72
+ type: typeof HISTORY_CHANGE_EVENT;
73
+ }
74
+ /**
75
+ * 初始化 history 拦截器
76
+ *
77
+ * 劫持 history.pushState 和 history.replaceState 方法,
78
+ * 在调用原始方法后触发 historychange 事件。
79
+ * 同时监听原生 popstate 事件并转发为 historychange 事件。
80
+ *
81
+ * @returns 清理函数,用于恢复原始方法和移除监听器
82
+ */
83
+ declare function initHistoryInterceptor(): () => void;
84
+ /** 检查拦截器是否已初始化 */
85
+ declare function isHistoryIntercepted(): boolean;
86
+ /**
87
+ * 事件监听函数
88
+ *
89
+ * @param callback 回调函数
90
+ * @returns 取消监听的函数
91
+ */
92
+ declare function onHistoryChange(callback: (detail: HistoryChangeEventDetail) => void): () => void;
38
93
 
39
94
  interface NavigatorType extends History {
40
95
  preload: (path: string, isReplace?: boolean, query?: ParsedQuery<string | number | boolean>) => Promise<void>;
@@ -50,4 +105,4 @@ declare function createNavigator(options: CreateNavigatorOptions): NavigatorType
50
105
  declare const getClientNavigator: () => NavigatorType;
51
106
  declare const routerReady: typeof loadableReady;
52
107
 
53
- export { type CreateNavigatorOptions, type GetRoutesConfig, Link, type NavigatorType, type PageComponent, type RouteConfig, Router, createNavigator, getClientNavigator, getRoutes, routerDynamicRegx, routerIndexRegx, routerReady };
108
+ export { type CreateNavigatorOptions, type GetRoutesConfig, HISTORY_CHANGE_EVENT, type HistoryChangeEvent, type HistoryChangeEventDetail, Link, type NavigatorType, type PageComponent, type RouteConfig, Router, createNavigator, getClientNavigator, getRoutes, initHistoryInterceptor, isHistoryIntercepted, onHistoryChange, routerDynamicRegx, routerIndexRegx, routerReady };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { History } from 'history';
2
1
  import { LoadableComponent, loadableReady } from '@loadable/component';
2
+ import { History } from 'history';
3
3
  import { ParsedQuery } from '@xfe-repo/web-utils/tools';
4
4
  import React, { ReactElement, PropsWithChildren, ComponentType } from 'react';
5
5
  import { RegisterComponentStatic } from '@xfe-repo/web-register';
@@ -22,6 +22,12 @@ declare const routerIndexRegx: RegExp;
22
22
  declare const routerDynamicRegx: RegExp;
23
23
  declare const getRoutes: (config: GetRoutesConfig) => RouteConfig[];
24
24
 
25
+ type LinkProps = Omit<LinkProps$1, 'to'> & {
26
+ to: string;
27
+ preload?: boolean;
28
+ };
29
+ declare const Link: React.MemoExoticComponent<(props: LinkProps) => react_jsx_runtime.JSX.Element>;
30
+
25
31
  type RouterProps = PropsWithChildren<{
26
32
  navigator: NavigatorType;
27
33
  routes: RouteConfig[];
@@ -30,11 +36,60 @@ type RouterProps = PropsWithChildren<{
30
36
  }>;
31
37
  declare const Router: React.MemoExoticComponent<(props: RouterProps) => react_jsx_runtime.JSX.Element>;
32
38
 
33
- type LinkProps = Omit<LinkProps$1, 'to'> & {
34
- to: string;
35
- preload?: boolean;
36
- };
37
- declare const Link: React.MemoExoticComponent<(props: LinkProps) => react_jsx_runtime.JSX.Element>;
39
+ /**
40
+ * History API 拦截器
41
+ *
42
+ * 劫持 history.pushState 和 history.replaceState 方法,
43
+ * 在调用原始方法后触发标准化的 historychange 事件。
44
+ *
45
+ * @example
46
+ * // 监听 URL 变化
47
+ * window.addEventListener('historychange', (event) => {
48
+ * console.log('URL changed:', event.detail.url)
49
+ * })
50
+ */
51
+ /** 自定义事件名称 */
52
+ declare const HISTORY_CHANGE_EVENT = "historychange";
53
+ /** History 变化事件详情 */
54
+ interface HistoryChangeEventDetail {
55
+ /** 变化类型 */
56
+ type: 'pushState' | 'replaceState' | 'popstate';
57
+ /** 完整 URL */
58
+ url: string;
59
+ /** 路径部分 */
60
+ pathname: string;
61
+ /** 查询参数部分 */
62
+ search: string;
63
+ /** hash 部分 */
64
+ hash: string;
65
+ /** history state */
66
+ state: any;
67
+ /** 时间戳 */
68
+ timestamp: number;
69
+ }
70
+ /** History 变化事件类型 */
71
+ interface HistoryChangeEvent extends CustomEvent<HistoryChangeEventDetail> {
72
+ type: typeof HISTORY_CHANGE_EVENT;
73
+ }
74
+ /**
75
+ * 初始化 history 拦截器
76
+ *
77
+ * 劫持 history.pushState 和 history.replaceState 方法,
78
+ * 在调用原始方法后触发 historychange 事件。
79
+ * 同时监听原生 popstate 事件并转发为 historychange 事件。
80
+ *
81
+ * @returns 清理函数,用于恢复原始方法和移除监听器
82
+ */
83
+ declare function initHistoryInterceptor(): () => void;
84
+ /** 检查拦截器是否已初始化 */
85
+ declare function isHistoryIntercepted(): boolean;
86
+ /**
87
+ * 事件监听函数
88
+ *
89
+ * @param callback 回调函数
90
+ * @returns 取消监听的函数
91
+ */
92
+ declare function onHistoryChange(callback: (detail: HistoryChangeEventDetail) => void): () => void;
38
93
 
39
94
  interface NavigatorType extends History {
40
95
  preload: (path: string, isReplace?: boolean, query?: ParsedQuery<string | number | boolean>) => Promise<void>;
@@ -50,4 +105,4 @@ declare function createNavigator(options: CreateNavigatorOptions): NavigatorType
50
105
  declare const getClientNavigator: () => NavigatorType;
51
106
  declare const routerReady: typeof loadableReady;
52
107
 
53
- export { type CreateNavigatorOptions, type GetRoutesConfig, Link, type NavigatorType, type PageComponent, type RouteConfig, Router, createNavigator, getClientNavigator, getRoutes, routerDynamicRegx, routerIndexRegx, routerReady };
108
+ export { type CreateNavigatorOptions, type GetRoutesConfig, HISTORY_CHANGE_EVENT, type HistoryChangeEvent, type HistoryChangeEventDetail, Link, type NavigatorType, type PageComponent, type RouteConfig, Router, createNavigator, getClientNavigator, getRoutes, initHistoryInterceptor, isHistoryIntercepted, onHistoryChange, routerDynamicRegx, routerIndexRegx, routerReady };
package/dist/index.js CHANGED
@@ -261,6 +261,9 @@ var __toCommonJS = function(mod) {
261
261
  // src/index.ts
262
262
  var src_exports = {};
263
263
  __export(src_exports, {
264
+ HISTORY_CHANGE_EVENT: function() {
265
+ return HISTORY_CHANGE_EVENT;
266
+ },
264
267
  Link: function() {
265
268
  return Link;
266
269
  },
@@ -276,6 +279,15 @@ __export(src_exports, {
276
279
  getRoutes: function() {
277
280
  return getRoutes;
278
281
  },
282
+ initHistoryInterceptor: function() {
283
+ return initHistoryInterceptor;
284
+ },
285
+ isHistoryIntercepted: function() {
286
+ return isHistoryIntercepted;
287
+ },
288
+ onHistoryChange: function() {
289
+ return onHistoryChange;
290
+ },
279
291
  routerDynamicRegx: function() {
280
292
  return routerDynamicRegx;
281
293
  },
@@ -287,90 +299,93 @@ __export(src_exports, {
287
299
  }
288
300
  });
289
301
  module.exports = __toCommonJS(src_exports);
290
- var import_history = require("history");
291
302
  var import_component2 = require("@loadable/component");
303
+ var import_history = require("history");
292
304
  var import_react_router_dom3 = require("react-router-dom");
293
305
  var import_tools = require("@xfe-repo/web-utils/tools");
294
- __reExport(src_exports, require("react-router-dom"), module.exports);
295
- // src/routes.ts
296
- var import_component = __toESM(require("@loadable/component"));
297
- var routerIndexRegx = /^(?!.*component)(.*)?\/index(\[[^.]+])?\.(ts|js)x?$/;
298
- var routerDynamicRegx = /\[([^.]+)]/;
299
- var getRoutes = function(config) {
300
- var pagesIndexPath = config.pagesIndexPath, getRoutePath = config.getRoutePath, getPageComponents = config.getPageComponents, fallback = config.fallback;
301
- var routes = [];
302
- pagesIndexPath.forEach(function(pageIndexPath) {
303
- var _pageIndexPath_match;
304
- if (pageIndexPath.startsWith("./")) return;
305
- var pageComponent = (0, import_component.default)(function() {
306
- return getPageComponents(pageIndexPath);
307
- }, {
308
- fallback: fallback
309
- });
310
- var routerPath = getRoutePath ? getRoutePath(pageIndexPath) : pageIndexPath.replace(routerIndexRegx, "$1");
311
- if (routerPath === "home" || routerPath === "index") routerPath = "/";
312
- var dynamicRoute = ((_pageIndexPath_match = pageIndexPath.match(routerDynamicRegx)) === null || _pageIndexPath_match === void 0 ? void 0 : _pageIndexPath_match[1]) || "";
313
- if (dynamicRoute) routerPath = "".concat(routerPath, "/").concat(dynamicRoute);
314
- var config2 = {
315
- path: routerPath,
316
- Component: pageComponent
317
- };
318
- routes.push(config2);
306
+ // src/historyInterceptor.ts
307
+ var HISTORY_CHANGE_EVENT = "historychange";
308
+ var originalPushState = null;
309
+ var originalReplaceState = null;
310
+ var isIntercepted = false;
311
+ function dispatchHistoryChangeEvent(detail) {
312
+ var event = new CustomEvent(HISTORY_CHANGE_EVENT, {
313
+ detail: detail,
314
+ bubbles: false,
315
+ cancelable: false
319
316
  });
320
- return routes;
321
- };
322
- // src/Router.tsx
317
+ window.dispatchEvent(event);
318
+ }
319
+ function createEventDetail(type, state) {
320
+ return {
321
+ type: type,
322
+ url: window.location.href,
323
+ pathname: window.location.pathname,
324
+ search: window.location.search,
325
+ hash: window.location.hash,
326
+ state: state,
327
+ timestamp: Date.now()
328
+ };
329
+ }
330
+ function initHistoryInterceptor() {
331
+ if (isIntercepted) {
332
+ return function() {};
333
+ }
334
+ originalPushState = history.pushState;
335
+ originalReplaceState = history.replaceState;
336
+ history.pushState = function(state, unused, url) {
337
+ originalPushState.call(this, state, unused, url);
338
+ dispatchHistoryChangeEvent(createEventDetail("pushState", state));
339
+ };
340
+ history.replaceState = function(state, unused, url) {
341
+ originalReplaceState.call(this, state, unused, url);
342
+ dispatchHistoryChangeEvent(createEventDetail("replaceState", state));
343
+ };
344
+ var handlePopState = function() {
345
+ dispatchHistoryChangeEvent(createEventDetail("popstate", history.state));
346
+ };
347
+ window.addEventListener("popstate", handlePopState);
348
+ isIntercepted = true;
349
+ return function() {
350
+ if (originalPushState) {
351
+ history.pushState = originalPushState;
352
+ originalPushState = null;
353
+ }
354
+ if (originalReplaceState) {
355
+ history.replaceState = originalReplaceState;
356
+ originalReplaceState = null;
357
+ }
358
+ window.removeEventListener("popstate", handlePopState);
359
+ isIntercepted = false;
360
+ };
361
+ }
362
+ function isHistoryIntercepted() {
363
+ return isIntercepted;
364
+ }
365
+ function onHistoryChange(callback) {
366
+ var handler = function(event) {
367
+ var customEvent = event;
368
+ callback(customEvent.detail);
369
+ };
370
+ window.addEventListener(HISTORY_CHANGE_EVENT, handler);
371
+ return function() {
372
+ window.removeEventListener(HISTORY_CHANGE_EVENT, handler);
373
+ };
374
+ }
375
+ // src/index.ts
376
+ __reExport(src_exports, require("react-router-dom"), module.exports);
377
+ // src/Link.tsx
323
378
  var import_react = require("react");
324
379
  var import_react_router_dom = require("react-router-dom");
325
380
  var import_jsx_runtime = require("react/jsx-runtime");
326
- var Router = (0, import_react.memo)(function(props) {
327
- var navigator = props.navigator, routes = props.routes, _props_basename = props.basename, basename = _props_basename === void 0 ? "/" : _props_basename, children = props.children, NotFoundPageComponent = props.NotFoundPageComponent;
328
- var _ref = _sliced_to_array((0, import_react.useState)({
329
- action: navigator.action,
330
- location: navigator.location
331
- }), 2), navigatorState = _ref[0], setNavigatorState = _ref[1];
332
- (0, import_react.useEffect)(function() {
333
- return navigator.listen(setNavigatorState);
334
- }, [
335
- navigator
336
- ]);
337
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_router_dom.Router, {
338
- navigator: navigator,
339
- navigationType: navigatorState.action,
340
- location: navigatorState.location,
341
- basename: basename,
342
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_router_dom.Routes, {
343
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_router_dom.Route, {
344
- path: "/",
345
- element: children,
346
- children: [
347
- routes.map(function(param) {
348
- var path = param.path, Component = param.Component;
349
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_router_dom.Route, {
350
- path: path,
351
- Component: Component
352
- }, path);
353
- }),
354
- NotFoundPageComponent && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_router_dom.Route, {
355
- path: "*",
356
- Component: NotFoundPageComponent
357
- })
358
- ]
359
- })
360
- })
361
- });
362
- });
363
- // src/Link.tsx
364
- var import_react2 = require("react");
365
- var import_react_router_dom2 = require("react-router-dom");
366
- var import_jsx_runtime2 = require("react/jsx-runtime");
367
- var Link = (0, import_react2.memo)(function(props) {
381
+ var Link = (0, import_react.memo)(function(props) {
368
382
  var to = props.to, children = props.children, preload = props.preload, replace = props.replace, className = props.className, target = props.target;
369
- var _navigator2 = (0, import_react2.useMemo)(function() {
383
+ var _navigator2 = (0, import_react.useMemo)(function() {
370
384
  return getClientNavigator();
371
385
  }, []);
372
386
  if (/http(s)?:\/{2}/.test(to)) {
373
387
  var handleLink = function(e) {
388
+ if (e.ctrlKey || e.metaKey) return;
374
389
  e.preventDefault();
375
390
  if (target === "_blank") {
376
391
  window.open(to);
@@ -378,7 +393,7 @@ var Link = (0, import_react2.memo)(function(props) {
378
393
  window.location.href = to;
379
394
  }
380
395
  };
381
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", {
396
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", {
382
397
  href: to,
383
398
  onClick: handleLink,
384
399
  className: className,
@@ -392,6 +407,9 @@ var Link = (0, import_react2.memo)(function(props) {
392
407
  return _ts_generator(this, function(_state) {
393
408
  switch(_state.label){
394
409
  case 0:
410
+ if (e.ctrlKey || e.metaKey) return [
411
+ 2
412
+ ];
395
413
  e.preventDefault();
396
414
  return [
397
415
  4,
@@ -409,15 +427,83 @@ var Link = (0, import_react2.memo)(function(props) {
409
427
  return _ref.apply(this, arguments);
410
428
  };
411
429
  }();
412
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", {
430
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", {
413
431
  href: to,
414
432
  onClick: handleLink1,
415
433
  className: className,
416
434
  children: children
417
435
  });
418
436
  }
419
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_router_dom2.Link, _object_spread({}, props));
437
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_router_dom.Link, _object_spread({}, props));
438
+ });
439
+ // src/Router.tsx
440
+ var import_react2 = require("react");
441
+ var import_react_router_dom2 = require("react-router-dom");
442
+ var import_jsx_runtime2 = require("react/jsx-runtime");
443
+ var Router = (0, import_react2.memo)(function(props) {
444
+ var navigator = props.navigator, routes = props.routes, _props_basename = props.basename, basename = _props_basename === void 0 ? "/" : _props_basename, children = props.children, NotFoundPageComponent = props.NotFoundPageComponent;
445
+ var _ref = _sliced_to_array((0, import_react2.useState)({
446
+ action: navigator.action,
447
+ location: navigator.location
448
+ }), 2), navigatorState = _ref[0], setNavigatorState = _ref[1];
449
+ (0, import_react2.useEffect)(function() {
450
+ return navigator.listen(setNavigatorState);
451
+ }, [
452
+ navigator
453
+ ]);
454
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_router_dom2.Router, {
455
+ navigator: navigator,
456
+ navigationType: navigatorState.action,
457
+ location: navigatorState.location,
458
+ basename: basename,
459
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_router_dom2.Routes, {
460
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_router_dom2.Route, {
461
+ path: "/",
462
+ element: children,
463
+ children: [
464
+ routes.map(function(param) {
465
+ var path = param.path, Component = param.Component;
466
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_router_dom2.Route, {
467
+ path: path,
468
+ Component: Component
469
+ }, path);
470
+ }),
471
+ NotFoundPageComponent && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_router_dom2.Route, {
472
+ path: "*",
473
+ Component: NotFoundPageComponent
474
+ })
475
+ ]
476
+ })
477
+ })
478
+ });
420
479
  });
480
+ // src/routes.ts
481
+ var import_component = __toESM(require("@loadable/component"));
482
+ var routerIndexRegx = /^(?!.*component)(.*)?\/index(\[[^.]+])?\.(ts|js)x?$/;
483
+ var routerDynamicRegx = /\[([^.]+)]/;
484
+ var getRoutes = function(config) {
485
+ var pagesIndexPath = config.pagesIndexPath, getRoutePath = config.getRoutePath, getPageComponents = config.getPageComponents, fallback = config.fallback;
486
+ var routes = [];
487
+ pagesIndexPath.forEach(function(pageIndexPath) {
488
+ var _pageIndexPath_match;
489
+ if (pageIndexPath.startsWith("./")) return;
490
+ var pageComponent = (0, import_component.default)(function() {
491
+ return getPageComponents(pageIndexPath);
492
+ }, {
493
+ fallback: fallback
494
+ });
495
+ var routerPath = getRoutePath ? getRoutePath(pageIndexPath) : pageIndexPath.replace(routerIndexRegx, "$1");
496
+ if (routerPath === "home" || routerPath === "index") routerPath = "/";
497
+ var dynamicRoute = ((_pageIndexPath_match = pageIndexPath.match(routerDynamicRegx)) === null || _pageIndexPath_match === void 0 ? void 0 : _pageIndexPath_match[1]) || "";
498
+ if (dynamicRoute) routerPath = "".concat(routerPath, "/").concat(dynamicRoute);
499
+ var config2 = {
500
+ path: routerPath,
501
+ Component: pageComponent
502
+ };
503
+ routes.push(config2);
504
+ });
505
+ return routes;
506
+ };
421
507
  // src/index.ts
422
508
  var _navigator;
423
509
  function createNavigator(options) {
@@ -504,13 +590,18 @@ var getClientNavigator = function() {
504
590
  return _navigator;
505
591
  };
506
592
  var routerReady = import_component2.loadableReady;
593
+ initHistoryInterceptor();
507
594
  // Annotate the CommonJS export names for ESM import in node:
508
595
  0 && (module.exports = _object_spread({
596
+ HISTORY_CHANGE_EVENT: HISTORY_CHANGE_EVENT,
509
597
  Link: Link,
510
598
  Router: Router,
511
599
  createNavigator: createNavigator,
512
600
  getClientNavigator: getClientNavigator,
513
601
  getRoutes: getRoutes,
602
+ initHistoryInterceptor: initHistoryInterceptor,
603
+ isHistoryIntercepted: isHistoryIntercepted,
604
+ onHistoryChange: onHistoryChange,
514
605
  routerDynamicRegx: routerDynamicRegx,
515
606
  routerIndexRegx: routerIndexRegx,
516
607
  routerReady: routerReady
package/dist/index.mjs CHANGED
@@ -197,90 +197,93 @@ function _ts_generator(thisArg, body) {
197
197
  };
198
198
  }
199
199
  }
200
- import { createHashHistory, createBrowserHistory, createMemoryHistory } from "history";
201
200
  import { loadableReady } from "@loadable/component";
201
+ import { createBrowserHistory, createHashHistory, createMemoryHistory } from "history";
202
202
  import { matchRoutes } from "react-router-dom";
203
203
  import { queryString } from "@xfe-repo/web-utils/tools";
204
- export * from "react-router-dom";
205
- // src/routes.ts
206
- import loadable from "@loadable/component";
207
- var routerIndexRegx = /^(?!.*component)(.*)?\/index(\[[^.]+])?\.(ts|js)x?$/;
208
- var routerDynamicRegx = /\[([^.]+)]/;
209
- var getRoutes = function(config) {
210
- var pagesIndexPath = config.pagesIndexPath, getRoutePath = config.getRoutePath, getPageComponents = config.getPageComponents, fallback = config.fallback;
211
- var routes = [];
212
- pagesIndexPath.forEach(function(pageIndexPath) {
213
- var _pageIndexPath_match;
214
- if (pageIndexPath.startsWith("./")) return;
215
- var pageComponent = loadable(function() {
216
- return getPageComponents(pageIndexPath);
217
- }, {
218
- fallback: fallback
219
- });
220
- var routerPath = getRoutePath ? getRoutePath(pageIndexPath) : pageIndexPath.replace(routerIndexRegx, "$1");
221
- if (routerPath === "home" || routerPath === "index") routerPath = "/";
222
- var dynamicRoute = ((_pageIndexPath_match = pageIndexPath.match(routerDynamicRegx)) === null || _pageIndexPath_match === void 0 ? void 0 : _pageIndexPath_match[1]) || "";
223
- if (dynamicRoute) routerPath = "".concat(routerPath, "/").concat(dynamicRoute);
224
- var config2 = {
225
- path: routerPath,
226
- Component: pageComponent
227
- };
228
- routes.push(config2);
229
- });
230
- return routes;
231
- };
232
- // src/Router.tsx
233
- import { memo, useState, useEffect } from "react";
234
- import { Router as OriginalRouter, Routes, Route } from "react-router-dom";
235
- import { jsx, jsxs } from "react/jsx-runtime";
236
- var Router = memo(function(props) {
237
- var navigator = props.navigator, routes = props.routes, _props_basename = props.basename, basename = _props_basename === void 0 ? "/" : _props_basename, children = props.children, NotFoundPageComponent = props.NotFoundPageComponent;
238
- var _useState = _sliced_to_array(useState({
239
- action: navigator.action,
240
- location: navigator.location
241
- }), 2), navigatorState = _useState[0], setNavigatorState = _useState[1];
242
- useEffect(function() {
243
- return navigator.listen(setNavigatorState);
244
- }, [
245
- navigator
246
- ]);
247
- return /* @__PURE__ */ jsx(OriginalRouter, {
248
- navigator: navigator,
249
- navigationType: navigatorState.action,
250
- location: navigatorState.location,
251
- basename: basename,
252
- children: /* @__PURE__ */ jsx(Routes, {
253
- children: /* @__PURE__ */ jsxs(Route, {
254
- path: "/",
255
- element: children,
256
- children: [
257
- routes.map(function(param) {
258
- var path = param.path, Component = param.Component;
259
- return /* @__PURE__ */ jsx(Route, {
260
- path: path,
261
- Component: Component
262
- }, path);
263
- }),
264
- NotFoundPageComponent && /* @__PURE__ */ jsx(Route, {
265
- path: "*",
266
- Component: NotFoundPageComponent
267
- })
268
- ]
269
- })
270
- })
204
+ // src/historyInterceptor.ts
205
+ var HISTORY_CHANGE_EVENT = "historychange";
206
+ var originalPushState = null;
207
+ var originalReplaceState = null;
208
+ var isIntercepted = false;
209
+ function dispatchHistoryChangeEvent(detail) {
210
+ var event = new CustomEvent(HISTORY_CHANGE_EVENT, {
211
+ detail: detail,
212
+ bubbles: false,
213
+ cancelable: false
271
214
  });
272
- });
215
+ window.dispatchEvent(event);
216
+ }
217
+ function createEventDetail(type, state) {
218
+ return {
219
+ type: type,
220
+ url: window.location.href,
221
+ pathname: window.location.pathname,
222
+ search: window.location.search,
223
+ hash: window.location.hash,
224
+ state: state,
225
+ timestamp: Date.now()
226
+ };
227
+ }
228
+ function initHistoryInterceptor() {
229
+ if (isIntercepted) {
230
+ return function() {};
231
+ }
232
+ originalPushState = history.pushState;
233
+ originalReplaceState = history.replaceState;
234
+ history.pushState = function(state, unused, url) {
235
+ originalPushState.call(this, state, unused, url);
236
+ dispatchHistoryChangeEvent(createEventDetail("pushState", state));
237
+ };
238
+ history.replaceState = function(state, unused, url) {
239
+ originalReplaceState.call(this, state, unused, url);
240
+ dispatchHistoryChangeEvent(createEventDetail("replaceState", state));
241
+ };
242
+ var handlePopState = function() {
243
+ dispatchHistoryChangeEvent(createEventDetail("popstate", history.state));
244
+ };
245
+ window.addEventListener("popstate", handlePopState);
246
+ isIntercepted = true;
247
+ return function() {
248
+ if (originalPushState) {
249
+ history.pushState = originalPushState;
250
+ originalPushState = null;
251
+ }
252
+ if (originalReplaceState) {
253
+ history.replaceState = originalReplaceState;
254
+ originalReplaceState = null;
255
+ }
256
+ window.removeEventListener("popstate", handlePopState);
257
+ isIntercepted = false;
258
+ };
259
+ }
260
+ function isHistoryIntercepted() {
261
+ return isIntercepted;
262
+ }
263
+ function onHistoryChange(callback) {
264
+ var handler = function(event) {
265
+ var customEvent = event;
266
+ callback(customEvent.detail);
267
+ };
268
+ window.addEventListener(HISTORY_CHANGE_EVENT, handler);
269
+ return function() {
270
+ window.removeEventListener(HISTORY_CHANGE_EVENT, handler);
271
+ };
272
+ }
273
+ // src/index.ts
274
+ export * from "react-router-dom";
273
275
  // src/Link.tsx
274
- import { memo as memo2, useMemo } from "react";
276
+ import { memo, useMemo } from "react";
275
277
  import { Link as OriginalLink } from "react-router-dom";
276
- import { jsx as jsx2 } from "react/jsx-runtime";
277
- var Link = memo2(function(props) {
278
+ import { jsx } from "react/jsx-runtime";
279
+ var Link = memo(function(props) {
278
280
  var to = props.to, children = props.children, preload = props.preload, replace = props.replace, className = props.className, target = props.target;
279
281
  var _navigator2 = useMemo(function() {
280
282
  return getClientNavigator();
281
283
  }, []);
282
284
  if (/http(s)?:\/{2}/.test(to)) {
283
285
  var handleLink = function(e) {
286
+ if (e.ctrlKey || e.metaKey) return;
284
287
  e.preventDefault();
285
288
  if (target === "_blank") {
286
289
  window.open(to);
@@ -288,7 +291,7 @@ var Link = memo2(function(props) {
288
291
  window.location.href = to;
289
292
  }
290
293
  };
291
- return /* @__PURE__ */ jsx2("a", {
294
+ return /* @__PURE__ */ jsx("a", {
292
295
  href: to,
293
296
  onClick: handleLink,
294
297
  className: className,
@@ -302,6 +305,9 @@ var Link = memo2(function(props) {
302
305
  return _ts_generator(this, function(_state) {
303
306
  switch(_state.label){
304
307
  case 0:
308
+ if (e.ctrlKey || e.metaKey) return [
309
+ 2
310
+ ];
305
311
  e.preventDefault();
306
312
  return [
307
313
  4,
@@ -319,15 +325,83 @@ var Link = memo2(function(props) {
319
325
  return _ref.apply(this, arguments);
320
326
  };
321
327
  }();
322
- return /* @__PURE__ */ jsx2("a", {
328
+ return /* @__PURE__ */ jsx("a", {
323
329
  href: to,
324
330
  onClick: handleLink1,
325
331
  className: className,
326
332
  children: children
327
333
  });
328
334
  }
329
- return /* @__PURE__ */ jsx2(OriginalLink, _object_spread({}, props));
335
+ return /* @__PURE__ */ jsx(OriginalLink, _object_spread({}, props));
330
336
  });
337
+ // src/Router.tsx
338
+ import { memo as memo2, useState, useEffect } from "react";
339
+ import { Router as OriginalRouter, Routes, Route } from "react-router-dom";
340
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
341
+ var Router = memo2(function(props) {
342
+ var navigator = props.navigator, routes = props.routes, _props_basename = props.basename, basename = _props_basename === void 0 ? "/" : _props_basename, children = props.children, NotFoundPageComponent = props.NotFoundPageComponent;
343
+ var _useState = _sliced_to_array(useState({
344
+ action: navigator.action,
345
+ location: navigator.location
346
+ }), 2), navigatorState = _useState[0], setNavigatorState = _useState[1];
347
+ useEffect(function() {
348
+ return navigator.listen(setNavigatorState);
349
+ }, [
350
+ navigator
351
+ ]);
352
+ return /* @__PURE__ */ jsx2(OriginalRouter, {
353
+ navigator: navigator,
354
+ navigationType: navigatorState.action,
355
+ location: navigatorState.location,
356
+ basename: basename,
357
+ children: /* @__PURE__ */ jsx2(Routes, {
358
+ children: /* @__PURE__ */ jsxs(Route, {
359
+ path: "/",
360
+ element: children,
361
+ children: [
362
+ routes.map(function(param) {
363
+ var path = param.path, Component = param.Component;
364
+ return /* @__PURE__ */ jsx2(Route, {
365
+ path: path,
366
+ Component: Component
367
+ }, path);
368
+ }),
369
+ NotFoundPageComponent && /* @__PURE__ */ jsx2(Route, {
370
+ path: "*",
371
+ Component: NotFoundPageComponent
372
+ })
373
+ ]
374
+ })
375
+ })
376
+ });
377
+ });
378
+ // src/routes.ts
379
+ import loadable from "@loadable/component";
380
+ var routerIndexRegx = /^(?!.*component)(.*)?\/index(\[[^.]+])?\.(ts|js)x?$/;
381
+ var routerDynamicRegx = /\[([^.]+)]/;
382
+ var getRoutes = function(config) {
383
+ var pagesIndexPath = config.pagesIndexPath, getRoutePath = config.getRoutePath, getPageComponents = config.getPageComponents, fallback = config.fallback;
384
+ var routes = [];
385
+ pagesIndexPath.forEach(function(pageIndexPath) {
386
+ var _pageIndexPath_match;
387
+ if (pageIndexPath.startsWith("./")) return;
388
+ var pageComponent = loadable(function() {
389
+ return getPageComponents(pageIndexPath);
390
+ }, {
391
+ fallback: fallback
392
+ });
393
+ var routerPath = getRoutePath ? getRoutePath(pageIndexPath) : pageIndexPath.replace(routerIndexRegx, "$1");
394
+ if (routerPath === "home" || routerPath === "index") routerPath = "/";
395
+ var dynamicRoute = ((_pageIndexPath_match = pageIndexPath.match(routerDynamicRegx)) === null || _pageIndexPath_match === void 0 ? void 0 : _pageIndexPath_match[1]) || "";
396
+ if (dynamicRoute) routerPath = "".concat(routerPath, "/").concat(dynamicRoute);
397
+ var config2 = {
398
+ path: routerPath,
399
+ Component: pageComponent
400
+ };
401
+ routes.push(config2);
402
+ });
403
+ return routes;
404
+ };
331
405
  // src/index.ts
332
406
  var _navigator;
333
407
  function createNavigator(options) {
@@ -414,4 +488,5 @@ var getClientNavigator = function() {
414
488
  return _navigator;
415
489
  };
416
490
  var routerReady = loadableReady;
417
- export { Link, Router, createNavigator, getClientNavigator, getRoutes, routerDynamicRegx, routerIndexRegx, routerReady };
491
+ initHistoryInterceptor();
492
+ export { HISTORY_CHANGE_EVENT, Link, Router, createNavigator, getClientNavigator, getRoutes, initHistoryInterceptor, isHistoryIntercepted, onHistoryChange, routerDynamicRegx, routerIndexRegx, routerReady };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xfe-repo/web-router",
3
- "version": "1.2.3",
3
+ "version": "1.2.6",
4
4
  "sideEffects": false,
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -28,12 +28,12 @@
28
28
  "@types/loadable__component": "^5.13.9",
29
29
  "@types/node": "^20.16.5",
30
30
  "@types/react": "^18",
31
- "@xfe-repo/eslint-config": "0.0.5",
32
31
  "@xfe-repo/typescript-config": "0.0.6",
32
+ "@xfe-repo/eslint-config": "0.0.5",
33
33
  "@xfe-repo/web-register": "1.3.5"
34
34
  },
35
35
  "peerDependencies": {
36
- "@xfe-repo/web-utils": "1.3.7"
36
+ "@xfe-repo/web-utils": "1.3.8"
37
37
  },
38
38
  "publishConfig": {
39
39
  "registry": "https://registry.npmjs.org/"