{"version":3,"file":"serialize-B8B4WXQs.cjs","names":["FILTER_TREE_PARAM","FILTER_TREE_VERSION","VERSION_PREFIX","isActiveFilterTree","tree","conditions","length","isCombinator","raw","sanitizeCondition","undefined","node","key","op","value","sanitizeGroup","combinator","Array","isArray","child","group","push","condition","parseFilterTree","startsWith","JSON","parse","slice","serializeFilterTree","stringify","useRef","isBrowser","createHistoryAdapter","listeners","Set","notify","listener","getSearch","globalThis","location","search","replace","setSearch","options","history","url","pathname","hash","push","pushState","replaceState","subscribe","onChange","size","addEventListener","add","delete","removeEventListener","createMemoryAdapter","initialSearch","current","historySingleton","getHistoryAdapter","resetHistoryAdapter","undefined","useResolvedAdapter","adapter","enabled","memoryRef","isRtlElement","element","globalThis","getComputedStyle","direction","nodeType","node","attr","getAttribute","isForcedLtrWrapper","parentElement","scoped","closest","cls","includes","MAX_COLUMN_WIDTH","MIN_COLUMN_WIDTH","CONTENT_PADDING","CLIP_EPSILON","intrinsicContentWidth","cell","document","body","probe","createElement","setAttribute","style","position","visibility","pointerEvents","height","width","maxWidth","whiteSpace","innerHTML","appendChild","scrollWidth","remove","cellNeededWidth","scroll","client","clientWidth","intrinsic","measureColumnWidth","root","key","cells","querySelectorAll","CSS","escape","length","widest","Math","max","min","autoSizeColumns","keys","setWidth","sized","isRtlElement","measureColumnWidth","MIN_COLUMN_WIDTH","MAX_COLUMN_WIDTH","COLUMN_RESIZE_STEP","cellWidth","handle","cell","closest","getBoundingClientRect","width","isRtl","columnResizeHandleProps","key","setWidth","label","role","tabIndex","onDoubleClick","event","currentTarget","ownerDocument","body","onPointerDown","preventDefault","stopPropagation","startX","clientX","startWidth","rtl","frame","lastX","commit","delta","Math","max","onMove","e","globalThis","requestAnimationFrame","onUp","cancelAnimationFrame","document","removeEventListener","addEventListener","onKeyDown","current","widen","MAX_COLUMN_WIDTH","MIN_COLUMN_WIDTH","parseFilterTree","serializeFilterTree","safeDecode","value","decodeURIComponent","splitRaw","raw","split","map","part","trim","filter","Boolean","PARAM_PAGE","PARAM_LIMIT","PARAM_SEARCH","PARAM_SORT_BY","PARAM_SORT_DIR","PARAM_SORT","PARAM_GROUP_BY","FILTER_PREFIX","PARAM_FILTER_TREE","PARAM_GROUP_CLOSED","PARAM_COL_HIDDEN","PARAM_COL_PINNED","PARAM_COL_ORDER","PARAM_COL_WIDTHS","PARAM_COL_GROUPS","PARAM_ROW_PIN","PARAM_DENSITY","PARAM_PIVOT","PARAM_FORMULA","readPage","params","fallback","prefix","get","n","Number","parseInt","NaN","isFinite","MAX_LIMIT","readLimit","readSortDir","undefined","readExtra","numberKeys","arrayKeys","filterPrefix","out","forEach","key","startsWith","bare","slice","length","includes","arr","v","isEmptyFilterValue","Array","isArray","writeExtra","extra","staleKeys","_","push","delete","Object","entries","param","String","set","encodeURIComponent","join","readFilterTreeParam","writeFilterTreeParam","tree","readColumnLayout","hideRaw","pinRaw","orderRaw","widthRaw","groupRaw","pinned","pair","encKey","side","widths","px","Math","min","max","collapsedGroups","hidden","order","writeColumnLayout","layout","setOrDelete","round","id","readSortLevels","dir","writeSortLevels","levels","l","readCollapsedGroups","writeCollapsedGroups","keys","readRowPins","top","bottom","colon","lastIndexOf","writeRowPins","state","pairs"],"sources":["../src/filters/filterTreeCodec.ts","../src/url/adapter.ts","../src/layout/writingDirection.ts","../src/columns/autoSizeColumns.ts","../src/columns/columnResize.ts","../src/url/serialize.ts"],"sourcesContent":["/**\n * Versioned AND/OR filter-tree encoding (`ft=1.{…}`).\n * Kept free of predicates so the URL layer does not pull the filter engine\n * into a table that never declares filters.\n */\nimport type { QueryCondition, QueryFilterGroup } from \"../source/queryContract\";\n\n/** URL param for the versioned tree (`ft=1.{…}`). */\nexport const FILTER_TREE_PARAM = \"ft\";\n\n/** Current encoding version. Unknown versions are dropped, never reinterpreted. */\nexport const FILTER_TREE_VERSION = 1;\n\nconst VERSION_PREFIX = `${FILTER_TREE_VERSION}.`;\n\n/** True when a tree has at least one condition (nested groups count). */\nexport function isActiveFilterTree(\n  tree: QueryFilterGroup | undefined\n): tree is QueryFilterGroup {\n  return tree != null && tree.conditions.length > 0;\n}\n\nfunction isCombinator(raw: unknown): raw is QueryFilterGroup[\"combinator\"] {\n  return raw === \"and\" || raw === \"or\";\n}\n\nfunction sanitizeCondition(raw: unknown): QueryCondition | undefined {\n  if (raw == null || typeof raw !== \"object\") return undefined;\n  const node = raw as Record<string, unknown>;\n  if (typeof node.key !== \"string\" || node.key === \"\") return undefined;\n  if (typeof node.op !== \"string\" || node.op === \"\") return undefined;\n  return { key: node.key, op: node.op, value: node.value };\n}\n\nfunction sanitizeGroup(raw: unknown): QueryFilterGroup | undefined {\n  if (raw == null || typeof raw !== \"object\") return undefined;\n  const node = raw as Record<string, unknown>;\n  if (!isCombinator(node.combinator)) return undefined;\n  if (!Array.isArray(node.conditions)) return undefined;\n  const conditions: (QueryCondition | QueryFilterGroup)[] = [];\n  for (const child of node.conditions) {\n    const group = sanitizeGroup(child);\n    if (group) {\n      conditions.push(group);\n      continue;\n    }\n    const condition = sanitizeCondition(child);\n    if (condition) conditions.push(condition);\n  }\n  return { combinator: node.combinator, conditions };\n}\n\n/**\n * Parse a stored `ft` value. Missing, malformed, or unknown-version\n * strings return `undefined` so an old or hand-edited link never\n * silently becomes a different query.\n */\nexport function parseFilterTree(\n  raw: string | null | undefined\n): QueryFilterGroup | undefined {\n  if (raw == null || raw === \"\") return undefined;\n  if (!raw.startsWith(VERSION_PREFIX)) return undefined;\n  try {\n    return sanitizeGroup(JSON.parse(raw.slice(VERSION_PREFIX.length)));\n  } catch {\n    return undefined;\n  }\n}\n\n/** Encode a tree for the URL. Empty / undefined trees omit the param. */\nexport function serializeFilterTree(\n  tree: QueryFilterGroup | undefined\n): string | undefined {\n  if (!isActiveFilterTree(tree)) return undefined;\n  return `${VERSION_PREFIX}${JSON.stringify(tree)}`;\n}\n","/**\n * The injectable seam that decouples AdaptTable's URL-synced state from\n * any particular router. A `UrlStateAdapter` is a tiny store over the\n * current query string; the table reads it via `useSyncExternalStore`\n * and writes through it.\n *\n * Core ships two implementations — {@link createHistoryAdapter} (browser\n * History API, the default) and {@link createMemoryAdapter} (in-memory,\n * for SSR/tests/URL-sync-disabled). Framework adapters (react-router,\n * Next.js) implement the same three methods.\n */\nimport { useRef } from \"react\";\n\nimport { isBrowser } from \"../utils/env\";\n\nexport interface UrlStateAdapter {\n  /** Current query string WITHOUT the leading `\"?\"` (e.g. `\"page=2&q=foo\"`). */\n  getSearch(): string;\n  /**\n   * Replace the query string.\n   * @param search - The next query string (without `\"?\"`).\n   * @param options - `push: true` adds a history entry; default replaces.\n   */\n  setSearch(search: string, options?: { push?: boolean }): void;\n  /**\n   * Subscribe to external changes (back/forward navigation, deep links).\n   * @returns An unsubscribe function.\n   */\n  subscribe(onChange: () => void): () => void;\n}\n\n/**\n * Browser History-API adapter. A single instance is shared per `window`\n * (the query string is global state), so this is safe to memoise as a\n * module singleton via {@link getHistoryAdapter}.\n *\n * @returns A {@link UrlStateAdapter} backed by `window.history` + `popstate`.\n */\nexport function createHistoryAdapter(): UrlStateAdapter {\n  const listeners = new Set<() => void>();\n\n  const notify = (): void => {\n    for (const listener of listeners) listener();\n  };\n\n  return {\n    getSearch() {\n      return globalThis.location.search.replace(/^\\?/, \"\");\n    },\n    setSearch(search, options) {\n      const { location, history } = globalThis;\n      const url =\n        location.pathname + (search ? `?${search}` : \"\") + location.hash;\n      if (options?.push) {\n        history.pushState(null, \"\", url);\n      } else {\n        history.replaceState(null, \"\", url);\n      }\n      notify();\n    },\n    subscribe(onChange) {\n      if (listeners.size === 0) {\n        globalThis.addEventListener(\"popstate\", notify);\n      }\n      listeners.add(onChange);\n      return () => {\n        listeners.delete(onChange);\n        if (listeners.size === 0) {\n          globalThis.removeEventListener(\"popstate\", notify);\n        }\n      };\n    },\n  };\n}\n\n/**\n * In-memory adapter. Holds the query string in a closure with its own\n * subscriber set — used for SSR, tests, and when URL sync is disabled\n * (the table still gets fully working local state).\n *\n * @param initialSearch - Optional starting query string (without `\"?\"`).\n * @returns A self-contained {@link UrlStateAdapter}.\n */\nexport function createMemoryAdapter(initialSearch = \"\"): UrlStateAdapter {\n  let current = initialSearch.replace(/^\\?/, \"\");\n  const listeners = new Set<() => void>();\n\n  return {\n    getSearch() {\n      return current;\n    },\n    setSearch(search) {\n      current = search;\n      for (const listener of listeners) listener();\n    },\n    subscribe(onChange) {\n      listeners.add(onChange);\n      return () => listeners.delete(onChange);\n    },\n  };\n}\n\nlet historySingleton: UrlStateAdapter | undefined;\n\n/**\n * Lazily create and reuse one History-API adapter per runtime. Returns a\n * fresh memory adapter when there is no `window` (SSR).\n *\n * @returns The shared history adapter, or a memory adapter under SSR.\n */\nexport function getHistoryAdapter(): UrlStateAdapter {\n  if (!isBrowser()) {\n    return createMemoryAdapter();\n  }\n  historySingleton ??= createHistoryAdapter();\n  return historySingleton;\n}\n\n/**\n * Reset the cached history singleton. Test-only seam so suites don't leak\n * adapter state across cases.\n *\n * @internal\n */\nexport function resetHistoryAdapter(): void {\n  historySingleton = undefined;\n}\n\n/**\n * Resolve which {@link UrlStateAdapter} a URL-synced hook should use: an\n * explicit `adapter` wins; otherwise the shared history adapter in the\n * browser, or a stable per-hook memory adapter when disabled or under SSR.\n *\n * @param adapter - Optional explicit adapter (router integration).\n * @param enabled - When false, always use the local memory adapter.\n * @returns The adapter to read/write the query string through.\n */\nexport function useResolvedAdapter(\n  adapter: UrlStateAdapter | undefined,\n  enabled: boolean\n): UrlStateAdapter {\n  // A per-hook memory adapter, created once, used when disabled or SSR.\n  const memoryRef = useRef<UrlStateAdapter | null>(null);\n  memoryRef.current ??= createMemoryAdapter();\n\n  // `enabled` is checked FIRST and beats an explicit adapter: \"not syncing\"\n  // has to mean writes land in memory, whoever supplied the adapter. With the\n  // checks the other way round a disabled hook kept writing to the caller's\n  // real adapter, and every disabled hook sharing one adapter also collided\n  // in the namespace registry — which made a single table warn about itself.\n  if (!enabled) return memoryRef.current;\n  if (adapter) return adapter;\n  if (!isBrowser()) return memoryRef.current;\n  return getHistoryAdapter();\n}\n","/**\n * Nearest writing direction for a grip or handle.\n *\n * `closest(\"[dir]\")` is not enough: Radix `Table.Root` wraps the table in a\n * ScrollArea that stamps `dir=\"ltr\"` on the viewport, then restores RTL with\n * CSS (`direction: rtl` on `.rt-ScrollAreaViewport`). Trust the computed\n * style first; when that throws (jsdom stubs) or reports the initial `ltr`,\n * walk ancestors and skip those forced-ltr scroll wrappers so the table's\n * own `dir` wins.\n */\nexport function isRtlElement(element: HTMLElement | null): boolean {\n  if (element == null) return false;\n  try {\n    if (globalThis.getComputedStyle(element).direction === \"rtl\") return true;\n  } catch {\n    // Stubs and detached nodes are not Elements jsdom will measure.\n  }\n  if (element.nodeType === 1) {\n    let node: Element | null = element;\n    while (node) {\n      const attr = node.getAttribute(\"dir\");\n      if (attr === \"rtl\") return true;\n      if (attr === \"ltr\" && !isForcedLtrWrapper(node)) return false;\n      node = node.parentElement;\n    }\n    return false;\n  }\n  const scoped = element.closest(\"[dir]\");\n  return scoped?.getAttribute(\"dir\") === \"rtl\";\n}\n\nfunction isForcedLtrWrapper(node: Element): boolean {\n  const cls = node.getAttribute(\"class\") ?? \"\";\n  return cls.includes(\"rt-ScrollArea\");\n}\n","/**\n * Sizing a column to what is actually in it.\n *\n * A width nobody chose is a width nobody likes: the default is the same for a\n * column of two-letter codes and one of email addresses, and the fix — dragging\n * every handle — is the kind of work a table should do for you. Double-clicking\n * a resize handle sizes that column to its content; a menu action does the lot.\n *\n * Measurement comes from the DOM rather than from the data, because the data is\n * not what has a width: a cell renders a badge, an avatar and a name, and the\n * only honest answer to \"how wide is this column\" is what the browser laid out.\n * That means auto-sizing measures the RENDERED rows — the page, or the window\n * under virtualization — which is the same set the reader is looking at.\n */\nimport { MAX_COLUMN_WIDTH, MIN_COLUMN_WIDTH } from \"./columnResize\";\n\n/** Breathing room added to the widest cell so text never touches the edge. */\nconst CONTENT_PADDING = 24;\n\n/** Sub-pixel slack: `scrollWidth === clientWidth` is already a fit. */\nconst CLIP_EPSILON = 1;\n\n/**\n * True content width of a cell that already fits in its box.\n *\n * `scrollWidth` equals the box once the column is wide enough, so using it\n * again would grow forever (`+ padding` on every click). A max-content probe\n * of the cell's children is the width a second click should keep.\n */\nfunction intrinsicContentWidth(cell: HTMLElement): number {\n  if (typeof document === \"undefined\" || !document.body) return 0;\n  const probe = document.createElement(\"div\");\n  probe.setAttribute(\"aria-hidden\", \"true\");\n  probe.style.position = \"absolute\";\n  probe.style.visibility = \"hidden\";\n  probe.style.pointerEvents = \"none\";\n  probe.style.height = \"auto\";\n  probe.style.width = \"max-content\";\n  probe.style.maxWidth = \"none\";\n  probe.style.whiteSpace = \"normal\";\n  probe.innerHTML = cell.innerHTML;\n  document.body.appendChild(probe);\n  const width = probe.scrollWidth;\n  probe.remove();\n  return width;\n}\n\n/** Width this cell needs, including breathing room when content was clipped. */\nfunction cellNeededWidth(cell: HTMLElement): number {\n  const scroll = cell.scrollWidth;\n  const client = cell.clientWidth;\n  if (scroll > client + CLIP_EPSILON) {\n    return scroll + CONTENT_PADDING;\n  }\n  const intrinsic = intrinsicContentWidth(cell);\n  if (intrinsic > 0) return intrinsic + CONTENT_PADDING;\n  return scroll;\n}\n\n/**\n * The width a column needs for its widest rendered cell.\n *\n * Cells are found by the `data-column-key` every adapter's cells carry, so this\n * needs no per-kit knowledge and works the same in a table of divs.\n *\n * @param root - The table element (or any ancestor of its cells).\n * @param key - The column key to measure.\n * @returns The width in pixels, clamped to the resize bounds, or `null` when\n *   the column has no cells on screen to measure.\n */\nexport function measureColumnWidth(\n  root: Element | null,\n  key: string\n): number | null {\n  if (!root) return null;\n  const cells = root.querySelectorAll<HTMLElement>(\n    `[data-column-key=\"${CSS.escape(key)}\"]`\n  );\n  if (cells.length === 0) return null;\n  let widest = 0;\n  for (const cell of cells) {\n    widest = Math.max(widest, cellNeededWidth(cell));\n  }\n  if (widest === 0) return null;\n  return Math.min(MAX_COLUMN_WIDTH, Math.max(MIN_COLUMN_WIDTH, widest));\n}\n\n/**\n * Size every rendered column to its content.\n *\n * @param root - The table element.\n * @param keys - The columns to size, in any order.\n * @param setWidth - The layout mutator that persists each width.\n * @returns How many columns were sized — zero when nothing was measurable.\n */\nexport function autoSizeColumns(\n  root: Element | null,\n  keys: readonly string[],\n  setWidth: (key: string, width: number) => void\n): number {\n  let sized = 0;\n  for (const key of keys) {\n    const width = measureColumnWidth(root, key);\n    if (width === null) continue;\n    setWidth(key, width);\n    sized++;\n  }\n  return sized;\n}\n","import type { KeyboardEvent, MouseEvent, PointerEvent } from \"react\";\n\nimport { isRtlElement } from \"../layout/writingDirection\";\nimport { measureColumnWidth } from \"./autoSizeColumns\";\n\n/** Minimum column width (px) a resize drag/keyboard step will not go below. */\nexport const MIN_COLUMN_WIDTH = 60;\n\n/**\n * Upper bound for a persisted/URL-restored column width — generous enough\n * for any real drag on an ultra-wide display, tight enough that a hostile\n * `colW=1e9` cannot blow the layout.\n */\nexport const MAX_COLUMN_WIDTH = 4000;\n/** Keyboard resize step (px) per arrow press. */\nexport const COLUMN_RESIZE_STEP = 16;\n\n/**\n * Props for a column-resize handle element. Modeled as a `button` (a focusable\n * `separator`/splitter would require `aria-valuenow/min/max`); ArrowLeft/Right\n * resize it for keyboard users.\n */\nexport interface ColumnResizeHandleProps {\n  role: \"button\";\n  tabIndex: 0;\n  \"aria-label\": string;\n  onPointerDown: (event: PointerEvent<HTMLElement>) => void;\n  onKeyDown: (event: KeyboardEvent<HTMLElement>) => void;\n  /** Double-click sizes the column to its content, as every grid does. */\n  onDoubleClick: (event: MouseEvent<HTMLElement>) => void;\n}\n\n/** Current rendered width of the resize handle's owning header cell. */\nfunction cellWidth(handle: HTMLElement): number {\n  const cell = handle.closest(\"th,td\");\n  return cell ? cell.getBoundingClientRect().width : MIN_COLUMN_WIDTH;\n}\n\n/**\n * Whether the handle sits in a right-to-left context. The handle renders at\n * the column's inline-end (the visual LEFT edge in RTL), so the physical drag\n * delta and the Arrow keys must flip to keep \"drag/press outward = wider\".\n * Prefers an explicit `[dir]` ancestor (what the adapters set on the root),\n * falling back to the resolved CSS `direction` for theme-only RTL.\n */\nfunction isRtl(handle: HTMLElement): boolean {\n  return isRtlElement(handle);\n}\n\n/**\n * Build the props for a column-resize handle. Pointer drag resizes live; arrow\n * keys nudge by {@link COLUMN_RESIZE_STEP} for keyboard a11y. Width is measured\n * from the live cell, so columns need no preset width to be resizable.\n *\n * @param key - Column key being resized.\n * @param setWidth - Layout mutator that persists the new width.\n * @param label - Accessible label for the handle.\n */\nexport function columnResizeHandleProps(\n  key: string,\n  setWidth: (key: string, width: number) => void,\n  label: string\n): ColumnResizeHandleProps {\n  return {\n    role: \"button\",\n    tabIndex: 0,\n    \"aria-label\": label,\n    onDoubleClick: (event) => {\n      // Measure from the table the handle is in, so this needs no wiring: the\n      // cells carry their column key and the browser has already laid them out.\n      const width = measureColumnWidth(\n        event.currentTarget.closest(\"table\") ??\n          event.currentTarget.ownerDocument.body,\n        key\n      );\n      if (width !== null) setWidth(key, width);\n    },\n    onPointerDown: (event) => {\n      event.preventDefault();\n      event.stopPropagation();\n      const startX = event.clientX;\n      const startWidth = cellWidth(event.currentTarget);\n      const rtl = isRtl(event.currentTarget);\n      // Coalesce pointer moves to one width commit per animation frame —\n      // every commit re-renders the table (and may write the URL), and a\n      // drag emits far more moves than frames.\n      let frame = 0;\n      let lastX = startX;\n      const commit = () => {\n        frame = 0;\n        const delta = rtl ? startX - lastX : lastX - startX;\n        setWidth(key, Math.max(MIN_COLUMN_WIDTH, startWidth + delta));\n      };\n      const onMove = (e: globalThis.PointerEvent) => {\n        lastX = e.clientX;\n        frame ||= globalThis.requestAnimationFrame(commit);\n      };\n      // `pointercancel` fires instead of `pointerup` when the browser takes\n      // over the gesture (touch scroll, alt-tab mid-drag) — clean up on both\n      // or the column keeps resizing with every later pointer move.\n      const onUp = () => {\n        // Flush a pending frame so the release position always lands; a\n        // drag-less click leaves no pending frame and commits nothing.\n        if (frame) {\n          globalThis.cancelAnimationFrame(frame);\n          frame = 0;\n          commit();\n        }\n        document.removeEventListener(\"pointermove\", onMove);\n        document.removeEventListener(\"pointerup\", onUp);\n        document.removeEventListener(\"pointercancel\", onUp);\n      };\n      document.addEventListener(\"pointermove\", onMove);\n      document.addEventListener(\"pointerup\", onUp);\n      document.addEventListener(\"pointercancel\", onUp);\n    },\n    onKeyDown: (event) => {\n      if (event.key !== \"ArrowLeft\" && event.key !== \"ArrowRight\") return;\n      event.preventDefault();\n      const current = cellWidth(event.currentTarget);\n      // The handle is at the inline-end edge: in LTR that's the right, so\n      // ArrowRight widens; in RTL it's the left, so ArrowLeft widens.\n      const widen =\n        event.key === (isRtl(event.currentTarget) ? \"ArrowLeft\" : \"ArrowRight\");\n      const delta = widen ? COLUMN_RESIZE_STEP : -COLUMN_RESIZE_STEP;\n      setWidth(key, Math.max(MIN_COLUMN_WIDTH, current + delta));\n    },\n  };\n}\n","/**\n * Pure helpers for reading and writing AdaptTable's URL state. Kept free\n * of React so they can be unit-tested directly and reused by any adapter.\n *\n * Conventions (compatible with shareable links):\n * - `page`, `limit`, `q`, `sortBy`, `sortDir`, `groupBy` are top-level params.\n * - Extra (caller-defined) filters live under the `f_` prefix.\n * - Arrays serialise as comma-separated, percent-encoded values (so a value\n *   may itself contain a comma); numbers are parsed back.\n * - Default values are omitted to keep the URL clean.\n */\nimport { MAX_COLUMN_WIDTH, MIN_COLUMN_WIDTH } from \"../columns/columnResize\";\nimport type { ColumnLayoutState } from \"../columns/useColumnLayout\";\nimport {\n  parseFilterTree,\n  serializeFilterTree,\n} from \"../filters/filterTreeCodec\";\nimport { type RowPinSide, type RowPinState } from \"../rows/rowPinning\";\nimport type { QueryFilterGroup } from \"../source/queryContract\";\nimport type { ExtraFilters, FilterValue, SortDirection } from \"../types\";\n\n/** Decode a URI component, tolerating malformed input from hand-edited URLs. */\nfunction safeDecode(value: string): string {\n  try {\n    return decodeURIComponent(value);\n  } catch {\n    return value;\n  }\n}\n\n/** Split a comma list into trimmed, non-empty raw (still-encoded) parts. */\nfunction splitRaw(raw: string | null): string[] {\n  if (!raw) return [];\n  return raw\n    .split(\",\")\n    .map((part) => part.trim())\n    .filter(Boolean);\n}\n\nexport const PARAM_PAGE = \"page\";\nexport const PARAM_LIMIT = \"limit\";\nexport const PARAM_SEARCH = \"q\";\nexport const PARAM_SORT_BY = \"sortBy\";\nexport const PARAM_SORT_DIR = \"sortDir\";\n/** Multi-sort chain: `sort=name:asc,age:desc` (keys percent-encoded). */\nexport const PARAM_SORT = \"sort\";\n/** Single-level row grouping column key. */\nexport const PARAM_GROUP_BY = \"groupBy\";\n/** Keys under this prefix flow through as-is into the `extra` bag. */\nexport const FILTER_PREFIX = \"f_\";\n/** Versioned AND/OR filter tree (`ft=1.{…}`). */\nexport const PARAM_FILTER_TREE = \"ft\";\n/** Column-layout params (hidden / pinned / order / widths). */\n/** Collapsed group keys, comma-separated. */\nexport const PARAM_GROUP_CLOSED = \"groupClosed\";\nexport const PARAM_COL_HIDDEN = \"colHide\";\nexport const PARAM_COL_PINNED = \"colPin\";\nexport const PARAM_COL_ORDER = \"colOrder\";\nexport const PARAM_COL_WIDTHS = \"colW\";\nexport const PARAM_COL_GROUPS = \"colGroupCollapse\";\n/** Pinned rows: `rowPin=id1:top,id2:bottom`. */\nexport const PARAM_ROW_PIN = \"rowPin\";\n\n/** Row density — a display choice, captured by saved views like the rest. */\nexport const PARAM_DENSITY = \"density\";\n\n/** The pivot configuration. See `@adapttable/core/pivot`. */\nexport const PARAM_PIVOT = \"pivot\";\n\n/** The user-typed formula columns. See `@adapttable/core/formula`. */\nexport const PARAM_FORMULA = \"formula\";\n\n/** Read a 1-based page number, falling back when absent/invalid. */\nexport function readPage(\n  params: URLSearchParams,\n  fallback: number,\n  prefix = \"\"\n): number {\n  const raw = params.get(prefix + PARAM_PAGE);\n  const n = raw ? Number.parseInt(raw, 10) : Number.NaN;\n  return Number.isFinite(n) && n > 0 ? n : fallback;\n}\n\n/** Largest accepted page size — shared by the reader and the setter. */\nexport const MAX_LIMIT = 500;\n\n/** Read a page size, clamped to a sane range, falling back when invalid. */\nexport function readLimit(\n  params: URLSearchParams,\n  fallback: number,\n  prefix = \"\"\n): number {\n  const raw = params.get(prefix + PARAM_LIMIT);\n  const n = raw ? Number.parseInt(raw, 10) : Number.NaN;\n  return Number.isFinite(n) && n > 0 && n <= MAX_LIMIT ? n : fallback;\n}\n\n/** Read a sort direction, or `undefined` when missing/invalid. */\nexport function readSortDir(\n  params: URLSearchParams,\n  prefix = \"\"\n): SortDirection | undefined {\n  const raw = params.get(prefix + PARAM_SORT_DIR);\n  return raw === \"asc\" || raw === \"desc\" ? raw : undefined;\n}\n\n/**\n * Read the `f_`-prefixed extra filters, applying number/array parsing for\n * the registered keys.\n */\nexport function readExtra(\n  params: URLSearchParams,\n  numberKeys: readonly string[],\n  arrayKeys: readonly string[],\n  prefix = \"\"\n): ExtraFilters {\n  const filterPrefix = prefix + FILTER_PREFIX;\n  const out: ExtraFilters = {};\n  params.forEach((raw, key) => {\n    if (!key.startsWith(filterPrefix) || raw === \"\") return;\n    const bare = key.slice(filterPrefix.length);\n    if (arrayKeys.includes(bare)) {\n      const arr = raw\n        .split(\",\")\n        .map((v) => safeDecode(v).trim())\n        .filter(Boolean);\n      if (arr.length > 0) out[bare] = arr;\n    } else if (numberKeys.includes(bare)) {\n      const n = Number(raw);\n      if (Number.isFinite(n)) out[bare] = n;\n    } else {\n      out[bare] = raw;\n    }\n  });\n  return out;\n}\n\n/** True when a filter value should remove its param (empty/cleared). */\nexport function isEmptyFilterValue(value: FilterValue): boolean {\n  if (value == null || value === \"\") return true;\n  return Array.isArray(value) && value.length === 0;\n}\n\n/**\n * Write the full extra-filter bag into `params`, stripping any existing\n * `f_` entries first so cleared keys actually leave the URL.\n */\nexport function writeExtra(\n  params: URLSearchParams,\n  extra: ExtraFilters,\n  prefix = \"\"\n): void {\n  const filterPrefix = prefix + FILTER_PREFIX;\n  // Collect existing filter keys first, then delete — mutating while\n  // iterating the live key iterator would skip entries.\n  const staleKeys: string[] = [];\n  params.forEach((_, key) => {\n    if (key.startsWith(filterPrefix)) staleKeys.push(key);\n  });\n  for (const key of staleKeys) params.delete(key);\n  for (const [key, value] of Object.entries(extra)) {\n    if (isEmptyFilterValue(value)) continue;\n    const param = `${filterPrefix}${key}`;\n    if (Array.isArray(value)) {\n      // Trim entries the same way the read side does, so values round-trip\n      // byte-identical; percent-encode each element so a value may contain\n      // the comma delimiter (and survives a URLSearchParams decode).\n      const entries = value.map((v) => String(v).trim()).filter(Boolean);\n      if (entries.length === 0) continue;\n      params.set(param, entries.map((v) => encodeURIComponent(v)).join(\",\"));\n    } else {\n      params.set(param, String(value));\n    }\n  }\n}\n\n/** Read the versioned filter tree; unknown versions are dropped. */\nexport function readFilterTreeParam(\n  params: URLSearchParams,\n  prefix = \"\"\n): QueryFilterGroup | undefined {\n  return parseFilterTree(params.get(prefix + PARAM_FILTER_TREE));\n}\n\n/** Write or clear the versioned filter tree. */\nexport function writeFilterTreeParam(\n  params: URLSearchParams,\n  tree: QueryFilterGroup | undefined,\n  prefix = \"\"\n): void {\n  const key = prefix + PARAM_FILTER_TREE;\n  const raw = serializeFilterTree(tree);\n  if (raw) params.set(key, raw);\n  else params.delete(key);\n}\n\n/**\n * Read the column layout (hidden / pinned / order / widths) from the URL.\n * Each column key is percent-encoded so `:` and `,` (the field/pair\n * delimiters) can never collide with a key. Returns `undefined` when the URL\n * carries no layout at all, so callers can fall back to their default layout.\n */\nexport function readColumnLayout(\n  params: URLSearchParams,\n  prefix = \"\"\n): ColumnLayoutState | undefined {\n  const hideRaw = params.get(prefix + PARAM_COL_HIDDEN);\n  const pinRaw = params.get(prefix + PARAM_COL_PINNED);\n  const orderRaw = params.get(prefix + PARAM_COL_ORDER);\n  const widthRaw = params.get(prefix + PARAM_COL_WIDTHS);\n  const groupRaw = params.get(prefix + PARAM_COL_GROUPS);\n  if (\n    hideRaw === null &&\n    pinRaw === null &&\n    orderRaw === null &&\n    widthRaw === null &&\n    groupRaw === null\n  ) {\n    return undefined;\n  }\n\n  const pinned: Record<string, \"start\" | \"end\"> = {};\n  for (const pair of splitRaw(pinRaw)) {\n    const [encKey, side] = pair.split(\":\");\n    if (encKey && (side === \"start\" || side === \"end\")) {\n      pinned[safeDecode(encKey)] = side;\n    }\n  }\n\n  const widths: Record<string, number> = {};\n  for (const pair of splitRaw(widthRaw)) {\n    const [encKey, px] = pair.split(\":\");\n    const n = Number(px);\n    if (encKey && Number.isFinite(n) && n > 0) {\n      // URL input is hostile: clamp to the same sane range the resize UI\n      // can produce, so a hand-edited colW of 1e9 cannot blow the layout.\n      widths[safeDecode(encKey)] = Math.min(\n        Math.max(n, MIN_COLUMN_WIDTH),\n        MAX_COLUMN_WIDTH\n      );\n    }\n  }\n\n  const collapsedGroups = splitRaw(groupRaw).map(safeDecode);\n  return {\n    hidden: splitRaw(hideRaw).map(safeDecode),\n    order: splitRaw(orderRaw).map(safeDecode),\n    pinned,\n    widths,\n    ...(collapsedGroups.length > 0 ? { collapsedGroups } : {}),\n  };\n}\n\n/**\n * Write the column layout into `params`, dropping any field that is empty so\n * a pristine layout leaves no params behind.\n */\nexport function writeColumnLayout(\n  params: URLSearchParams,\n  layout: ColumnLayoutState,\n  prefix = \"\"\n): void {\n  const setOrDelete = (param: string, value: string): void => {\n    if (value) params.set(prefix + param, value);\n    else params.delete(prefix + param);\n  };\n  setOrDelete(\n    PARAM_COL_HIDDEN,\n    layout.hidden.map((key) => encodeURIComponent(key)).join(\",\")\n  );\n  setOrDelete(\n    PARAM_COL_PINNED,\n    Object.entries(layout.pinned)\n      .map(([key, side]) => `${encodeURIComponent(key)}:${side}`)\n      .join(\",\")\n  );\n  setOrDelete(\n    PARAM_COL_ORDER,\n    layout.order.map((key) => encodeURIComponent(key)).join(\",\")\n  );\n  setOrDelete(\n    PARAM_COL_WIDTHS,\n    Object.entries(layout.widths)\n      .map(([key, px]) => `${encodeURIComponent(key)}:${Math.round(px)}`)\n      .join(\",\")\n  );\n  setOrDelete(\n    PARAM_COL_GROUPS,\n    (layout.collapsedGroups ?? []).map((id) => encodeURIComponent(id)).join(\",\")\n  );\n}\n\n/** Read the multi-sort chain (`sort=key:dir,key2:dir2`). */\nexport function readSortLevels(\n  params: URLSearchParams,\n  prefix = \"\"\n): { key: string; dir: SortDirection }[] {\n  const out: { key: string; dir: SortDirection }[] = [];\n  for (const pair of splitRaw(params.get(prefix + PARAM_SORT))) {\n    const [encKey, dir] = pair.split(\":\");\n    if (encKey && (dir === \"asc\" || dir === \"desc\")) {\n      out.push({ key: safeDecode(encKey), dir });\n    }\n  }\n  return out;\n}\n\n/** Write (or clear, when empty) the multi-sort chain. */\nexport function writeSortLevels(\n  params: URLSearchParams,\n  levels: readonly { key: string; dir: SortDirection }[],\n  prefix = \"\"\n): void {\n  if (levels.length === 0) {\n    params.delete(prefix + PARAM_SORT);\n    return;\n  }\n  params.set(\n    prefix + PARAM_SORT,\n    levels.map((l) => `${encodeURIComponent(l.key)}:${l.dir}`).join(\",\")\n  );\n}\n\n/**\n * Read the collapsed group keys.\n *\n * @param params - The URL parameters.\n * @param prefix - The table's namespace, when it has one.\n * @returns The keys, or `undefined` when the parameter is absent — which means\n *   \"nothing has been said\", not \"nothing is collapsed\".\n */\nexport function readCollapsedGroups(\n  params: URLSearchParams,\n  prefix = \"\"\n): string[] | undefined {\n  const raw = params.get(prefix + PARAM_GROUP_CLOSED);\n  if (raw === null) return undefined;\n  return raw\n    .split(\",\")\n    .filter((key) => key.length > 0)\n    .map((key) => decodeURIComponent(key));\n}\n\n/**\n * Write the collapsed group keys, dropping the parameter when none are.\n *\n * @param params - The URL parameters, mutated in place.\n * @param keys - The collapsed group keys.\n * @param prefix - The table's namespace, when it has one.\n */\nexport function writeCollapsedGroups(\n  params: URLSearchParams,\n  keys: readonly string[],\n  prefix = \"\"\n): void {\n  const value = keys.map((key) => encodeURIComponent(key)).join(\",\");\n  if (value) params.set(prefix + PARAM_GROUP_CLOSED, value);\n  else params.delete(prefix + PARAM_GROUP_CLOSED);\n}\n\n/**\n * Read pinned row ids (`rowPin=id1:top,id2:bottom`).\n *\n * @param params - The URL parameters.\n * @param prefix - The table's namespace, when it has one.\n * @returns The lists, or `undefined` when the parameter is absent.\n */\nexport function readRowPins(\n  params: URLSearchParams,\n  prefix = \"\"\n): RowPinState | undefined {\n  const raw = params.get(prefix + PARAM_ROW_PIN);\n  if (raw === null) return undefined;\n  const top: string[] = [];\n  const bottom: string[] = [];\n  for (const pair of splitRaw(raw)) {\n    const colon = pair.lastIndexOf(\":\");\n    if (colon <= 0) continue;\n    const id = safeDecode(pair.slice(0, colon));\n    const side = pair.slice(colon + 1);\n    if (!id) continue;\n    if (side === \"top\") top.push(id);\n    else if (side === \"bottom\") bottom.push(id);\n  }\n  return { top, bottom };\n}\n\n/**\n * Write pinned row ids, dropping the parameter when both lists are empty.\n *\n * @param params - The URL parameters, mutated in place.\n * @param state - The pin lists.\n * @param prefix - The table's namespace, when it has one.\n */\nexport function writeRowPins(\n  params: URLSearchParams,\n  state: RowPinState,\n  prefix = \"\"\n): void {\n  const pairs: string[] = [];\n  const push = (id: string, side: RowPinSide): void => {\n    pairs.push(`${encodeURIComponent(id)}:${side}`);\n  };\n  for (const id of state.top) push(id, \"top\");\n  for (const id of state.bottom) push(id, \"bottom\");\n  if (pairs.length > 0) params.set(prefix + PARAM_ROW_PIN, pairs.join(\",\"));\n  else params.delete(prefix + PARAM_ROW_PIN);\n}\n"],"mappings":"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"}