From 4d969249e58dc4292edb688ea05b57d5b29ce219 Mon Sep 17 00:00:00 2001 From: Jakob Rosenberg Date: Wed, 24 Jan 2024 20:32:58 +0100 Subject: [PATCH] feat: support nodes as input on $goto, $url and $isActive --- lib/runtime/helpers/index.js | 43 ++++++++++++++++---------- typings/lib/runtime/helpers/index.d.ts | 14 ++++----- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/lib/runtime/helpers/index.js b/lib/runtime/helpers/index.js index a3f558d9..92c1dbd3 100644 --- a/lib/runtime/helpers/index.js +++ b/lib/runtime/helpers/index.js @@ -37,20 +37,28 @@ export const getPath = (node1, node2) => { /** * @callback Goto - * @param {string} path relative, absolute or named URL + * @param {string|RNodeRuntime} pathOrNode relative, absolute or named URL * @param {Object.=} userParams * @param {Partial<$UrlOptions & RouteState>=} options * @type {Readable} */ export const goto = { subscribe: (run, invalidate) => { const { router } = contexts - return derived(url, $url => (path, userParams, options) => { - const defaults = { mode: 'push', state: {} } - options = { ...defaults, ...options } - const newUrl = $url(path, userParams, options) - router.url[options.mode](newUrl, options.state) - return '' - }).subscribe(run, invalidate) + + return derived(url, $url => + /** @type {Goto} */ + (pathOrNode, userParams, options) => { + const path = + typeof pathOrNode === 'string' ? pathOrNode : pathOrNode?.path + + /** @type {options} */ + const defaults = { mode: 'push', state: {} } + options = { ...defaults, ...options } + const newUrl = $url(path, userParams, options) + router.url[options.mode](newUrl, options.state) + return '' + }, + ).subscribe(run, invalidate) }, } @@ -90,7 +98,7 @@ export const goto = { /** * @typedef {(( - * inputPath: string, + * pathOrNode: string|RNodeRuntime, * userParams?: { [x: string]: string; }, * options?: Partial<$UrlOptions> * ) => string)} UrlFromString @@ -150,7 +158,8 @@ export const url = { export const createUrl = (fragment, router) => /** @type {UrlFromString} */ - (_inputPath, userParams = {}, options = {}) => { + (pathOrNode, userParams = {}, options = {}) => { + let _inputPath = typeof pathOrNode === 'string' ? pathOrNode : pathOrNode?.path const route = fragment.route // in case we swapped the routes tree (rootNode), make sure we find @@ -217,7 +226,7 @@ export const params = { /** * @callback IsActive - * @param {String=} path + * @param {String|RNodeRuntime=} pathOrNode * @param {Object.} [params] * @param {IsActiveOptions} [options] * @returns {Boolean} @@ -317,7 +326,9 @@ export const isActiveUrl = renderContext => { const { router, fragment } = renderContext /** @type {IsActive} */ - return (path, params = {}, options = {}) => { + return (pathOrNode, params = {}, options = {}) => { + let _path = typeof pathOrNode === 'string' ? pathOrNode : pathOrNode?.path + /** * @type {{recursive: boolean, silent: TraverseOptions['silent']}} */ @@ -326,7 +337,7 @@ export const isActiveUrl = renderContext => { // if we're using a custom rootNode, we need to strip it from the path if (router.rootNode.path !== '/') - path = path.substring(router.rootNode.path.length) + _path = _path.substring(router.rootNode.path.length) /** * @type {TraverseOptions} @@ -343,9 +354,9 @@ export const isActiveUrl = renderContext => { ) if (!allWantedParamsAreInActiveChain) return false - const wantedNode = path.startsWith('.') - ? fragment.node.traverse(path, chainOptions) - : router.rootNode.getChainTo(path, chainOptions).pop().node + const wantedNode = _path.startsWith('.') + ? fragment.node.traverse(_path, chainOptions) + : router.rootNode.getChainTo(_path, chainOptions).pop().node const actNodes = [...route.fragments.map(fragment => fragment.node)] diff --git a/typings/lib/runtime/helpers/index.d.ts b/typings/lib/runtime/helpers/index.d.ts index caee6e65..33a13724 100644 --- a/typings/lib/runtime/helpers/index.d.ts +++ b/typings/lib/runtime/helpers/index.d.ts @@ -11,7 +11,7 @@ export function getMRCA(node1: RNodeRuntime, node2: RNodeRuntime): { export function getPath(node1: any, node2: any): string; /** * @callback Goto - * @param {string} path relative, absolute or named URL + * @param {string|RNodeRuntime} pathOrNode relative, absolute or named URL * @param {Object.=} userParams * @param {Partial<$UrlOptions & RouteState>=} options * @type {Readable} */ @@ -47,7 +47,7 @@ export const goto: Readable; */ /** * @typedef {(( - * inputPath: string, + * pathOrNode: string|RNodeRuntime, * userParams?: { [x: string]: string; }, * options?: Partial<$UrlOptions> * ) => string)} UrlFromString @@ -69,7 +69,7 @@ export const params: Readable<{ }>; /** * @callback IsActive - * @param {String=} path + * @param {String|RNodeRuntime=} pathOrNode * @param {Object.} [params] * @param {IsActiveOptions} [options] * @returns {Boolean} @@ -79,7 +79,7 @@ export const isActive: Readable; export namespace isActiveFragment { function subscribe(run: any, invalidate: any): import("svelte/store").Unsubscriber; } -export function isActiveUrl(renderContext: RenderContext): (path: string, params?: { +export function isActiveUrl(renderContext: RenderContext): (pathOrNode: string | import("../Instance/RNodeRuntime.js").RNodeRuntime, params?: { [x: string]: string; }, options?: IsActiveOptions) => boolean; export function resolveNode(path: string): import("../Instance/RNodeRuntime.js").RNodeRuntime; @@ -108,7 +108,7 @@ export const beforeUrlChange: Readable<(arg0: BeforeUrlChangeCallback) => any>; * @type {getDirectionCB & Readable>} */ export const getDirection: getDirectionCB & Readable>; -export type Goto = (path: string, userParams?: { +export type Goto = (pathOrNode: string | RNodeRuntime, userParams?: { [x: string]: string; } | undefined, options?: Partial<$UrlOptions & RouteState> | undefined) => any; export type Readable = import('svelte/store').Readable; @@ -144,10 +144,10 @@ export type RouteState = { export type Url = (inputPath: T, userParams?: { [x: string]: string; }, options?: Partial<$UrlOptions>) => T extends HTMLAnchorElement ? void : string; -export type UrlFromString = (inputPath: string, userParams?: { +export type UrlFromString = (pathOrNode: string | RNodeRuntime, userParams?: { [x: string]: string; }, options?: Partial<$UrlOptions>) => string; -export type IsActive = (path?: string | undefined, params?: { +export type IsActive = (pathOrNode?: (string | RNodeRuntime) | undefined, params?: { [x: string]: string; }, options?: IsActiveOptions) => boolean; export type getDirectionCB = (boundary?: RNodeRuntime | undefined, newRoute?: Route | undefined, oldRoute?: Route | undefined) => 'first' | 'last' | 'same' | 'next' | 'prev' | 'higher' | 'lower' | 'na';