mobx-route 0.17.0 → 0.19.0

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 (163) hide show
  1. package/index.cjs +536 -17
  2. package/index.cjs.map +1 -0
  3. package/index.d.ts +420 -2
  4. package/index.js +532 -2
  5. package/index.js.map +1 -0
  6. package/package.json +21 -64
  7. package/react.cjs +170 -0
  8. package/react.cjs.map +1 -0
  9. package/react.d.ts +71 -0
  10. package/react.js +170 -0
  11. package/react.js.map +1 -0
  12. package/view-model.cjs +56 -0
  13. package/view-model.cjs.map +1 -0
  14. package/view-model.d.ts +14 -0
  15. package/view-model.js +56 -0
  16. package/view-model.js.map +1 -0
  17. package/core/config/config.cjs +0 -43
  18. package/core/config/config.d.cts +0 -7
  19. package/core/config/config.d.cts.map +0 -1
  20. package/core/config/config.d.ts +0 -7
  21. package/core/config/config.d.ts.map +0 -1
  22. package/core/config/config.js +0 -40
  23. package/core/config/config.types.cjs +0 -2
  24. package/core/config/config.types.d.cts +0 -11
  25. package/core/config/config.types.d.cts.map +0 -1
  26. package/core/config/config.types.d.ts +0 -11
  27. package/core/config/config.types.d.ts.map +0 -1
  28. package/core/config/config.types.js +0 -1
  29. package/core/config/index.cjs +0 -18
  30. package/core/config/index.d.cts +0 -3
  31. package/core/config/index.d.cts.map +0 -1
  32. package/core/config/index.d.ts +0 -3
  33. package/core/config/index.d.ts.map +0 -1
  34. package/core/config/index.js +0 -2
  35. package/core/index.cjs +0 -21
  36. package/core/index.d.cts +0 -6
  37. package/core/index.d.cts.map +0 -1
  38. package/core/index.d.ts +0 -6
  39. package/core/index.d.ts.map +0 -1
  40. package/core/index.js +0 -5
  41. package/core/route/index.cjs +0 -18
  42. package/core/route/index.d.cts +0 -3
  43. package/core/route/index.d.cts.map +0 -1
  44. package/core/route/index.d.ts +0 -3
  45. package/core/route/index.d.ts.map +0 -1
  46. package/core/route/index.js +0 -2
  47. package/core/route/route.cjs +0 -296
  48. package/core/route/route.d.cts +0 -107
  49. package/core/route/route.d.cts.map +0 -1
  50. package/core/route/route.d.ts +0 -107
  51. package/core/route/route.d.ts.map +0 -1
  52. package/core/route/route.js +0 -291
  53. package/core/route/route.types.cjs +0 -2
  54. package/core/route/route.types.d.cts +0 -142
  55. package/core/route/route.types.d.cts.map +0 -1
  56. package/core/route/route.types.d.ts +0 -142
  57. package/core/route/route.types.d.ts.map +0 -1
  58. package/core/route/route.types.js +0 -1
  59. package/core/route-group/index.cjs +0 -18
  60. package/core/route-group/index.d.cts +0 -3
  61. package/core/route-group/index.d.cts.map +0 -1
  62. package/core/route-group/index.d.ts +0 -3
  63. package/core/route-group/index.d.ts.map +0 -1
  64. package/core/route-group/index.js +0 -2
  65. package/core/route-group/route-group.cjs +0 -67
  66. package/core/route-group/route-group.d.cts +0 -31
  67. package/core/route-group/route-group.d.cts.map +0 -1
  68. package/core/route-group/route-group.d.ts +0 -31
  69. package/core/route-group/route-group.d.ts.map +0 -1
  70. package/core/route-group/route-group.js +0 -62
  71. package/core/route-group/route-group.types.cjs +0 -2
  72. package/core/route-group/route-group.types.d.cts +0 -15
  73. package/core/route-group/route-group.types.d.cts.map +0 -1
  74. package/core/route-group/route-group.types.d.ts +0 -15
  75. package/core/route-group/route-group.types.d.ts.map +0 -1
  76. package/core/route-group/route-group.types.js +0 -1
  77. package/core/router/index.cjs +0 -18
  78. package/core/router/index.d.cts +0 -3
  79. package/core/router/index.d.cts.map +0 -1
  80. package/core/router/index.d.ts +0 -3
  81. package/core/router/index.d.ts.map +0 -1
  82. package/core/router/index.js +0 -2
  83. package/core/router/router.cjs +0 -42
  84. package/core/router/router.d.cts +0 -18
  85. package/core/router/router.d.cts.map +0 -1
  86. package/core/router/router.d.ts +0 -18
  87. package/core/router/router.d.ts.map +0 -1
  88. package/core/router/router.js +0 -37
  89. package/core/router/router.types.cjs +0 -2
  90. package/core/router/router.types.d.cts +0 -13
  91. package/core/router/router.types.d.cts.map +0 -1
  92. package/core/router/router.types.d.ts +0 -13
  93. package/core/router/router.types.d.ts.map +0 -1
  94. package/core/router/router.types.js +0 -1
  95. package/core/utils/is-route-entity.cjs +0 -5
  96. package/core/utils/is-route-entity.d.cts +0 -3
  97. package/core/utils/is-route-entity.d.cts.map +0 -1
  98. package/core/utils/is-route-entity.d.ts +0 -3
  99. package/core/utils/is-route-entity.d.ts.map +0 -1
  100. package/core/utils/is-route-entity.js +0 -1
  101. package/core/virtual-route/index.cjs +0 -18
  102. package/core/virtual-route/index.d.cts +0 -3
  103. package/core/virtual-route/index.d.cts.map +0 -1
  104. package/core/virtual-route/index.d.ts +0 -3
  105. package/core/virtual-route/index.d.ts.map +0 -1
  106. package/core/virtual-route/index.js +0 -2
  107. package/core/virtual-route/virtual-route.cjs +0 -133
  108. package/core/virtual-route/virtual-route.d.cts +0 -39
  109. package/core/virtual-route/virtual-route.d.cts.map +0 -1
  110. package/core/virtual-route/virtual-route.d.ts +0 -39
  111. package/core/virtual-route/virtual-route.d.ts.map +0 -1
  112. package/core/virtual-route/virtual-route.js +0 -128
  113. package/core/virtual-route/virtual-route.types.cjs +0 -2
  114. package/core/virtual-route/virtual-route.types.d.cts +0 -61
  115. package/core/virtual-route/virtual-route.types.d.cts.map +0 -1
  116. package/core/virtual-route/virtual-route.types.d.ts +0 -61
  117. package/core/virtual-route/virtual-route.types.d.ts.map +0 -1
  118. package/core/virtual-route/virtual-route.types.js +0 -1
  119. package/index.d.cts +0 -3
  120. package/index.d.cts.map +0 -1
  121. package/index.d.ts.map +0 -1
  122. package/react/components/index.cjs +0 -21
  123. package/react/components/index.d.cts +0 -4
  124. package/react/components/index.d.cts.map +0 -1
  125. package/react/components/index.d.ts +0 -4
  126. package/react/components/index.d.ts.map +0 -1
  127. package/react/components/index.js +0 -5
  128. package/react/components/link.cjs +0 -79
  129. package/react/components/link.d.cts +0 -23
  130. package/react/components/link.d.cts.map +0 -1
  131. package/react/components/link.d.ts +0 -23
  132. package/react/components/link.d.ts.map +0 -1
  133. package/react/components/link.js +0 -76
  134. package/react/components/route-view-group.cjs +0 -57
  135. package/react/components/route-view-group.d.cts +0 -26
  136. package/react/components/route-view-group.d.cts.map +0 -1
  137. package/react/components/route-view-group.d.ts +0 -26
  138. package/react/components/route-view-group.d.ts.map +0 -1
  139. package/react/components/route-view-group.js +0 -54
  140. package/react/components/route-view.cjs +0 -43
  141. package/react/components/route-view.d.cts +0 -25
  142. package/react/components/route-view.d.cts.map +0 -1
  143. package/react/components/route-view.d.ts +0 -25
  144. package/react/components/route-view.d.ts.map +0 -1
  145. package/react/components/route-view.js +0 -40
  146. package/react/index.cjs +0 -17
  147. package/react/index.d.cts +0 -2
  148. package/react/index.d.cts.map +0 -1
  149. package/react/index.d.ts +0 -2
  150. package/react/index.d.ts.map +0 -1
  151. package/react/index.js +0 -1
  152. package/view-model/index.cjs +0 -17
  153. package/view-model/index.d.cts +0 -2
  154. package/view-model/index.d.cts.map +0 -1
  155. package/view-model/index.d.ts +0 -2
  156. package/view-model/index.d.ts.map +0 -1
  157. package/view-model/index.js +0 -1
  158. package/view-model/route-view-model.cjs +0 -37
  159. package/view-model/route-view-model.d.cts +0 -13
  160. package/view-model/route-view-model.d.cts.map +0 -1
  161. package/view-model/route-view-model.d.ts +0 -13
  162. package/view-model/route-view-model.d.ts.map +0 -1
  163. package/view-model/route-view-model.js +0 -33
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mobx-route",
3
- "version": "0.17.0",
3
+ "version": "0.19.0",
4
4
  "keywords": [
5
5
  "mobx",
6
6
  "react",
@@ -22,11 +22,11 @@
22
22
  "url": "git://github.com/js2me/mobx-route"
23
23
  },
