@tanstack/router-core
Version:
Modern and scalable routing for React applications
1 lines • 6.54 kB
Source Map (JSON)
{"version":3,"file":"stores.cjs","names":[],"sources":["../../src/stores.ts"],"sourcesContent":["import { arraysEqual, functionalUpdate } from './utils'\n\nimport type { AnyRoute } from './route'\nimport type { RouterState } from './router'\nimport type { FullSearchSchema } from './routeInfo'\nimport type { ParsedLocation } from './location'\nimport type { AnyRouteMatch } from './Matches'\n\nexport interface RouterReadableStore<TValue> {\n get: () => TValue\n}\n\nexport interface RouterWritableStore<\n TValue,\n> extends RouterReadableStore<TValue> {\n set: ((updater: (prev: TValue) => TValue) => void) & ((value: TValue) => void)\n}\n\nexport type RouterBatchFn = (fn: () => void) => void\n\nexport type MutableStoreFactory = <TValue>(\n initialValue: TValue,\n) => RouterWritableStore<TValue>\n\nexport type ReadonlyStoreFactory = <TValue>(\n read: () => TValue,\n) => RouterReadableStore<TValue>\n\nexport type GetStoreConfig = (opts: { isServer?: boolean }) => StoreConfig\n\nexport type StoreConfig = {\n createMutableStore: MutableStoreFactory\n createReadonlyStore: ReadonlyStoreFactory\n batch: RouterBatchFn\n}\n\ntype MatchStore = RouterWritableStore<AnyRouteMatch | undefined>\ntype ReadableStore<TValue> = RouterReadableStore<TValue>\n\n/** SSR non-reactive createMutableStore */\nexport function createNonReactiveMutableStore<TValue>(\n initialValue: TValue,\n): RouterWritableStore<TValue> {\n let value = initialValue\n\n return {\n get() {\n return value\n },\n set(nextOrUpdater: TValue | ((prev: TValue) => TValue)) {\n value = functionalUpdate(nextOrUpdater, value)\n },\n }\n}\n\n/** SSR non-reactive createReadonlyStore */\nexport function createNonReactiveReadonlyStore<TValue>(\n read: () => TValue,\n): RouterReadableStore<TValue> {\n return {\n get() {\n return read()\n },\n }\n}\n\nexport interface RouterStores<in out TRouteTree extends AnyRoute> {\n status: RouterWritableStore<RouterState<TRouteTree>['status']>\n location: RouterWritableStore<ParsedLocation<FullSearchSchema<TRouteTree>>>\n resolvedLocation: RouterWritableStore<\n ParsedLocation<FullSearchSchema<TRouteTree>> | undefined\n >\n ids: RouterWritableStore<Array<string>>\n matches: ReadableStore<Array<AnyRouteMatch>>\n __store: RouterReadableStore<RouterState<TRouteTree>>\n\n byRoute: Map<string, MatchStore>\n\n /**\n * Get the stable atom for a route's presented match. The atom remains in the\n * pool when the route leaves and contains `undefined` until it re-enters.\n */\n getMatchStore: (\n routeId: string,\n ) => RouterReadableStore<AnyRouteMatch | undefined>\n\n setMatches: (nextMatches: Array<AnyRouteMatch>) => void\n}\n\nexport function createRouterStores<TRouteTree extends AnyRoute>(\n initialLocation: RouterState<TRouteTree>['location'],\n config: StoreConfig,\n): RouterStores<TRouteTree> {\n const { createMutableStore, createReadonlyStore, batch } = config\n\n // non reactive utilities\n const byRoute = new Map<string, MatchStore>()\n\n // atoms\n const status = createMutableStore<RouterState<TRouteTree>['status']>('idle')\n const location = createMutableStore(initialLocation)\n const resolvedLocation =\n createMutableStore<RouterState<TRouteTree>['resolvedLocation']>(undefined)\n const ids = createMutableStore<Array<string>>([])\n\n // 1st order derived stores\n const matches = createReadonlyStore(() =>\n ids.get().map((id) => byRoute.get(id)!.get()!),\n )\n\n // compatibility \"big\" state store\n const __store = createReadonlyStore(() => ({\n status: status.get(),\n isLoading: status.get() === 'pending',\n matches: matches.get(),\n location: location.get(),\n resolvedLocation: resolvedLocation.get(),\n }))\n\n function getMatchStore(routeId: string): MatchStore {\n let matchStore = byRoute.get(routeId)\n if (!matchStore) {\n matchStore = createMutableStore<AnyRouteMatch | undefined>(undefined)\n byRoute.set(routeId, matchStore)\n }\n return matchStore\n }\n\n const store = {\n // atoms\n status,\n location,\n resolvedLocation,\n ids,\n\n // derived\n matches,\n\n // non-reactive state\n byRoute,\n\n // compatibility \"big\" state\n __store,\n\n // stable per-route presentation atoms\n getMatchStore,\n\n // methods\n setMatches,\n }\n\n // setters to update non-reactive utilities in sync with the reactive stores\n function setMatches(nextMatches: Array<AnyRouteMatch>) {\n const previousIds = ids.get()\n const nextIds = nextMatches.map((match) => match.routeId)\n\n batch(() => {\n // Publish lane membership first so framework trees reconcile departures\n // before observers of a leaving route receive its tombstone.\n if (!arraysEqual(previousIds, nextIds)) {\n ids.set(nextIds)\n }\n\n for (const id of previousIds) {\n if (!nextIds.includes(id)) {\n byRoute.get(id)!.set(() => undefined)\n }\n }\n\n for (const nextMatch of nextMatches) {\n const matchStore = getMatchStore(nextMatch.routeId)\n if (matchStore.get() !== nextMatch) {\n matchStore.set(nextMatch)\n }\n }\n })\n }\n\n return store\n}\n"],"mappings":";;;AAwCA,SAAgB,8BACd,cAC6B;CAC7B,IAAI,QAAQ;CAEZ,OAAO;EACL,MAAM;GACJ,OAAO;EACT;EACA,IAAI,eAAoD;GACtD,QAAQ,cAAA,iBAAiB,eAAe,KAAK;EAC/C;CACF;AACF;;AAGA,SAAgB,+BACd,MAC6B;CAC7B,OAAO,EACL,MAAM;EACJ,OAAO,KAAK;CACd,EACF;AACF;AAyBA,SAAgB,mBACd,iBACA,QAC0B;CAC1B,MAAM,EAAE,oBAAoB,qBAAqB,UAAU;CAG3D,MAAM,0BAAU,IAAI,IAAwB;CAG5C,MAAM,SAAS,mBAAsD,MAAM;CAC3E,MAAM,WAAW,mBAAmB,eAAe;CACnD,MAAM,mBACJ,mBAAgE,KAAA,CAAS;CAC3E,MAAM,MAAM,mBAAkC,CAAC,CAAC;CAGhD,MAAM,UAAU,0BACd,IAAI,IAAI,EAAE,KAAK,OAAO,QAAQ,IAAI,EAAE,EAAG,IAAI,CAAE,CAC/C;CAGA,MAAM,UAAU,2BAA2B;EACzC,QAAQ,OAAO,IAAI;EACnB,WAAW,OAAO,IAAI,MAAM;EAC5B,SAAS,QAAQ,IAAI;EACrB,UAAU,SAAS,IAAI;EACvB,kBAAkB,iBAAiB,IAAI;CACzC,EAAE;CAEF,SAAS,cAAc,SAA6B;EAClD,IAAI,aAAa,QAAQ,IAAI,OAAO;EACpC,IAAI,CAAC,YAAY;GACf,aAAa,mBAA8C,KAAA,CAAS;GACpE,QAAQ,IAAI,SAAS,UAAU;EACjC;EACA,OAAO;CACT;CAEA,MAAM,QAAQ;EAEZ;EACA;EACA;EACA;EAGA;EAGA;EAGA;EAGA;EAGA;CACF;CAGA,SAAS,WAAW,aAAmC;EACrD,MAAM,cAAc,IAAI,IAAI;EAC5B,MAAM,UAAU,YAAY,KAAK,UAAU,MAAM,OAAO;EAExD,YAAY;GAGV,IAAI,CAAC,cAAA,YAAY,aAAa,OAAO,GACnC,IAAI,IAAI,OAAO;GAGjB,KAAK,MAAM,MAAM,aACf,IAAI,CAAC,QAAQ,SAAS,EAAE,GACtB,QAAQ,IAAI,EAAE,EAAG,UAAU,KAAA,CAAS;GAIxC,KAAK,MAAM,aAAa,aAAa;IACnC,MAAM,aAAa,cAAc,UAAU,OAAO;IAClD,IAAI,WAAW,IAAI,MAAM,WACvB,WAAW,IAAI,SAAS;GAE5B;EACF,CAAC;CACH;CAEA,OAAO;AACT"}