path-rush 1.5.0 → 1.6.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.
- package/dist/react.d.cts +67 -2
- package/dist/react.d.ts +67 -2
- package/dist/react.js +124 -36
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +121 -34
- package/dist/react.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react.d.cts
CHANGED
|
@@ -51,6 +51,45 @@ declare const NavLink: React.ForwardRefExoticComponent<NavLinkProps & React.RefA
|
|
|
51
51
|
*/
|
|
52
52
|
declare const Navigate: typeof Navigate$1;
|
|
53
53
|
|
|
54
|
+
interface RouteTransitionProps {
|
|
55
|
+
children: React__default.ReactNode;
|
|
56
|
+
/**
|
|
57
|
+
* CSS класс для анимации входа
|
|
58
|
+
* @default 'route-enter'
|
|
59
|
+
*/
|
|
60
|
+
enterClass?: string;
|
|
61
|
+
/**
|
|
62
|
+
* CSS класс для активного состояния (после входа)
|
|
63
|
+
* @default 'route-enter-active'
|
|
64
|
+
*/
|
|
65
|
+
enterActiveClass?: string;
|
|
66
|
+
/**
|
|
67
|
+
* CSS класс для анимации выхода
|
|
68
|
+
* @default 'route-exit'
|
|
69
|
+
*/
|
|
70
|
+
exitClass?: string;
|
|
71
|
+
/**
|
|
72
|
+
* CSS класс для активного состояния выхода
|
|
73
|
+
* @default 'route-exit-active'
|
|
74
|
+
*/
|
|
75
|
+
exitActiveClass?: string;
|
|
76
|
+
/**
|
|
77
|
+
* Длительность анимации в миллисекундах
|
|
78
|
+
* @default 300
|
|
79
|
+
*/
|
|
80
|
+
duration?: number;
|
|
81
|
+
/**
|
|
82
|
+
* Кастомная функция для анимации
|
|
83
|
+
*/
|
|
84
|
+
onTransition?: (direction: 'enter' | 'exit') => void;
|
|
85
|
+
/**
|
|
86
|
+
* Режим анимации: 'fade', 'slide', 'custom'
|
|
87
|
+
* @default 'fade'
|
|
88
|
+
*/
|
|
89
|
+
mode?: 'fade' | 'slide' | 'custom';
|
|
90
|
+
}
|
|
91
|
+
declare function RouteTransition({ children, enterClass, enterActiveClass, exitClass, exitActiveClass, duration, onTransition, mode, }: RouteTransitionProps): react_jsx_runtime.JSX.Element;
|
|
92
|
+
|
|
54
93
|
type RouterProviderProps = {
|
|
55
94
|
/**
|
|
56
95
|
* ⏳ Кастомный индикатор загрузки
|
|
@@ -77,10 +116,36 @@ type RouterProviderProps = {
|
|
|
77
116
|
* @default '/'
|
|
78
117
|
*/
|
|
79
118
|
basePath?: string;
|
|
119
|
+
/**
|
|
120
|
+
* 🎬 Включить анимации переходов между страницами
|
|
121
|
+
*
|
|
122
|
+
* ▸ Если true, страницы будут анимироваться при переключении
|
|
123
|
+
*
|
|
124
|
+
* ▸ Можно настроить через transitionConfig
|
|
125
|
+
*
|
|
126
|
+
* @default false
|
|
127
|
+
*/
|
|
128
|
+
enableTransitions?: boolean;
|
|
129
|
+
/**
|
|
130
|
+
* ⚙️ Конфигурация анимаций переходов
|
|
131
|
+
*
|
|
132
|
+
* ▸ Настройка CSS классов и параметров анимации
|
|
133
|
+
*
|
|
134
|
+
* ▸ Если не указано, используются значения по умолчанию
|
|
135
|
+
*/
|
|
136
|
+
transitionConfig?: {
|
|
137
|
+
enterClass?: string;
|
|
138
|
+
enterActiveClass?: string;
|
|
139
|
+
exitClass?: string;
|
|
140
|
+
exitActiveClass?: string;
|
|
141
|
+
duration?: number;
|
|
142
|
+
mode?: 'fade' | 'slide' | 'custom';
|
|
143
|
+
onTransition?: (direction: 'enter' | 'exit') => void;
|
|
144
|
+
};
|
|
80
145
|
children?: React__default.ReactNode;
|
|
81
146
|
};
|
|
82
147
|
|
|
83
|
-
declare function RouterProvider({ children, preloader, basePath, }: Readonly<RouterProviderProps>): react_jsx_runtime.JSX.Element;
|
|
148
|
+
declare function RouterProvider({ children, preloader, basePath, enableTransitions, transitionConfig, }: Readonly<RouterProviderProps>): react_jsx_runtime.JSX.Element;
|
|
84
149
|
|
|
85
150
|
/**
|
|
86
151
|
* Тип локации с информацией о текущем маршруте
|
|
@@ -143,4 +208,4 @@ declare function useParams<T extends Params = Params>(): T;
|
|
|
143
208
|
*/
|
|
144
209
|
declare function useSearchParams(): [URLSearchParams, react_router_dom.SetURLSearchParams];
|
|
145
210
|
|
|
146
|
-
export { Link, type Location, NavLink, Navigate, type Params, RouterProvider, type RouterProviderProps, useLink, useLocation, useNavigate, useParams, useSearchParams };
|
|
211
|
+
export { Link, type Location, NavLink, Navigate, type Params, RouteTransition, type RouteTransitionProps, RouterProvider, type RouterProviderProps, useLink, useLocation, useNavigate, useParams, useSearchParams };
|
package/dist/react.d.ts
CHANGED
|
@@ -51,6 +51,45 @@ declare const NavLink: React.ForwardRefExoticComponent<NavLinkProps & React.RefA
|
|
|
51
51
|
*/
|
|
52
52
|
declare const Navigate: typeof Navigate$1;
|
|
53
53
|
|
|
54
|
+
interface RouteTransitionProps {
|
|
55
|
+
children: React__default.ReactNode;
|
|
56
|
+
/**
|
|
57
|
+
* CSS класс для анимации входа
|
|
58
|
+
* @default 'route-enter'
|
|
59
|
+
*/
|
|
60
|
+
enterClass?: string;
|
|
61
|
+
/**
|
|
62
|
+
* CSS класс для активного состояния (после входа)
|
|
63
|
+
* @default 'route-enter-active'
|
|
64
|
+
*/
|
|
65
|
+
enterActiveClass?: string;
|
|
66
|
+
/**
|
|
67
|
+
* CSS класс для анимации выхода
|
|
68
|
+
* @default 'route-exit'
|
|
69
|
+
*/
|
|
70
|
+
exitClass?: string;
|
|
71
|
+
/**
|
|
72
|
+
* CSS класс для активного состояния выхода
|
|
73
|
+
* @default 'route-exit-active'
|
|
74
|
+
*/
|
|
75
|
+
exitActiveClass?: string;
|
|
76
|
+
/**
|
|
77
|
+
* Длительность анимации в миллисекундах
|
|
78
|
+
* @default 300
|
|
79
|
+
*/
|
|
80
|
+
duration?: number;
|
|
81
|
+
/**
|
|
82
|
+
* Кастомная функция для анимации
|
|
83
|
+
*/
|
|
84
|
+
onTransition?: (direction: 'enter' | 'exit') => void;
|
|
85
|
+
/**
|
|
86
|
+
* Режим анимации: 'fade', 'slide', 'custom'
|
|
87
|
+
* @default 'fade'
|
|
88
|
+
*/
|
|
89
|
+
mode?: 'fade' | 'slide' | 'custom';
|
|
90
|
+
}
|
|
91
|
+
declare function RouteTransition({ children, enterClass, enterActiveClass, exitClass, exitActiveClass, duration, onTransition, mode, }: RouteTransitionProps): react_jsx_runtime.JSX.Element;
|
|
92
|
+
|
|
54
93
|
type RouterProviderProps = {
|
|
55
94
|
/**
|
|
56
95
|
* ⏳ Кастомный индикатор загрузки
|
|
@@ -77,10 +116,36 @@ type RouterProviderProps = {
|
|
|
77
116
|
* @default '/'
|
|
78
117
|
*/
|
|
79
118
|
basePath?: string;
|
|
119
|
+
/**
|
|
120
|
+
* 🎬 Включить анимации переходов между страницами
|
|
121
|
+
*
|
|
122
|
+
* ▸ Если true, страницы будут анимироваться при переключении
|
|
123
|
+
*
|
|
124
|
+
* ▸ Можно настроить через transitionConfig
|
|
125
|
+
*
|
|
126
|
+
* @default false
|
|
127
|
+
*/
|
|
128
|
+
enableTransitions?: boolean;
|
|
129
|
+
/**
|
|
130
|
+
* ⚙️ Конфигурация анимаций переходов
|
|
131
|
+
*
|
|
132
|
+
* ▸ Настройка CSS классов и параметров анимации
|
|
133
|
+
*
|
|
134
|
+
* ▸ Если не указано, используются значения по умолчанию
|
|
135
|
+
*/
|
|
136
|
+
transitionConfig?: {
|
|
137
|
+
enterClass?: string;
|
|
138
|
+
enterActiveClass?: string;
|
|
139
|
+
exitClass?: string;
|
|
140
|
+
exitActiveClass?: string;
|
|
141
|
+
duration?: number;
|
|
142
|
+
mode?: 'fade' | 'slide' | 'custom';
|
|
143
|
+
onTransition?: (direction: 'enter' | 'exit') => void;
|
|
144
|
+
};
|
|
80
145
|
children?: React__default.ReactNode;
|
|
81
146
|
};
|
|
82
147
|
|
|
83
|
-
declare function RouterProvider({ children, preloader, basePath, }: Readonly<RouterProviderProps>): react_jsx_runtime.JSX.Element;
|
|
148
|
+
declare function RouterProvider({ children, preloader, basePath, enableTransitions, transitionConfig, }: Readonly<RouterProviderProps>): react_jsx_runtime.JSX.Element;
|
|
84
149
|
|
|
85
150
|
/**
|
|
86
151
|
* Тип локации с информацией о текущем маршруте
|
|
@@ -143,4 +208,4 @@ declare function useParams<T extends Params = Params>(): T;
|
|
|
143
208
|
*/
|
|
144
209
|
declare function useSearchParams(): [URLSearchParams, react_router_dom.SetURLSearchParams];
|
|
145
210
|
|
|
146
|
-
export { Link, type Location, NavLink, Navigate, type Params, RouterProvider, type RouterProviderProps, useLink, useLocation, useNavigate, useParams, useSearchParams };
|
|
211
|
+
export { Link, type Location, NavLink, Navigate, type Params, RouteTransition, type RouteTransitionProps, RouterProvider, type RouterProviderProps, useLink, useLocation, useNavigate, useParams, useSearchParams };
|
package/dist/react.js
CHANGED
|
@@ -33,6 +33,7 @@ __export(react_exports, {
|
|
|
33
33
|
Link: () => Link,
|
|
34
34
|
NavLink: () => NavLink,
|
|
35
35
|
Navigate: () => Navigate,
|
|
36
|
+
RouteTransition: () => RouteTransition,
|
|
36
37
|
RouterProvider: () => RouterProvider,
|
|
37
38
|
useLink: () => useLink,
|
|
38
39
|
useLocation: () => useLocation,
|
|
@@ -72,21 +73,97 @@ var NavLink = import_react_router_dom3.NavLink;
|
|
|
72
73
|
var import_react_router_dom4 = require("react-router-dom");
|
|
73
74
|
var Navigate = import_react_router_dom4.Navigate;
|
|
74
75
|
|
|
76
|
+
// src/components/route-transition.tsx
|
|
77
|
+
var import_react = require("react");
|
|
78
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
79
|
+
function RouteTransition({
|
|
80
|
+
children,
|
|
81
|
+
enterClass = "route-enter",
|
|
82
|
+
enterActiveClass = "route-enter-active",
|
|
83
|
+
exitClass = "route-exit",
|
|
84
|
+
exitActiveClass = "route-exit-active",
|
|
85
|
+
duration = 300,
|
|
86
|
+
onTransition,
|
|
87
|
+
mode = "fade"
|
|
88
|
+
}) {
|
|
89
|
+
const location = useLocation();
|
|
90
|
+
const [displayChildren, setDisplayChildren] = (0, import_react.useState)(children);
|
|
91
|
+
const [isExiting, setIsExiting] = (0, import_react.useState)(false);
|
|
92
|
+
const [isEntering, setIsEntering] = (0, import_react.useState)(false);
|
|
93
|
+
const prevLocationRef = (0, import_react.useRef)(location.pathname);
|
|
94
|
+
const timeoutRef = (0, import_react.useRef)(null);
|
|
95
|
+
(0, import_react.useEffect)(() => {
|
|
96
|
+
if (prevLocationRef.current !== location.pathname) {
|
|
97
|
+
if (timeoutRef.current) {
|
|
98
|
+
clearTimeout(timeoutRef.current);
|
|
99
|
+
}
|
|
100
|
+
setIsExiting(true);
|
|
101
|
+
setIsEntering(false);
|
|
102
|
+
onTransition?.("exit");
|
|
103
|
+
timeoutRef.current = setTimeout(() => {
|
|
104
|
+
setDisplayChildren(children);
|
|
105
|
+
setIsExiting(false);
|
|
106
|
+
setIsEntering(true);
|
|
107
|
+
onTransition?.("enter");
|
|
108
|
+
timeoutRef.current = setTimeout(() => {
|
|
109
|
+
setIsEntering(false);
|
|
110
|
+
timeoutRef.current = null;
|
|
111
|
+
}, duration);
|
|
112
|
+
}, duration);
|
|
113
|
+
prevLocationRef.current = location.pathname;
|
|
114
|
+
} else {
|
|
115
|
+
setDisplayChildren(children);
|
|
116
|
+
}
|
|
117
|
+
return () => {
|
|
118
|
+
if (timeoutRef.current) {
|
|
119
|
+
clearTimeout(timeoutRef.current);
|
|
120
|
+
timeoutRef.current = null;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
}, [location.pathname, children, duration, onTransition]);
|
|
124
|
+
const getClassName = () => {
|
|
125
|
+
if (isExiting) {
|
|
126
|
+
return `${exitClass} ${exitActiveClass}`;
|
|
127
|
+
}
|
|
128
|
+
if (isEntering) {
|
|
129
|
+
return `${enterClass} ${enterActiveClass}`;
|
|
130
|
+
}
|
|
131
|
+
return "";
|
|
132
|
+
};
|
|
133
|
+
const getDefaultStyles = () => {
|
|
134
|
+
if (mode === "fade") {
|
|
135
|
+
return {
|
|
136
|
+
transition: `opacity ${duration}ms ease-in-out`,
|
|
137
|
+
opacity: isExiting ? 0 : isEntering ? 0 : 1
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
if (mode === "slide") {
|
|
141
|
+
return {
|
|
142
|
+
transition: `transform ${duration}ms ease-in-out, opacity ${duration}ms ease-in-out`,
|
|
143
|
+
transform: isExiting ? "translateX(-100%)" : isEntering ? "translateX(100%)" : "translateX(0)",
|
|
144
|
+
opacity: isExiting ? 0 : isEntering ? 0 : 1
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return {};
|
|
148
|
+
};
|
|
149
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: getClassName(), style: getDefaultStyles(), children: displayChildren });
|
|
150
|
+
}
|
|
151
|
+
|
|
75
152
|
// src/components/router-provider.tsx
|
|
76
153
|
var import_virtual_routes = require("virtual:routes");
|
|
77
154
|
|
|
78
155
|
// src/components/router-layout.tsx
|
|
79
|
-
var
|
|
156
|
+
var import_react4 = __toESM(require("react"), 1);
|
|
80
157
|
var import_react_router_dom6 = require("react-router-dom");
|
|
81
158
|
|
|
82
159
|
// src/components/router-utils.tsx
|
|
83
|
-
var
|
|
160
|
+
var import_react3 = __toESM(require("react"), 1);
|
|
84
161
|
var import_react_router_dom5 = require("react-router-dom");
|
|
85
162
|
|
|
86
163
|
// src/components/error-boundary.tsx
|
|
87
|
-
var
|
|
88
|
-
var
|
|
89
|
-
var ErrorBoundary = class extends
|
|
164
|
+
var import_react2 = __toESM(require("react"), 1);
|
|
165
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
166
|
+
var ErrorBoundary = class extends import_react2.default.Component {
|
|
90
167
|
constructor(props) {
|
|
91
168
|
super(props);
|
|
92
169
|
this.state = { hasError: false, error: null };
|
|
@@ -104,12 +181,12 @@ var ErrorBoundary = class extends import_react.default.Component {
|
|
|
104
181
|
if (this.state.hasError && this.state.error) {
|
|
105
182
|
if (this.props.fallback) {
|
|
106
183
|
const Fallback = this.props.fallback;
|
|
107
|
-
return /* @__PURE__ */ (0,
|
|
184
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Fallback, { error: this.state.error, resetError: this.resetError });
|
|
108
185
|
}
|
|
109
|
-
return /* @__PURE__ */ (0,
|
|
110
|
-
/* @__PURE__ */ (0,
|
|
111
|
-
/* @__PURE__ */ (0,
|
|
112
|
-
/* @__PURE__ */ (0,
|
|
186
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { padding: "20px" }, children: [
|
|
187
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: "Something went wrong" }),
|
|
188
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("pre", { children: this.state.error.message }),
|
|
189
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: this.resetError, children: "Try again" })
|
|
113
190
|
] });
|
|
114
191
|
}
|
|
115
192
|
return this.props.children;
|
|
@@ -117,30 +194,30 @@ var ErrorBoundary = class extends import_react.default.Component {
|
|
|
117
194
|
};
|
|
118
195
|
|
|
119
196
|
// src/components/router-utils.tsx
|
|
120
|
-
var
|
|
197
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
121
198
|
function wrapLayouts(layouts, pageEl) {
|
|
122
199
|
if (!layouts || layouts.length === 0) return pageEl;
|
|
123
200
|
return layouts.reduceRight((child, loader) => {
|
|
124
|
-
const Layout =
|
|
201
|
+
const Layout = import_react3.default.lazy(async () => {
|
|
125
202
|
const module2 = await loader();
|
|
126
203
|
return "default" in module2 ? module2 : { default: module2.Layout };
|
|
127
204
|
});
|
|
128
|
-
return /* @__PURE__ */ (0,
|
|
205
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Layout, { children: child });
|
|
129
206
|
}, pageEl);
|
|
130
207
|
}
|
|
131
208
|
function createLoadingFallback(loadingLoader) {
|
|
132
209
|
if (!loadingLoader) return void 0;
|
|
133
|
-
const Loading =
|
|
134
|
-
return /* @__PURE__ */ (0,
|
|
210
|
+
const Loading = import_react3.default.lazy(loadingLoader);
|
|
211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Loading, {});
|
|
135
212
|
}
|
|
136
213
|
function createErrorFallback(errorLoader) {
|
|
137
214
|
if (!errorLoader) return void 0;
|
|
138
|
-
const ErrorComponent =
|
|
139
|
-
return (props) => /* @__PURE__ */ (0,
|
|
215
|
+
const ErrorComponent = import_react3.default.lazy(errorLoader);
|
|
216
|
+
return (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ErrorComponent, { ...props });
|
|
140
217
|
}
|
|
141
218
|
var renderManifestAsRoutes = (manifest2, globalNotFound2) => {
|
|
142
219
|
return manifest2.map((n) => {
|
|
143
|
-
const Page =
|
|
220
|
+
const Page = import_react3.default.lazy(async () => {
|
|
144
221
|
const module2 = await n.loader();
|
|
145
222
|
if (module2 && typeof module2 === "object" && "default" in module2 && module2.default) {
|
|
146
223
|
return module2;
|
|
@@ -165,29 +242,29 @@ var renderManifestAsRoutes = (manifest2, globalNotFound2) => {
|
|
|
165
242
|
});
|
|
166
243
|
const loadingFallback = createLoadingFallback(n.loading);
|
|
167
244
|
const errorFallback = createErrorFallback(n.error);
|
|
168
|
-
const pageElement = wrapLayouts(n.layouts, /* @__PURE__ */ (0,
|
|
169
|
-
const wrappedElement = errorFallback ? /* @__PURE__ */ (0,
|
|
170
|
-
const element = loadingFallback ? /* @__PURE__ */ (0,
|
|
171
|
-
return /* @__PURE__ */ (0,
|
|
245
|
+
const pageElement = wrapLayouts(n.layouts, /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Page, {}));
|
|
246
|
+
const wrappedElement = errorFallback ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ErrorBoundary, { fallback: errorFallback, children: pageElement }) : pageElement;
|
|
247
|
+
const element = loadingFallback ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react3.default.Suspense, { fallback: loadingFallback, children: wrappedElement }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react3.default.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: "Loading..." }), children: wrappedElement });
|
|
248
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_router_dom5.Route, { path: n.path, element }, n.id);
|
|
172
249
|
}).concat(
|
|
173
250
|
// Добавляем 404 маршрут в конец
|
|
174
|
-
globalNotFound2 ? /* @__PURE__ */ (0,
|
|
251
|
+
globalNotFound2 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
175
252
|
import_react_router_dom5.Route,
|
|
176
253
|
{
|
|
177
254
|
path: "*",
|
|
178
|
-
element: /* @__PURE__ */ (0,
|
|
179
|
-
const NotFound =
|
|
180
|
-
return /* @__PURE__ */ (0,
|
|
255
|
+
element: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react3.default.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: "Loading..." }), children: (() => {
|
|
256
|
+
const NotFound = import_react3.default.lazy(globalNotFound2);
|
|
257
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(NotFound, {});
|
|
181
258
|
})() })
|
|
182
259
|
},
|
|
183
260
|
"__not_found__"
|
|
184
|
-
) : /* @__PURE__ */ (0,
|
|
261
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
185
262
|
import_react_router_dom5.Route,
|
|
186
263
|
{
|
|
187
264
|
path: "*",
|
|
188
|
-
element: /* @__PURE__ */ (0,
|
|
189
|
-
/* @__PURE__ */ (0,
|
|
190
|
-
/* @__PURE__ */ (0,
|
|
265
|
+
element: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { padding: "20px", textAlign: "center" }, children: [
|
|
266
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h1", { children: "404" }),
|
|
267
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: "Page not found" })
|
|
191
268
|
] })
|
|
192
269
|
},
|
|
193
270
|
"__not_found__"
|
|
@@ -196,30 +273,40 @@ var renderManifestAsRoutes = (manifest2, globalNotFound2) => {
|
|
|
196
273
|
};
|
|
197
274
|
|
|
198
275
|
// src/components/router-layout.tsx
|
|
199
|
-
var
|
|
276
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
200
277
|
var RouterLayout = ({
|
|
201
278
|
manifest: manifest2,
|
|
202
279
|
children,
|
|
203
280
|
preloader,
|
|
204
281
|
basePath = "/",
|
|
205
|
-
globalNotFound: globalNotFound2
|
|
206
|
-
|
|
282
|
+
globalNotFound: globalNotFound2,
|
|
283
|
+
enableTransitions = false,
|
|
284
|
+
transitionConfig
|
|
285
|
+
}) => {
|
|
286
|
+
const routes = renderManifestAsRoutes(manifest2, globalNotFound2);
|
|
287
|
+
const routesElement = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_router_dom6.Routes, { children: routes });
|
|
288
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_router_dom6.BrowserRouter, { basename: basePath, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react4.default.Suspense, { fallback: children || preloader || /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { children: "Loading..." }), children: enableTransitions ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RouteTransition, { ...transitionConfig, children: routesElement }) : routesElement }) });
|
|
289
|
+
};
|
|
207
290
|
|
|
208
291
|
// src/components/router-provider.tsx
|
|
209
|
-
var
|
|
292
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
210
293
|
function RouterProvider({
|
|
211
294
|
children,
|
|
212
295
|
preloader,
|
|
213
|
-
basePath
|
|
296
|
+
basePath,
|
|
297
|
+
enableTransitions,
|
|
298
|
+
transitionConfig
|
|
214
299
|
}) {
|
|
215
300
|
const finalBasePath = basePath ?? import_virtual_routes.basePath ?? "/";
|
|
216
|
-
return /* @__PURE__ */ (0,
|
|
301
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
217
302
|
RouterLayout,
|
|
218
303
|
{
|
|
219
304
|
manifest: import_virtual_routes.manifest,
|
|
220
305
|
preloader,
|
|
221
306
|
basePath: finalBasePath,
|
|
222
307
|
globalNotFound: import_virtual_routes.globalNotFound,
|
|
308
|
+
enableTransitions,
|
|
309
|
+
transitionConfig,
|
|
223
310
|
children
|
|
224
311
|
}
|
|
225
312
|
);
|
|
@@ -247,6 +334,7 @@ function useSearchParams() {
|
|
|
247
334
|
Link,
|
|
248
335
|
NavLink,
|
|
249
336
|
Navigate,
|
|
337
|
+
RouteTransition,
|
|
250
338
|
RouterProvider,
|
|
251
339
|
useLink,
|
|
252
340
|
useLocation,
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react.ts","../src/components/link.tsx","../src/components/hooks/use-location.ts","../src/components/hooks/use-links.tsx","../src/components/nav-link.tsx","../src/components/navigate.tsx","../src/components/router-provider.tsx","../src/components/router-layout.tsx","../src/components/router-utils.tsx","../src/components/error-boundary.tsx","../src/components/hooks/use-navigate.ts","../src/components/hooks/use-params.ts","../src/components/hooks/use-search-params.ts"],"sourcesContent":["// Компоненты\r\nexport { Link } from './components/link'\r\nexport { NavLink } from './components/nav-link'\r\nexport { Navigate } from './components/navigate'\r\nexport { default as RouterProvider } from './components/router-provider'\r\n\r\n// Хуки\r\nexport { useLink } from './components/hooks/use-links'\r\nexport { useLocation } from './components/hooks/use-location'\r\nexport { useNavigate } from './components/hooks/use-navigate'\r\nexport { useParams } from './components/hooks/use-params'\r\nexport { useSearchParams } from './components/hooks/use-search-params'\r\n\r\n// Типы\r\nexport type {\r\n\tLinkProps,\r\n\tLocation,\r\n\tNavigateOptions,\r\n\tNavigateProps,\r\n\tNavLinkProps,\r\n\tParams,\r\n\tTo,\r\n} from './components/types/router-types'\r\n\r\nexport type { RouterProviderProps } from './components/types/types'\r\n","import type { LinkProps as ReactRouterLinkProps } from 'react-router-dom'\r\nimport { Link as ReactRouterLink } from 'react-router-dom'\r\n\r\nexport type LinkProps = ReactRouterLinkProps\r\n\r\n/**\r\n * Компонент для навигационных ссылок\r\n * \r\n * Используется для клиентской навигации без перезагрузки страницы\r\n * \r\n * @example\r\n * ```tsx\r\n * <Link to=\"/about\">About</Link>\r\n * <Link to=\"/users/123\" state={{ from: 'home' }}>User Profile</Link>\r\n * ```\r\n */\r\nexport const Link = ReactRouterLink\r\n\r\nexport { useLink } from './hooks/use-links'\r\n","import { useLocation as useRouterLocation } from 'react-router-dom'\r\nimport type { Location as RouterLocation } from 'react-router-dom'\r\n\r\n/**\r\n * Тип локации с информацией о текущем маршруте\r\n */\r\nexport type Location = RouterLocation\r\n\r\n/**\r\n * Хук для получения текущей локации\r\n * \r\n * @returns Объект с информацией о текущем маршруте\r\n * \r\n * @example\r\n * ```tsx\r\n * const location = useLocation()\r\n * console.log(location.pathname) // '/about'\r\n * console.log(location.search) // '?id=123'\r\n * ```\r\n */\r\nexport function useLocation(): Location {\r\n\treturn useRouterLocation()\r\n}\r\n","import { useLocation } from './use-location'\r\n\r\nexport function useLink(props: { href: string }) {\r\n const location = useLocation()\r\n const currentPath = location.pathname\r\n \r\n return {\r\n href: props.href,\r\n isActive: currentPath === props.href,\r\n }\r\n}","import type { NavLinkProps as ReactRouterNavLinkProps } from 'react-router-dom'\r\nimport { NavLink as ReactRouterNavLink } from 'react-router-dom'\r\n\r\nexport type NavLinkProps = ReactRouterNavLinkProps\r\n\r\n/**\r\n * Компонент для навигационных ссылок с поддержкой активного состояния\r\n * \r\n * Автоматически добавляет класс 'active' когда маршрут активен\r\n * \r\n * @example\r\n * ```tsx\r\n * <NavLink to=\"/about\">About</NavLink>\r\n * <NavLink to=\"/users\" className={({ isActive }) => isActive ? 'active' : ''}>\r\n * Users\r\n * </NavLink>\r\n * ```\r\n */\r\nexport const NavLink = ReactRouterNavLink\r\n","import type { NavigateProps as ReactRouterNavigateProps } from 'react-router-dom'\r\nimport { Navigate as ReactRouterNavigate } from 'react-router-dom'\r\n\r\nexport type NavigateProps = ReactRouterNavigateProps\r\n\r\n/**\r\n * Компонент для программного редиректа\r\n * \r\n * @example\r\n * ```tsx\r\n * <Navigate to=\"/login\" replace />\r\n * <Navigate to=\"/dashboard\" state={{ from: location }} />\r\n * ```\r\n */\r\nexport const Navigate = ReactRouterNavigate\r\n","import {\r\n\tbasePath as configBasePath,\r\n\tglobalNotFound,\r\n\tmanifest,\r\n} from 'virtual:routes'\r\nimport { RouterLayout } from './router-layout'\r\nimport type { RouterProviderProps } from './types/types'\r\n\r\nexport default function RouterProvider({\r\n\tchildren,\r\n\tpreloader,\r\n\tbasePath,\r\n}: Readonly<RouterProviderProps>) {\r\n\t// Используем basePath из пропсов, если указан, иначе из конфигурации\r\n\tconst finalBasePath = basePath ?? configBasePath ?? '/'\r\n\t\r\n\treturn (\r\n\t\t<RouterLayout\r\n\t\t\tmanifest={manifest}\r\n\t\t\tpreloader={preloader}\r\n\t\t\tbasePath={finalBasePath}\r\n\t\t\tglobalNotFound={globalNotFound}\r\n\t\t>\r\n\t\t\t{children}\r\n\t\t</RouterLayout>\r\n\t)\r\n}\r\n","import React from 'react'\r\nimport { BrowserRouter, Routes } from 'react-router-dom'\r\nimport { renderManifestAsRoutes } from './router-utils'\r\nimport type { RouterLayoutProps } from './types/types'\r\n\r\nexport const RouterLayout = ({\r\n\tmanifest,\r\n\tchildren,\r\n\tpreloader,\r\n\tbasePath = '/',\r\n\tglobalNotFound,\r\n}: RouterLayoutProps) => (\r\n\t<BrowserRouter basename={basePath}>\r\n\t\t<React.Suspense fallback={children || preloader || <div>Loading...</div>}>\r\n\t\t\t<Routes>{renderManifestAsRoutes(manifest, globalNotFound)}</Routes>\r\n\t\t</React.Suspense>\r\n\t</BrowserRouter>\r\n)\r\n","import React from 'react'\r\nimport { Route } from 'react-router-dom'\r\nimport { ErrorBoundary } from './error-boundary'\r\nimport type { Node } from './types/types'\r\n\r\nfunction wrapLayouts(\r\n\tlayouts: Node['layouts'] | undefined,\r\n\tpageEl: React.ReactNode\r\n) {\r\n\tif (!layouts || layouts.length === 0) return pageEl\r\n\r\n\treturn layouts.reduceRight((child, loader) => {\r\n\t\tconst Layout = React.lazy(async () => {\r\n\t\t\tconst module = await loader()\r\n\t\t\t// Поддерживаем как default, так и именованный экспорт Layout\r\n\t\t\treturn 'default' in module ? module : { default: module.Layout }\r\n\t\t})\r\n\t\treturn <Layout>{child}</Layout>\r\n\t}, pageEl as React.ReactElement)\r\n}\r\n\r\nfunction createLoadingFallback(loadingLoader?: () => Promise<{ default: React.ComponentType }>) {\r\n\tif (!loadingLoader) return undefined\r\n\t\r\n\t// Loading компонент lazy, но он используется как fallback в Suspense\r\n\tconst Loading = React.lazy(loadingLoader)\r\n\treturn <Loading />\r\n}\r\n\r\nfunction createErrorFallback(errorLoader?: () => Promise<{ default: React.ComponentType<{ error?: Error; resetError?: () => void }> }>) {\r\n\tif (!errorLoader) return undefined\r\n\t\r\n\tconst ErrorComponent = React.lazy(errorLoader)\r\n\treturn (props: { error?: Error; resetError?: () => void }) => <ErrorComponent {...props} />\r\n}\r\n\r\nexport const renderManifestAsRoutes = (\r\n\tmanifest: Node[],\r\n\tglobalNotFound?: () => Promise<{ default: React.ComponentType }>\r\n) => {\r\n\treturn manifest.map(n => {\r\n\t\tconst Page = React.lazy(async () => {\r\n\t\t\tconst module = await n.loader()\r\n\r\n\t\t\t// Если есть default экспорт, используем его\r\n\t\t\tif (\r\n\t\t\t\tmodule &&\r\n\t\t\t\ttypeof module === 'object' &&\r\n\t\t\t\t'default' in module &&\r\n\t\t\t\tmodule.default\r\n\t\t\t) {\r\n\t\t\t\treturn module as { default: React.ComponentType }\r\n\t\t\t}\r\n\r\n\t\t\t// Ищем любой именованный экспорт, который является функцией или компонентом\r\n\t\t\tif (module && typeof module === 'object') {\r\n\t\t\t\tconst namedExports = Object.keys(module).filter(\r\n\t\t\t\t\tkey => key !== 'default'\r\n\t\t\t\t)\r\n\t\t\t\tfor (const key of namedExports) {\r\n\t\t\t\t\tconst exportValue = module[key]\r\n\t\t\t\t\tif (\r\n\t\t\t\t\t\ttypeof exportValue === 'function' ||\r\n\t\t\t\t\t\t(typeof exportValue === 'object' && exportValue !== null)\r\n\t\t\t\t\t) {\r\n\t\t\t\t\t\treturn {\r\n\t\t\t\t\t\t\tdefault: exportValue as React.ComponentType,\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Если ничего не найдено, возвращаем ошибку\r\n\t\t\tconst availableExports =\r\n\t\t\t\tmodule && typeof module === 'object'\r\n\t\t\t\t\t? Object.keys(module).join(', ')\r\n\t\t\t\t\t: 'unknown'\r\n\t\t\tthrow new Error(\r\n\t\t\t\t`No valid export found in module for route ${n.path}. Available exports: ${availableExports}`\r\n\t\t\t)\r\n\t\t})\r\n\r\n\t\tconst loadingFallback = createLoadingFallback(n.loading)\r\n\t\tconst errorFallback = createErrorFallback(n.error)\r\n\t\t\r\n\t\tconst pageElement = wrapLayouts(n.layouts, <Page />)\r\n\t\t\r\n\t\t// Оборачиваем в ErrorBoundary если есть error компонент\r\n\t\tconst wrappedElement = errorFallback ? (\r\n\t\t\t<ErrorBoundary fallback={errorFallback}>\r\n\t\t\t\t{pageElement}\r\n\t\t\t</ErrorBoundary>\r\n\t\t) : pageElement\r\n\r\n\t\t// Оборачиваем в Suspense с loading fallback\r\n\t\tconst element = loadingFallback ? (\r\n\t\t\t<React.Suspense fallback={loadingFallback}>\r\n\t\t\t\t{wrappedElement}\r\n\t\t\t</React.Suspense>\r\n\t\t) : (\r\n\t\t\t<React.Suspense fallback={<div>Loading...</div>}>\r\n\t\t\t\t{wrappedElement}\r\n\t\t\t</React.Suspense>\r\n\t\t)\r\n\r\n\t\treturn <Route key={n.id} path={n.path} element={element} />\r\n\t}).concat(\r\n\t\t// Добавляем 404 маршрут в конец\r\n\t\tglobalNotFound ? (\r\n\t\t\t<Route\r\n\t\t\t\tkey=\"__not_found__\"\r\n\t\t\t\tpath=\"*\"\r\n\t\t\t\telement={\r\n\t\t\t\t\t<React.Suspense fallback={<div>Loading...</div>}>\r\n\t\t\t\t\t\t{(() => {\r\n\t\t\t\t\t\t\tconst NotFound = React.lazy(globalNotFound)\r\n\t\t\t\t\t\t\treturn <NotFound />\r\n\t\t\t\t\t\t})()}\r\n\t\t\t\t\t</React.Suspense>\r\n\t\t\t\t}\r\n\t\t\t/>\r\n\t\t) : (\r\n\t\t\t<Route\r\n\t\t\t\tkey=\"__not_found__\"\r\n\t\t\t\tpath=\"*\"\r\n\t\t\t\telement={\r\n\t\t\t\t\t<div style={{ padding: '20px', textAlign: 'center' }}>\r\n\t\t\t\t\t\t<h1>404</h1>\r\n\t\t\t\t\t\t<p>Page not found</p>\r\n\t\t\t\t\t</div>\r\n\t\t\t\t}\r\n\t\t\t/>\r\n\t\t)\r\n\t)\r\n}\r\n","import React from 'react'\r\n\r\nexport interface ErrorBoundaryProps {\r\n\tchildren: React.ReactNode\r\n\tfallback?: React.ComponentType<{ error?: Error; resetError?: () => void }>\r\n\tonError?: (error: Error, errorInfo: React.ErrorInfo) => void\r\n}\r\n\r\ninterface ErrorBoundaryState {\r\n\thasError: boolean\r\n\terror: Error | null\r\n}\r\n\r\n/**\r\n * ErrorBoundary компонент для обработки ошибок рендеринга\r\n */\r\nexport class ErrorBoundary extends React.Component<\r\n\tErrorBoundaryProps,\r\n\tErrorBoundaryState\r\n> {\r\n\tconstructor(props: ErrorBoundaryProps) {\r\n\t\tsuper(props)\r\n\t\tthis.state = { hasError: false, error: null }\r\n\t}\r\n\r\n\tstatic getDerivedStateFromError(error: Error): ErrorBoundaryState {\r\n\t\treturn { hasError: true, error }\r\n\t}\r\n\r\n\tcomponentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\r\n\t\tthis.props.onError?.(error, errorInfo)\r\n\t}\r\n\r\n\tresetError = () => {\r\n\t\tthis.setState({ hasError: false, error: null })\r\n\t}\r\n\r\n\trender() {\r\n\t\tif (this.state.hasError && this.state.error) {\r\n\t\t\tif (this.props.fallback) {\r\n\t\t\t\tconst Fallback = this.props.fallback\r\n\t\t\t\treturn <Fallback error={this.state.error} resetError={this.resetError} />\r\n\t\t\t}\r\n\t\t\treturn (\r\n\t\t\t\t<div style={{ padding: '20px' }}>\r\n\t\t\t\t\t<h2>Something went wrong</h2>\r\n\t\t\t\t\t<pre>{this.state.error.message}</pre>\r\n\t\t\t\t\t<button onClick={this.resetError}>Try again</button>\r\n\t\t\t\t</div>\r\n\t\t\t)\r\n\t\t}\r\n\r\n\t\treturn this.props.children\r\n\t}\r\n}\r\n","import { useNavigate as useRouterNavigate } from 'react-router-dom'\r\n\r\nexport type NavigateOptions = {\r\n\treplace?: boolean\r\n\tstate?: unknown\r\n\trelative?: 'route' | 'path'\r\n}\r\n\r\nexport type To = string | number | { pathname?: string; search?: string; hash?: string }\r\n\r\n/**\r\n * Хук для программной навигации\r\n * \r\n * @returns Функция для навигации\r\n * \r\n * @example\r\n * ```tsx\r\n * const navigate = useNavigate()\r\n * navigate('/about')\r\n * navigate('/users', { replace: true })\r\n * navigate(-1) // назад\r\n * ```\r\n */\r\nexport function useNavigate() {\r\n\treturn useRouterNavigate()\r\n}\r\n","import { useParams as useRouterParams } from 'react-router-dom'\r\n\r\nexport type Params = Record<string, string | undefined>\r\n\r\n/**\r\n * Хук для получения параметров маршрута\r\n * \r\n * @returns Объект с параметрами текущего маршрута\r\n * \r\n * @example\r\n * ```tsx\r\n * // Для маршрута /users/:id\r\n * const { id } = useParams()\r\n * ```\r\n */\r\nexport function useParams<T extends Params = Params>(): T {\r\n\treturn useRouterParams() as T\r\n}\r\n","import { useSearchParams as useRouterSearchParams } from 'react-router-dom'\r\n\r\n/**\r\n * Хук для работы с query параметрами URL\r\n * \r\n * @returns Кортеж из [searchParams, setSearchParams]\r\n * \r\n * @example\r\n * ```tsx\r\n * const [searchParams, setSearchParams] = useSearchParams()\r\n * const id = searchParams.get('id')\r\n * setSearchParams({ id: '123' })\r\n * ```\r\n */\r\nexport function useSearchParams() {\r\n\treturn useRouterSearchParams()\r\n}\r\n"],"mappings":"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","names":["import_react_router_dom","useRouterLocation","ReactRouterLink","import_react_router_dom","ReactRouterNavLink","import_react_router_dom","ReactRouterNavigate","import_react","import_react_router_dom","import_react","import_react_router_dom","React","import_jsx_runtime","React","module","manifest","globalNotFound","import_jsx_runtime","manifest","globalNotFound","React","import_jsx_runtime","configBasePath","import_react_router_dom","useRouterNavigate","import_react_router_dom","useRouterParams","import_react_router_dom","useRouterSearchParams"]}
|
|
1
|
+
{"version":3,"sources":["../src/react.ts","../src/components/link.tsx","../src/components/hooks/use-location.ts","../src/components/hooks/use-links.tsx","../src/components/nav-link.tsx","../src/components/navigate.tsx","../src/components/route-transition.tsx","../src/components/router-provider.tsx","../src/components/router-layout.tsx","../src/components/router-utils.tsx","../src/components/error-boundary.tsx","../src/components/hooks/use-navigate.ts","../src/components/hooks/use-params.ts","../src/components/hooks/use-search-params.ts"],"sourcesContent":["// Компоненты\r\nexport { Link } from './components/link'\r\nexport { NavLink } from './components/nav-link'\r\nexport { Navigate } from './components/navigate'\r\nexport { RouteTransition } from './components/route-transition'\r\nexport { default as RouterProvider } from './components/router-provider'\r\n\r\n// Хуки\r\nexport { useLink } from './components/hooks/use-links'\r\nexport { useLocation } from './components/hooks/use-location'\r\nexport { useNavigate } from './components/hooks/use-navigate'\r\nexport { useParams } from './components/hooks/use-params'\r\nexport { useSearchParams } from './components/hooks/use-search-params'\r\n\r\n// Типы\r\nexport type {\r\n\tLinkProps,\r\n\tLocation,\r\n\tNavigateOptions,\r\n\tNavigateProps,\r\n\tNavLinkProps,\r\n\tParams,\r\n\tTo,\r\n} from './components/types/router-types'\r\n\r\nexport type { RouteTransitionProps } from './components/route-transition'\r\nexport type { RouterProviderProps } from './components/types/types'\r\n","import type { LinkProps as ReactRouterLinkProps } from 'react-router-dom'\r\nimport { Link as ReactRouterLink } from 'react-router-dom'\r\n\r\nexport type LinkProps = ReactRouterLinkProps\r\n\r\n/**\r\n * Компонент для навигационных ссылок\r\n * \r\n * Используется для клиентской навигации без перезагрузки страницы\r\n * \r\n * @example\r\n * ```tsx\r\n * <Link to=\"/about\">About</Link>\r\n * <Link to=\"/users/123\" state={{ from: 'home' }}>User Profile</Link>\r\n * ```\r\n */\r\nexport const Link = ReactRouterLink\r\n\r\nexport { useLink } from './hooks/use-links'\r\n","import { useLocation as useRouterLocation } from 'react-router-dom'\r\nimport type { Location as RouterLocation } from 'react-router-dom'\r\n\r\n/**\r\n * Тип локации с информацией о текущем маршруте\r\n */\r\nexport type Location = RouterLocation\r\n\r\n/**\r\n * Хук для получения текущей локации\r\n * \r\n * @returns Объект с информацией о текущем маршруте\r\n * \r\n * @example\r\n * ```tsx\r\n * const location = useLocation()\r\n * console.log(location.pathname) // '/about'\r\n * console.log(location.search) // '?id=123'\r\n * ```\r\n */\r\nexport function useLocation(): Location {\r\n\treturn useRouterLocation()\r\n}\r\n","import { useLocation } from './use-location'\r\n\r\nexport function useLink(props: { href: string }) {\r\n const location = useLocation()\r\n const currentPath = location.pathname\r\n \r\n return {\r\n href: props.href,\r\n isActive: currentPath === props.href,\r\n }\r\n}","import type { NavLinkProps as ReactRouterNavLinkProps } from 'react-router-dom'\r\nimport { NavLink as ReactRouterNavLink } from 'react-router-dom'\r\n\r\nexport type NavLinkProps = ReactRouterNavLinkProps\r\n\r\n/**\r\n * Компонент для навигационных ссылок с поддержкой активного состояния\r\n * \r\n * Автоматически добавляет класс 'active' когда маршрут активен\r\n * \r\n * @example\r\n * ```tsx\r\n * <NavLink to=\"/about\">About</NavLink>\r\n * <NavLink to=\"/users\" className={({ isActive }) => isActive ? 'active' : ''}>\r\n * Users\r\n * </NavLink>\r\n * ```\r\n */\r\nexport const NavLink = ReactRouterNavLink\r\n","import type { NavigateProps as ReactRouterNavigateProps } from 'react-router-dom'\r\nimport { Navigate as ReactRouterNavigate } from 'react-router-dom'\r\n\r\nexport type NavigateProps = ReactRouterNavigateProps\r\n\r\n/**\r\n * Компонент для программного редиректа\r\n * \r\n * @example\r\n * ```tsx\r\n * <Navigate to=\"/login\" replace />\r\n * <Navigate to=\"/dashboard\" state={{ from: location }} />\r\n * ```\r\n */\r\nexport const Navigate = ReactRouterNavigate\r\n","import React, { useEffect, useState, useRef } from 'react'\r\nimport { useLocation } from './hooks/use-location'\r\n\r\nexport interface RouteTransitionProps {\r\n\tchildren: React.ReactNode\r\n\t/**\r\n\t * CSS класс для анимации входа\r\n\t * @default 'route-enter'\r\n\t */\r\n\tenterClass?: string\r\n\t/**\r\n\t * CSS класс для активного состояния (после входа)\r\n\t * @default 'route-enter-active'\r\n\t */\r\n\tenterActiveClass?: string\r\n\t/**\r\n\t * CSS класс для анимации выхода\r\n\t * @default 'route-exit'\r\n\t */\r\n\texitClass?: string\r\n\t/**\r\n\t * CSS класс для активного состояния выхода\r\n\t * @default 'route-exit-active'\r\n\t */\r\n\texitActiveClass?: string\r\n\t/**\r\n\t * Длительность анимации в миллисекундах\r\n\t * @default 300\r\n\t */\r\n\tduration?: number\r\n\t/**\r\n\t * Кастомная функция для анимации\r\n\t */\r\n\tonTransition?: (direction: 'enter' | 'exit') => void\r\n\t/**\r\n\t * Режим анимации: 'fade', 'slide', 'custom'\r\n\t * @default 'fade'\r\n\t */\r\n\tmode?: 'fade' | 'slide' | 'custom'\r\n}\r\n\r\nexport function RouteTransition({\r\n\tchildren,\r\n\tenterClass = 'route-enter',\r\n\tenterActiveClass = 'route-enter-active',\r\n\texitClass = 'route-exit',\r\n\texitActiveClass = 'route-exit-active',\r\n\tduration = 300,\r\n\tonTransition,\r\n\tmode = 'fade',\r\n}: RouteTransitionProps) {\r\n\tconst location = useLocation()\r\n\tconst [displayChildren, setDisplayChildren] = useState(children)\r\n\tconst [isExiting, setIsExiting] = useState(false)\r\n\tconst [isEntering, setIsEntering] = useState(false)\r\n\tconst prevLocationRef = useRef(location.pathname)\r\n\tconst timeoutRef = useRef<NodeJS.Timeout | null>(null)\r\n\r\n\tuseEffect(() => {\r\n\t\tif (prevLocationRef.current !== location.pathname) {\r\n\t\t\t// Очищаем предыдущий таймер если есть\r\n\t\t\tif (timeoutRef.current) {\r\n\t\t\t\tclearTimeout(timeoutRef.current)\r\n\t\t\t}\r\n\r\n\t\t\t// Начинаем анимацию выхода\r\n\t\t\tsetIsExiting(true)\r\n\t\t\tsetIsEntering(false)\r\n\t\t\tonTransition?.('exit')\r\n\r\n\t\t\ttimeoutRef.current = setTimeout(() => {\r\n\t\t\t\t// Меняем контент\r\n\t\t\t\tsetDisplayChildren(children)\r\n\t\t\t\tsetIsExiting(false)\r\n\t\t\t\tsetIsEntering(true)\r\n\t\t\t\tonTransition?.('enter')\r\n\r\n\t\t\t\t// Начинаем анимацию входа\r\n\t\t\t\ttimeoutRef.current = setTimeout(() => {\r\n\t\t\t\t\tsetIsEntering(false)\r\n\t\t\t\t\ttimeoutRef.current = null\r\n\t\t\t\t}, duration)\r\n\t\t\t}, duration)\r\n\r\n\t\t\tprevLocationRef.current = location.pathname\r\n\t\t} else {\r\n\t\t\t// Если location не изменился, просто обновляем children\r\n\t\t\tsetDisplayChildren(children)\r\n\t\t}\r\n\r\n\t\treturn () => {\r\n\t\t\tif (timeoutRef.current) {\r\n\t\t\t\tclearTimeout(timeoutRef.current)\r\n\t\t\t\ttimeoutRef.current = null\r\n\t\t\t}\r\n\t\t}\r\n\t}, [location.pathname, children, duration, onTransition])\r\n\r\n\t// Определяем классы в зависимости от состояния\r\n\tconst getClassName = () => {\r\n\t\tif (isExiting) {\r\n\t\t\treturn `${exitClass} ${exitActiveClass}`\r\n\t\t}\r\n\t\tif (isEntering) {\r\n\t\t\treturn `${enterClass} ${enterActiveClass}`\r\n\t\t}\r\n\t\treturn ''\r\n\t}\r\n\r\n\t// Стили для режима fade (по умолчанию)\r\n\tconst getDefaultStyles = () => {\r\n\t\tif (mode === 'fade') {\r\n\t\t\treturn {\r\n\t\t\t\ttransition: `opacity ${duration}ms ease-in-out`,\r\n\t\t\t\topacity: isExiting ? 0 : isEntering ? 0 : 1,\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (mode === 'slide') {\r\n\t\t\treturn {\r\n\t\t\t\ttransition: `transform ${duration}ms ease-in-out, opacity ${duration}ms ease-in-out`,\r\n\t\t\t\ttransform: isExiting\r\n\t\t\t\t\t? 'translateX(-100%)'\r\n\t\t\t\t\t: isEntering\r\n\t\t\t\t\t\t? 'translateX(100%)'\r\n\t\t\t\t\t\t: 'translateX(0)',\r\n\t\t\t\topacity: isExiting ? 0 : isEntering ? 0 : 1,\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn {}\r\n\t}\r\n\r\n\treturn (\r\n\t\t<div className={getClassName()} style={getDefaultStyles()}>\r\n\t\t\t{displayChildren}\r\n\t\t</div>\r\n\t)\r\n}\r\n","import {\r\n\tbasePath as configBasePath,\r\n\tglobalNotFound,\r\n\tmanifest,\r\n} from 'virtual:routes'\r\nimport { RouterLayout } from './router-layout'\r\nimport type { RouterProviderProps } from './types/types'\r\n\r\nexport default function RouterProvider({\r\n\tchildren,\r\n\tpreloader,\r\n\tbasePath,\r\n\tenableTransitions,\r\n\ttransitionConfig,\r\n}: Readonly<RouterProviderProps>) {\r\n\t// Используем basePath из пропсов, если указан, иначе из конфигурации\r\n\tconst finalBasePath = basePath ?? configBasePath ?? '/'\r\n\t\r\n\treturn (\r\n\t\t<RouterLayout\r\n\t\t\tmanifest={manifest}\r\n\t\t\tpreloader={preloader}\r\n\t\t\tbasePath={finalBasePath}\r\n\t\t\tglobalNotFound={globalNotFound}\r\n\t\t\tenableTransitions={enableTransitions}\r\n\t\t\ttransitionConfig={transitionConfig}\r\n\t\t>\r\n\t\t\t{children}\r\n\t\t</RouterLayout>\r\n\t)\r\n}\r\n","import React from 'react'\r\nimport { BrowserRouter, Routes } from 'react-router-dom'\r\nimport { RouteTransition } from './route-transition'\r\nimport { renderManifestAsRoutes } from './router-utils'\r\nimport type { RouterLayoutProps } from './types/types'\r\n\r\nexport const RouterLayout = ({\r\n\tmanifest,\r\n\tchildren,\r\n\tpreloader,\r\n\tbasePath = '/',\r\n\tglobalNotFound,\r\n\tenableTransitions = false,\r\n\ttransitionConfig,\r\n}: RouterLayoutProps) => {\r\n\tconst routes = renderManifestAsRoutes(manifest, globalNotFound)\r\n\tconst routesElement = <Routes>{routes}</Routes>\r\n\r\n\treturn (\r\n\t\t<BrowserRouter basename={basePath}>\r\n\t\t\t<React.Suspense fallback={children || preloader || <div>Loading...</div>}>\r\n\t\t\t\t{enableTransitions ? (\r\n\t\t\t\t\t<RouteTransition {...transitionConfig}>{routesElement}</RouteTransition>\r\n\t\t\t\t) : (\r\n\t\t\t\t\troutesElement\r\n\t\t\t\t)}\r\n\t\t\t</React.Suspense>\r\n\t\t</BrowserRouter>\r\n\t)\r\n}\r\n","import React from 'react'\r\nimport { Route } from 'react-router-dom'\r\nimport { ErrorBoundary } from './error-boundary'\r\nimport type { Node } from './types/types'\r\n\r\nfunction wrapLayouts(\r\n\tlayouts: Node['layouts'] | undefined,\r\n\tpageEl: React.ReactNode\r\n) {\r\n\tif (!layouts || layouts.length === 0) return pageEl\r\n\r\n\treturn layouts.reduceRight((child, loader) => {\r\n\t\tconst Layout = React.lazy(async () => {\r\n\t\t\tconst module = await loader()\r\n\t\t\t// Поддерживаем как default, так и именованный экспорт Layout\r\n\t\t\treturn 'default' in module ? module : { default: module.Layout }\r\n\t\t})\r\n\t\treturn <Layout>{child}</Layout>\r\n\t}, pageEl as React.ReactElement)\r\n}\r\n\r\nfunction createLoadingFallback(loadingLoader?: () => Promise<{ default: React.ComponentType }>) {\r\n\tif (!loadingLoader) return undefined\r\n\t\r\n\t// Loading компонент lazy, но он используется как fallback в Suspense\r\n\tconst Loading = React.lazy(loadingLoader)\r\n\treturn <Loading />\r\n}\r\n\r\nfunction createErrorFallback(errorLoader?: () => Promise<{ default: React.ComponentType<{ error?: Error; resetError?: () => void }> }>) {\r\n\tif (!errorLoader) return undefined\r\n\t\r\n\tconst ErrorComponent = React.lazy(errorLoader)\r\n\treturn (props: { error?: Error; resetError?: () => void }) => <ErrorComponent {...props} />\r\n}\r\n\r\nexport const renderManifestAsRoutes = (\r\n\tmanifest: Node[],\r\n\tglobalNotFound?: () => Promise<{ default: React.ComponentType }>\r\n) => {\r\n\treturn manifest.map(n => {\r\n\t\tconst Page = React.lazy(async () => {\r\n\t\t\tconst module = await n.loader()\r\n\r\n\t\t\t// Если есть default экспорт, используем его\r\n\t\t\tif (\r\n\t\t\t\tmodule &&\r\n\t\t\t\ttypeof module === 'object' &&\r\n\t\t\t\t'default' in module &&\r\n\t\t\t\tmodule.default\r\n\t\t\t) {\r\n\t\t\t\treturn module as { default: React.ComponentType }\r\n\t\t\t}\r\n\r\n\t\t\t// Ищем любой именованный экспорт, который является функцией или компонентом\r\n\t\t\tif (module && typeof module === 'object') {\r\n\t\t\t\tconst namedExports = Object.keys(module).filter(\r\n\t\t\t\t\tkey => key !== 'default'\r\n\t\t\t\t)\r\n\t\t\t\tfor (const key of namedExports) {\r\n\t\t\t\t\tconst exportValue = module[key]\r\n\t\t\t\t\tif (\r\n\t\t\t\t\t\ttypeof exportValue === 'function' ||\r\n\t\t\t\t\t\t(typeof exportValue === 'object' && exportValue !== null)\r\n\t\t\t\t\t) {\r\n\t\t\t\t\t\treturn {\r\n\t\t\t\t\t\t\tdefault: exportValue as React.ComponentType,\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Если ничего не найдено, возвращаем ошибку\r\n\t\t\tconst availableExports =\r\n\t\t\t\tmodule && typeof module === 'object'\r\n\t\t\t\t\t? Object.keys(module).join(', ')\r\n\t\t\t\t\t: 'unknown'\r\n\t\t\tthrow new Error(\r\n\t\t\t\t`No valid export found in module for route ${n.path}. Available exports: ${availableExports}`\r\n\t\t\t)\r\n\t\t})\r\n\r\n\t\tconst loadingFallback = createLoadingFallback(n.loading)\r\n\t\tconst errorFallback = createErrorFallback(n.error)\r\n\t\t\r\n\t\tconst pageElement = wrapLayouts(n.layouts, <Page />)\r\n\t\t\r\n\t\t// Оборачиваем в ErrorBoundary если есть error компонент\r\n\t\tconst wrappedElement = errorFallback ? (\r\n\t\t\t<ErrorBoundary fallback={errorFallback}>\r\n\t\t\t\t{pageElement}\r\n\t\t\t</ErrorBoundary>\r\n\t\t) : pageElement\r\n\r\n\t\t// Оборачиваем в Suspense с loading fallback\r\n\t\tconst element = loadingFallback ? (\r\n\t\t\t<React.Suspense fallback={loadingFallback}>\r\n\t\t\t\t{wrappedElement}\r\n\t\t\t</React.Suspense>\r\n\t\t) : (\r\n\t\t\t<React.Suspense fallback={<div>Loading...</div>}>\r\n\t\t\t\t{wrappedElement}\r\n\t\t\t</React.Suspense>\r\n\t\t)\r\n\r\n\t\treturn <Route key={n.id} path={n.path} element={element} />\r\n\t}).concat(\r\n\t\t// Добавляем 404 маршрут в конец\r\n\t\tglobalNotFound ? (\r\n\t\t\t<Route\r\n\t\t\t\tkey=\"__not_found__\"\r\n\t\t\t\tpath=\"*\"\r\n\t\t\t\telement={\r\n\t\t\t\t\t<React.Suspense fallback={<div>Loading...</div>}>\r\n\t\t\t\t\t\t{(() => {\r\n\t\t\t\t\t\t\tconst NotFound = React.lazy(globalNotFound)\r\n\t\t\t\t\t\t\treturn <NotFound />\r\n\t\t\t\t\t\t})()}\r\n\t\t\t\t\t</React.Suspense>\r\n\t\t\t\t}\r\n\t\t\t/>\r\n\t\t) : (\r\n\t\t\t<Route\r\n\t\t\t\tkey=\"__not_found__\"\r\n\t\t\t\tpath=\"*\"\r\n\t\t\t\telement={\r\n\t\t\t\t\t<div style={{ padding: '20px', textAlign: 'center' }}>\r\n\t\t\t\t\t\t<h1>404</h1>\r\n\t\t\t\t\t\t<p>Page not found</p>\r\n\t\t\t\t\t</div>\r\n\t\t\t\t}\r\n\t\t\t/>\r\n\t\t)\r\n\t)\r\n}\r\n","import React from 'react'\r\n\r\nexport interface ErrorBoundaryProps {\r\n\tchildren: React.ReactNode\r\n\tfallback?: React.ComponentType<{ error?: Error; resetError?: () => void }>\r\n\tonError?: (error: Error, errorInfo: React.ErrorInfo) => void\r\n}\r\n\r\ninterface ErrorBoundaryState {\r\n\thasError: boolean\r\n\terror: Error | null\r\n}\r\n\r\n/**\r\n * ErrorBoundary компонент для обработки ошибок рендеринга\r\n */\r\nexport class ErrorBoundary extends React.Component<\r\n\tErrorBoundaryProps,\r\n\tErrorBoundaryState\r\n> {\r\n\tconstructor(props: ErrorBoundaryProps) {\r\n\t\tsuper(props)\r\n\t\tthis.state = { hasError: false, error: null }\r\n\t}\r\n\r\n\tstatic getDerivedStateFromError(error: Error): ErrorBoundaryState {\r\n\t\treturn { hasError: true, error }\r\n\t}\r\n\r\n\tcomponentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\r\n\t\tthis.props.onError?.(error, errorInfo)\r\n\t}\r\n\r\n\tresetError = () => {\r\n\t\tthis.setState({ hasError: false, error: null })\r\n\t}\r\n\r\n\trender() {\r\n\t\tif (this.state.hasError && this.state.error) {\r\n\t\t\tif (this.props.fallback) {\r\n\t\t\t\tconst Fallback = this.props.fallback\r\n\t\t\t\treturn <Fallback error={this.state.error} resetError={this.resetError} />\r\n\t\t\t}\r\n\t\t\treturn (\r\n\t\t\t\t<div style={{ padding: '20px' }}>\r\n\t\t\t\t\t<h2>Something went wrong</h2>\r\n\t\t\t\t\t<pre>{this.state.error.message}</pre>\r\n\t\t\t\t\t<button onClick={this.resetError}>Try again</button>\r\n\t\t\t\t</div>\r\n\t\t\t)\r\n\t\t}\r\n\r\n\t\treturn this.props.children\r\n\t}\r\n}\r\n","import { useNavigate as useRouterNavigate } from 'react-router-dom'\r\n\r\nexport type NavigateOptions = {\r\n\treplace?: boolean\r\n\tstate?: unknown\r\n\trelative?: 'route' | 'path'\r\n}\r\n\r\nexport type To = string | number | { pathname?: string; search?: string; hash?: string }\r\n\r\n/**\r\n * Хук для программной навигации\r\n * \r\n * @returns Функция для навигации\r\n * \r\n * @example\r\n * ```tsx\r\n * const navigate = useNavigate()\r\n * navigate('/about')\r\n * navigate('/users', { replace: true })\r\n * navigate(-1) // назад\r\n * ```\r\n */\r\nexport function useNavigate() {\r\n\treturn useRouterNavigate()\r\n}\r\n","import { useParams as useRouterParams } from 'react-router-dom'\r\n\r\nexport type Params = Record<string, string | undefined>\r\n\r\n/**\r\n * Хук для получения параметров маршрута\r\n * \r\n * @returns Объект с параметрами текущего маршрута\r\n * \r\n * @example\r\n * ```tsx\r\n * // Для маршрута /users/:id\r\n * const { id } = useParams()\r\n * ```\r\n */\r\nexport function useParams<T extends Params = Params>(): T {\r\n\treturn useRouterParams() as T\r\n}\r\n","import { useSearchParams as useRouterSearchParams } from 'react-router-dom'\r\n\r\n/**\r\n * Хук для работы с query параметрами URL\r\n * \r\n * @returns Кортеж из [searchParams, setSearchParams]\r\n * \r\n * @example\r\n * ```tsx\r\n * const [searchParams, setSearchParams] = useSearchParams()\r\n * const id = searchParams.get('id')\r\n * setSearchParams({ id: '123' })\r\n * ```\r\n */\r\nexport function useSearchParams() {\r\n\treturn useRouterSearchParams()\r\n}\r\n"],"mappings":"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","names":["import_react_router_dom","useRouterLocation","ReactRouterLink","import_react_router_dom","ReactRouterNavLink","import_react_router_dom","ReactRouterNavigate","import_react","import_react_router_dom","import_react","import_react_router_dom","import_react","import_jsx_runtime","React","import_jsx_runtime","React","module","manifest","globalNotFound","import_jsx_runtime","manifest","globalNotFound","React","import_jsx_runtime","configBasePath","import_react_router_dom","useRouterNavigate","import_react_router_dom","useRouterParams","import_react_router_dom","useRouterSearchParams"]}
|
package/dist/react.mjs
CHANGED
|
@@ -28,6 +28,82 @@ var NavLink = ReactRouterNavLink;
|
|
|
28
28
|
import { Navigate as ReactRouterNavigate } from "react-router-dom";
|
|
29
29
|
var Navigate = ReactRouterNavigate;
|
|
30
30
|
|
|
31
|
+
// src/components/route-transition.tsx
|
|
32
|
+
import { useEffect, useState, useRef } from "react";
|
|
33
|
+
import { jsx } from "react/jsx-runtime";
|
|
34
|
+
function RouteTransition({
|
|
35
|
+
children,
|
|
36
|
+
enterClass = "route-enter",
|
|
37
|
+
enterActiveClass = "route-enter-active",
|
|
38
|
+
exitClass = "route-exit",
|
|
39
|
+
exitActiveClass = "route-exit-active",
|
|
40
|
+
duration = 300,
|
|
41
|
+
onTransition,
|
|
42
|
+
mode = "fade"
|
|
43
|
+
}) {
|
|
44
|
+
const location = useLocation();
|
|
45
|
+
const [displayChildren, setDisplayChildren] = useState(children);
|
|
46
|
+
const [isExiting, setIsExiting] = useState(false);
|
|
47
|
+
const [isEntering, setIsEntering] = useState(false);
|
|
48
|
+
const prevLocationRef = useRef(location.pathname);
|
|
49
|
+
const timeoutRef = useRef(null);
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (prevLocationRef.current !== location.pathname) {
|
|
52
|
+
if (timeoutRef.current) {
|
|
53
|
+
clearTimeout(timeoutRef.current);
|
|
54
|
+
}
|
|
55
|
+
setIsExiting(true);
|
|
56
|
+
setIsEntering(false);
|
|
57
|
+
onTransition?.("exit");
|
|
58
|
+
timeoutRef.current = setTimeout(() => {
|
|
59
|
+
setDisplayChildren(children);
|
|
60
|
+
setIsExiting(false);
|
|
61
|
+
setIsEntering(true);
|
|
62
|
+
onTransition?.("enter");
|
|
63
|
+
timeoutRef.current = setTimeout(() => {
|
|
64
|
+
setIsEntering(false);
|
|
65
|
+
timeoutRef.current = null;
|
|
66
|
+
}, duration);
|
|
67
|
+
}, duration);
|
|
68
|
+
prevLocationRef.current = location.pathname;
|
|
69
|
+
} else {
|
|
70
|
+
setDisplayChildren(children);
|
|
71
|
+
}
|
|
72
|
+
return () => {
|
|
73
|
+
if (timeoutRef.current) {
|
|
74
|
+
clearTimeout(timeoutRef.current);
|
|
75
|
+
timeoutRef.current = null;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}, [location.pathname, children, duration, onTransition]);
|
|
79
|
+
const getClassName = () => {
|
|
80
|
+
if (isExiting) {
|
|
81
|
+
return `${exitClass} ${exitActiveClass}`;
|
|
82
|
+
}
|
|
83
|
+
if (isEntering) {
|
|
84
|
+
return `${enterClass} ${enterActiveClass}`;
|
|
85
|
+
}
|
|
86
|
+
return "";
|
|
87
|
+
};
|
|
88
|
+
const getDefaultStyles = () => {
|
|
89
|
+
if (mode === "fade") {
|
|
90
|
+
return {
|
|
91
|
+
transition: `opacity ${duration}ms ease-in-out`,
|
|
92
|
+
opacity: isExiting ? 0 : isEntering ? 0 : 1
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
if (mode === "slide") {
|
|
96
|
+
return {
|
|
97
|
+
transition: `transform ${duration}ms ease-in-out, opacity ${duration}ms ease-in-out`,
|
|
98
|
+
transform: isExiting ? "translateX(-100%)" : isEntering ? "translateX(100%)" : "translateX(0)",
|
|
99
|
+
opacity: isExiting ? 0 : isEntering ? 0 : 1
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return {};
|
|
103
|
+
};
|
|
104
|
+
return /* @__PURE__ */ jsx("div", { className: getClassName(), style: getDefaultStyles(), children: displayChildren });
|
|
105
|
+
}
|
|
106
|
+
|
|
31
107
|
// src/components/router-provider.tsx
|
|
32
108
|
import {
|
|
33
109
|
basePath as configBasePath,
|
|
@@ -36,17 +112,17 @@ import {
|
|
|
36
112
|
} from "virtual:routes";
|
|
37
113
|
|
|
38
114
|
// src/components/router-layout.tsx
|
|
39
|
-
import
|
|
115
|
+
import React4 from "react";
|
|
40
116
|
import { BrowserRouter, Routes } from "react-router-dom";
|
|
41
117
|
|
|
42
118
|
// src/components/router-utils.tsx
|
|
43
|
-
import
|
|
119
|
+
import React3 from "react";
|
|
44
120
|
import { Route } from "react-router-dom";
|
|
45
121
|
|
|
46
122
|
// src/components/error-boundary.tsx
|
|
47
|
-
import
|
|
48
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
49
|
-
var ErrorBoundary = class extends
|
|
123
|
+
import React2 from "react";
|
|
124
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
125
|
+
var ErrorBoundary = class extends React2.Component {
|
|
50
126
|
constructor(props) {
|
|
51
127
|
super(props);
|
|
52
128
|
this.state = { hasError: false, error: null };
|
|
@@ -64,12 +140,12 @@ var ErrorBoundary = class extends React.Component {
|
|
|
64
140
|
if (this.state.hasError && this.state.error) {
|
|
65
141
|
if (this.props.fallback) {
|
|
66
142
|
const Fallback = this.props.fallback;
|
|
67
|
-
return /* @__PURE__ */
|
|
143
|
+
return /* @__PURE__ */ jsx2(Fallback, { error: this.state.error, resetError: this.resetError });
|
|
68
144
|
}
|
|
69
145
|
return /* @__PURE__ */ jsxs("div", { style: { padding: "20px" }, children: [
|
|
70
|
-
/* @__PURE__ */
|
|
71
|
-
/* @__PURE__ */
|
|
72
|
-
/* @__PURE__ */
|
|
146
|
+
/* @__PURE__ */ jsx2("h2", { children: "Something went wrong" }),
|
|
147
|
+
/* @__PURE__ */ jsx2("pre", { children: this.state.error.message }),
|
|
148
|
+
/* @__PURE__ */ jsx2("button", { onClick: this.resetError, children: "Try again" })
|
|
73
149
|
] });
|
|
74
150
|
}
|
|
75
151
|
return this.props.children;
|
|
@@ -77,30 +153,30 @@ var ErrorBoundary = class extends React.Component {
|
|
|
77
153
|
};
|
|
78
154
|
|
|
79
155
|
// src/components/router-utils.tsx
|
|
80
|
-
import { jsx as
|
|
156
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
81
157
|
function wrapLayouts(layouts, pageEl) {
|
|
82
158
|
if (!layouts || layouts.length === 0) return pageEl;
|
|
83
159
|
return layouts.reduceRight((child, loader) => {
|
|
84
|
-
const Layout =
|
|
160
|
+
const Layout = React3.lazy(async () => {
|
|
85
161
|
const module = await loader();
|
|
86
162
|
return "default" in module ? module : { default: module.Layout };
|
|
87
163
|
});
|
|
88
|
-
return /* @__PURE__ */
|
|
164
|
+
return /* @__PURE__ */ jsx3(Layout, { children: child });
|
|
89
165
|
}, pageEl);
|
|
90
166
|
}
|
|
91
167
|
function createLoadingFallback(loadingLoader) {
|
|
92
168
|
if (!loadingLoader) return void 0;
|
|
93
|
-
const Loading =
|
|
94
|
-
return /* @__PURE__ */
|
|
169
|
+
const Loading = React3.lazy(loadingLoader);
|
|
170
|
+
return /* @__PURE__ */ jsx3(Loading, {});
|
|
95
171
|
}
|
|
96
172
|
function createErrorFallback(errorLoader) {
|
|
97
173
|
if (!errorLoader) return void 0;
|
|
98
|
-
const ErrorComponent =
|
|
99
|
-
return (props) => /* @__PURE__ */
|
|
174
|
+
const ErrorComponent = React3.lazy(errorLoader);
|
|
175
|
+
return (props) => /* @__PURE__ */ jsx3(ErrorComponent, { ...props });
|
|
100
176
|
}
|
|
101
177
|
var renderManifestAsRoutes = (manifest2, globalNotFound2) => {
|
|
102
178
|
return manifest2.map((n) => {
|
|
103
|
-
const Page =
|
|
179
|
+
const Page = React3.lazy(async () => {
|
|
104
180
|
const module = await n.loader();
|
|
105
181
|
if (module && typeof module === "object" && "default" in module && module.default) {
|
|
106
182
|
return module;
|
|
@@ -125,29 +201,29 @@ var renderManifestAsRoutes = (manifest2, globalNotFound2) => {
|
|
|
125
201
|
});
|
|
126
202
|
const loadingFallback = createLoadingFallback(n.loading);
|
|
127
203
|
const errorFallback = createErrorFallback(n.error);
|
|
128
|
-
const pageElement = wrapLayouts(n.layouts, /* @__PURE__ */
|
|
129
|
-
const wrappedElement = errorFallback ? /* @__PURE__ */
|
|
130
|
-
const element = loadingFallback ? /* @__PURE__ */
|
|
131
|
-
return /* @__PURE__ */
|
|
204
|
+
const pageElement = wrapLayouts(n.layouts, /* @__PURE__ */ jsx3(Page, {}));
|
|
205
|
+
const wrappedElement = errorFallback ? /* @__PURE__ */ jsx3(ErrorBoundary, { fallback: errorFallback, children: pageElement }) : pageElement;
|
|
206
|
+
const element = loadingFallback ? /* @__PURE__ */ jsx3(React3.Suspense, { fallback: loadingFallback, children: wrappedElement }) : /* @__PURE__ */ jsx3(React3.Suspense, { fallback: /* @__PURE__ */ jsx3("div", { children: "Loading..." }), children: wrappedElement });
|
|
207
|
+
return /* @__PURE__ */ jsx3(Route, { path: n.path, element }, n.id);
|
|
132
208
|
}).concat(
|
|
133
209
|
// Добавляем 404 маршрут в конец
|
|
134
|
-
globalNotFound2 ? /* @__PURE__ */
|
|
210
|
+
globalNotFound2 ? /* @__PURE__ */ jsx3(
|
|
135
211
|
Route,
|
|
136
212
|
{
|
|
137
213
|
path: "*",
|
|
138
|
-
element: /* @__PURE__ */
|
|
139
|
-
const NotFound =
|
|
140
|
-
return /* @__PURE__ */
|
|
214
|
+
element: /* @__PURE__ */ jsx3(React3.Suspense, { fallback: /* @__PURE__ */ jsx3("div", { children: "Loading..." }), children: (() => {
|
|
215
|
+
const NotFound = React3.lazy(globalNotFound2);
|
|
216
|
+
return /* @__PURE__ */ jsx3(NotFound, {});
|
|
141
217
|
})() })
|
|
142
218
|
},
|
|
143
219
|
"__not_found__"
|
|
144
|
-
) : /* @__PURE__ */
|
|
220
|
+
) : /* @__PURE__ */ jsx3(
|
|
145
221
|
Route,
|
|
146
222
|
{
|
|
147
223
|
path: "*",
|
|
148
224
|
element: /* @__PURE__ */ jsxs2("div", { style: { padding: "20px", textAlign: "center" }, children: [
|
|
149
|
-
/* @__PURE__ */
|
|
150
|
-
/* @__PURE__ */
|
|
225
|
+
/* @__PURE__ */ jsx3("h1", { children: "404" }),
|
|
226
|
+
/* @__PURE__ */ jsx3("p", { children: "Page not found" })
|
|
151
227
|
] })
|
|
152
228
|
},
|
|
153
229
|
"__not_found__"
|
|
@@ -156,30 +232,40 @@ var renderManifestAsRoutes = (manifest2, globalNotFound2) => {
|
|
|
156
232
|
};
|
|
157
233
|
|
|
158
234
|
// src/components/router-layout.tsx
|
|
159
|
-
import { jsx as
|
|
235
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
160
236
|
var RouterLayout = ({
|
|
161
237
|
manifest: manifest2,
|
|
162
238
|
children,
|
|
163
239
|
preloader,
|
|
164
240
|
basePath = "/",
|
|
165
|
-
globalNotFound: globalNotFound2
|
|
166
|
-
|
|
241
|
+
globalNotFound: globalNotFound2,
|
|
242
|
+
enableTransitions = false,
|
|
243
|
+
transitionConfig
|
|
244
|
+
}) => {
|
|
245
|
+
const routes = renderManifestAsRoutes(manifest2, globalNotFound2);
|
|
246
|
+
const routesElement = /* @__PURE__ */ jsx4(Routes, { children: routes });
|
|
247
|
+
return /* @__PURE__ */ jsx4(BrowserRouter, { basename: basePath, children: /* @__PURE__ */ jsx4(React4.Suspense, { fallback: children || preloader || /* @__PURE__ */ jsx4("div", { children: "Loading..." }), children: enableTransitions ? /* @__PURE__ */ jsx4(RouteTransition, { ...transitionConfig, children: routesElement }) : routesElement }) });
|
|
248
|
+
};
|
|
167
249
|
|
|
168
250
|
// src/components/router-provider.tsx
|
|
169
|
-
import { jsx as
|
|
251
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
170
252
|
function RouterProvider({
|
|
171
253
|
children,
|
|
172
254
|
preloader,
|
|
173
|
-
basePath
|
|
255
|
+
basePath,
|
|
256
|
+
enableTransitions,
|
|
257
|
+
transitionConfig
|
|
174
258
|
}) {
|
|
175
259
|
const finalBasePath = basePath ?? configBasePath ?? "/";
|
|
176
|
-
return /* @__PURE__ */
|
|
260
|
+
return /* @__PURE__ */ jsx5(
|
|
177
261
|
RouterLayout,
|
|
178
262
|
{
|
|
179
263
|
manifest,
|
|
180
264
|
preloader,
|
|
181
265
|
basePath: finalBasePath,
|
|
182
266
|
globalNotFound,
|
|
267
|
+
enableTransitions,
|
|
268
|
+
transitionConfig,
|
|
183
269
|
children
|
|
184
270
|
}
|
|
185
271
|
);
|
|
@@ -206,6 +292,7 @@ export {
|
|
|
206
292
|
Link,
|
|
207
293
|
NavLink,
|
|
208
294
|
Navigate,
|
|
295
|
+
RouteTransition,
|
|
209
296
|
RouterProvider,
|
|
210
297
|
useLink,
|
|
211
298
|
useLocation,
|
package/dist/react.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/link.tsx","../src/components/hooks/use-location.ts","../src/components/hooks/use-links.tsx","../src/components/nav-link.tsx","../src/components/navigate.tsx","../src/components/router-provider.tsx","../src/components/router-layout.tsx","../src/components/router-utils.tsx","../src/components/error-boundary.tsx","../src/components/hooks/use-navigate.ts","../src/components/hooks/use-params.ts","../src/components/hooks/use-search-params.ts"],"sourcesContent":["import type { LinkProps as ReactRouterLinkProps } from 'react-router-dom'\r\nimport { Link as ReactRouterLink } from 'react-router-dom'\r\n\r\nexport type LinkProps = ReactRouterLinkProps\r\n\r\n/**\r\n * Компонент для навигационных ссылок\r\n * \r\n * Используется для клиентской навигации без перезагрузки страницы\r\n * \r\n * @example\r\n * ```tsx\r\n * <Link to=\"/about\">About</Link>\r\n * <Link to=\"/users/123\" state={{ from: 'home' }}>User Profile</Link>\r\n * ```\r\n */\r\nexport const Link = ReactRouterLink\r\n\r\nexport { useLink } from './hooks/use-links'\r\n","import { useLocation as useRouterLocation } from 'react-router-dom'\r\nimport type { Location as RouterLocation } from 'react-router-dom'\r\n\r\n/**\r\n * Тип локации с информацией о текущем маршруте\r\n */\r\nexport type Location = RouterLocation\r\n\r\n/**\r\n * Хук для получения текущей локации\r\n * \r\n * @returns Объект с информацией о текущем маршруте\r\n * \r\n * @example\r\n * ```tsx\r\n * const location = useLocation()\r\n * console.log(location.pathname) // '/about'\r\n * console.log(location.search) // '?id=123'\r\n * ```\r\n */\r\nexport function useLocation(): Location {\r\n\treturn useRouterLocation()\r\n}\r\n","import { useLocation } from './use-location'\r\n\r\nexport function useLink(props: { href: string }) {\r\n const location = useLocation()\r\n const currentPath = location.pathname\r\n \r\n return {\r\n href: props.href,\r\n isActive: currentPath === props.href,\r\n }\r\n}","import type { NavLinkProps as ReactRouterNavLinkProps } from 'react-router-dom'\r\nimport { NavLink as ReactRouterNavLink } from 'react-router-dom'\r\n\r\nexport type NavLinkProps = ReactRouterNavLinkProps\r\n\r\n/**\r\n * Компонент для навигационных ссылок с поддержкой активного состояния\r\n * \r\n * Автоматически добавляет класс 'active' когда маршрут активен\r\n * \r\n * @example\r\n * ```tsx\r\n * <NavLink to=\"/about\">About</NavLink>\r\n * <NavLink to=\"/users\" className={({ isActive }) => isActive ? 'active' : ''}>\r\n * Users\r\n * </NavLink>\r\n * ```\r\n */\r\nexport const NavLink = ReactRouterNavLink\r\n","import type { NavigateProps as ReactRouterNavigateProps } from 'react-router-dom'\r\nimport { Navigate as ReactRouterNavigate } from 'react-router-dom'\r\n\r\nexport type NavigateProps = ReactRouterNavigateProps\r\n\r\n/**\r\n * Компонент для программного редиректа\r\n * \r\n * @example\r\n * ```tsx\r\n * <Navigate to=\"/login\" replace />\r\n * <Navigate to=\"/dashboard\" state={{ from: location }} />\r\n * ```\r\n */\r\nexport const Navigate = ReactRouterNavigate\r\n","import {\r\n\tbasePath as configBasePath,\r\n\tglobalNotFound,\r\n\tmanifest,\r\n} from 'virtual:routes'\r\nimport { RouterLayout } from './router-layout'\r\nimport type { RouterProviderProps } from './types/types'\r\n\r\nexport default function RouterProvider({\r\n\tchildren,\r\n\tpreloader,\r\n\tbasePath,\r\n}: Readonly<RouterProviderProps>) {\r\n\t// Используем basePath из пропсов, если указан, иначе из конфигурации\r\n\tconst finalBasePath = basePath ?? configBasePath ?? '/'\r\n\t\r\n\treturn (\r\n\t\t<RouterLayout\r\n\t\t\tmanifest={manifest}\r\n\t\t\tpreloader={preloader}\r\n\t\t\tbasePath={finalBasePath}\r\n\t\t\tglobalNotFound={globalNotFound}\r\n\t\t>\r\n\t\t\t{children}\r\n\t\t</RouterLayout>\r\n\t)\r\n}\r\n","import React from 'react'\r\nimport { BrowserRouter, Routes } from 'react-router-dom'\r\nimport { renderManifestAsRoutes } from './router-utils'\r\nimport type { RouterLayoutProps } from './types/types'\r\n\r\nexport const RouterLayout = ({\r\n\tmanifest,\r\n\tchildren,\r\n\tpreloader,\r\n\tbasePath = '/',\r\n\tglobalNotFound,\r\n}: RouterLayoutProps) => (\r\n\t<BrowserRouter basename={basePath}>\r\n\t\t<React.Suspense fallback={children || preloader || <div>Loading...</div>}>\r\n\t\t\t<Routes>{renderManifestAsRoutes(manifest, globalNotFound)}</Routes>\r\n\t\t</React.Suspense>\r\n\t</BrowserRouter>\r\n)\r\n","import React from 'react'\r\nimport { Route } from 'react-router-dom'\r\nimport { ErrorBoundary } from './error-boundary'\r\nimport type { Node } from './types/types'\r\n\r\nfunction wrapLayouts(\r\n\tlayouts: Node['layouts'] | undefined,\r\n\tpageEl: React.ReactNode\r\n) {\r\n\tif (!layouts || layouts.length === 0) return pageEl\r\n\r\n\treturn layouts.reduceRight((child, loader) => {\r\n\t\tconst Layout = React.lazy(async () => {\r\n\t\t\tconst module = await loader()\r\n\t\t\t// Поддерживаем как default, так и именованный экспорт Layout\r\n\t\t\treturn 'default' in module ? module : { default: module.Layout }\r\n\t\t})\r\n\t\treturn <Layout>{child}</Layout>\r\n\t}, pageEl as React.ReactElement)\r\n}\r\n\r\nfunction createLoadingFallback(loadingLoader?: () => Promise<{ default: React.ComponentType }>) {\r\n\tif (!loadingLoader) return undefined\r\n\t\r\n\t// Loading компонент lazy, но он используется как fallback в Suspense\r\n\tconst Loading = React.lazy(loadingLoader)\r\n\treturn <Loading />\r\n}\r\n\r\nfunction createErrorFallback(errorLoader?: () => Promise<{ default: React.ComponentType<{ error?: Error; resetError?: () => void }> }>) {\r\n\tif (!errorLoader) return undefined\r\n\t\r\n\tconst ErrorComponent = React.lazy(errorLoader)\r\n\treturn (props: { error?: Error; resetError?: () => void }) => <ErrorComponent {...props} />\r\n}\r\n\r\nexport const renderManifestAsRoutes = (\r\n\tmanifest: Node[],\r\n\tglobalNotFound?: () => Promise<{ default: React.ComponentType }>\r\n) => {\r\n\treturn manifest.map(n => {\r\n\t\tconst Page = React.lazy(async () => {\r\n\t\t\tconst module = await n.loader()\r\n\r\n\t\t\t// Если есть default экспорт, используем его\r\n\t\t\tif (\r\n\t\t\t\tmodule &&\r\n\t\t\t\ttypeof module === 'object' &&\r\n\t\t\t\t'default' in module &&\r\n\t\t\t\tmodule.default\r\n\t\t\t) {\r\n\t\t\t\treturn module as { default: React.ComponentType }\r\n\t\t\t}\r\n\r\n\t\t\t// Ищем любой именованный экспорт, который является функцией или компонентом\r\n\t\t\tif (module && typeof module === 'object') {\r\n\t\t\t\tconst namedExports = Object.keys(module).filter(\r\n\t\t\t\t\tkey => key !== 'default'\r\n\t\t\t\t)\r\n\t\t\t\tfor (const key of namedExports) {\r\n\t\t\t\t\tconst exportValue = module[key]\r\n\t\t\t\t\tif (\r\n\t\t\t\t\t\ttypeof exportValue === 'function' ||\r\n\t\t\t\t\t\t(typeof exportValue === 'object' && exportValue !== null)\r\n\t\t\t\t\t) {\r\n\t\t\t\t\t\treturn {\r\n\t\t\t\t\t\t\tdefault: exportValue as React.ComponentType,\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Если ничего не найдено, возвращаем ошибку\r\n\t\t\tconst availableExports =\r\n\t\t\t\tmodule && typeof module === 'object'\r\n\t\t\t\t\t? Object.keys(module).join(', ')\r\n\t\t\t\t\t: 'unknown'\r\n\t\t\tthrow new Error(\r\n\t\t\t\t`No valid export found in module for route ${n.path}. Available exports: ${availableExports}`\r\n\t\t\t)\r\n\t\t})\r\n\r\n\t\tconst loadingFallback = createLoadingFallback(n.loading)\r\n\t\tconst errorFallback = createErrorFallback(n.error)\r\n\t\t\r\n\t\tconst pageElement = wrapLayouts(n.layouts, <Page />)\r\n\t\t\r\n\t\t// Оборачиваем в ErrorBoundary если есть error компонент\r\n\t\tconst wrappedElement = errorFallback ? (\r\n\t\t\t<ErrorBoundary fallback={errorFallback}>\r\n\t\t\t\t{pageElement}\r\n\t\t\t</ErrorBoundary>\r\n\t\t) : pageElement\r\n\r\n\t\t// Оборачиваем в Suspense с loading fallback\r\n\t\tconst element = loadingFallback ? (\r\n\t\t\t<React.Suspense fallback={loadingFallback}>\r\n\t\t\t\t{wrappedElement}\r\n\t\t\t</React.Suspense>\r\n\t\t) : (\r\n\t\t\t<React.Suspense fallback={<div>Loading...</div>}>\r\n\t\t\t\t{wrappedElement}\r\n\t\t\t</React.Suspense>\r\n\t\t)\r\n\r\n\t\treturn <Route key={n.id} path={n.path} element={element} />\r\n\t}).concat(\r\n\t\t// Добавляем 404 маршрут в конец\r\n\t\tglobalNotFound ? (\r\n\t\t\t<Route\r\n\t\t\t\tkey=\"__not_found__\"\r\n\t\t\t\tpath=\"*\"\r\n\t\t\t\telement={\r\n\t\t\t\t\t<React.Suspense fallback={<div>Loading...</div>}>\r\n\t\t\t\t\t\t{(() => {\r\n\t\t\t\t\t\t\tconst NotFound = React.lazy(globalNotFound)\r\n\t\t\t\t\t\t\treturn <NotFound />\r\n\t\t\t\t\t\t})()}\r\n\t\t\t\t\t</React.Suspense>\r\n\t\t\t\t}\r\n\t\t\t/>\r\n\t\t) : (\r\n\t\t\t<Route\r\n\t\t\t\tkey=\"__not_found__\"\r\n\t\t\t\tpath=\"*\"\r\n\t\t\t\telement={\r\n\t\t\t\t\t<div style={{ padding: '20px', textAlign: 'center' }}>\r\n\t\t\t\t\t\t<h1>404</h1>\r\n\t\t\t\t\t\t<p>Page not found</p>\r\n\t\t\t\t\t</div>\r\n\t\t\t\t}\r\n\t\t\t/>\r\n\t\t)\r\n\t)\r\n}\r\n","import React from 'react'\r\n\r\nexport interface ErrorBoundaryProps {\r\n\tchildren: React.ReactNode\r\n\tfallback?: React.ComponentType<{ error?: Error; resetError?: () => void }>\r\n\tonError?: (error: Error, errorInfo: React.ErrorInfo) => void\r\n}\r\n\r\ninterface ErrorBoundaryState {\r\n\thasError: boolean\r\n\terror: Error | null\r\n}\r\n\r\n/**\r\n * ErrorBoundary компонент для обработки ошибок рендеринга\r\n */\r\nexport class ErrorBoundary extends React.Component<\r\n\tErrorBoundaryProps,\r\n\tErrorBoundaryState\r\n> {\r\n\tconstructor(props: ErrorBoundaryProps) {\r\n\t\tsuper(props)\r\n\t\tthis.state = { hasError: false, error: null }\r\n\t}\r\n\r\n\tstatic getDerivedStateFromError(error: Error): ErrorBoundaryState {\r\n\t\treturn { hasError: true, error }\r\n\t}\r\n\r\n\tcomponentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\r\n\t\tthis.props.onError?.(error, errorInfo)\r\n\t}\r\n\r\n\tresetError = () => {\r\n\t\tthis.setState({ hasError: false, error: null })\r\n\t}\r\n\r\n\trender() {\r\n\t\tif (this.state.hasError && this.state.error) {\r\n\t\t\tif (this.props.fallback) {\r\n\t\t\t\tconst Fallback = this.props.fallback\r\n\t\t\t\treturn <Fallback error={this.state.error} resetError={this.resetError} />\r\n\t\t\t}\r\n\t\t\treturn (\r\n\t\t\t\t<div style={{ padding: '20px' }}>\r\n\t\t\t\t\t<h2>Something went wrong</h2>\r\n\t\t\t\t\t<pre>{this.state.error.message}</pre>\r\n\t\t\t\t\t<button onClick={this.resetError}>Try again</button>\r\n\t\t\t\t</div>\r\n\t\t\t)\r\n\t\t}\r\n\r\n\t\treturn this.props.children\r\n\t}\r\n}\r\n","import { useNavigate as useRouterNavigate } from 'react-router-dom'\r\n\r\nexport type NavigateOptions = {\r\n\treplace?: boolean\r\n\tstate?: unknown\r\n\trelative?: 'route' | 'path'\r\n}\r\n\r\nexport type To = string | number | { pathname?: string; search?: string; hash?: string }\r\n\r\n/**\r\n * Хук для программной навигации\r\n * \r\n * @returns Функция для навигации\r\n * \r\n * @example\r\n * ```tsx\r\n * const navigate = useNavigate()\r\n * navigate('/about')\r\n * navigate('/users', { replace: true })\r\n * navigate(-1) // назад\r\n * ```\r\n */\r\nexport function useNavigate() {\r\n\treturn useRouterNavigate()\r\n}\r\n","import { useParams as useRouterParams } from 'react-router-dom'\r\n\r\nexport type Params = Record<string, string | undefined>\r\n\r\n/**\r\n * Хук для получения параметров маршрута\r\n * \r\n * @returns Объект с параметрами текущего маршрута\r\n * \r\n * @example\r\n * ```tsx\r\n * // Для маршрута /users/:id\r\n * const { id } = useParams()\r\n * ```\r\n */\r\nexport function useParams<T extends Params = Params>(): T {\r\n\treturn useRouterParams() as T\r\n}\r\n","import { useSearchParams as useRouterSearchParams } from 'react-router-dom'\r\n\r\n/**\r\n * Хук для работы с query параметрами URL\r\n * \r\n * @returns Кортеж из [searchParams, setSearchParams]\r\n * \r\n * @example\r\n * ```tsx\r\n * const [searchParams, setSearchParams] = useSearchParams()\r\n * const id = searchParams.get('id')\r\n * setSearchParams({ id: '123' })\r\n * ```\r\n */\r\nexport function useSearchParams() {\r\n\treturn useRouterSearchParams()\r\n}\r\n"],"mappings":"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","names":["React","React","jsx","jsxs","React","manifest","globalNotFound","jsx","manifest","globalNotFound","React","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/link.tsx","../src/components/hooks/use-location.ts","../src/components/hooks/use-links.tsx","../src/components/nav-link.tsx","../src/components/navigate.tsx","../src/components/route-transition.tsx","../src/components/router-provider.tsx","../src/components/router-layout.tsx","../src/components/router-utils.tsx","../src/components/error-boundary.tsx","../src/components/hooks/use-navigate.ts","../src/components/hooks/use-params.ts","../src/components/hooks/use-search-params.ts"],"sourcesContent":["import type { LinkProps as ReactRouterLinkProps } from 'react-router-dom'\r\nimport { Link as ReactRouterLink } from 'react-router-dom'\r\n\r\nexport type LinkProps = ReactRouterLinkProps\r\n\r\n/**\r\n * Компонент для навигационных ссылок\r\n * \r\n * Используется для клиентской навигации без перезагрузки страницы\r\n * \r\n * @example\r\n * ```tsx\r\n * <Link to=\"/about\">About</Link>\r\n * <Link to=\"/users/123\" state={{ from: 'home' }}>User Profile</Link>\r\n * ```\r\n */\r\nexport const Link = ReactRouterLink\r\n\r\nexport { useLink } from './hooks/use-links'\r\n","import { useLocation as useRouterLocation } from 'react-router-dom'\r\nimport type { Location as RouterLocation } from 'react-router-dom'\r\n\r\n/**\r\n * Тип локации с информацией о текущем маршруте\r\n */\r\nexport type Location = RouterLocation\r\n\r\n/**\r\n * Хук для получения текущей локации\r\n * \r\n * @returns Объект с информацией о текущем маршруте\r\n * \r\n * @example\r\n * ```tsx\r\n * const location = useLocation()\r\n * console.log(location.pathname) // '/about'\r\n * console.log(location.search) // '?id=123'\r\n * ```\r\n */\r\nexport function useLocation(): Location {\r\n\treturn useRouterLocation()\r\n}\r\n","import { useLocation } from './use-location'\r\n\r\nexport function useLink(props: { href: string }) {\r\n const location = useLocation()\r\n const currentPath = location.pathname\r\n \r\n return {\r\n href: props.href,\r\n isActive: currentPath === props.href,\r\n }\r\n}","import type { NavLinkProps as ReactRouterNavLinkProps } from 'react-router-dom'\r\nimport { NavLink as ReactRouterNavLink } from 'react-router-dom'\r\n\r\nexport type NavLinkProps = ReactRouterNavLinkProps\r\n\r\n/**\r\n * Компонент для навигационных ссылок с поддержкой активного состояния\r\n * \r\n * Автоматически добавляет класс 'active' когда маршрут активен\r\n * \r\n * @example\r\n * ```tsx\r\n * <NavLink to=\"/about\">About</NavLink>\r\n * <NavLink to=\"/users\" className={({ isActive }) => isActive ? 'active' : ''}>\r\n * Users\r\n * </NavLink>\r\n * ```\r\n */\r\nexport const NavLink = ReactRouterNavLink\r\n","import type { NavigateProps as ReactRouterNavigateProps } from 'react-router-dom'\r\nimport { Navigate as ReactRouterNavigate } from 'react-router-dom'\r\n\r\nexport type NavigateProps = ReactRouterNavigateProps\r\n\r\n/**\r\n * Компонент для программного редиректа\r\n * \r\n * @example\r\n * ```tsx\r\n * <Navigate to=\"/login\" replace />\r\n * <Navigate to=\"/dashboard\" state={{ from: location }} />\r\n * ```\r\n */\r\nexport const Navigate = ReactRouterNavigate\r\n","import React, { useEffect, useState, useRef } from 'react'\r\nimport { useLocation } from './hooks/use-location'\r\n\r\nexport interface RouteTransitionProps {\r\n\tchildren: React.ReactNode\r\n\t/**\r\n\t * CSS класс для анимации входа\r\n\t * @default 'route-enter'\r\n\t */\r\n\tenterClass?: string\r\n\t/**\r\n\t * CSS класс для активного состояния (после входа)\r\n\t * @default 'route-enter-active'\r\n\t */\r\n\tenterActiveClass?: string\r\n\t/**\r\n\t * CSS класс для анимации выхода\r\n\t * @default 'route-exit'\r\n\t */\r\n\texitClass?: string\r\n\t/**\r\n\t * CSS класс для активного состояния выхода\r\n\t * @default 'route-exit-active'\r\n\t */\r\n\texitActiveClass?: string\r\n\t/**\r\n\t * Длительность анимации в миллисекундах\r\n\t * @default 300\r\n\t */\r\n\tduration?: number\r\n\t/**\r\n\t * Кастомная функция для анимации\r\n\t */\r\n\tonTransition?: (direction: 'enter' | 'exit') => void\r\n\t/**\r\n\t * Режим анимации: 'fade', 'slide', 'custom'\r\n\t * @default 'fade'\r\n\t */\r\n\tmode?: 'fade' | 'slide' | 'custom'\r\n}\r\n\r\nexport function RouteTransition({\r\n\tchildren,\r\n\tenterClass = 'route-enter',\r\n\tenterActiveClass = 'route-enter-active',\r\n\texitClass = 'route-exit',\r\n\texitActiveClass = 'route-exit-active',\r\n\tduration = 300,\r\n\tonTransition,\r\n\tmode = 'fade',\r\n}: RouteTransitionProps) {\r\n\tconst location = useLocation()\r\n\tconst [displayChildren, setDisplayChildren] = useState(children)\r\n\tconst [isExiting, setIsExiting] = useState(false)\r\n\tconst [isEntering, setIsEntering] = useState(false)\r\n\tconst prevLocationRef = useRef(location.pathname)\r\n\tconst timeoutRef = useRef<NodeJS.Timeout | null>(null)\r\n\r\n\tuseEffect(() => {\r\n\t\tif (prevLocationRef.current !== location.pathname) {\r\n\t\t\t// Очищаем предыдущий таймер если есть\r\n\t\t\tif (timeoutRef.current) {\r\n\t\t\t\tclearTimeout(timeoutRef.current)\r\n\t\t\t}\r\n\r\n\t\t\t// Начинаем анимацию выхода\r\n\t\t\tsetIsExiting(true)\r\n\t\t\tsetIsEntering(false)\r\n\t\t\tonTransition?.('exit')\r\n\r\n\t\t\ttimeoutRef.current = setTimeout(() => {\r\n\t\t\t\t// Меняем контент\r\n\t\t\t\tsetDisplayChildren(children)\r\n\t\t\t\tsetIsExiting(false)\r\n\t\t\t\tsetIsEntering(true)\r\n\t\t\t\tonTransition?.('enter')\r\n\r\n\t\t\t\t// Начинаем анимацию входа\r\n\t\t\t\ttimeoutRef.current = setTimeout(() => {\r\n\t\t\t\t\tsetIsEntering(false)\r\n\t\t\t\t\ttimeoutRef.current = null\r\n\t\t\t\t}, duration)\r\n\t\t\t}, duration)\r\n\r\n\t\t\tprevLocationRef.current = location.pathname\r\n\t\t} else {\r\n\t\t\t// Если location не изменился, просто обновляем children\r\n\t\t\tsetDisplayChildren(children)\r\n\t\t}\r\n\r\n\t\treturn () => {\r\n\t\t\tif (timeoutRef.current) {\r\n\t\t\t\tclearTimeout(timeoutRef.current)\r\n\t\t\t\ttimeoutRef.current = null\r\n\t\t\t}\r\n\t\t}\r\n\t}, [location.pathname, children, duration, onTransition])\r\n\r\n\t// Определяем классы в зависимости от состояния\r\n\tconst getClassName = () => {\r\n\t\tif (isExiting) {\r\n\t\t\treturn `${exitClass} ${exitActiveClass}`\r\n\t\t}\r\n\t\tif (isEntering) {\r\n\t\t\treturn `${enterClass} ${enterActiveClass}`\r\n\t\t}\r\n\t\treturn ''\r\n\t}\r\n\r\n\t// Стили для режима fade (по умолчанию)\r\n\tconst getDefaultStyles = () => {\r\n\t\tif (mode === 'fade') {\r\n\t\t\treturn {\r\n\t\t\t\ttransition: `opacity ${duration}ms ease-in-out`,\r\n\t\t\t\topacity: isExiting ? 0 : isEntering ? 0 : 1,\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (mode === 'slide') {\r\n\t\t\treturn {\r\n\t\t\t\ttransition: `transform ${duration}ms ease-in-out, opacity ${duration}ms ease-in-out`,\r\n\t\t\t\ttransform: isExiting\r\n\t\t\t\t\t? 'translateX(-100%)'\r\n\t\t\t\t\t: isEntering\r\n\t\t\t\t\t\t? 'translateX(100%)'\r\n\t\t\t\t\t\t: 'translateX(0)',\r\n\t\t\t\topacity: isExiting ? 0 : isEntering ? 0 : 1,\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn {}\r\n\t}\r\n\r\n\treturn (\r\n\t\t<div className={getClassName()} style={getDefaultStyles()}>\r\n\t\t\t{displayChildren}\r\n\t\t</div>\r\n\t)\r\n}\r\n","import {\r\n\tbasePath as configBasePath,\r\n\tglobalNotFound,\r\n\tmanifest,\r\n} from 'virtual:routes'\r\nimport { RouterLayout } from './router-layout'\r\nimport type { RouterProviderProps } from './types/types'\r\n\r\nexport default function RouterProvider({\r\n\tchildren,\r\n\tpreloader,\r\n\tbasePath,\r\n\tenableTransitions,\r\n\ttransitionConfig,\r\n}: Readonly<RouterProviderProps>) {\r\n\t// Используем basePath из пропсов, если указан, иначе из конфигурации\r\n\tconst finalBasePath = basePath ?? configBasePath ?? '/'\r\n\t\r\n\treturn (\r\n\t\t<RouterLayout\r\n\t\t\tmanifest={manifest}\r\n\t\t\tpreloader={preloader}\r\n\t\t\tbasePath={finalBasePath}\r\n\t\t\tglobalNotFound={globalNotFound}\r\n\t\t\tenableTransitions={enableTransitions}\r\n\t\t\ttransitionConfig={transitionConfig}\r\n\t\t>\r\n\t\t\t{children}\r\n\t\t</RouterLayout>\r\n\t)\r\n}\r\n","import React from 'react'\r\nimport { BrowserRouter, Routes } from 'react-router-dom'\r\nimport { RouteTransition } from './route-transition'\r\nimport { renderManifestAsRoutes } from './router-utils'\r\nimport type { RouterLayoutProps } from './types/types'\r\n\r\nexport const RouterLayout = ({\r\n\tmanifest,\r\n\tchildren,\r\n\tpreloader,\r\n\tbasePath = '/',\r\n\tglobalNotFound,\r\n\tenableTransitions = false,\r\n\ttransitionConfig,\r\n}: RouterLayoutProps) => {\r\n\tconst routes = renderManifestAsRoutes(manifest, globalNotFound)\r\n\tconst routesElement = <Routes>{routes}</Routes>\r\n\r\n\treturn (\r\n\t\t<BrowserRouter basename={basePath}>\r\n\t\t\t<React.Suspense fallback={children || preloader || <div>Loading...</div>}>\r\n\t\t\t\t{enableTransitions ? (\r\n\t\t\t\t\t<RouteTransition {...transitionConfig}>{routesElement}</RouteTransition>\r\n\t\t\t\t) : (\r\n\t\t\t\t\troutesElement\r\n\t\t\t\t)}\r\n\t\t\t</React.Suspense>\r\n\t\t</BrowserRouter>\r\n\t)\r\n}\r\n","import React from 'react'\r\nimport { Route } from 'react-router-dom'\r\nimport { ErrorBoundary } from './error-boundary'\r\nimport type { Node } from './types/types'\r\n\r\nfunction wrapLayouts(\r\n\tlayouts: Node['layouts'] | undefined,\r\n\tpageEl: React.ReactNode\r\n) {\r\n\tif (!layouts || layouts.length === 0) return pageEl\r\n\r\n\treturn layouts.reduceRight((child, loader) => {\r\n\t\tconst Layout = React.lazy(async () => {\r\n\t\t\tconst module = await loader()\r\n\t\t\t// Поддерживаем как default, так и именованный экспорт Layout\r\n\t\t\treturn 'default' in module ? module : { default: module.Layout }\r\n\t\t})\r\n\t\treturn <Layout>{child}</Layout>\r\n\t}, pageEl as React.ReactElement)\r\n}\r\n\r\nfunction createLoadingFallback(loadingLoader?: () => Promise<{ default: React.ComponentType }>) {\r\n\tif (!loadingLoader) return undefined\r\n\t\r\n\t// Loading компонент lazy, но он используется как fallback в Suspense\r\n\tconst Loading = React.lazy(loadingLoader)\r\n\treturn <Loading />\r\n}\r\n\r\nfunction createErrorFallback(errorLoader?: () => Promise<{ default: React.ComponentType<{ error?: Error; resetError?: () => void }> }>) {\r\n\tif (!errorLoader) return undefined\r\n\t\r\n\tconst ErrorComponent = React.lazy(errorLoader)\r\n\treturn (props: { error?: Error; resetError?: () => void }) => <ErrorComponent {...props} />\r\n}\r\n\r\nexport const renderManifestAsRoutes = (\r\n\tmanifest: Node[],\r\n\tglobalNotFound?: () => Promise<{ default: React.ComponentType }>\r\n) => {\r\n\treturn manifest.map(n => {\r\n\t\tconst Page = React.lazy(async () => {\r\n\t\t\tconst module = await n.loader()\r\n\r\n\t\t\t// Если есть default экспорт, используем его\r\n\t\t\tif (\r\n\t\t\t\tmodule &&\r\n\t\t\t\ttypeof module === 'object' &&\r\n\t\t\t\t'default' in module &&\r\n\t\t\t\tmodule.default\r\n\t\t\t) {\r\n\t\t\t\treturn module as { default: React.ComponentType }\r\n\t\t\t}\r\n\r\n\t\t\t// Ищем любой именованный экспорт, который является функцией или компонентом\r\n\t\t\tif (module && typeof module === 'object') {\r\n\t\t\t\tconst namedExports = Object.keys(module).filter(\r\n\t\t\t\t\tkey => key !== 'default'\r\n\t\t\t\t)\r\n\t\t\t\tfor (const key of namedExports) {\r\n\t\t\t\t\tconst exportValue = module[key]\r\n\t\t\t\t\tif (\r\n\t\t\t\t\t\ttypeof exportValue === 'function' ||\r\n\t\t\t\t\t\t(typeof exportValue === 'object' && exportValue !== null)\r\n\t\t\t\t\t) {\r\n\t\t\t\t\t\treturn {\r\n\t\t\t\t\t\t\tdefault: exportValue as React.ComponentType,\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Если ничего не найдено, возвращаем ошибку\r\n\t\t\tconst availableExports =\r\n\t\t\t\tmodule && typeof module === 'object'\r\n\t\t\t\t\t? Object.keys(module).join(', ')\r\n\t\t\t\t\t: 'unknown'\r\n\t\t\tthrow new Error(\r\n\t\t\t\t`No valid export found in module for route ${n.path}. Available exports: ${availableExports}`\r\n\t\t\t)\r\n\t\t})\r\n\r\n\t\tconst loadingFallback = createLoadingFallback(n.loading)\r\n\t\tconst errorFallback = createErrorFallback(n.error)\r\n\t\t\r\n\t\tconst pageElement = wrapLayouts(n.layouts, <Page />)\r\n\t\t\r\n\t\t// Оборачиваем в ErrorBoundary если есть error компонент\r\n\t\tconst wrappedElement = errorFallback ? (\r\n\t\t\t<ErrorBoundary fallback={errorFallback}>\r\n\t\t\t\t{pageElement}\r\n\t\t\t</ErrorBoundary>\r\n\t\t) : pageElement\r\n\r\n\t\t// Оборачиваем в Suspense с loading fallback\r\n\t\tconst element = loadingFallback ? (\r\n\t\t\t<React.Suspense fallback={loadingFallback}>\r\n\t\t\t\t{wrappedElement}\r\n\t\t\t</React.Suspense>\r\n\t\t) : (\r\n\t\t\t<React.Suspense fallback={<div>Loading...</div>}>\r\n\t\t\t\t{wrappedElement}\r\n\t\t\t</React.Suspense>\r\n\t\t)\r\n\r\n\t\treturn <Route key={n.id} path={n.path} element={element} />\r\n\t}).concat(\r\n\t\t// Добавляем 404 маршрут в конец\r\n\t\tglobalNotFound ? (\r\n\t\t\t<Route\r\n\t\t\t\tkey=\"__not_found__\"\r\n\t\t\t\tpath=\"*\"\r\n\t\t\t\telement={\r\n\t\t\t\t\t<React.Suspense fallback={<div>Loading...</div>}>\r\n\t\t\t\t\t\t{(() => {\r\n\t\t\t\t\t\t\tconst NotFound = React.lazy(globalNotFound)\r\n\t\t\t\t\t\t\treturn <NotFound />\r\n\t\t\t\t\t\t})()}\r\n\t\t\t\t\t</React.Suspense>\r\n\t\t\t\t}\r\n\t\t\t/>\r\n\t\t) : (\r\n\t\t\t<Route\r\n\t\t\t\tkey=\"__not_found__\"\r\n\t\t\t\tpath=\"*\"\r\n\t\t\t\telement={\r\n\t\t\t\t\t<div style={{ padding: '20px', textAlign: 'center' }}>\r\n\t\t\t\t\t\t<h1>404</h1>\r\n\t\t\t\t\t\t<p>Page not found</p>\r\n\t\t\t\t\t</div>\r\n\t\t\t\t}\r\n\t\t\t/>\r\n\t\t)\r\n\t)\r\n}\r\n","import React from 'react'\r\n\r\nexport interface ErrorBoundaryProps {\r\n\tchildren: React.ReactNode\r\n\tfallback?: React.ComponentType<{ error?: Error; resetError?: () => void }>\r\n\tonError?: (error: Error, errorInfo: React.ErrorInfo) => void\r\n}\r\n\r\ninterface ErrorBoundaryState {\r\n\thasError: boolean\r\n\terror: Error | null\r\n}\r\n\r\n/**\r\n * ErrorBoundary компонент для обработки ошибок рендеринга\r\n */\r\nexport class ErrorBoundary extends React.Component<\r\n\tErrorBoundaryProps,\r\n\tErrorBoundaryState\r\n> {\r\n\tconstructor(props: ErrorBoundaryProps) {\r\n\t\tsuper(props)\r\n\t\tthis.state = { hasError: false, error: null }\r\n\t}\r\n\r\n\tstatic getDerivedStateFromError(error: Error): ErrorBoundaryState {\r\n\t\treturn { hasError: true, error }\r\n\t}\r\n\r\n\tcomponentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\r\n\t\tthis.props.onError?.(error, errorInfo)\r\n\t}\r\n\r\n\tresetError = () => {\r\n\t\tthis.setState({ hasError: false, error: null })\r\n\t}\r\n\r\n\trender() {\r\n\t\tif (this.state.hasError && this.state.error) {\r\n\t\t\tif (this.props.fallback) {\r\n\t\t\t\tconst Fallback = this.props.fallback\r\n\t\t\t\treturn <Fallback error={this.state.error} resetError={this.resetError} />\r\n\t\t\t}\r\n\t\t\treturn (\r\n\t\t\t\t<div style={{ padding: '20px' }}>\r\n\t\t\t\t\t<h2>Something went wrong</h2>\r\n\t\t\t\t\t<pre>{this.state.error.message}</pre>\r\n\t\t\t\t\t<button onClick={this.resetError}>Try again</button>\r\n\t\t\t\t</div>\r\n\t\t\t)\r\n\t\t}\r\n\r\n\t\treturn this.props.children\r\n\t}\r\n}\r\n","import { useNavigate as useRouterNavigate } from 'react-router-dom'\r\n\r\nexport type NavigateOptions = {\r\n\treplace?: boolean\r\n\tstate?: unknown\r\n\trelative?: 'route' | 'path'\r\n}\r\n\r\nexport type To = string | number | { pathname?: string; search?: string; hash?: string }\r\n\r\n/**\r\n * Хук для программной навигации\r\n * \r\n * @returns Функция для навигации\r\n * \r\n * @example\r\n * ```tsx\r\n * const navigate = useNavigate()\r\n * navigate('/about')\r\n * navigate('/users', { replace: true })\r\n * navigate(-1) // назад\r\n * ```\r\n */\r\nexport function useNavigate() {\r\n\treturn useRouterNavigate()\r\n}\r\n","import { useParams as useRouterParams } from 'react-router-dom'\r\n\r\nexport type Params = Record<string, string | undefined>\r\n\r\n/**\r\n * Хук для получения параметров маршрута\r\n * \r\n * @returns Объект с параметрами текущего маршрута\r\n * \r\n * @example\r\n * ```tsx\r\n * // Для маршрута /users/:id\r\n * const { id } = useParams()\r\n * ```\r\n */\r\nexport function useParams<T extends Params = Params>(): T {\r\n\treturn useRouterParams() as T\r\n}\r\n","import { useSearchParams as useRouterSearchParams } from 'react-router-dom'\r\n\r\n/**\r\n * Хук для работы с query параметрами URL\r\n * \r\n * @returns Кортеж из [searchParams, setSearchParams]\r\n * \r\n * @example\r\n * ```tsx\r\n * const [searchParams, setSearchParams] = useSearchParams()\r\n * const id = searchParams.get('id')\r\n * setSearchParams({ id: '123' })\r\n * ```\r\n */\r\nexport function useSearchParams() {\r\n\treturn useRouterSearchParams()\r\n}\r\n"],"mappings":"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","names":["React","React","React","jsx","jsx","jsxs","React","manifest","globalNotFound","jsx","manifest","globalNotFound","React","jsx"]}
|