24
24
  "dependencies": {
25
- "linked-abort-controller": "^1.1.0",
26
- "mobx-location-history": "^8.1.1",
27
- "path-to-regexp": "^8.2.0",
28
- "react-simple-loadable": "^2.3.8",
29
- "yummies": "^6.0.0"
25
+ "linked-abort-controller": "^1.1.1",
26
+ "mobx-location-history": "^9.1.1",
27
+ "path-to-regexp": "^8.3.0",
28
+ "react-simple-loadable": "^3.0.0",
29
+ "yummies": "^6.6.0"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "mobx": "^6.12.4",
@@ -45,71 +45,28 @@
45
45
  "optional": true
46
46
  }
47
47
  },
48
- "devDependencies": {
49
- "@biomejs/biome": "2.2.4",
50
- "@changesets/changelog-github": "^0.5.1",
51
- "@changesets/cli": "^2.29.5",
52
- "@testing-library/react": "^16.3.0",
53
- "@types/lodash-es": "^4.17.12",
54
- "@types/node": "^20.17.30",
55
- "@types/react": "^18.0.0 || ^19.0.0",
56
- "@vitejs/plugin-react-swc": "^3.9.0",
57
- "@vitest/coverage-istanbul": "^3.1.2",
58
- "commitfmt": "^1.0.4",
59
- "js2me-biome-config": "^1.0.5",
60
- "sborshik": "^1.0.8",
61
- "jsdom": "^26.1.0",
62
- "lefthook": "^1.11.13",
63
- "nodemon": "^3.1.10",
64
- "rimraf": "^6.0.1",
65
- "typescript": "^5.8.3",
66
- "vitest": "^3.1.2",
67
- "zshy": "^0.4.2"
68
- },
69
- "files": [
70
- "*"
71
- ],
72
- "main": "./index.cjs",
73
- "module": "./index.js",
74
- "types": "./index.d.cts",
48
+ "main": "index.js",
75
49
  "exports": {
76
- "./package.json": "./package.json",
77
50
  ".": {
78
- "types": "./index.d.cts",
51
+ "types": "./index.d.ts",
79
52
  "import": "./index.js",
80
- "require": "./index.cjs"
53
+ "require": "./index.cjs",
54
+ "default": "./index.js"
81
55
  },
82
56
  "./react": {
83
- "types": "./react/index.d.cts",
84
- "import": "./react/index.js",
85
- "require": "./react/index.cjs"
57
+ "types": "./react.d.ts",
58
+ "import": "./react.js",
59
+ "require": "./react.cjs",
60
+ "default": "./react.js"
86
61
  },
87
62
  "./view-model": {
88
- "types": "./view-model/index.d.cts",
89
- "import": "./view-model/index.js",
90
- "require": "./view-model/index.cjs"
63
+ "types": "./view-model.d.ts",
64
+ "import": "./view-model.js",
65
+ "require": "./view-model.cjs",
66
+ "default": "./view-model.js"
91
67
  }
92
68
  },
93
- "scripts": {
94
- "clean": "rimraf dist",
95
- "lint:check": "pnpm exec biome check --write --no-errors-on-unmatched --files-ignore-unknown=true",
96
- "ts:check": "tsc --noEmit",
97
- "check": "npm run lint:check && npm run ts:check",
98
- "prebuild": "npm run clean && npm run check",
99
- "build:watch": "pnpm build && nodemon --watch src --ext ts --exec \"pnpm build\"",
100
- "build": "sborshik build --fillDist",
101
- "pub": "pnpm build && sborshik publish --useDistDir",
102
- "pub:patch": "PUBLISH_VERSION=patch pnpm pub",
103
- "pub:minor": "PUBLISH_VERSION=minor pnpm pub",
104
- "pub:major": "PUBLISH_VERSION=major pnpm pub",
105
- "test": "vitest run --config vitest.config.ts",
106
- "test:watch": "vitest watch --config vitest.config.ts",
107
- "test:coverage": "vitest run --config vitest.config.ts --coverage",
108
- "docs": "pnpm build && cd docs && pnpm dev",
109
- "docs:install": "cd docs && pnpm i",
110
- "docs:build": "cd docs && pnpm build",
111
- "docs:serve": "cd docs && pnpm preview",
112
- "dev": "pnpm test:watch",
113
- "dev:install-hooks": "if [ -z \"$CI\" ]; then lefthook install; fi"
114
- }
69
+ "files": [
70
+ "*"
71
+ ]
115
72
  }
