spb/countryatlas
Public
TypeScript 57%
Python 38.6%
JavaScript 3.6%
CSS 0.6%
1/**2 * Server-safe URL parameter helpers (no 'use client' directive) shared by server components (searchParams3 * parsing) and the client `useUrlState` hook in ./url-state.ts, which re-exports them.4 */5export type UrlPatch = Record<string, string | number | boolean | null | undefined>;67export function applyPatch(current: URLSearchParams, patch: UrlPatch): URLSearchParams {8 const p = new URLSearchParams(current.toString());9 for (const [k, v] of Object.entries(patch)) {10 if (v === undefined || v === null || v === '' || v === false) p.delete(k);11 else p.set(k, v === true ? '1' : String(v));12 }13 return p;14}1516/** Parse "a,b,c" → ["a","b","c"] limited to slug-safe tokens. */17export function parseList(v: string | null | undefined, max = 8): string[] {18 if (!v) return [];19 const out: string[] = [];20 for (const part of v.split(',')) {21 const s = part.trim().toLowerCase();22 if (s && /^[a-z0-9][a-z0-9-]*$/.test(s) && !out.includes(s)) out.push(s);23 if (out.length >= max) break;24 }25 return out;26}2728export function parseYear(v: string | null | undefined): number | null {29 if (!v) return null;30 const n = Number(v);31 return Number.isInteger(n) && n >= 1750 && n <= 2100 ? n : null;32}3334/** First string value of a Next `searchParams` entry. */35export function firstParam(v: string | string[] | undefined): string | null {36 return Array.isArray(v) ? (v[0] ?? null) : (v ?? null);37}38