{"version":3,"file":"ngxtension-linked-query-param.mjs","sources":["../../../../libs/ngxtension/linked-query-param/src/linked-query-param.ts","../../../../libs/ngxtension/linked-query-param/src/ngxtension-linked-query-param.ts"],"sourcesContent":["import {\n\tcomputed,\n\teffect,\n\tinject,\n\tInjectable,\n\tInjectionToken,\n\tInjector,\n\tisSignal,\n\tlinkedSignal,\n\tProvider,\n\trunInInjectionContext,\n\tSignal,\n\tuntracked,\n\tValueEqualityFn,\n\tWritableSignal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport {\n\tActivatedRoute,\n\tNavigationExtras,\n\tParams,\n\tRouter,\n} from '@angular/router';\nimport { assertInjector } from 'ngxtension/assert-injector';\nimport { createNotifier } from 'ngxtension/create-notifier';\n\nimport { computedPrevious } from 'ngxtension/computed-previous';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { distinctUntilKeyChanged, map } from 'rxjs';\n\n/**\n * The type of the stringified value.\n * After transforming the value before it is passed to the query param, this type will be used.\n */\ntype StringifyReturnType = string | number | boolean | null | undefined;\n\ntype QueryParamKeyType =\n\t| string\n\t| Signal<string | undefined>\n\t| (() => string | undefined);\n\n/**\n * These are the options that can be passed to the `linkedQueryParam` function.\n * They are taken from the `NavigationExtras` type in the `@angular/router` package.\n */\ntype NavigateMethodFields = Pick<\n\tNavigationExtras,\n\t| 'queryParamsHandling'\n\t| 'onSameUrlNavigation'\n\t| 'replaceUrl'\n\t| 'skipLocationChange'\n\t| 'preserveFragment'\n>;\n\nconst defaultConfig: Partial<NavigateMethodFields> &\n\tLinkedQueryParamOptions<string> = {\n\tqueryParamsHandling: 'merge',\n\tautomaticallySynchronizeOnKeyChange: true,\n};\n\nconst _LINKED_QUERY_PARAM_CONFIG_TOKEN = new InjectionToken<\n\tPartial<NavigateMethodFields> &\n\t\tExclude<LinkedQueryParamOptions<string>, 'injector' | 'equal' | 'source'>\n>('LinkedQueryParamConfig', {\n\tprovidedIn: 'root',\n\tfactory: () => defaultConfig,\n});\n\n/*\n * This function allows users to override the default behavior of the `linkedQueryParam` navigation extras per component.\n *\n * @example\n * ```ts\n * @Component({\n *   providers: [\n *     provideLinkedQueryParamConfig({ preserveFragment: true })\n *   ]\n * })\n * export class MyComponent {\n *   // No matter which query param changes, the `preserveFragment` option\n *   // will be set to `true` for all the `linkedQueryParam` functions in this component.\n *   readonly searchQuery = linkedQueryParam('searchQuery');\n *   readonly page = linkedQueryParam('page');\n * }\n * ```\n *\n * As always, you can override this behavior on a per-function basis by passing the navigation extras to the `linkedQueryParam` function.\n *\n */\nexport function provideLinkedQueryParamConfig(\n\tconfig: Partial<NavigateMethodFields> &\n\t\tExclude<LinkedQueryParamOptions<string>, 'injector' | 'equal' | 'source'>,\n): Provider {\n\treturn {\n\t\tprovide: _LINKED_QUERY_PARAM_CONFIG_TOKEN,\n\t\tuseValue: { ...defaultConfig, ...config },\n\t};\n}\n\n/**\n * Service to coalesce multiple navigation calls into a single navigation event.\n */\n@Injectable({ providedIn: 'root' })\nexport class LinkedQueryParamGlobalHandler {\n\tprivate _router = inject(Router);\n\t/**\n\t * @internal\n\t * The current query params that will be set on the next navigation event.\n\t */\n\tprivate _currentKeys: Record<string, StringifyReturnType> = {};\n\t/**\n\t * @internal\n\t * The navigation extras that will be used on the next navigation event.\n\t */\n\tprivate _navigationExtras: NavigationExtras = {};\n\t/**\n\t * @internal\n\t * The notifier that will be used to schedule the navigation event.\n\t */\n\tprivate _schedulerNotifier = createNotifier();\n\n\tconstructor() {\n\t\teffect(() => {\n\t\t\t// listen to the scheduler notifier to schedule the navigation event\n\t\t\t// we wrap the listen in a condition (listen() default value is 0) in order to not schedule\n\t\t\t// the first navigation event by default, because only changes should trigger it\n\t\t\tif (this._schedulerNotifier.listen()) {\n\t\t\t\t// we need to untrack the navigation call in order to not register any other signal as a dependency\n\t\t\t\tuntracked(() => void this.navigate());\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Schedules the navigation event.\n\t */\n\tscheduleNavigation() {\n\t\tthis._schedulerNotifier.notify();\n\t}\n\n\t/**\n\t * Sets the value of a query param.\n\t * This will be used on the next navigation event.\n\t */\n\tsetParamKeyValue(key: string, value: StringifyReturnType) {\n\t\tthis._currentKeys[key] = value;\n\t}\n\n\t/**\n\t * Sets the navigation extras that will be used on the next navigation event.\n\t */\n\tsetCurrentNavigationExtras(config: Partial<NavigateMethodFields> = {}) {\n\t\tconst {\n\t\t\tqueryParamsHandling,\n\t\t\tonSameUrlNavigation,\n\t\t\treplaceUrl,\n\t\t\tskipLocationChange,\n\t\t\tpreserveFragment,\n\t\t} = config;\n\t\tif (queryParamsHandling || queryParamsHandling === '') {\n\t\t\tthis._navigationExtras.queryParamsHandling = queryParamsHandling;\n\t\t}\n\t\tif (onSameUrlNavigation) {\n\t\t\tthis._navigationExtras.onSameUrlNavigation = onSameUrlNavigation;\n\t\t}\n\t\tif (replaceUrl) {\n\t\t\tthis._navigationExtras.replaceUrl = replaceUrl;\n\t\t}\n\t\tif (skipLocationChange) {\n\t\t\tthis._navigationExtras.skipLocationChange = skipLocationChange;\n\t\t}\n\t\tif (preserveFragment) {\n\t\t\tthis._navigationExtras.preserveFragment = preserveFragment;\n\t\t}\n\t}\n\n\t/**\n\t * Navigates to the current URL with the accumulated query parameters and navigation extras.\n\t * Cleans up the current keys and navigation extras after the navigation.\n\t */\n\tprivate navigate(): Promise<boolean> {\n\t\treturn this._router\n\t\t\t.navigate([], {\n\t\t\t\tqueryParams: this._currentKeys,\n\t\t\t\t...this._navigationExtras, // override the navigation extras\n\t\t\t})\n\t\t\t.then((value) => {\n\t\t\t\t// we reset the current keys and navigation extras on navigation\n\t\t\t\t// in order to avoid leaking to other navigations\n\t\t\t\tthis._currentKeys = {};\n\t\t\t\tthis._navigationExtras = {};\n\t\t\t\treturn value;\n\t\t\t});\n\t}\n}\n\ntype LinkedQueryParamOptions<T> = {\n\t/**\n\t * The injector to use to inject the router and activated route.\n\t */\n\tinjector?: Injector;\n\n\t/**\n\t * A comparison function which defines equality for signal values.\n\t */\n\tequal?: ValueEqualityFn<T>;\n\n\t/**\n\t * The source signal to use to update the query param when it changes (two-way binding between this source and the query param).\n\t * @experimental\n\t */\n\tsource?: WritableSignal<T>;\n\n\t/**\n\t * Controls whether the query param value should be synchronized with the source signal when the key changes.\n\t * When true, if the key changes (e.g. from 'key1' to 'key2'), the value from the source signal will be used to set the new query param.\n\t * When false, the new query param will be initialized as null/undefined when the key changes.\n\t * Default is true.\n\t *\n\t * This is useful when you want to preserve the source signal's value across key changes, rather than resetting the query param.\n\t * @experimental\n\t */\n\tautomaticallySynchronizeOnKeyChange?: boolean;\n} & Partial<NavigateMethodFields>;\n\n/**\n * These are the function types that will be used to parse and stringify the query param value.\n */\ntype ParseFn<T> = (value: string | null) => T;\ntype StringifyFn<T> = (value: T) => StringifyReturnType;\n\n/**\n *These types will be used to define the return types of the `set` and `update` methods of the signal.\n * We need to re-type the WritableSignal, so that the set and update methods can have null in the call signature.\n * But the WritableSignal itself won't have null in the call signature, so we need to re-type it.\n * This is needed in order to be able to reset the value to null,\n * which is not possible with the WritableSignal that doesn't have null in it's type.\n */\ntype SignalSetFn<T> = (value: T) => void;\ntype SignalUpdateFn<T> = (fn: (value: T) => T) => void;\n\n/**\n * Creates a signal that is linked to a query parameter.\n *\n * You can parse the query param value before it is passed to the signal, this way you can transform the value from a string to a number or boolean or whatever you need.\n * You can also stringify the value before it is passed to the query param, this way you can stringify the value from a number or boolean or object to a string or null.\n *\n * You can also use the `defaultValue` option to set a default value if the query param is not present in the url (null or undefined).\n * NOTE: You cannot use both `defaultValue` and `parse` at the same time. You should use `parse` instead to handle the default value.\n *\n * You can set the signal to update the query parameter by calling the `set` or `update` method.\n * Both methods will accept the value + null as a valid value, so you can remove the query parameter by passing null if needed.\n *\n * The 'set' and 'update' methods will update the value synchronously, but will schedule the navigation event to\n * happen on the next tick (using root effect scheduling). This means the query params will be updated asynchronously.\n * The changes will be coalesced into a single navigation event. This means that if you call `set` or `update` multiple times\n * in a row (synchronously), only the last value will be updated in the query params.\n *\n * If you have multiple signals listening to the same query parameter, they will all be updated when the navigation event happens.\n *\n * @param key The name of the query parameter.\n * @param options Configuration options for the signal.\n * @returns A signal that is linked to the query parameter.\n */\nexport function linkedQueryParam<T = string>(\n\tkey: QueryParamKeyType,\n\toptions: LinkedQueryParamOptions<T> & {\n\t\tparse: ParseFn<T>;\n\t\tstringify: StringifyFn<T>;\n\t},\n): WritableSignal<T> & {\n\tset: SignalSetFn<T | null>;\n\tupdate: SignalUpdateFn<T | null>;\n};\n\n/**\n * You cannot use both `defaultValue` and `parse` at the same time.\n * You should use `parse` instead to handle the default value.\n *\n * For example, you cannot do this:\n *\n * ```ts\n * linkedQueryParam('param', { defaultValue: 1, parse: (x) => x ? parseInt(x, 10) : x });\n * ```\n *\n * Instead, you should do this:\n *\n * ```ts\n * linkedQueryParam('param', { parse: (x) => x ? parseInt(x, 10) : 1 });\n * ```\n */\nexport function linkedQueryParam<T = string>(\n\tkey: QueryParamKeyType,\n\toptions: LinkedQueryParamOptions<T> & {\n\t\tdefaultValue: Exclude<T, undefined> | (() => Exclude<T, undefined>);\n\t\tparse: ParseFn<T>;\n\t\tstringify?: StringifyFn<T>;\n\t},\n): never;\n\nexport function linkedQueryParam<T = string>(\n\tkey: QueryParamKeyType,\n\toptions: LinkedQueryParamOptions<T> & {\n\t\tdefaultValue: T | (() => T);\n\t\tstringify: StringifyFn<T>;\n\t},\n): WritableSignal<T | null>;\n\nexport function linkedQueryParam<T>(\n\tkey: QueryParamKeyType,\n\toptions: LinkedQueryParamOptions<T> & { defaultValue: T | (() => T) },\n): WritableSignal<T> & {\n\tset: SignalSetFn<T | null>;\n\tupdate: SignalUpdateFn<T | null>;\n};\n\nexport function linkedQueryParam<T>(\n\tkey: QueryParamKeyType,\n\toptions: LinkedQueryParamOptions<T> & {\n\t\tdefaultValue: T | (() => T) | (() => T | null) | null;\n\t},\n): WritableSignal<T | null>;\n\nexport function linkedQueryParam<T>(\n\tkey: QueryParamKeyType,\n\toptions: LinkedQueryParamOptions<T> & {\n\t\tdefaultValue: T | (() => T) | (() => T | undefined) | undefined;\n\t},\n): WritableSignal<T | undefined>;\n\nexport function linkedQueryParam<T = string>(\n\tkey: QueryParamKeyType,\n\toptions: LinkedQueryParamOptions<T> & { defaultValue: undefined },\n): WritableSignal<T | null>;\n\nexport function linkedQueryParam<T>(\n\tkey: QueryParamKeyType,\n\toptions: LinkedQueryParamOptions<T> & { parse: ParseFn<T> },\n): WritableSignal<T> & {\n\tset: SignalSetFn<T | null>;\n\tupdate: SignalUpdateFn<T | null>;\n};\n\nexport function linkedQueryParam<T = string>(\n\tkey: QueryParamKeyType,\n\toptions: LinkedQueryParamOptions<T> & { stringify: StringifyFn<T> },\n): WritableSignal<T | null>;\n\nexport function linkedQueryParam<T = string>(\n\tkey: QueryParamKeyType,\n\toptions: LinkedQueryParamOptions<T>,\n): WritableSignal<T | null>;\n\nexport function linkedQueryParam<T = string>(\n\tkey: QueryParamKeyType,\n): WritableSignal<T | null>;\n\nexport function linkedQueryParam<T>(\n\tkey: QueryParamKeyType,\n\toptions?: LinkedQueryParamOptions<T> & {\n\t\tdefaultValue?: T | (() => T);\n\t\tparse?: ParseFn<T>;\n\t\tstringify?: StringifyFn<T>;\n\t\tsource?: WritableSignal<T>;\n\t\tautomaticallySynchronizeOnKeyChange?: boolean;\n\t},\n): WritableSignal<T> {\n\tif (options?.defaultValue !== undefined && options?.parse) {\n\t\tthrow new Error(\n\t\t\t'linkedQueryParam: You cannot have both defaultValue and parse at the same time!',\n\t\t);\n\t}\n\n\tconst injector = assertInjector(linkedQueryParam, options?.injector);\n\n\treturn runInInjectionContext(injector, () => {\n\t\tconst route = inject(ActivatedRoute);\n\t\tconst globalHandler = inject(LinkedQueryParamGlobalHandler);\n\t\tconst config = inject(_LINKED_QUERY_PARAM_CONFIG_TOKEN);\n\n\t\t// We have a dynamic key, so everytime the key changes, we need to make sure we remove the old one from the params\n\t\tconst queryParamKey = computed(() => getCurrentKey(key));\n\t\t// We keep track of the previous queryParam key to remove the old one from the params\n\t\tconst previousQueryParamKey = computedPrevious(queryParamKey);\n\n\t\tconst parsedInitialValue = computed(() => {\n\t\t\treturn parseParamValue(\n\t\t\t\troute.snapshot.queryParams,\n\t\t\t\tqueryParamKey(),\n\t\t\t\toptions,\n\t\t\t);\n\t\t});\n\n\t\tlet source!: WritableSignal<T>;\n\n\t\tif (options?.source) {\n\t\t\tsource = options.source;\n\n\t\t\tconst effRef = effect(() => {\n\t\t\t\tsource.set(parsedInitialValue() as T);\n\t\t\t\t// we want to set the initial value once on the source signal\n\t\t\t\teffRef.destroy();\n\t\t\t});\n\t\t} else {\n\t\t\tsource = linkedSignal<T>(() => parsedInitialValue() as T, {\n\t\t\t\tequal: options?.equal ?? undefined,\n\t\t\t\t// debugName: `linkedQueryParam-${queryParamKey()}`, TODO: enable when available\n\t\t\t});\n\t\t}\n\n\t\t// we need to keep a reference to the original set function\n\t\t// so we can use it to update the source signal whenever the query param changes\n\t\tconst sourceSignalSetMethod: (value: T) => void = source.set;\n\n\t\t// By subscribing directly to the queryParams, we know this subscription is synchronous,\n\t\t// So we don't have to depend on another effect to synchronise the values between params and source signal\n\t\troute.queryParams\n\t\t\t.pipe(\n\t\t\t\tdistinctUntilKeyChanged(queryParamKey()), // skip if no changes on same key\n\t\t\t\tmap((qp) => parseParamValue(qp, queryParamKey(), options)),\n\t\t\t\ttakeUntilDestroyed(),\n\t\t\t)\n\t\t\t.subscribe((value) => {\n\t\t\t\tif (value === source() && !options?.equal) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// we want to call the source set method only when\n\t\t\t\t// - the equal function is not provided or\n\t\t\t\t// - when the value is different from the current source value\n\t\t\t\tsourceSignalSetMethod(value as T);\n\t\t\t});\n\n\t\tconst setSourceValueAndScheduleNavigation = (value: T) => {\n\t\t\t// first we check if the value is undefined or null, so we can set the default value instead\n\t\t\tif (isNil(value) && options?.defaultValue !== undefined) {\n\t\t\t\tvalue = getValueOrReactiveValue(options.defaultValue);\n\t\t\t}\n\n\t\t\t// we first set the initial value so it synchronous (same as a normal signal)\n\t\t\tsourceSignalSetMethod(value);\n\n\t\t\tif (queryParamKey() !== previousQueryParamKey()) {\n\t\t\t\t// remove the previous query param if it's different from the current one\n\t\t\t\t// this way the url is cleaned up, and also the update is scheduled on the same tick as the current one\n\t\t\t\t// NOTE: If the user wants to set a value on the previous queryParam key,\n\t\t\t\t// they should do it synchronously after setting this linkedQueryParam value (check setParamKeyValue for more)\n\t\t\t\tif (previousQueryParamKey()) {\n\t\t\t\t\t// we want to prevent setting the param if the previous key is === \"\", null or undefined\n\t\t\t\t\tglobalHandler.setParamKeyValue(previousQueryParamKey(), null);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tglobalHandler.setParamKeyValue(\n\t\t\t\tqueryParamKey(),\n\t\t\t\tstringifyParamValue(value, options),\n\t\t\t);\n\n\t\t\tglobalHandler.setCurrentNavigationExtras({\n\t\t\t\t...defaultConfig,\n\t\t\t\t...config,\n\t\t\t\t...(options ?? {}),\n\t\t\t});\n\n\t\t\t// schedule the navigation event (multiple synchronous navigations will be coalesced)\n\t\t\t// this will also reset the current keys and navigation extras after the navigation\n\t\t\tglobalHandler.scheduleNavigation();\n\t\t};\n\n\t\tconst update = (fn: (value: T) => T) =>\n\t\t\tsetSourceValueAndScheduleNavigation(fn(source()));\n\n\t\tif (options?.source) {\n\t\t\t// When the source signal changes from outside\n\t\t\t// (lets say someone changes the form field and doesn't use the signal returned from linkedQueryParam),\n\t\t\t// we want to schedule a navigation event to update the query param\n\t\t\t// We use defer to skip the initial effect run as the initial value is already handled\n\t\t\texplicitEffect(\n\t\t\t\t[options.source],\n\t\t\t\t([value]) => setSourceValueAndScheduleNavigation(value as T),\n\t\t\t\t{ defer: true },\n\t\t\t);\n\t\t}\n\n\t\tconst automaticallySynchronizeOnKeyChange =\n\t\t\toptions?.automaticallySynchronizeOnKeyChange ??\n\t\t\tconfig.automaticallySynchronizeOnKeyChange;\n\n\t\tif (automaticallySynchronizeOnKeyChange && isSignalOrFunction(key)) {\n\t\t\t// we want to register the effect when the key is dynamic and the automaticallySynchronizeOnKeyChange is true\n\t\t\texplicitEffect(\n\t\t\t\t[queryParamKey],\n\t\t\t\t// only when queryParamKey changes we want to schedule a navigation\n\t\t\t\t() => setSourceValueAndScheduleNavigation(source() as T),\n\t\t\t\t{ defer: true },\n\t\t\t);\n\t\t}\n\n\t\treturn Object.assign(source, {\n\t\t\tset: setSourceValueAndScheduleNavigation,\n\t\t\tupdate,\n\t\t});\n\t});\n}\n\nconst getValueOrReactiveValue = <T>(value: T | (() => T) | Signal<T>) => {\n\tif (isSignal(value)) {\n\t\treturn value();\n\t}\n\tif (value && typeof value === 'function') {\n\t\treturn (value as () => T)();\n\t}\n\treturn value;\n};\n\nconst isSignalOrFunction = <T>(value: T | (() => T) | Signal<T>) => {\n\treturn isSignal(value) || typeof value === 'function';\n};\n\n// Get the current key value or throw an error if it's null or undefined\nconst getCurrentKey = (key: QueryParamKeyType): string => {\n\tconst queryParamName = getValueOrReactiveValue(key);\n\tif (queryParamName === undefined) {\n\t\tthrow new Error(\n\t\t\t'ngxtension/linkedQueryParam: key cannot be null or undefined',\n\t\t);\n\t}\n\treturn queryParamName;\n};\n\n/**\n * Parses a parameter value based on provided configuration.\n * @param key\n * @param options\n * @param params - An object containing parameters.\n * @returns The parsed parameter value.\n */\nconst parseParamValue = <T>(\n\tparams: Params,\n\tkey: string,\n\toptions?: LinkedQueryParamOptions<T> & {\n\t\tdefaultValue?: T | (() => T);\n\t\tparse?: ParseFn<T>;\n\t\tstringify?: StringifyFn<T>;\n\t},\n) => {\n\t// Get the value from the params object.\n\tconst value: string | null = params[key] ?? null;\n\t// If a parsing function is provided in the config, use it to parse the value.\n\tif (options?.parse) {\n\t\treturn options.parse(value);\n\t}\n\t// If the value is undefined or null and a default value is provided, return the default value.\n\tif (isNil(value) && options?.defaultValue !== undefined) {\n\t\treturn getValueOrReactiveValue(options.defaultValue);\n\t}\n\t// Otherwise, return the original value or the parsed value (if it was parsed).\n\treturn value;\n};\n\n/**\n * Can be used to parse a query param value to a number.\n * You can also use the `defaultValue` option to set a default value if the query param is not present in the url (null or undefined).\n *\n * Example:\n * ```ts\n * linkedQueryParam('page', { parse: paramToNumber() });\n * ```\n * Will return null if the query param is not present in the url.\n *\n * Or with a default value:\n * ```ts\n * linkedQueryParam('page', { parse: paramToNumber({defaultValue: 1}) });\n * ```\n *\n * Will return 1 if the query param is not present in the url.\n */\nexport function paramToNumber(): (x: string | null) => number | null;\nexport function paramToNumber(config: {\n\tdefaultValue: number;\n}): (x: string | null) => number;\n\nexport function paramToNumber(\n\tconfig: { defaultValue?: number | null | undefined } = { defaultValue: null },\n): (x: string | null) => number | null | undefined {\n\treturn (x: string | null) => {\n\t\tif (isNil(x)) return config.defaultValue;\n\t\tconst parsed = parseInt(x, 10);\n\t\tif (Number.isNaN(parsed)) return config.defaultValue;\n\t\treturn parsed;\n\t};\n}\n\n/**\n * Can be used to parse a query param value to a boolean.\n * You can also use the `defaultValue` option to set a default value if the query param is not present in the url (null or undefined).\n *\n * Example:\n * ```ts\n * linkedQueryParam('showHidden', { parse: paramToBoolean() });\n * ```\n * Will return null if the query param is not present in the url or true/false if the query param is present.\n *\n * Or with a default value:\n * ```ts\n * linkedQueryParam('showHidden', { parse: paramToBoolean({defaultValue: true}) });\n * ```\n *\n * Will return true if the query param is not present in the url.\n * Otherwise, it will return whatever the query param value is.\n */\nexport function paramToBoolean(): (x: string | null) => boolean | null;\nexport function paramToBoolean(config: {\n\tdefaultValue: boolean;\n}): (x: string | null) => boolean;\n\nexport function paramToBoolean(\n\tconfig: { defaultValue?: boolean | null | undefined } = {\n\t\tdefaultValue: null,\n\t},\n): (x: string | null) => boolean | null | undefined {\n\treturn (x: string | null) => (isNil(x) ? config.defaultValue : x === 'true');\n}\n\nfunction isNil<T>(value: T | null | undefined): value is null {\n\treturn value === null || value === undefined;\n}\n\nfunction stringifyParamValue<T>(\n\tvalue: T,\n\toptions?: { stringify?: StringifyFn<T> },\n) {\n\t// when the source signal changes, update the query param\n\t// store the new value in the current keys so that we can coalesce the navigation\n\treturn options?.stringify\n\t\t? options.stringify(value)\n\t\t: isNil(value)\n\t\t\t? null\n\t\t\t: typeof value === 'string'\n\t\t\t\t? value\n\t\t\t\t: String(value);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}