package/react.cjs ADDED
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const mobxReactLite = require("mobx-react-lite");
5
+ const mobxRoute = require("mobx-route");
6
+ const react = require("react");
7
+ const data = require("yummies/data");
8
+ const reactSimpleLoadable = require("react-simple-loadable");
9
+ const Link = mobxReactLite.observer(
10
+ react.forwardRef(
11
+ ({
12
+ to,
13
+ href: outerHref,
14
+ mergeQuery,
15
+ asChild,
16
+ children,
17
+ params,
18
+ // route navigate params
19
+ query,
20
+ replace,
21
+ state,
22
+ ...outerAnchorProps
23
+ }, ref) => {
24
+ const isExternalNavigation = outerAnchorProps.target === "_blank" || outerAnchorProps.target === "blank";
25
+ const queryDataRef = react.useRef(query);
26
+ if (!data.isShallowEqual(queryDataRef.current, query)) {
27
+ queryDataRef.current = query;
28
+ }
29
+ const { href, navigateParams } = react.useMemo(() => {
30
+ const navigateParams2 = {
31
+ mergeQuery,
32
+ query,
33
+ replace,
34
+ state
35
+ };
36
+ const cfg = mobxRoute.routeConfig.get();
37
+ let href2;
38
+ if (outerHref) {
39
+ href2 = outerHref;
40
+ } else {
41
+ if (typeof to === "string") {
42
+ const isNeedToMergeQuery = navigateParams2.mergeQuery ?? cfg.mergeQuery;
43
+ const [path, ...querySegments] = to.split("?");
44
+ const existedQuery = mobxRoute.parseSearchString(querySegments.join("?"));
45
+ const query2 = {
46
+ ...isNeedToMergeQuery ? cfg.queryParams.data : {},
47
+ ...existedQuery,
48
+ ...navigateParams2.query
49
+ };
50
+ href2 = `${path}${mobxRoute.buildSearchString(query2)}`;
51
+ } else {
52
+ href2 = to.createUrl(
53
+ params,
54
+ navigateParams2.query,
55
+ navigateParams2.mergeQuery
56
+ );
57
+ }
58
+ }
59
+ return {
60
+ href: cfg.formatLinkHref?.(href2) ?? href2,
61
+ navigateParams: navigateParams2
62
+ };
63
+ }, [mergeQuery, replace, state, to, queryDataRef.current]);
64
+ const handleClick = (event) => {
65
+ if (isExternalNavigation || event.ctrlKey || event.metaKey || event.altKey || event.shiftKey || event.button !== 0)
66
+ return;
67
+ outerAnchorProps.onClick?.(event);
68
+ if (!event.defaultPrevented) {
69
+ event.preventDefault();
70
+ if (navigateParams.replace) {
71
+ mobxRoute.routeConfig.get().history.replace(href, navigateParams.state);
72
+ } else {
73
+ mobxRoute.routeConfig.get().history.push(href, navigateParams.state);
74
+ }
75
+ }
76
+ };
77
+ const anchorProps = {
78
+ ...outerAnchorProps,
79
+ href,
80
+ onClick: handleClick,
81
+ rel: outerAnchorProps.rel ?? (isExternalNavigation ? "noopener noreferrer" : void 0)
82
+ };
83
+ return asChild && react.isValidElement(children) ? react.cloneElement(children, anchorProps) : /* @__PURE__ */ jsxRuntime.jsx("a", { ...anchorProps, ref, children });
84
+ }
85
+ )
86
+ );
87
+ function RouteViewBase(props) {
88
+ const lazyViewComponentRef = react.useRef();
89
+ let Component;
90
+ if (!("route" in props)) {
91
+ return typeof props.children === "function" ? props.children() : props.children;
92
+ }
93
+ if (!props.route.isOpened) {
94
+ return props.fallback ?? null;
95
+ }
96
+ if (props.loadView) {
97
+ if (!lazyViewComponentRef.current) {
98
+ lazyViewComponentRef.current = reactSimpleLoadable.loadable({
99
+ load: () => props.loadView(props.route),
100
+ loading: props.loading,
101
+ preload: props.preload,
102
+ throwOnError: props.throwOnError
103
+ });
104
+ }
105
+ Component = lazyViewComponentRef.current;
106
+ } else {
107
+ Component = props.view;
108
+ }
109
+ const params = "params" in props.route ? props.route.params : {};
110
+ if (Component) {
111
+ return /* @__PURE__ */ jsxRuntime.jsx(Component, { params, children: props.children });
112
+ }
113
+ if (typeof props.children === "function") {
114
+ return props.children(params, props.route);
115
+ }
116
+ return props.children;
117
+ }
118
+ const RouteView = mobxReactLite.observer(RouteViewBase);
119
+ const RouteViewGroup = mobxReactLite.observer(
120
+ ({
121
+ children,
122
+ layout: Layout,
123
+ otherwise: otherwiseNavigation,
124
+ // @ts-expect-error
125
+ params,
126
+ ...navigateParams
127
+ }) => {
128
+ let activeChildNode = null;
129
+ let lastInactiveChildNode = null;
130
+ const childNodes = Array.isArray(children) ? children : [children];
131
+ for (const childNode of childNodes) {
132
+ if (react.isValidElement(childNode) && // @ts-expect-error redundand checks better to wrap in this directive
133
+ mobxRoute.isRouteEntity(childNode.props?.route) && // @ts-expect-error redundand checks better to wrap in this directive
134
+ childNode.props.route.isOpened) {
135
+ activeChildNode = childNode;
136
+ break;
137
+ } else {
138
+ lastInactiveChildNode = childNode;
139
+ }
140
+ }
141
+ const hasActiveChildNode = !!activeChildNode;
142
+ react.useEffect(() => {
143
+ if (!hasActiveChildNode && otherwiseNavigation) {
144
+ if (typeof otherwiseNavigation === "string") {
145
+ const history = mobxRoute.routeConfig.get().history;
146
+ const url = `${otherwiseNavigation}${mobxRoute.buildSearchString(navigateParams.query || {})}`;
147
+ if (navigateParams.replace) {
148
+ history.replace(url, navigateParams.state);
149
+ } else {
150
+ history.push(url, navigateParams.state);
151
+ }
152
+ } else if (!otherwiseNavigation.isOpened) {
153
+ otherwiseNavigation.open(params, navigateParams);
154
+ }
155
+ }
156
+ }, [hasActiveChildNode, otherwiseNavigation]);
157
+ if (otherwiseNavigation && !activeChildNode) {
158
+ return null;
159
+ }
160
+ const resultNodeToRender = activeChildNode ?? lastInactiveChildNode ?? null;
161
+ if (Layout) {
162
+ return /* @__PURE__ */ jsxRuntime.jsx(Layout, { children: resultNodeToRender });
163
+ }
164
+ return resultNodeToRender;
165
+ }
166
+ );
167
+ exports.Link = Link;
168
+ exports.RouteView = RouteView;
169
+ exports.RouteViewGroup = RouteViewGroup;
170
+ //# sourceMappingURL=react.cjs.map
package/react.cjs.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.cjs","sources":["../src/react/components/link.tsx","../src/react/components/route-view.tsx","../src/react/components/route-view-group.tsx"],"sourcesContent":["import { observer } from 'mobx-react-lite';\nimport {\n type AnyRoute,\n buildSearchString,\n type InputPathParams,\n parseSearchString,\n type RouteNavigateParams,\n routeConfig,\n} from 'mobx-route';\nimport {\n type AnchorHTMLAttributes,\n cloneElement,\n forwardRef,\n isValidElement,\n type MouseEvent,\n useMemo,\n useRef,\n} from 'react';\nimport { isShallowEqual } from 'yummies/data';\nimport type { IsPartial } from 'yummies/types';\n\ninterface LinkAnchorProps\n extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {\n asChild?: boolean;\n}\n\ntype LinkPathRouteProps<TRoute extends AnyRoute> = {\n to: TRoute;\n} & (IsPartial<InputPathParams<TRoute['path']>> extends true\n ? {\n params?: InputPathParams<TRoute['path']> | null | undefined;\n }\n : { params: InputPathParams<TRoute['path']> });\n\ntype LinkSimpleRouteProps =\n | {\n to: string;\n }\n | {\n href: string;\n };\n\nexport type LinkProps<TRoute extends AnyRoute> = LinkAnchorProps &\n RouteNavigateParams &\n (LinkPathRouteProps<TRoute> | LinkSimpleRouteProps);\n\ntype LinkComponentType = <TRoute extends AnyRoute>(\n props: LinkProps<TRoute>,\n) => React.ReactNode;\n\nexport const Link = observer(\n forwardRef<\n HTMLAnchorElement,\n LinkAnchorProps &\n RouteNavigateParams & {\n params?: any;\n to: string | AnyRoute;\n href: string;\n }\n >(\n (\n {\n to,\n href: outerHref,\n mergeQuery,\n asChild,\n children,\n params,\n // route navigate params\n query,\n replace,\n state,\n ...outerAnchorProps\n },\n ref,\n ) => {\n const isExternalNavigation =\n outerAnchorProps.target === '_blank' ||\n outerAnchorProps.target === 'blank';\n const queryDataRef = useRef<RouteNavigateParams['query']>(query);\n\n if (!isShallowEqual(queryDataRef.current, query)) {\n queryDataRef.current = query;\n }\n\n const { href, navigateParams } = useMemo(() => {\n const navigateParams: RouteNavigateParams = {\n mergeQuery,\n query,\n replace,\n state,\n };\n\n const cfg = routeConfig.get();\n\n let href: string;\n\n if (outerHref) {\n href = outerHref;\n } else {\n if (typeof to === 'string') {\n const isNeedToMergeQuery =\n navigateParams.mergeQuery ?? cfg.mergeQuery;\n\n const [path, ...querySegments] = to.split('?');\n\n const existedQuery = parseSearchString(querySegments.join('?'));\n\n const query = {\n ...(isNeedToMergeQuery ? cfg.queryParams.data : {}),\n ...existedQuery,\n ...navigateParams.query,\n };\n\n href = `${path}${buildSearchString(query)}`;\n } else {\n href = to.createUrl(\n params,\n navigateParams.query,\n navigateParams.mergeQuery,\n );\n }\n }\n\n return {\n href: cfg.formatLinkHref?.(href) ?? href,\n navigateParams,\n };\n }, [mergeQuery, replace, state, to, queryDataRef.current]);\n\n const handleClick = (event: MouseEvent<HTMLAnchorElement>) => {\n if (\n isExternalNavigation ||\n event.ctrlKey ||\n event.metaKey ||\n event.altKey ||\n event.shiftKey ||\n event.button !== 0\n )\n return;\n\n outerAnchorProps.onClick?.(event);\n\n if (!event.defaultPrevented) {\n event.preventDefault();\n\n if (navigateParams.replace) {\n routeConfig.get().history.replace(href, navigateParams.state);\n } else {\n routeConfig.get().history.push(href, navigateParams.state);\n }\n }\n };\n\n const anchorProps = {\n ...outerAnchorProps,\n href,\n onClick: handleClick,\n rel:\n outerAnchorProps.rel ??\n (isExternalNavigation ? 'noopener noreferrer' : undefined),\n };\n\n return asChild && isValidElement(children) ? (\n cloneElement(children, anchorProps)\n ) : (\n <a {...anchorProps} ref={ref}>\n {children}\n </a>\n );\n },\n ),\n) as unknown as LinkComponentType;\n","import { observer } from 'mobx-react-lite';\nimport type {\n AnyAbstractRouteEntity,\n AnyRoute,\n AnyVirtualRoute,\n} from 'mobx-route';\nimport { useRef } from 'react';\nimport { type LoadableConfig, loadable } from 'react-simple-loadable';\n\nexport type RouteViewComponent<TRoute extends AnyAbstractRouteEntity> =\n React.ComponentType<RouteViewProps<TRoute>>;\n\ninterface RouteViewConfigWithoutRoute {\n children?: React.ReactNode | (() => React.ReactNode);\n}\n\nexport interface RouteViewConfigWithRoute<TRoute extends AnyAbstractRouteEntity>\n extends Pick<LoadableConfig, 'loading' | 'preload' | 'throwOnError'> {\n route: TRoute;\n view?: RouteViewComponent<TRoute>;\n loadView?: (route: TRoute) => Promise<RouteViewComponent<TRoute>>;\n /**\n * Case when route is not opened\n */\n fallback?: React.ReactNode;\n children?:\n | React.ReactNode\n | ((\n params: RouteViewProps<TRoute>['params'],\n route: TRoute,\n ) => React.ReactNode);\n}\n\nexport type RouteViewConfig<TRoute extends AnyAbstractRouteEntity> =\n | RouteViewConfigWithRoute<TRoute>\n | RouteViewConfigWithoutRoute;\n\nexport type RouteViewProps<TRoute extends AnyAbstractRouteEntity> = {\n children?: React.ReactNode;\n params: TRoute extends AnyRoute\n ? Exclude<TRoute['params'], null | undefined>\n : TRoute extends AnyVirtualRoute\n ? TRoute['params']\n : never;\n};\n\ntype RouteViewBaseComponent = <TRoute extends AnyAbstractRouteEntity>(\n props: RouteViewConfig<TRoute>,\n) => React.ReactNode;\n\nfunction RouteViewBase<TRoute extends AnyAbstractRouteEntity>(\n props: Readonly<RouteViewConfig<TRoute>>,\n): React.ReactNode {\n // @ts-expect-error redundand pass first argument\n const lazyViewComponentRef = useRef<React.ComponentType<any>>();\n\n let Component: React.ComponentType<any> | undefined;\n\n if (!('route' in props)) {\n return typeof props.children === 'function'\n ? props.children()\n : props.children;\n }\n\n if (!props.route.isOpened) {\n return props.fallback ?? null;\n }\n\n if (props.loadView) {\n if (!lazyViewComponentRef.current) {\n lazyViewComponentRef.current = loadable({\n load: () => props.loadView!(props.route),\n loading: props.loading,\n preload: props.preload,\n throwOnError: props.throwOnError,\n });\n }\n Component = lazyViewComponentRef.current;\n } else {\n Component = props.view;\n }\n\n const params: any = 'params' in props.route ? props.route.params : {};\n\n if (Component) {\n return <Component params={params}>{props.children}</Component>;\n }\n\n if (typeof props.children === 'function') {\n return props.children(params, props.route);\n }\n\n return props.children;\n}\n\nexport const RouteView = observer(RouteViewBase) as RouteViewBaseComponent;\n","import { observer } from 'mobx-react-lite';\nimport {\n type AnyRouteEntity,\n buildSearchString,\n isRouteEntity,\n type RouteNavigateParams,\n type RouteParams,\n routeConfig,\n} from 'mobx-route';\nimport { isValidElement, useEffect } from 'react';\nimport type { IsPartial, Maybe } from 'yummies/types';\n\ntype LayoutComponent =\n | React.ComponentType<{ children?: React.ReactNode }>\n | React.ComponentType<{ children: React.ReactNode }>;\n\ninterface BaseProps extends RouteNavigateParams {\n children: React.ReactNode;\n layout?: LayoutComponent;\n}\n\ntype PropsWithDefaultRoute<TRoute extends AnyRouteEntity> = BaseProps & {\n otherwise?: TRoute;\n} & (IsPartial<RouteParams<TRoute>> extends true\n ? {\n params?: Maybe<RouteParams<TRoute>>;\n }\n : {\n params: RouteParams<TRoute>;\n });\n\ntype PropsWithDefaultUrl = BaseProps & {\n otherwise?: string;\n};\n\nexport type RouteViewGroupProps<TRoute extends AnyRouteEntity> =\n | PropsWithDefaultRoute<TRoute>\n | PropsWithDefaultUrl;\n\ntype RouteViewGroupComponent = <TRoute extends AnyRouteEntity>(\n props: RouteViewGroupProps<TRoute>,\n) => React.ReactNode;\n\nexport const RouteViewGroup = observer(\n <TRoute extends AnyRouteEntity>({\n children,\n layout: Layout,\n otherwise: otherwiseNavigation,\n // @ts-expect-error\n params,\n ...navigateParams\n }: RouteViewGroupProps<TRoute>) => {\n let activeChildNode: React.ReactNode = null;\n let lastInactiveChildNode: React.ReactNode = null;\n\n const childNodes: React.ReactNode[] = Array.isArray(children)\n ? children\n : [children];\n\n for (const childNode of childNodes) {\n if (\n isValidElement(childNode) &&\n // @ts-expect-error redundand checks better to wrap in this directive\n isRouteEntity(childNode.props?.route) &&\n // @ts-expect-error redundand checks better to wrap in this directive\n childNode.props.route.isOpened\n ) {\n activeChildNode = childNode;\n break;\n } else {\n lastInactiveChildNode = childNode;\n }\n }\n\n const hasActiveChildNode = !!activeChildNode;\n\n useEffect(() => {\n if (!hasActiveChildNode && otherwiseNavigation) {\n if (typeof otherwiseNavigation === 'string') {\n const history = routeConfig.get().history;\n const url = `${otherwiseNavigation}${buildSearchString(navigateParams.query || {})}`;\n\n if (navigateParams.replace) {\n history.replace(url, navigateParams.state);\n } else {\n history.push(url, navigateParams.state);\n }\n } else if (!otherwiseNavigation.isOpened) {\n otherwiseNavigation.open(params, navigateParams);\n }\n }\n }, [hasActiveChildNode, otherwiseNavigation]);\n\n if (otherwiseNavigation && !activeChildNode) {\n return null;\n }\n\n const resultNodeToRender = activeChildNode ?? lastInactiveChildNode ?? null;\n\n if (Layout) {\n return <Layout>{resultNodeToRender}</Layout>;\n }\n\n return resultNodeToRender;\n },\n) as unknown as RouteViewGroupComponent;\n"],"names":["observer","forwardRef","useRef","isShallowEqual","useMemo","navigateParams","routeConfig","href","parseSearchString","query","buildSearchString","isValidElement","cloneElement","jsx","loadable","isRouteEntity","useEffect"],"mappings":"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"}
package/react.d.ts ADDED
@@ -0,0 +1,71 @@
1
+ import { AnyRoute, RouteNavigateParams, InputPathParams, AnyAbstractRouteEntity, AnyVirtualRoute, AnyRouteEntity, RouteParams } from 'mobx-route';
2
+ import { AnchorHTMLAttributes } from 'react';
3
+ import { IsPartial, Maybe } from 'yummies/types';
4
+ import { LoadableConfig } from 'react-simple-loadable';
5
+
6
+ interface LinkAnchorProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {
7
+ asChild?: boolean;
8
+ }
9
+ type LinkPathRouteProps<TRoute extends AnyRoute> = {
10
+ to: TRoute;
11
+ } & (IsPartial<InputPathParams<TRoute['path']>> extends true ? {
12
+ params?: InputPathParams<TRoute['path']> | null | undefined;
13
+ } : {
14
+ params: InputPathParams<TRoute['path']>;
15
+ });
16
+ type LinkSimpleRouteProps = {
17
+ to: string;
18
+ } | {
19
+ href: string;
20
+ };
21
+ type LinkProps<TRoute extends AnyRoute> = LinkAnchorProps & RouteNavigateParams & (LinkPathRouteProps<TRoute> | LinkSimpleRouteProps);
22
+ type LinkComponentType = <TRoute extends AnyRoute>(props: LinkProps<TRoute>) => React.ReactNode;
23
+ declare const Link: LinkComponentType;
24
+
25
+ type RouteViewComponent<TRoute extends AnyAbstractRouteEntity> = React.ComponentType<RouteViewProps<TRoute>>;
26
+ interface RouteViewConfigWithoutRoute {
27
+ children?: React.ReactNode | (() => React.ReactNode);
28
+ }
29
+ interface RouteViewConfigWithRoute<TRoute extends AnyAbstractRouteEntity> extends Pick<LoadableConfig, 'loading' | 'preload' | 'throwOnError'> {
30
+ route: TRoute;
31
+ view?: RouteViewComponent<TRoute>;
32
+ loadView?: (route: TRoute) => Promise<RouteViewComponent<TRoute>>;
33
+ /**
34
+ * Case when route is not opened
35
+ */
36
+ fallback?: React.ReactNode;
37
+ children?: React.ReactNode | ((params: RouteViewProps<TRoute>['params'], route: TRoute) => React.ReactNode);
38
+ }
39
+ type RouteViewConfig<TRoute extends AnyAbstractRouteEntity> = RouteViewConfigWithRoute<TRoute> | RouteViewConfigWithoutRoute;
40
+ type RouteViewProps<TRoute extends AnyAbstractRouteEntity> = {
41
+ children?: React.ReactNode;
42
+ params: TRoute extends AnyRoute ? Exclude<TRoute['params'], null | undefined> : TRoute extends AnyVirtualRoute ? TRoute['params'] : never;
43
+ };
44
+ type RouteViewBaseComponent = <TRoute extends AnyAbstractRouteEntity>(props: RouteViewConfig<TRoute>) => React.ReactNode;
45
+ declare const RouteView: RouteViewBaseComponent;
46
+
47
+ type LayoutComponent = React.ComponentType<{
48
+ children?: React.ReactNode;
49
+ }> | React.ComponentType<{
50
+ children: React.ReactNode;
51
+ }>;
52
+ interface BaseProps extends RouteNavigateParams {
53
+ children: React.ReactNode;
54
+ layout?: LayoutComponent;
55
+ }
56
+ type PropsWithDefaultRoute<TRoute extends AnyRouteEntity> = BaseProps & {
57
+ otherwise?: TRoute;
58
+ } & (IsPartial<RouteParams<TRoute>> extends true ? {
59
+ params?: Maybe<RouteParams<TRoute>>;
60
+ } : {
61
+ params: RouteParams<TRoute>;
62
+ });
63
+ type PropsWithDefaultUrl = BaseProps & {
64
+ otherwise?: string;
65
+ };
66
+ type RouteViewGroupProps<TRoute extends AnyRouteEntity> = PropsWithDefaultRoute<TRoute> | PropsWithDefaultUrl;
67
+ type RouteViewGroupComponent = <TRoute extends AnyRouteEntity>(props: RouteViewGroupProps<TRoute>) => React.ReactNode;
68
+ declare const RouteViewGroup: RouteViewGroupComponent;
69
+
70
+ export { Link, RouteView, RouteViewGroup };
71
+ export type { LinkProps, RouteViewComponent, RouteViewConfig, RouteViewConfigWithRoute, RouteViewGroupProps, RouteViewProps };
package/react.js ADDED
@@ -0,0 +1,170 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { observer } from "mobx-react-lite";
3
+ import { routeConfig, parseSearchString, buildSearchString, isRouteEntity } from "mobx-route";
4
+ import { forwardRef, useRef, useMemo, cloneElement, isValidElement, useEffect } from "react";
5
+ import { isShallowEqual } from "yummies/data";
6
+ import { loadable } from "react-simple-loadable";
7
+ const Link = observer(
8
+ forwardRef(
9
+ ({
10
+ to,
11
+ href: outerHref,
12
+ mergeQuery,
13
+ asChild,
14
+ children,
15
+ params,
16
+ // route navigate params
17
+ query,
18
+ replace,
19
+ state,
20
+ ...outerAnchorProps
21
+ }, ref) => {
22
+ const isExternalNavigation = outerAnchorProps.target === "_blank" || outerAnchorProps.target === "blank";
23
+ const queryDataRef = useRef(query);
24
+ if (!isShallowEqual(queryDataRef.current, query)) {
25
+ queryDataRef.current = query;
26
+ }
27
+ const { href, navigateParams } = useMemo(() => {
28
+ const navigateParams2 = {
29
+ mergeQuery,
30
+ query,
31
+ replace,
32
+ state
33
+ };
34
+ const cfg = routeConfig.get();
35
+ let href2;
36
+ if (outerHref) {
37
+ href2 = outerHref;
38
+ } else {
39
+ if (typeof to === "string") {
40
+ const isNeedToMergeQuery = navigateParams2.mergeQuery ?? cfg.mergeQuery;
41
+ const [path, ...querySegments] = to.split("?");
42
+ const existedQuery = parseSearchString(querySegments.join("?"));
43
+ const query2 = {
44
+ ...isNeedToMergeQuery ? cfg.queryParams.data : {},
45
+ ...existedQuery,
46
+ ...navigateParams2.query
47
+ };
48
+ href2 = `${path}${buildSearchString(query2)}`;
49
+ } else {
50
+ href2 = to.createUrl(
51
+ params,
52
+ navigateParams2.query,
53
+ navigateParams2.mergeQuery
54
+ );
55
+ }
56
+ }
57
+ return {
58
+ href: cfg.formatLinkHref?.(href2) ?? href2,
59
+ navigateParams: navigateParams2
60
+ };
61
+ }, [mergeQuery, replace, state, to, queryDataRef.current]);
62
+ const handleClick = (event) => {
63
+ if (isExternalNavigation || event.ctrlKey || event.metaKey || event.altKey || event.shiftKey || event.button !== 0)
64
+ return;
65
+ outerAnchorProps.onClick?.(event);
66
+ if (!event.defaultPrevented) {
67
+ event.preventDefault();
68
+ if (navigateParams.replace) {
69
+ routeConfig.get().history.replace(href, navigateParams.state);
70
+ } else {
71
+ routeConfig.get().history.push(href, navigateParams.state);
72
+ }
73
+ }
74
+ };
75
+ const anchorProps = {
76
+ ...outerAnchorProps,
77
+ href,
78
+ onClick: handleClick,
79
+ rel: outerAnchorProps.rel ?? (isExternalNavigation ? "noopener noreferrer" : void 0)
80
+ };
81
+ return asChild && isValidElement(children) ? cloneElement(children, anchorProps) : /* @__PURE__ */ jsx("a", { ...anchorProps, ref, children });
82
+ }
83
+ )
84
+ );
85
+ function RouteViewBase(props) {
86
+ const lazyViewComponentRef = useRef();
87
+ let Component;
88
+ if (!("route" in props)) {
89
+ return typeof props.children === "function" ? props.children() : props.children;
90
+ }
91
+ if (!props.route.isOpened) {
92
+ return props.fallback ?? null;
93
+ }
94
+ if (props.loadView) {
95
+ if (!lazyViewComponentRef.current) {
96
+ lazyViewComponentRef.current = loadable({
97
+ load: () => props.loadView(props.route),
98
+ loading: props.loading,
99
+ preload: props.preload,
100
+ throwOnError: props.throwOnError
101
+ });
102
+ }
103
+ Component = lazyViewComponentRef.current;
104
+ } else {
105
+ Component = props.view;
106
+ }
107
+ const params = "params" in props.route ? props.route.params : {};
108
+ if (Component) {
109
+ return /* @__PURE__ */ jsx(Component, { params, children: props.children });
110
+ }
111
+ if (typeof props.children === "function") {
112
+ return props.children(params, props.route);
113
+ }
114
+ return props.children;
115
+ }
116
+ const RouteView = observer(RouteViewBase);
117
+ const RouteViewGroup = observer(
118
+ ({
119
+ children,
120
+ layout: Layout,
121
+ otherwise: otherwiseNavigation,
122
+ // @ts-expect-error
123
+ params,
124
+ ...navigateParams
125
+ }) => {
126
+ let activeChildNode = null;
127
+ let lastInactiveChildNode = null;
128
+ const childNodes = Array.isArray(children) ? children : [children];
129
+ for (const childNode of childNodes) {
130
+ if (isValidElement(childNode) && // @ts-expect-error redundand checks better to wrap in this directive
131
+ isRouteEntity(childNode.props?.route) && // @ts-expect-error redundand checks better to wrap in this directive
132
+ childNode.props.route.isOpened) {
133
+ activeChildNode = childNode;
134
+ break;
135
+ } else {
136
+ lastInactiveChildNode = childNode;
137
+ }
138
+ }
139
+ const hasActiveChildNode = !!activeChildNode;
140
+ useEffect(() => {
141
+ if (!hasActiveChildNode && otherwiseNavigation) {
142
+ if (typeof otherwiseNavigation === "string") {
143
+ const history = routeConfig.get().history;
144
+ const url = `${otherwiseNavigation}${buildSearchString(navigateParams.query || {})}`;
145
+ if (navigateParams.replace) {
146
+ history.replace(url, navigateParams.state);
147
+ } else {
148
+ history.push(url, navigateParams.state);
149
+ }
150
+ } else if (!otherwiseNavigation.isOpened) {
151
+ otherwiseNavigation.open(params, navigateParams);
152
+ }
153
+ }
154
+ }, [hasActiveChildNode, otherwiseNavigation]);
155
+ if (otherwiseNavigation && !activeChildNode) {
156
+ return null;
157
+ }
158
+ const resultNodeToRender = activeChildNode ?? lastInactiveChildNode ?? null;
159
+ if (Layout) {
160
+ return /* @__PURE__ */ jsx(Layout, { children: resultNodeToRender });
161
+ }
162
+ return resultNodeToRender;
163
+ }
164
+ );
165
+ export {
166
+ Link,
167
+ RouteView,
168
+ RouteViewGroup
169
+ };
170
+ //# sourceMappingURL=react.js.map
package/react.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.js","sources":["../src/react/components/link.tsx","../src/react/components/route-view.tsx","../src/react/components/route-view-group.tsx"],"sourcesContent":["import { observer } from 'mobx-react-lite';\nimport {\n type AnyRoute,\n buildSearchString,\n type InputPathParams,\n parseSearchString,\n type RouteNavigateParams,\n routeConfig,\n} from 'mobx-route';\nimport {\n type AnchorHTMLAttributes,\n cloneElement,\n forwardRef,\n isValidElement,\n type MouseEvent,\n useMemo,\n useRef,\n} from 'react';\nimport { isShallowEqual } from 'yummies/data';\nimport type { IsPartial } from 'yummies/types';\n\ninterface LinkAnchorProps\n extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {\n asChild?: boolean;\n}\n\ntype LinkPathRouteProps<TRoute extends AnyRoute> = {\n to: TRoute;\n} & (IsPartial<InputPathParams<TRoute['path']>> extends true\n ? {\n params?: InputPathParams<TRoute['path']> | null | undefined;\n }\n : { params: InputPathParams<TRoute['path']> });\n\ntype LinkSimpleRouteProps =\n | {\n to: string;\n }\n | {\n href: string;\n };\n\nexport type LinkProps<TRoute extends AnyRoute> = LinkAnchorProps &\n RouteNavigateParams &\n (LinkPathRouteProps<TRoute> | LinkSimpleRouteProps);\n\ntype LinkComponentType = <TRoute extends AnyRoute>(\n props: LinkProps<TRoute>,\n) => React.ReactNode;\n\nexport const Link = observer(\n forwardRef<\n HTMLAnchorElement,\n LinkAnchorProps &\n RouteNavigateParams & {\n params?: any;\n to: string | AnyRoute;\n href: string;\n }\n >(\n (\n {\n to,\n href: outerHref,\n mergeQuery,\n asChild,\n children,\n params,\n // route navigate params\n query,\n replace,\n state,\n ...outerAnchorProps\n },\n ref,\n ) => {\n const isExternalNavigation =\n outerAnchorProps.target === '_blank' ||\n outerAnchorProps.target === 'blank';\n const queryDataRef = useRef<RouteNavigateParams['query']>(query);\n\n if (!isShallowEqual(queryDataRef.current, query)) {\n queryDataRef.current = query;\n }\n\n const { href, navigateParams } = useMemo(() => {\n const navigateParams: RouteNavigateParams = {\n mergeQuery,\n query,\n replace,\n state,\n };\n\n const cfg = routeConfig.get();\n\n let href: string;\n\n if (outerHref) {\n href = outerHref;\n } else {\n if (typeof to === 'string') {\n const isNeedToMergeQuery =\n navigateParams.mergeQuery ?? cfg.mergeQuery;\n\n const [path, ...querySegments] = to.split('?');\n\n const existedQuery = parseSearchString(querySegments.join('?'));\n\n const query = {\n ...(isNeedToMergeQuery ? cfg.queryParams.data : {}),\n ...existedQuery,\n ...navigateParams.query,\n };\n\n href = `${path}${buildSearchString(query)}`;\n } else {\n href = to.createUrl(\n params,\n navigateParams.query,\n navigateParams.mergeQuery,\n );\n }\n }\n\n return {\n href: cfg.formatLinkHref?.(href) ?? href,\n navigateParams,\n };\n }, [mergeQuery, replace, state, to, queryDataRef.current]);\n\n const handleClick = (event: MouseEvent<HTMLAnchorElement>) => {\n if (\n isExternalNavigation ||\n event.ctrlKey ||\n event.metaKey ||\n event.altKey ||\n event.shiftKey ||\n event.button !== 0\n )\n return;\n\n outerAnchorProps.onClick?.(event);\n\n if (!event.defaultPrevented) {\n event.preventDefault();\n\n if (navigateParams.replace) {\n routeConfig.get().history.replace(href, navigateParams.state);\n } else {\n routeConfig.get().history.push(href, navigateParams.state);\n }\n }\n };\n\n const anchorProps = {\n ...outerAnchorProps,\n href,\n onClick: handleClick,\n rel:\n outerAnchorProps.rel ??\n (isExternalNavigation ? 'noopener noreferrer' : undefined),\n };\n\n return asChild && isValidElement(children) ? (\n cloneElement(children, anchorProps)\n ) : (\n <a {...anchorProps} ref={ref}>\n {children}\n </a>\n );\n },\n ),\n) as unknown as LinkComponentType;\n","import { observer } from 'mobx-react-lite';\nimport type {\n AnyAbstractRouteEntity,\n AnyRoute,\n AnyVirtualRoute,\n} from 'mobx-route';\nimport { useRef } from 'react';\nimport { type LoadableConfig, loadable } from 'react-simple-loadable';\n\nexport type RouteViewComponent<TRoute extends AnyAbstractRouteEntity> =\n React.ComponentType<RouteViewProps<TRoute>>;\n\ninterface RouteViewConfigWithoutRoute {\n children?: React.ReactNode | (() => React.ReactNode);\n}\n\nexport interface RouteViewConfigWithRoute<TRoute extends AnyAbstractRouteEntity>\n extends Pick<LoadableConfig, 'loading' | 'preload' | 'throwOnError'> {\n route: TRoute;\n view?: RouteViewComponent<TRoute>;\n loadView?: (route: TRoute) => Promise<RouteViewComponent<TRoute>>;\n /**\n * Case when route is not opened\n */\n fallback?: React.ReactNode;\n children?:\n | React.ReactNode\n | ((\n params: RouteViewProps<TRoute>['params'],\n route: TRoute,\n ) => React.ReactNode);\n}\n\nexport type RouteViewConfig<TRoute extends AnyAbstractRouteEntity> =\n | RouteViewConfigWithRoute<TRoute>\n | RouteViewConfigWithoutRoute;\n\nexport type RouteViewProps<TRoute extends AnyAbstractRouteEntity> = {\n children?: React.ReactNode;\n params: TRoute extends AnyRoute\n ? Exclude<TRoute['params'], null | undefined>\n : TRoute extends AnyVirtualRoute\n ? TRoute['params']\n : never;\n};\n\ntype RouteViewBaseComponent = <TRoute extends AnyAbstractRouteEntity>(\n props: RouteViewConfig<TRoute>,\n) => React.ReactNode;\n\nfunction RouteViewBase<TRoute extends AnyAbstractRouteEntity>(\n props: Readonly<RouteViewConfig<TRoute>>,\n): React.ReactNode {\n // @ts-expect-error redundand pass first argument\n const lazyViewComponentRef = useRef<React.ComponentType<any>>();\n\n let Component: React.ComponentType<any> | undefined;\n\n if (!('route' in props)) {\n return typeof props.children === 'function'\n ? props.children()\n : props.children;\n }\n\n if (!props.route.isOpened) {\n return props.fallback ?? null;\n }\n\n if (props.loadView) {\n if (!lazyViewComponentRef.current) {\n lazyViewComponentRef.current = loadable({\n load: () => props.loadView!(props.route),\n loading: props.loading,\n preload: props.preload,\n throwOnError: props.throwOnError,\n });\n }\n Component = lazyViewComponentRef.current;\n } else {\n Component = props.view;\n }\n\n const params: any = 'params' in props.route ? props.route.params : {};\n\n if (Component) {\n return <Component params={params}>{props.children}</Component>;\n }\n\n if (typeof props.children === 'function') {\n return props.children(params, props.route);\n }\n\n return props.children;\n}\n\nexport const RouteView = observer(RouteViewBase) as RouteViewBaseComponent;\n","import { observer } from 'mobx-react-lite';\nimport {\n type AnyRouteEntity,\n buildSearchString,\n isRouteEntity,\n type RouteNavigateParams,\n type RouteParams,\n routeConfig,\n} from 'mobx-route';\nimport { isValidElement, useEffect } from 'react';\nimport type { IsPartial, Maybe } from 'yummies/types';\n\ntype LayoutComponent =\n | React.ComponentType<{ children?: React.ReactNode }>\n | React.ComponentType<{ children: React.ReactNode }>;\n\ninterface BaseProps extends RouteNavigateParams {\n children: React.ReactNode;\n layout?: LayoutComponent;\n}\n\ntype PropsWithDefaultRoute<TRoute extends AnyRouteEntity> = BaseProps & {\n otherwise?: TRoute;\n} & (IsPartial<RouteParams<TRoute>> extends true\n ? {\n params?: Maybe<RouteParams<TRoute>>;\n }\n : {\n params: RouteParams<TRoute>;\n });\n\ntype PropsWithDefaultUrl = BaseProps & {\n otherwise?: string;\n};\n\nexport type RouteViewGroupProps<TRoute extends AnyRouteEntity> =\n | PropsWithDefaultRoute<TRoute>\n | PropsWithDefaultUrl;\n\ntype RouteViewGroupComponent = <TRoute extends AnyRouteEntity>(\n props: RouteViewGroupProps<TRoute>,\n) => React.ReactNode;\n\nexport const RouteViewGroup = observer(\n <TRoute extends AnyRouteEntity>({\n children,\n layout: Layout,\n otherwise: otherwiseNavigation,\n // @ts-expect-error\n params,\n ...navigateParams\n }: RouteViewGroupProps<TRoute>) => {\n let activeChildNode: React.ReactNode = null;\n let lastInactiveChildNode: React.ReactNode = null;\n\n const childNodes: React.ReactNode[] = Array.isArray(children)\n ? children\n : [children];\n\n for (const childNode of childNodes) {\n if (\n isValidElement(childNode) &&\n // @ts-expect-error redundand checks better to wrap in this directive\n isRouteEntity(childNode.props?.route) &&\n // @ts-expect-error redundand checks better to wrap in this directive\n childNode.props.route.isOpened\n ) {\n activeChildNode = childNode;\n break;\n } else {\n lastInactiveChildNode = childNode;\n }\n }\n\n const hasActiveChildNode = !!activeChildNode;\n\n useEffect(() => {\n if (!hasActiveChildNode && otherwiseNavigation) {\n if (typeof otherwiseNavigation === 'string') {\n const history = routeConfig.get().history;\n const url = `${otherwiseNavigation}${buildSearchString(navigateParams.query || {})}`;\n\n if (navigateParams.replace) {\n history.replace(url, navigateParams.state);\n } else {\n history.push(url, navigateParams.state);\n }\n } else if (!otherwiseNavigation.isOpened) {\n otherwiseNavigation.open(params, navigateParams);\n }\n }\n }, [hasActiveChildNode, otherwiseNavigation]);\n\n if (otherwiseNavigation && !activeChildNode) {\n return null;\n }\n\n const resultNodeToRender = activeChildNode ?? lastInactiveChildNode ?? null;\n\n if (Layout) {\n return <Layout>{resultNodeToRender}</Layout>;\n }\n\n return resultNodeToRender;\n },\n) as unknown as RouteViewGroupComponent;\n"],"names":["navigateParams","href","query"],"mappings":"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"}
package/view-model.cjs ADDED
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const mobx = require("mobx");
4
+ const mobxRoute = require("mobx-route");
5
+ const mobxViewModel = require("mobx-view-model");
6
+ class RouteViewModel extends mobxViewModel.ViewModelBase {
7
+ constructor(params) {
8
+ super(params);
9
+ mobxViewModel.applyObservable(
10
+ this,
11
+ [
12
+ ["pathParams", mobx.computed.struct],
13
+ ["query", mobx.computed]
14
+ ],
15
+ this.vmConfig.observable.viewModels
16
+ );
17
+ mobx.when(
18
+ () => this.isMounted,
19
+ () => {
20
+ mobx.reaction(
21
+ () => this.route.isOpened,
22
+ (isOpened) => {
23
+ if (!isOpened && this.isMounted) {
24
+ this.unmount();
25
+ }
26
+ },
27
+ { fireImmediately: true, signal: this.unmountSignal }
28
+ );
29
+ },
30
+ { signal: this.unmountSignal }
31
+ );
32
+ }
33
+ get payload() {
34
+ if (this.route instanceof mobxRoute.Route) {
35
+ return this.route.params || {};
36
+ }
37
+ if (this.route instanceof mobxRoute.VirtualRoute) {
38
+ return this.route.params;
39
+ }
40
+ return {};
41
+ }
42
+ get query() {
43
+ if ("query" in this.route) {
44
+ return this.route.query;
45
+ }
46
+ return mobxRoute.routeConfig.get().queryParams;
47
+ }
48
+ get pathParams() {
49
+ return this.payload;
50
+ }
51
+ get isMounted() {
52
+ return super.isMounted && this.route.isOpened;
53
+ }
54
+ }
55
+ exports.RouteViewModel = RouteViewModel;
56
+ //# sourceMappingURL=view-model.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"view-model.cjs","sources":["../src/view-model/route-view-model.ts"],"sourcesContent":["import { computed, reaction, when } from 'mobx';\nimport {\n type AnyAbstractRouteEntity,\n type IQueryParams,\n Route,\n type RouteParams,\n routeConfig,\n VirtualRoute,\n} from 'mobx-route';\nimport {\n applyObservable,\n ViewModelBase,\n type ViewModelParams,\n} from 'mobx-view-model';\nimport type { EmptyObject } from 'yummies/types';\n\nexport abstract class RouteViewModel<\n TRoute extends AnyAbstractRouteEntity = AnyAbstractRouteEntity,\n> extends ViewModelBase<EmptyObject> {\n abstract readonly route: TRoute;\n\n constructor(params: ViewModelParams<EmptyObject, any>) {\n super(params);\n\n applyObservable(\n this,\n [\n ['pathParams', computed.struct],\n ['query', computed],\n ],\n this.vmConfig.observable.viewModels,\n );\n\n when(\n () => this.isMounted,\n () => {\n reaction(\n () => this.route.isOpened,\n (isOpened) => {\n if (!isOpened && this.isMounted) {\n this.unmount();\n }\n },\n { fireImmediately: true, signal: this.unmountSignal },\n );\n },\n { signal: this.unmountSignal },\n );\n }\n\n override get payload(): RouteParams<TRoute> {\n if (this.route instanceof Route) {\n return this.route.params || ({} as any);\n }\n\n if (this.route instanceof VirtualRoute) {\n return this.route.params as any;\n }\n\n return {} as EmptyObject as any;\n }\n\n get query(): IQueryParams {\n if ('query' in this.route) {\n return this.route.query as IQueryParams;\n }\n\n return routeConfig.get().queryParams;\n }\n\n get pathParams() {\n return this.payload;\n }\n\n get isMounted() {\n return super.isMounted && this.route.isOpened;\n }\n}\n"],"names":["ViewModelBase","applyObservable","computed","when","reaction","Route","VirtualRoute","routeConfig"],"mappings":";;;;;AAgBO,MAAe,uBAEZA,cAAAA,cAA2B;AAAA,EAGnC,YAAY,QAA2C;AACrD,UAAM,MAAM;AAEZC,kBAAAA;AAAAA,MACE;AAAA,MACA;AAAA,QACE,CAAC,cAAcC,KAAAA,SAAS,MAAM;AAAA,QAC9B,CAAC,SAASA,KAAAA,QAAQ;AAAA,MAAA;AAAA,MAEpB,KAAK,SAAS,WAAW;AAAA,IAAA;AAG3BC,SAAAA;AAAAA,MACE,MAAM,KAAK;AAAA,MACX,MAAM;AACJC,aAAAA;AAAAA,UACE,MAAM,KAAK,MAAM;AAAA,UACjB,CAAC,aAAa;AACZ,gBAAI,CAAC,YAAY,KAAK,WAAW;AAC/B,mBAAK,QAAA;AAAA,YACP;AAAA,UACF;AAAA,UACA,EAAE,iBAAiB,MAAM,QAAQ,KAAK,cAAA;AAAA,QAAc;AAAA,MAExD;AAAA,MACA,EAAE,QAAQ,KAAK,cAAA;AAAA,IAAc;AAAA,EAEjC;AAAA,EAEA,IAAa,UAA+B;AAC1C,QAAI,KAAK,iBAAiBC,iBAAO;AAC/B,aAAO,KAAK,MAAM,UAAW,CAAA;AAAA,IAC/B;AAEA,QAAI,KAAK,iBAAiBC,wBAAc;AACtC,aAAO,KAAK,MAAM;AAAA,IACpB;AAEA,WAAO,CAAA;AAAA,EACT;AAAA,EAEA,IAAI,QAAsB;AACxB,QAAI,WAAW,KAAK,OAAO;AACzB,aAAO,KAAK,MAAM;AAAA,IACpB;AAEA,WAAOC,UAAAA,YAAY,MAAM;AAAA,EAC3B;AAAA,EAEA,IAAI,aAAa;AACf,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,YAAY;AACd,WAAO,MAAM,aAAa,KAAK,MAAM;AAAA,EACvC;AACF;;"}