import { type LogLevel } from '../Logger'; import { type ISearchParamsParser, JSONSearchParamsParser } from '../SearchParamsParser'; import { SearchParamsStore, type SearchParamsStoreInitOptions } from '../SearchParamsStore'; import { type BlockerFunction, type IBlocker, type IRouterProvider, type Location, type MatchPath, type Navigate, type NavigateAsync, type ParsedSearchParams, type RawRouteParams, type RouteConfig, type RouteCreator, type RouteCreatorParams, type SetSearchParams, type SubscribeRouteChange } from '../types'; import { Route } from './Route'; type Params = { /** * Устанавливает уровень логирования * Для отключения логирования установите 'silent' * @default 'error' */ logLevel?: LogLevel; /** * Позволяет задать кастомный search params parser. * Должен реализовывать интерфейс ISearchParamsParser */ searchParamsParser?: TSearchParamsParser; /** * Позволяет задать базовый путь для маршрутов. */ baseName?: string; }; type Routes = Record> = { [TRouteName in keyof TRoutes]: ReturnType; }; export declare class Router = Record, TSearchParamsParser extends ISearchParamsParser = JSONSearchParamsParser> { private readonly _provider; /** * Объект, содержащий все маршруты приложения. * Ключ соответствует имени маршрута. * Routes позволяет навигировать, сохраняя типобезопасность для конкретного route * @example * ```ts * router.routes.request.navigate({ orgId }); * router.routes.request.isActive; * ``` */ readonly routes: Routes; /** * Исключительно для внутреннего использования. * Сделан публичным чтобы в defineRoute можно было получить доступ к parser */ readonly _searchParamsParser: TSearchParamsParser; /** * Хранит снепшоты переходов. Каждый снепшот содержит данные о маршруте, на который происходит переход или был произведен переход. * Причина использования: новый компонент при переходе должен получать сразу свежие данные, при этом старый компонент не должен перерендериться, пока переход не завершится. * В in-progress фазе старый компонент подписан на старый snapshot, а новый компонент подписывается сразу на новый. После завершения перехода старый компонент подписывается на новый snapshot (смотрите на getter activeSnapshot). * Последний snapshot соответствует текущему активному маршруту или маршруту, на который происходит переход в данный момент. * Перевод в completed фазу происходит только после того, как произошел рендер нового маршрута. * navigationStack после успешного перехода уменьшается до одного элемента - последний актуальный переход. */ private navigationStack; /** * Текущая фаза навигации. * - 'in-progress': Переход начался, новый маршрут еще не rendered React. * В этой фазе создается inProgressSnapshot и геттеры возвращают данные из него. * - 'completed': Переход завершен, произошел render React с новым маршрутом. * В этой фазе inProgressSnapshot очищается, currentSnapshot обновляется, * и геттеры возвращают данные из currentSnapshot. */ private navigationPhase; /** * Количество синхронных вызовов setSearchParams до применения изменений в provider * Позволяет делать batch синхронизаций с provider, чтобы не было изменения react state в момент рендера */ private searchParamsSetterBatchingCount; private readonly preInitOperations; private readonly logger; private readonly baseName?; constructor(_provider: IRouterProvider, routes: TRoutes, params?: Params); /** * Является observable */ get location(): Location; /** * Содержит сырые параметры пути. Используйте routes.routeName.params для получения типобезопасных данных * Является observable * @example * ```ts * // /user/:id -> /user/123 * router.routeParams.id; // '123' * router.routeParams.name; // undefined * ``` */ get routeParams(): RawRouteParams; /** * Содержит объект, полученный при парсинге URLSearchParams. Поддерживает все примитивы, массивы и plain objects. Если не удалось распарсить значение, то оно записывается как строка. * Используйте router.createSearchParamsStore для работы с типобезопасными данными * Является observable. * @example * ```ts * router.searchParams.test; // '1' * router.searchParams.array; // [1, 2, 3] * router.searchParams.object; // { a: 1, b: 2, c: 3 } * ``` */ get searchParams(): ParsedSearchParams; /** * Возвращает активный снепшот навигации. * Не является computed. * Механизм работы: новый подписчик в фазе in-progress получает сразу свежий snapshot. * При этом старый подписчик не получит изменений, пока не произойдет переход в completed фазу. * Так как activeNavigationSnapshot не computed, то подписчики при обращении подписываются на observable объект, реакция произойдет только после перехода - смотрите метод syncNavigationStack * Для полного понимания работы механизма читайте комментарий к navigationStack. */ private get activeNavigationSnapshot(); /** * Позволяет делать переходы между рутами приложения * @example * ```ts * router.navigate('/main'); * router.navigate({ pathname: '/main', search: '?test=1' }, { replace: true }) * ``` */ navigate: Navigate; /** * Асинхронный переход между рутами приложения. * * @example * ```ts * // Переход по строковому пути * await router.navigateAsync('/main'); * * // Переход с объектом Location и опциями * await router.navigateAsync( * { pathname: '/main', search: '?test=1' }, * { replace: true } * ); * ``` * * @param to - Путь для навигации (строка или объект Location). * @param options - Опции навигации, включая `replace` и `searchParams`. * @returns PromiseLike - Promise, который резолвится после завершения навигации. */ navigateAsync: NavigateAsync; /** * Подписывается на событие начала изменения маршрута (до фактического перехода). * * Вызывается сразу после инициирования навигации, до активации нового маршрута. * * @param handler Обработчик. Вызывается с `Location` целевого (следующего) маршрута. * @returns Функция для отписки от события. * * @example * // Подписка на начало навигации * const unsubscribe = router.subscribeRouteChangeStart((location) => { * console.log('Переходим на', location.pathname); * }); * * // Отписываемся * unsubscribe(); */ subscribeRouteChangeStart: SubscribeRouteChange; /** * Подписывается на событие окончания изменения маршрута (после успешного перехода и рендера). * * Считается окончанием, когда навигация завершена и произошёл успешный ререндер * нового маршрута. * * @param handler Обработчик. Вызывается с `Location` активного (текущего) маршрута. * @returns Функция для отписки от события. * * @example * // Подписка на окончание навигации * const unsubscribe = router.subscribeRouteChangeEnd((location) => { * console.log('Уже на', location.pathname); * }); * * // Отписываемся * unsubscribe(); */ subscribeRouteChangeEnd: SubscribeRouteChange; /** * Возврат на предыдущий URL в истории */ back: () => void; /** * Перезагружает текущую страницу */ reload: () => void; /** * Позволяет изменять searchParams * Работает с данными в виде объекта. Используйте router.createSearchParamsStore для работы с типобезопасными данными * @example * ```ts * router.setSearchParams({ page: 1 }); * * // Изменение с доступом к предыдущим параметрам * router.setSearchParams(({ page }) => { page: ++page }); * ``` */ setSearchParams: SetSearchParams>; /** * Создает SearchParamsStore для работы с типобезопасными данными * @example * ```ts * const store = router.createSearchParamsStore<{ id: string; page?: number }>(); * * store.set('id', '123'); * store.set('page', 1); * * store.values; // { id: '123', page: 1 } * ``` */ createSearchParamsStore: >(options: SearchParamsStoreInitOptions) => SearchParamsStore; /** * Создает новый экземпляр Blocker для управления блокировкой переходов между маршрутами. * @example * ```ts * const blocker = router.createBlocker(({ nextLocation }) => { * if( nextLocation === '/' ) { * return true; * } * return false * }); * * blocker.isBlocked; // Состояние блокера * * blocker.proceed(); * * blocker.reset(); * ``` */ createBlocker: (shouldBlock: BlockerFunction) => IBlocker; /** * Сопоставляет паттерн маршрута с URL pathname. * Возвращает информацию о совпадении или null, если совпадения нет. * isExact=true по-дефолту * * @param pattern - Паттерн маршрута (строка или объект MatchPathPattern) * @param path - URL pathname для сопоставления * @returns Информация о совпадении или null * * @example * ```typescript * const match = matchPath('/user/:id', '/user/123'); * // Результат: { params: { id: '123' }, pathname: '/user/123', ... } * ``` */ matchPath: MatchPath; private calculateRouteParams; private initNavigationStack; private initRoutes; /** * Синхронизирует состояние Router с provider. * Для понимания работы механизма читайте комментарий к navigationStack и activeNavigationSnapshot */ private syncNavigationStack; private processInProgressPhase; private processCompletedPhase; /** * Позволяет определить маршрут с типизированными параметрами и функциями генерации пути. * * @param config - Конфигурация маршрута * @param config.pattern - Паттерн URL маршрута (например, '/user/:id' или '/home'). Соответствует pattern используемого роутера * @param config.generatePath - Функция для генерации пути на основе параметров * * @throws {Error} Если generatePath принимает более одного параметра * * @example * ```ts * new Router(provider, { * home: Router.defineRoute({ * pattern: '/home', * generatePath: () => ({ path: '/home' }) * }), * user: Router.defineRoute({ * pattern: '/user/:id', * generatePath: (params: { id: string }) => ({ * path: `/user/${params.id}` * }) * }), * }); * ``` */ static defineRoute: (config: RouteConfig) => (router: RouteCreatorParams) => Route>; } export {};